1.order-only依赖:
还是以上一篇的sudoku项目为例,之前写的目标之后的依赖都属于普通依赖,普通依赖都对应自身的规则,order-only依赖也是一样的,但是当依赖文件中的内容发生改动的时候,两种依赖就会产生差别:对于普通依赖而言,当依赖发生改变需要重新与目标文件生成链接,也就是说如果任何一个依赖文件修改时间比目标晚,那么就需要重新生成目标文件;对于order-only依赖而言,如果发生改变,它不会对目标文件更新产生影响,或者说,不需要重新产生新的链接。order-only的格式也很简单,就是文件名前面加一个“|”
e.g. sudoku : block.o command.o … | test.o
根据示例,“|”之后的依赖就是order-only依赖。
2.多个目标多个规则的情况:
这个其实很好理解,因为总会出现同一个目标有相同的依赖这个问题,那么独立的这几个目标就可以使用符号“:”进行链接,也就是写成:
block.o input.o scene.o : common.h
这句的意思其实就是block.o,input.o和scene.o分别都依赖common.h这个文件。如此进行改编,那么相应的编译命令也可以改编:
block.o command.o input.o main.o scene.o test.o : common.h block.h command.h ...
g++ -c $(@:%.o=%.cpp)
g++ -c $(@:%.o=%.cpp) 和之前的例子都是一个编译命令,用于编译一个名为%.o的object文件(其中%是一个通配符,表示任意字符串)。编译器使用g++,-c表示仅编译,不链接。$(@:%.o=%.cpp)是一个变量赋值命令,将%.o替换为%.cpp,即获取源文件名,一个意思换种写法。作用是将一个名为%.o的object文件编译成对应的源文件%.cpp。
3.静态模式:
在进行多目标的编写时,如果出现文件经常改动,每次都需要重新编译生成文件的话会比较麻烦,这个时候可以用一种方法进一步去简化sudoku这个例子,并且解决依赖的问题,这个方法就是静态模式。
因为makefile的一种书写方式时独立多目标的书写,独立多目标可以简化Makefile的书写,但是不利于将各个目标的依赖分开,让目标文件根据各自的依赖进行更新。静态模式可以在一定程度上改进依赖分开问题。直接上改编之后的例子(未完全):
objs = block.o command.o i18n.o input.o main.o scene.o
sudoku: $(objs)
g++ -o $@ $^
$(objs) : %.o : %.cpp %.h
g++ -c $<
相比较于上一篇末的sudoku的例子,这个写法大幅度的简化了写法。其中命令行:$(objs) : %.o : %.cpp %.h就是主要的改编内容。翻译一下就是:取每一个.o文件对应的依赖文件.cpp以及.h文件,%号第二点也说过了是通配符,类似于“所有”的意思。那这样make一下,系统就会自己推断寻找文件目录下的对应文件了。当然对于当前的例子,还是有点问题的,因为main文件没有对应的.h文件,所以make一下会报错。因此如果有个别文件是缺少.o或者.h等文件的,需要单独拿出来写。
objs = block.o command.o i18n.o input.o main.o scene.o
sudoku: $(objs) main.o
g++ -o $@ $^
$(objs) : %.o : %.cpp %.h
g++ -c $<
main.o : %.o : %.cpp
g++ -c $<
4.依赖路径指定
路径的指定一般发生在系统找不到文件的情况。还是以sudoku作为例子,原先的所有文件都在同一个目录中,先新建两个文件夹,将除了main.cpp以外所有的.cpp文件存储到src文件夹中,将所有的.h文件以及.inl文件存储到include文件夹中。此时如果还是按照之前的语言来make,那么会报错,因为找不到文件。
->
这个时候需要指定一下路径,有两种方式
VPATH:
注意观察VPATH这一行,src和include就是我们刚刚新建的文件夹,“:”放在不同的文件夹之间。那么这个时候系统就会去这两个文件夹中搜索问价了。其中,要注意的是“-I”命令,就如例子所写的-Iinclude,因为我们编译器是在当前的main所在的文件夹中的,但是我们去找头文件等是在include文件夹中的(之前我们把.h等文件放在include文件夹中了),这和编译器不在一个目录里面,因此如果没有这个-I命令,就会编译错误。
objs = block.o command.o i18n.o input.o main.o scene.o
VPATH = src:include
sudoku: $(objs) main.o
g++ -o $@ $^
$(objs) : %.o : %.cpp %.h
g++ -c $< -Iinclude
main.o : %.o : %.cpp
g++ -c $< -Iinclude
.PHONY: clean
clean:
-rm sudoku.exe
-rm $(objs)main.o
vpath:
对于小写的vpath,这种用法要更灵活一点,因为它是单独为某种文件指定对应的路径,语法格式为:vpath <文件格式(可以是具体的文件名)> <路径>。
objs = block.o command.o i18n.o input.o main.o scene.o
vpath %.h include
vpath %.cpp src
sudoku: $(objs) main.o
g++ -o $@ $^
$(objs) : %.o : %.cpp %.h
g++ -c $< -Iinclude
main.o : %.o : %.cpp
g++ -c $< -Iinclude
.PHONY: clean
clean:
-rm sudoku.exe
-rm $(objs)main.o
将这两行替换VPATH那一行,也是正确的。
标签:知识点,objs,%.,入门,文件,++,Makefile,cpp,main From: https://blog.csdn.net/qq_43224194/article/details/143026336