1.Makefile文件的语法
咕咕咕.......鸽王终于回来啦,最近由于自己的事情比较多所以拖更了两周还请大家见谅。本篇文章还将继续学习Makefile文件的编写,之前的文章小伙伴们还没来得及看的话,请点击此处Makefile文件 | 编写指南开始愉快的学习。
1.1 注释
#符号在Makefile文件中表示注释,如下面的代码所示:
[njust@njust Make_Tutorials]$ cat Makefile demo:demo.c gcc -g demo.c -o demo # 此处是注释 .PHONY:clean clean: rm *.o result.txt:source.txt cp source.txt result.txt source.txt: echo "This is a demo!" > source.txt .ONESHELL: var: # export foo=bar;echo "foo=[$$foo]" # export foo=bar;\ # echo "foo=[$$foo]" export foo=bar; export "foo=[$$foo]"
1.2 回声echo
正常情况下,make命令会先打印出每条命令,然后再执行命令,这个过程叫做回声。如下面的代码,执行make命令后会得到如下结果:
[njust@njust Make_Tutorials]$ ls a.o b.o Makefile [njust@njust Make_Tutorials]$ make test # delete all object files. rm *.o [njust@njust Make_Tutorials]$ ls Makefile [njust@njust Make_Tutorials]$ cat Makefile test: # delete all object files. rm *.o export "foo=[$$foo]"
如果想关闭回声功能,可以在每条命令前加上@,这样执行make test构建命令时就不会打印出每条命令了,直接得到每条命令的执行结果。由于make在构建过程中,需要知道当前已执行到Makefile文件中哪条命令,因此通常只需要在注释和echo命令(类似于打印功能)前加上@关闭回声功能。
[njust@njust Make_Tutorials]$ ls a.o b.o Makefile [njust@njust Make_Tutorials]$ cat Makefile test: @# delete all object files. @rm *.o [njust@njust Make_Tutorials]$ make test [njust@njust Make_Tutorials]$ ls Makefile
1.3 正则表达式
正则表达式用来匹配一组符合特定条件的文件名,Makefile文件中的正则表达式用法与其他编程语言中的类似,基本的通配符有*、[...]、?等,具体使用如下所示:
[njust@njust Make_Tutorials]$ ls a.o b.o Makefile [njust@njust Make_Tutorials]$ make test # delete all object files. rm *.o [njust@njust Make_Tutorials]$ ls Makefile [njust@njust Make_Tutorials]$ cat Makefile test: # delete all object files. rm *.o
Make命令还允许对文件名,进行类似正则运算的匹配。主要使用的匹配符是%。例如,将当前目录下的两个源文件foo.c、bar.c编译为对应的目标文件,可以简单用如下的一条语句就行:
[njust@njust Make_Tutorials]$ ls bar.c foo.c Makefile [njust@njust Make_Tutorials]$ cat Makefile %.o:%.c @echo source file has been converted to object file. [njust@njust Make_Tutorials]$ make foo.o source file has been converted to object file. [njust@njust Make_Tutorials]$ make bar.o source file has been converted to object file. [njust@njust Make_Tutorials]$ make bbb.o make: *** 没有规则可以创建目标“bbb.o”。 停止。 Makefile
值得注意的是:%.o:%.c可以等同于bar.o:bar.c、foo.o:foo.c,但绝不等于bbb.o:bar.c/foo.c,否则会出现上面的构建错误。
1.4 变量和赋值符
Makefile文件中也允许使用等号、自定义变量。具体如下例所示:
[njust@njust Make_Tutorials]$ ls bar.c foo.c Makefile [njust@njust Make_Tutorials]$ cat Makefile txt = Hello CurryCoder test: @echo $(txt) %.o:%.c @echo source file has been converted to object file. [njust@njust Make_Tutorials]$ make test Hello CurryCoder
在上面的代码段中,我们发现变量txt等于Hello CurryCoder。使用变量txt时,需要将变量放在$()中。此外,调用shell中的变量时,需要注意在美元符号前再加一个美元符号,这表示Make构建命令会对美元符号进行转义。如下所示:
[njust@njust Make_Tutorials]$ ls bar.c foo.c Makefile [njust@njust Make_Tutorials]$ cat Makefile txt = Hello CurryCoder test: @echo $(txt) @echo $$HOME %.o:%.c @echo source file has been converted to object file. [njust@njust Make_Tutorials]$ make test Hello CurryCoder /home/njust
此外,一个变量的值可以赋值给另一个变量,如v1 = $(v2)。值得思考的是,变量v1的值是静态扩展(类似于静态语言类型如C语言)的,还是动态扩展(类似于动态语言类型如Python)的?为了解决这个问题,Makefile文件中提供了四种赋值运算符,如下所示:
VARIABLE = value # 在执行时扩展,允许递归扩展 VARIABLE := value # 在定义时扩展 VARIABLE ?= value # 只有在该变量为空时才设置值 VARIABLE += value # 将值追加到变量的尾端
1.5 内置变量
Make构建命令提供了一系列内置变量,如$(CC)表示当前使用的编译器;$(MAKE)表示当前使用Make工具,设置这两个内置变量的目的主要是考虑到跨平台的兼容性问题。更多内置变量请见参考资料[2]。
[njust@njust Make_Tutorials]$ ls bar.c foo.c Makefile [njust@njust Make_Tutorials]$ cat Makefile txt = Hello CurryCoder test: @echo $(txt) @echo $$HOME demo: $(CC) -o demo bar.c %.o:%.c @echo source file has been converted to object file. [njust@njust Make_Tutorials]$ make demo cc -o demo bar.c [njust@njust Make_Tutorials]$ ls bar.c demo foo.c Makefile
1.6 自动变量
Make构建命令还提供了一些自动变量,它们的值与当前构建规则有关,主要有如下几个。更多自动变量请见参考资料[3]
(1).$@:表示当前目标,例如make demo时,$@就表示demo;
(2).$<:表示第一个依赖条件,例如test:source1.txt source2.txt,则$<就表示source1.txt;
(3).$?:表示比目标的时间戳更加新的所有依赖条件,之间以空格分开。例如,t:p1 p2,其中p2的时间戳比t新,则$?表示p2;
(4).$^:表示所有的依赖条件,它们之间以空格分开。例如,t:p1 p2,则$?表示p1 p2;
(5).$*:表示匹配符%所匹配的部分,例如,%匹配file.o中的file,则$*表示file;
1.7 判断和循环
Makefile文件中使用Bash语法,实现判断和循环。下面的代码判断当前编译器是否为gcc,然后指定不同的库文件。
ifeq ($(CC),gcc) libs=$(libs_for_gcc) else libs=$(normal_libs) endif
Makefile文件中的循环示例代码如下所示:
LIST = one two three all: for i in $(LIST); do \ echo $$i; \ done # 等同于 all: for i in one two three; do \ echo $i; \ done
1.8 函数
Makefile文件中也可以使用函数,具体的格式如下所示。更多内置函数请见参考资料[4]
$(function arguments) # 或者 ${function arguments}
2.参考资料
[1].http://www.ruanyifeng.com/blog/2015/02/make.html
[2].https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html
[3].https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html
[4].https://www.gnu.org/software/make/manual/html_node/Functions.html