tips
- 顺序很重要,且只有一个最终目标(第一条规则中的第一个目标)
- make[1] make[2] make[3] ... 这个表示递归的深度,表示当前处理的是第几层makefile子文件
- - include filename , ‘-’ 参数可防止程序在include失败后exit,可继续往下走
- 凡是以tab开头的,make都会将其当作命令行来处理
makefile打印:
- $(info “here add the debug info”)
- $(warning “here add the debug info”)
- $(error “error: this will stop the compile”) -- 这个可以停止编译
- echo-- 它只能在target:后面的语句中使用,且前面需要一个TAB,例如:
all: xxx xxx
@echo "start compileing all modules"
make 执行步骤:
- 读入所有的makefile
- 读入被include的makefile
- 初始化变量(延时)
- 自动推导隐含规则,并分析所有规则
- 为所有的目标文件创建依赖关系链
- 根据依赖关系,决定哪些目标要重新生成
- 执行生成命令
1-5步为第一阶段,6-7为第二阶段,第一阶段中,如果定义的变量被使用了,那么make会把其展开在使用的位置。
make 隐含规则
- 自动推导obj文件的 .c 和.h文件,并用gcc -c 编译: $(CC) -c $(CFLAGS)
- 如果目标文件的先决条件比它新,那么make就会执行目标文件的cmd
make 变量
- 等于C/C++的宏
- 变量默认类型为字串,可由declare重新定义其它类型
$ sum=100+300+50 #若不指定类型, $echo $sum 输出为“100+300+50”
$ declare -i sum=100+300+50 #指定sum变量为整形,输出为450
$ declare -x sum #指定sum变量为环境变量
.PHONY 伪目标
clean 是一个典型的伪目标。假如makefile目录下有个同样名为clean的文件,如果去执行make clean,这时会提示clean是最新的:
所以需要加上.PHONY: clean 标识clean 是一个假的目标(clean文件在make眼中相当于 main.c 目标文件),真正的目的是执行clean下面一行的rm语句
参考 https://www.cnblogs.com/yuanqiangfei/p/8058369.html
make 参数
-C $(KDIR) //当make的目标为all时,-C 指明跳转到源码目录下读取那里的Makefile;M=$(PWD) 表明然后返回到当前目录继续读入、执行当前的Makefile。
冒号规则:
makefile文件会在变量全部展开后才开始赋值,而加了冒号后则立即赋值,不用理会后续的操作。比如:
var1=xy
var2=$(var1)
var1=xyz
此处的var2受$var1变量影响,会在makefile全部展开后才赋值,也就是xyz,加个冒号即可改正。
gcc 编译参数:
- -c , gcc -c hello.c //会自动生成hello.o 这个档案
- -i 后接头文件名称,可省略
- -I/path (大写的i) ,后接头文件的路径,默认都为 /usr/lib 和/lib两个路径,可省略
- -l (小写的L),接函数库名称,比如 -lm 表示 libm.a 或 libm.so
- -L 接函数库路径,比如 -L/usr/lib
- -o 指定输出的bin档,gcc -o hello hello.c
- -O 优化执行速度
ifeq 、 findstring、及逻辑判断
Makefile中的变量以$开头,使用$(VAR)或${VAR}来引用变量的定义。 所以,为了避免和shell的变量冲突,shell的变量以$$开头,例如:
ifeq ($(findstring MODULE_CONFIG_QR_URL,$(shell cat ${MODULE_CONFIG_FILE} | awk '{print $$2}')),MODULE_CONFIG_QR_URL)
LIBS += $(CASE_LIB_DIR)/libqrcode.so
LIBS += $(SDK_LIB_DIR)/lib_enc_buf.so
endif