1."="和":="的区别
"=" makefile会将整个makefile展开后,再决定变量的值,也就是说,变量的值将会是整个makefile中最后被指定的值.
x = foo
y=$(x)bar
x=xyz
y的值是xyzbar,而不是foobar
":="表示的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值。
x:=foo
y:=$(x)bar
x:=xyz
以上定义只对变量的赋值会有影响,但命令中的定义不会受影响,而是全局展开的。
查看makefile的隐藏规则:
make -p -f /dev/null |grep MAKE
获取绝对地址:
makefile的realpath返回文件的绝对地址,可以使用 $(shell pwd)来替代。
INCLUDE的优先级:
如果任何一个通过include引入文件的被规则更新,那么makefile会接着清除它的内部数据库并重新读取整个Makefile,在完成了读取,更新,重新读取的过程后,如果仍有文件不存在而导致的include 指令执行失败,那么makefile就会报告错误并终止执行。
Makefile的静态模式%.o : %.c
Makefile的静态模式%.o : %.c_猪哥-嵌入式的博客-CSDN博客_%.o
静态模式可以更加容易地定义多目标的规则,可以让我们的规则变得更加的有弹性和灵活
我们还是先来看一下语法:
<targets ...>: <target-pattern>: <prereq-patterns ...>
<commands>
....
targets 定义了一系列的目标文件,可以有通配符。是目标的一个集合。
target-parrtern 是指明了 targets 的模式,也就是的目标集模式。
prereq-parrterns 是目标的依赖模式,它对 target-parrtern 形成的模式再进行一次依赖目标的定义。
看一个例子:
objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
上面的例子中,指明了我们的目标从$object 中获取,“%.o”表明要所有以“.o”结尾的目标,也就是“foo.o bar.o”,也就是变量$object 集合的模式,而依赖模式“%.c”则取模式“%.o”的“%”,也就是“foo bar”,并为其加下“.c”的后缀,于是,我们的依赖目标就是“foo.c bar.c”。而命令中的“$<”和“$@”则是自动化变量,“$<”表示所有的依赖目标集(也就是“foo.c bar.c”),“$@”表示目标集(也就是“foo.o bar.o”)。于是,上面的规则展开后等价于下面的规则:
foo.o : foo.c
$(CC) -c $(CFLAGS) foo.c -o foo.o
bar.o : bar.c
$(CC) -c $(CFLAGS) bar.c -o bar.o
关于$符号:
Makefile 里面 $ 是元字符(meta-chara...),也就是它是有特殊意义的。那在 Makefile 里面表示"字符" $ 就得用 $$. 看第一次求值的结果就知道了,不用多说。
有的时候$$可以代替括号,用来对多字母标识符进行引用:
解读:
第一遍,Makefile读取时候,直接对$展开,遇到 $ABC,由于 A表示符没有定义,所以展开为" BC",输出 BC。而$(ABC),由于()的作用,ABC被识别为整体标识符,由于ABC有定义,所以展开为 "i love you", 第三和第四种情况只查一个""符,没有本质区别,以echo $$ABC为例, $$ABC第一遍展开为$ABC,当给echo 输出的时候,再次展开的时候,变为$ABC,有定义,直接输出"i love you."
至于为何第一次 直接在makefile中echo $ABC不行,而经过$$两级展开后,变得可以,只能怀疑第三行的第一次展开是makfile系统下展开的,没有括号的情况下,$只和第一个字母配对,多字母标识符必须要加括号。而第6行则不同,它第二次是给echo看的,是echo解析的,echo 不需要加括号就可以识别整个多字母标识符号。这个过程有点像直接在bash shell中这样调用:
makefile强制更新目标:
第一步,建立空目标
PHONY += FORCE
FORCE:
第二步,将空目标作为想要强制更新的目标的依赖:
$(target): FORCE
xxx
Makefile中获取git环境的版本ID
commid = $(shell git rev-parse HEAD)
all:
echo $(commid)