研一
makefile
- 使用make自动推导依赖项的隐式规则减少代码
…
$(Targets): def.h
foo.o: name.h
…
- 添加搜索源文件路径
…
VPATH = /etc : …/header : ./include
…
- 使用vpath添加搜索源文件路径
vpath <pattern> # 清除pattern模式的文件目录
vpath <pattern> <dirctories> # 为符合模式的文件指定搜索目录<dirctories>
vpath # 清除所有已设置好的文件搜索目录
示例:
vpath %.c …/header : src
- 伪目标
伪目标也是目标,可以有依赖可以有指令,但没有生成项。为了防止伪目标的名称和文件名称一致导致出错,应当通过.PHONY声明伪目标。
.PHONY: clean
clean:
rm -ifr *.o
伪目标的特性是每次必执行,因此可以取巧地通过伪目标指令生成多目标文件,实现多个命令,实现生成目标后自行清除等的功能(没试过,不过感觉理论上可以)。
- 多目标生成
make可以不止生成一个文件,通过‘$@’自动化变量可以达到该功能。
bigoutput littleoutput:text.g
generate text.g - ( s u b s t o u t p u t , , (subst output,, (substoutput,,@) >$@ #还不能完全理解,需要到后面讲到函数和变量的时候才会懂
以上示例等价于:
bigoutput: text.g
generate text.g -big > bigoutput
littleoutput: text.g
generate text.g -little > littleoutput
- 静态模式
静态模式也是为了生成多目标,和上面的功能相同,只不过是进阶版,更灵活更高级。
<targets …>: <target-pattern>: <prereq-patterns …>
<commands>
…
举例如下:
`objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@`
举个大栗子:
文件列表:
以上图片中oper.c和main.c中分别有一个main函数,其中oper.c只是简单打印hello, world的文件,而剩余其他所有文件都与main.c编译有关(除了.dat文件和resultReport.txt文件,这些文件是被生成的可执行程序调用的)。
以下是make文件的编译指令,通过编译可以直接生成两个可执行文件。
可以看到直接生成两个可执行文件。
以下为makefile代码:
all: randomtest oper #伪目标
.PHONY: all #声明伪目标
vpath %.h ./include #增加一个给make文件找头文件的路径
CFLAGS = -I ./include -lm #原来看《跟我一起学makefile》一直不知道这个指令是干嘛的,
#上网查了一下发现就是一个自己声明的变量,名字随便换,作用
#是减少代码输入量(虽然这个例子里并没有)
objects = main.o HU_random.o YS_RandomTest.o \
filehandle.o test.o #同上,自己声明的变量,这里确实减少了代码量
randomtest: $(objects) #指明randomtest依赖关系:依赖以上定义那些的.o文件
gcc -o randomtest $(objects) -lm #makefile正常编译,由于文件里include了math.h头文件,因此需要额外添加-lm指令链接math库
$(objects): %.o : %.c #这里是静态模式的定义,该行指令可自动生成多文件依赖关系
gcc -c $(CFLAGS) $< -o $@ #编译,汇编.c文件成为.o文件,其中'$<'指依赖集'$@'指目标集。看不懂没关系,先背下来。
oper: oper.o #以下三行为oper可执行文件的正常编译流程
gcc -o oper oper.o
oper.o: oper.c
.PHONY: clean #声明clean为伪目标,.PHONY防止伪目标和真正的目标重名
clean:
@rm -f *.o #@符号指该行运行时不把命令打印在命令行中,否则会在屏幕上打印"rm -f *.o",-f指删除文件前不需要询问