Makefile¶
基本语法¶
make 指令参数¶
-n: 只打印编译过程,不执行指令,方便调试查看编译过程-w: 在编译是打印Entering directory ...信息,方便查看当前执行路径-j: 指定多核编译,加快编译速度-t: touch,更新明白文件的时间,但不更改文件-I: 指定一个搜索路径-d: 打印debug信息,帮助分析调试
变量¶
:=: 变量赋值为新的值,Foo:=bar?=: 如果没有定义过则赋值新值,Foo?=bar+=: 追加变量值empty :=: 空变量space := $(empty) $(empty): 空格变量$(foo:.o=.c): 变量替换,将*.o替换为*.c$(foo:%o=%c): 静态模式的变量替换,将%.o替换为%.c$($(x)): 变量值作为新变量名y = $(subst a,b,$(x)): 将变量x中的a替换为b,赋值给yoverride: 重写make命令行传入的参数值define: 定义多行变量
自动化变量:
$@: 目标文件集$%: 目标成员名$<: 依赖目标中的首个目标名称$?: 所有比目标新的依赖目标的集合$^: 所有依赖目标的集合,自动去除重复目标$+: 与$^类似,但不去除重复的依赖目标$*: 目标模式中%与之前的部分
条件判断¶
ifeq,ifneq: 判断变量是否等于或不等于某值ifdef,ifndef: 判断是否定义或未定义某变量
使用函数¶
$(<function> <args>): 调用函数, 参数间逗号分隔
字符串相关:
subst: 字符串替换patsubst: 模式字符串替换strip: 去除字符串首尾空字符findstring: 查看字符串子串filter: 过滤函数,模式匹配filter-out: 反过滤函数,去除匹配到的参数
单词相关:
sort: 按单词排序word: 取单词函数,指定字符串第n个单词wordlist: 取单词串函数,指定起始位置和结束位置words: 统计单词个数firstword: 获取首个单词
文件目录相关:
dir:取目录路径notdir: 取文件名suffix: 取文件名后缀basename: 取文件路径的前缀addsuffix: 添加后缀addprefix: 添加前缀join: 连接字符串
循环或函数调用相关:
foreach: 循环if: 条件判断call: 调用其它函数shell: 执行 shell 指令
make 执行控制相关:
error: 产生错误信息,停止编译warnning: 产生警告信息,继续编译
DEPENDS¶
在openwrt中,package可能会依赖一个或多个其它package,通过使用DEPENDS去定义依赖。
举例说明,当前有 package 名为 demo_pack, 依赖了两个package,pack_a, pack_b, 那么需要在Makefile中添加DEPENDS。
define Package/demo_pack
DEPENDS:=+pack_a +pack_b
endef
在编译FW之前,需要在 buildroot 目录生成 .config 文件,通常会调用make oldconfig指令完成。这个指令会遍历所有packages,并根据Makefile确定依赖关系,这关系到不同package的编译顺序。
默认情况下,make过程根据package名称从小到大排序(a-z), demo_pack 以d开头,先于 pack_a, pack_b, 但是添加依赖以后,编译时会更改编译顺序,先编译其依赖库pack_a, pack_b, 之后再编译 demo_pack.
添加依赖包含以下几种方式:
DEPENDS:=+pack_a表示只要选中了demo_pack,pack_a就会强制被选中,该方式最常用DEPENDS:=pack_a表示只有选中pack_a之后,才可以选中demo_packDEPENDS:=+FUNC_HAVE_A:pack_b表示只有选中FUNC_HAVE_A之后,才可以选中pack_bDEPENDS:=@pack_a表示除非先选中pack_a, 否则别想在menuconfig中看到demo_pack, 不推荐DEPENDS:=+@pack_a与+pack_a类似,不同在于,在安装demo_pack时不会检查依赖性,pack_a没有被安装是无法识别的
这里要说明的是,第3种方式在某些特定情况下非常有用。比如存在多个项目(A,B),基于相同的code base,但是又有差异(使用不同的.config),假设项目A中的CONFIG FUNC_HAVE_A 为 y , pack_b 需要在该CONFIG选中情况下才生效,但项目B不需要支持 pack_b, 同时 FUNC_HAVE_A is not set 。这种情况下,如果使用以下依赖方式,
define Package/demo_pack
DEPENDS:=+pack_b
endef
项目A可以正常编译和工作,但是对项目B而言,根据以上第1个选项的说明, make oldconfig 同样也会给项目B默认选中 pack_b ,这是我们不想要的。此时,使用 +FUNC_HAVE_A:pack_b 就再合适不过了。
define Package/demo_pack
DEPENDS:=+FUNC_HAVE_A:pack_b
endef
这样既保证需要支持 pack_b 的项目A在 make oldconfig 时可以正确添加依赖库,又可以防止不需要支持的项目B不会默认选中 pack_b.