Makefile学习笔记
一、foreach函数
foreach函数是用来做循环的,语法规则是:
$(foreach <var>,<list>,<text>)
函数的功能就是把参数list中的单词逐个取出放在参数var所指定的变量中,然后执行text所包含的表达式。每一次text会返回一个字符串,循环过程中,text所返回的每个字符串以空格分隔,最后当整个循环结束时,text所放回的每个字符串所组成的整个字符串将会是该函数的返回值。
举例:
names := a b c d
files := $(foreach n,$(names),$(n).o)
$(names)中的单词会挨个取出,并存在变量n中,
$(n).o每次根据$(n)计算出一个值,这些值会以空格分隔,
最后作为foreach函数的返回值,所以$(files)的值是a.o b.o c.o d.o
二、if函数
if函数的语法:
$(if <condition>,<then-part>)
或是
$(if <condition>,<then-part>,<else-part>)
如果condition为真,那then-part的执行结果会是整个函数的返回值,如果condition为假,那else-part的执行结果会是整个函数的返回值。
三、call函数
call函数可以给表达式传递参数。其语法是:
$(call <expression>,<parm1>,<parm2>,<parm3>...)
当make执行这个函数时,expression参数中的变量会被parm1、parm2、parm3所取代。parm参数的个数会根据expression中的变量来决定。
举例:
reverse = $(1) $(2)
foo = $(call reverse,a,b)
所以上面代码的功能就是reverse中的变量会被a,b所取代。并且foo的值也是a,b
四、origin函数
origin函数的功能就是告诉某个参数是哪里来的。语法规则如下:
$(origin <variable>)
variable是变量的名字,不应该是引用。所以最好不要用$这个字符,origin函数会以返回值的形式来告诉这个变量的出生情况。
下面是这个函数的一些返回值情况:
undefined:
如果variable从未定义过,那么返回undefined。
default:
如果variable是一个默认的变量,比如"CC"这个变量
environment:
如果variable是一个环境变量,并且当makefile被执行时,“-e”参数没有被打开的情况下。
file:
如果variable这个变量被定义到makefile中。
command line:
如果variable这个变量是被命令行定义的。
override:
如果variable这个变量是被override指示符重新定义的。
automatic:
如果variable这个变量是一个在命令中运行中的自动化变量。
五、shell函数
它的参数应该就是该操作系统shell的命令,shell函数把执行操作系统命令后的输出作为函数的返回值。
contents := $(shell cat foo)
files := $(shell echo *.c)
使用shell函数要注意它是否影响运行性能,如果makefile中的规则很复杂,并且大量使用了这个函数,那么对于系统性能是有害的。
六、控制make的函数
make提供了一些函数来控制make的运行。通常,我们会根据makefile的运行信息来判断make是否继续运行。
$(error <text ...>)
text是错误信息。error函数不会再一被使用就产生错误信息,所以如果把其定义在一个变量中,并在后序的脚本里面使用这个变量,那也是行的通的。
举例:
ifdef ERROR_001
$(error error is $(ERROR_001))
endif
还有这个警告函数。
$(warning <text ...>)
这个函数和error函数很像,只是它不会让make退出,只是输出一些警告信息,而继续执行make。
七、make的运行
接下来讲述怎样使用make命令。
1、make的退出码
make命令执行后有三个退出码:
0 — 表示成功执行
1 — 如果make运行时出现任何错误,其返回1
2 — 如果你使用了make的“-q”选项,并且make使得一些目标不需要更新,那么返回2
2、指定makefile
make找寻默认的makefile时,首先是在当前目录下面找“makefile”、“Makefile”、“GNUmakefile”。先查找这三个文件看存不存在,一旦找到,就开始读取这个文件并执行。
当前,我们也可以给make命令指定一个特殊名字的makefile。但是要使用make命令的-f参数或者–file参数。例如我们自己定义一个文件名叫makefiletome,那么我们就要这样执行我们的makefile:
make -f makefiletome
如果在make命令行中,我们不止一次使用-f参数,那么所有指定的makefile将会一起传递给make执行。
3、指定目标
一般来说,make的最终目标是makefile中的第一个目标,而其他的目标一般是被这个第一个目标连带出来的。但是,一般情况下,我们的makefile中的第一个目标会由许多目标组成,你可以指示make,让其完成所指定的目标,要实现这一功能很简单,直接在make后面跟一个目标名字就可以了。
我们可以参照这种规则来书写我们的makefile中的目标。
“all”
这个伪目标是所有目标的目标,其功能一般是编译所有的目标。
“clean”
这个伪目标功能是删除所有被make创建的文件。
“install”
这个伪目标功能是安装已编译好的程序,其实就是把目标执行文件拷贝到指定的目标中去。
“print”
这个伪目标的功能是例出改变过的源文件。
“tar”
这个伪目标功能是把源程序打包备份。也就是一个tar文件。
“dist”
这个伪目标功能是创建一个压缩文件,一般是把tar文件压成Z文件。或是gz文件。
“TAGS”
这个伪目标功能是更新所有的目标,以备完整地重编译使用。
“check”和“test”
这两个伪目标一般用来测试makefile的流程。
这些不是硬要求,名字是可以自定义的,只不过这些名字规范些。
4、检查规则
有时,我们只是想让我们的makefile中的规则执行起来,我们只想检查一些我们的命令,或是执行的序列。于是我们可以使用make命令的下述参数
“-n”
“--just-print”
“--dry-run”
“--recon”
不执行参数,这些参数只是打印命令,不管目标是否更新,把规则和连带规则下的命令打印出来,但不执行,这些参数对于我们调试makefile很有用处。
“-t”
“--touch”
这个参数的意思就是把目标文件的时间更新,但不更改目标文件。也就是说,make假装编译目标,但不是真正的编译目标,只是把目标编程以编译过的状态。
“-q”
“--question”
这个参数的行为就是找目标的意思,也就是说,如果目标存在,那么其什么也不会输出,当然也不会执行编译,如果目标不存在,那么将会打印一条错误信息。
“-W <file>”
“--what-if=<file>”
“--assume-new=<file>”
“--new-file=<file>”
这个参数需要指定一个文件,一般是源文件(或依赖文件),make会根据规则推导来运行依赖于这个文件的命令,一般来说,可以和-n参数一同使用,来查看这个依赖文件所发生的的规则命令。
5、make的参数
“-B”
“--always-make”
认为所有的目标都需要更新(重编译)。
“-C <dir>”
“--directory=<dir>”
指定读取makefile的目录。如果有多个“-C”参数,make的解释是后面的路径以前面的作为相对路径,并以最后的目录作为被指定目录。如:“make –C ~hchen/test –C prog”等价于“make –C ~hchen/test/prog”。
参考资料:
https://blog.youkuaiyun.com/haoel/article/details/2896(make的运行部分)
参考资料:
https://blog.youkuaiyun.com/haoel/article/details/2895