概述
在Linux下编程,掌握makefile是必备的技能。一个工程当中可能有很多不同类型不同功能的模块,它们被存放于不同的目录当中,这目录下存放着源码文件。而它们之间存在这依赖关系,makefile就是规定了一系列编译的规则,哪些文件先编译,哪些文件后编译,以及链接。而且它也可以像shell脚本一样执行系统命令,这使得它更加的灵活,能够进行更复杂的操作。
当然现在很多跨平台项目用cmake写cmakelist文件,就能自动生成makefile文件,很是方便。不过,我们也应该掌握makefile的基本语法规则,这样遇到问题的时候,方便我们更快的定位和解决。
掌握makfile,重要的是掌握makefile的语法和规则,这个一定要熟知,其他扩展可在脑子力,毕竟工程一旦建立,我们也没有必要天天修改makefile。
基本规则
target ... : prerequisites ...
command
...
target是要生成的目标
prerequisites是生成target所需要的依赖项
command就是执行命令,这个前面必须要以[tabl]开头(如若和prerequisites在一行,那么前面加;分隔也可以)
makefile中可能有很多条规则,但第一条规则应该是这个文件的最终目标,其他目标都是为了生成这个目标而存在的。
规则
文件名
- makefile中默认文件名是GNUmakefile,makefile,Makefile,也可以指定特定的makefile文件,然后这样用 make -f xxx.mk 其中xxx.mk是makefile文件
-
引用其他makefile文件,类似C语言的include,如果filename不存在,则会报错,如果这个文件并不重要,可以设置忽略错误信息,如下
-include <filename>
隐含规则
- <n>.o的依赖会自动推导<n>.c或者<n>.cpp
- <n>的依赖会自动推导<n>.o
- 自动化变量
- $@ 规则中的目标文件集
- $% 目标的成员名
- $<第一个目标的名字
- $?所有比目标新的依赖目标的集合
- $^所有依赖目标的集合 去重
- $+ 所有依赖目标的集合 不去重
- 支持通配符,所有[.o]的文件名的集合 objects := $(wildcard *.o)
变量
makefile中的变量类似C语言中的宏,定义无需指定类型,使用格式$(var)
另外注意一点,和常规语言不同,makefile中的变量是从后向前推导的。但我们可以通过使用:=替代=来规避这个问题。
makefile中海内这了很多函数,调用格式$(<function> <arg>),
比如subst字符串替换函数,$(patsubst <pattern>,<replacement>,<text>) 可用通配符,words统计单词个数,firstword 第一个单词等等,对字符串操作的函数;
foreach函数files := $(foreach n,$(names),$(n).o), if函数$(if <cond>,<thenaprt>,<else-part>)等等语法相关函数
$(error <text>), $(warning <text>) 信息输出函数
语法
注释 一是使用 #
二是
推导过程
运行
- 读入所有makefile,包括include文件
- 初始化变量
- 推导隐晦规则,分析出目标的所有规则,创建依赖链
- 根据依赖关系决定哪些要生成
- 执行
退出码 1 表示错误; 0 表示成功; 2 目标不更新
clean 伪目标,用于清除目标文件
install 安装应用
显示命令
@echo 正在编译
make -n cmd 只显示命令
make -s cmd 执行但不现实命令