Makefile 知识点记录
1. 依赖类型:normal Prerequisites,order-only prerequisites
normal Prerequisites:标准依赖具有两层含义的声明,一 它声明了方法运行的顺序,所有依赖的的方法必须在对象的方法运行之前运行完。二 它声明了对象的依赖关系,如果有任何依赖比对象新,那么目标对象就认为是过期的,必须要重建。
order-only prerequisites:顺序依赖,只取标准依赖的声明一。它只声明顺序关系。不会因为依赖的时间戳的更新而重建。
标准依赖和顺序依赖的声明方式如下
targets : normal-prerequisites | order-only-prerequisites
依赖之间用管道符号分隔,左边的是标准依赖,右边的是顺序依赖。
例子:
OBJS := date_test
.phony: all clean
all: $(OBJS)
$(OBJS): date.c | version
$(CC) -o $@ $<
version:
date | xargs echo > version
clean:
rm -f $(OBJS) version
上面的例子中,编译对象依赖于version,但是不会因为向version中手动添加记录而导致后边的重新编译。 date.c 是标准依赖, version是顺序依赖。
2. make 的参数传递
make 传递的时候,可以放在make前边,也可以放在make后边。 但是放在后边会出现问题,最后在执行时,make后边的参数是最后赋值的。
如下例子,所以make传递参数的时候,一定要放在前边。
.pthony: all
P_before += -I
P_after += -I./
all:
@echo $(P_after)
@echo $(P_before)
执行P_before=hello make P_after=world all
结果:
world
hello -I
只有放在make前边,才跟我们预想的结果一致。放在前边的是环境变量,放在后边的是make 参数,环境变量在makefile中不会被覆盖,参数会使用传递的值覆盖掉。
变量如何获取它们的值
overriding variable
当在make 后边以var=value的方式定义变量时,var在makefile的任何赋值都不起作用,都会被value所覆盖。
使用赋值或者define 指令
环境变量
当make启动的时候,make看到的所有环境变量,都会建立相同名字的变量,它的值就是环境变量的值。
内置变量
CURDIR是Makefile的内嵌变量,自动设置为当前目录
Make will set the special variable MAKECMDGOALS to the list of goals you specified on the command line. If no goals were given on the command line, this variable is empty. Note that this variable should be used only in special circumstances.
There are seven “core” automatic variables:
$@: The filename representing the target.
$%: The filename element of an archive member specification.
$<: The filename of the first prerequisite.
$?: The names of all prerequisites that are newer than the target, separated by spaces.
$^: The filenames of all the prerequisites, separated by spaces. This list has duplicate filenames removed since for most uses, such as compiling, copying, etc., duplicates are not wanted.
$+: Similar to $^, this is the names of all the prerequisites separated by spaces, except that $+ includes duplicates. This variable was created for specific situations such as arguments to linkers where duplicate values have meaning.
$*: The stem of the target filename. A stem is typically a filename without its suffix. Its use outside of pattern rules is discouraged.
In addition, each of the above variables has two variants for compatibility with other makes. One variant returns only the directory portion of the value. This is indicated by appending a “D” to the symbol, $(@D), $(<D), etc. The other variant returns only the file portion of the value. This is indicated by appending an “F” to the symbol, $(@F), $(<F), etc. Note that these variant names are more than one character long and so must be enclosed in parentheses. GNU make provides a more readable alternative with the dir and notdir functions.
隐含规则使用的变量
程序名变量如CC
程序flag 变量如CFLAGS
makefile 内置函数
wildcard
匹配给出的文件模式
通常用法
$(wildcard pattern…)
$(wildcard *.c)
$(patsubst %.c,%.o,$(wildcard *.c))
objects := $(patsubst %.c,%.o,$(wildcard *.c))
foo : $(objects)
cc -o foo $(objects)
call
make 函数调用,函数调用在当前上下文中替换参数$(0) $(1) $(2)。 返回的结果是字串。若在函数调用中定义target:dependence recipi规则,用call 展开后只是字串,而不能解释为makefile语法格式。
eval
eval函数将它的参数按照makefile的语法进行解释。在当前位置进行展开。
eval是两次展开。所以$在展开中若要被识别为$需要用$$表示。
function.mk
define compile_app
$(1): $(2)
gcc -o $@ $^
endef
makefile
.phony: all clean
define compile_app
$(1): $(2)
gcc -o $$@ $$^
endef
all: main
$(eval $(call compile_app, main, main.c))