一、变量
= := ?= +=的区别
= 最基本的赋值方式,与变量在Makefile中的位置无关,变量自动推导为为最终被指定的值
# 示例1
var=aaa.c
target:
@echo $(var)
var=bbb.c
root@localhost:~ # make
bbb.c
root@localhost:~ #
# 示例2
var1=aaa
var2=$(var1).c
var1=bbb
target:
@echo $(var2)
root@localhost:~ # make
bbb.c
root@localhost:~ #
:= 覆盖式赋值,只能推导前面的值
# 示例1
var=aaa.c
var:=bbb.c
target:
@echo $(var)
root@localhost:~ # make
bbb.c
root@localhost:~ #
# 示例2
var1:=$(var2).c
var2=bbb
target:
@echo $(var1)
root@localhost:~ # make
.c
root@localhost:~ #
?= 会判断该变量在前面是否已经定义过,如果没有定义过才赋值
# 示例1
var=aaa.c
var?=bbb.c
target:
@echo $(var)
root@localhost:~ # make
aaa.c
root@localhost:~ #
# 示例2
var?=bbb.c
target:
@echo $(var)
root@localhost:~ # make
bbb.c
root@localhost:~ #
+= 追加赋值,自动以空格分隔
var=aaa.c
var+=bbb.c
target:
@echo $(var)
root@localhost:~ # make
aaa.c bbb.c
root@localhost:~ #
自动化变量
- $@:表示规则中的目标文件名。
- $<:表示规则中的第一个依赖文件名。
- $^:表示规则中的所有依赖文件列表,以空格分隔并去重。
- $?:表示规则中所有比目标文件更新的依赖文件列表。
- $*:表示不包括扩展名的目标文件名。
- $(@D):表示目标文件所在的目录。
- $(@F):表示目标文件的文件名部分。
- $(<D):表示第一个依赖文件所在的目录。
- $(<F):表示第一个依赖文件的文件名部分。
https://blog.youkuaiyun.com/sunxiaopengsun/article/details/62218843
二、选项
make -n, --just-print 只显示命令,不执行,用于调试Makefile
三、目标和伪目标
https://blog.youkuaiyun.com/oqqHuTu12345678/article/details/125641363
目标和依赖可以单独声明
命令声明在依赖之后
# 先声明目标与依赖 target: dependency1 dependency2 #命令声明在依赖之后就行,不用紧挨着,中间可以有其他代码 # 后面再写命令 target: command1 command2
四、静态模式
<targets ...>: <target-pattern>: <prereq-patterns ...>
<commands>
比如:$(OBJ): %.o: %.c
即OBJ都是以.o为后缀的目标,每个.o目标依赖文件名相同后缀为.c的文件
$(OBJ)可以省略,直接写%.o:%.c
五、内置函数
$(wildcard pattern1 pattern2 ...) 展开通配符
SRC:=wildcard(*.c *.cc *.cpp *.cxx)
target:
$(info "source file: $(SRC)")
$(patsubst pattern,replacement,text) 模式替换
OBJ:=$(patsubst %.c, %.o, $(wildcard *.c))
target:
$(info "object file: $(OBJ)")
$(filter pattern..., text) 保留符合pattern的字符串
$(filter-out pattern..., text) 过滤掉符合pattern的字符串
SRC:=aaa.cc bbb.cc ccc.cpp ddd.cpp eee.hpp fff.cxx
target1:
@echo $(filter %.cc, $(SRC))
target2:
@echo $(filter-out %.hpp %.cxx, $(SRC))
root@localhost:~ # make target1
aaa.cc bbb.cc
root@localhost:~ # make target2
aaa.cc bbb.cc ccc.cpp ddd.cpp
root@localhost:~ #
$(info ...) 打印调试信息
$(warning ...) 打印警告信息
$(error ...) 打印错误信息,并终止Makefile的执行
六、自定义函数
1.定义
define MY_MAKEFILE_FUNC
@echo "my name is $(0)"
@echo "my name is $(1)"
@echo "my name is $(2)"
# ...
endef
$(0) 表示函数名
$(1) $(2) ...表示传递给函数的参数
1.调用
$(call MY_MAKEFILE_FUNC PARAM1 PARAM2)
七、include命令
Makefile中使用include命令包含一个文件时,make首先会读取该文件。如果该文件找不到,会继续检查Makefile中是否有一个模式规则匹配该文件,如果有则这个规则会被执行。然后make会重新读取整个Makefile,包括include命令缺失的文件。
dependencies := oam_shell_main.d
-include $(dependencies) #如果当前目录找不到oam_shell_main.d
%.d: %.c # 模式%.d刚好匹配缺失的文件oam_shell_main.d,则会执行该规则下的命令(以生成oam_shell_main.d)
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -MM $< | \
$(SED) 's,\($*\.o\) *:,\1 $@: ,' > $@.tmp
$(MV) $@.tmp $@
# 重新读取整个Makefile,包括oam_shell_main.d
有了以上规则,我们在编写Makefile时可以借助其他工具(比如Yacc)自动生成源文件、头文件等
当目标依赖的文件不存在时,make会Makefile中寻找可以生成缺失文件的模式规则,然后执行该规则
# 示例1
target1: oam_xml_res.rc #如果oam_xml_res.rc不存在则执行下面的规则
%.rc: %.rc.in
sed -i '/#include/r oam_xml_res.h' $<
$(MV) path/$*.rc $*.rc #移动到指定目录
%.rc:
$(SHELL) generate.sh #执行generate.sh或generate.py生成缺失文件
# $(PYTHON) generate.py
# 示例2
target2: y.tab.c y.tab.h #如果y.tab.c y.tab.h不存在则执行下面的规则
%.c %.h: %.y # 缺失的.c .h文件都是由yacc工具根据同名的.y生成
$(YACC.y) --defines $<
$(MV) y.tab.c $*.c
$(MV) y.tab.h $*.h
1902

被折叠的 条评论
为什么被折叠?



