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_pack
DEPENDS:=+FUNC_HAVE_A:pack_b
表示只有选中FUNC_HAVE_A
之后,才可以选中pack_b
DEPENDS:=@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
.