Make

make的作用: * 控制源代码的编译 * 手册页的编写 * 将应用程序安装到目标目录

make的使用规则: * 如果工程没有编译过,需要编译所有源文件和链接所有目标文件. * 如果工程里某几个目标文件被修改,只需要编译修改的源文件,并链接所有目标文件. * 如果头文件被修改,只需要编译引用了被修改的头文件的源文件,并链接所有目标文件.

makefile文件查找顺序: * 当前目录找makefile * 当前目录找Makefile * 当前目录找GNUmakefile

make命令

make命令会执行当前目录的makefile/Makefile/GNUmakefile文件.

1
2
3
4
5
6
7
8
9
make [options] [target] ...
-f FILE, --file=FILE, --makefile=FILE    # 指定makefile文件
-n, --just-print, --dry-run, --recon # 只打印,不执行
-k, --keep-going # 忽略错误继续执行

make
make all
make install
make clean

make的工作顺序: * 读入所有makefile文件 * 读入include的其它makefile文件 * 初始化变量 * 推导隐晦规则,分析所有规则 * 为所有目标文件创建依赖关系链 * 根据依赖关系决定哪些目标需要重新生成 * 执行生成的命令

makefile语法

make命令执行makefile文件时,会比较target和prerequisites的时间戳,如果后者比前者新,或者前者不存在,就会执行command,否则会跳过command.

其中#表示注释,\表示续行.@表示该命令的执行不会打印到stdout,-表示忽略错误继续执行.

makefile中的command必须以tab开头,target和prerequisites有多个时用空格分开.

1
2
3
4
5
6
7
8
# comment
target...: prerequisites...
    command
    command1 too \
    long
    @command2
    -command3
    ...

makefile变量赋值:

1
2
3
4
var=val
var := val  覆盖之前的值
var ?= val  如果没有被赋值过,就赋值
var += val  添加一个值

通过命令定义变量:

1
2
3
var := $(shell <command>)
为了区分makefile变量和shell命令里面的变量,用$$var表示shell变量
var := $(shell cat file | awk '/.*/{print $$0}')

makefile的变量:

1
2
3
4
定义变量:
obj=a.o b.o c.o
使用变量:
$(obj)

自动化变量:

1
2
3
4
5
6
7
$<    # 第一个依赖文件
$^    # 所有的依赖文件
$@    # 目标文件
$*    # 不包含扩展名的目标文件名称
$+    # 所有的依赖文件,用空格分开
$?    # 所有时间戳比目标文件晚的依赖文件,以空格分开
$%    # 如果目标是归档成员,则表示目标的归档成员

清空目标文件:

1
2
3
4
5
6
clean:
    -rm elf $(obj)
# 或者用.PHONY表示clean是一个伪目标
.PHONY: clean
clean:
    -rm elf $(obj)

在makefile中引用外部makefile:

1
2
# 优先在当前目录查找,-l可以指定额外的查找路径
-include a.makefile b.makefile ...

makefile支持的通配符:

1
2
3
~    # 用来表示$HOME环境变量
*    # 用来表示任意长度字符串
[...]

自动推导和隐晦规则:

伪目标:

查找路径: