makefile 基本语法
目标文件:依赖文件
[Tab] 命令
上述makefile语法被称为一组规则
- 目标文件是此规则想要生成的文件
- 依赖文件指生成目标文件所用到的其他文件,是一个文件列表
- 命令指此规则中要执行的shell命令。一个命令独占一行,行首必须以Tab键开头。
make程序通过比较依赖文件和目标文件的mtime属性,判断是否执行命令。
当test2的mtime比test1新时,将执行相应的命令
test1:test2
echo "test1"
当我门修改test1,此时test1的mtime比test2新,则不再执行命令
伪目标
当makefile中有多个规则时,通过make <指定目标名>
的方式,可以单独执行目标名处的规则如:
ps:@可以在输出中屏蔽命令显示
然而,当target2的mtime比test1新时,make target2 将不执行对应命令,有时候我们希望有些命令不管在什么情况下都能执行,这时候就需要用到伪目标了。
当规则中不存在依赖文件时,这个目标文件名就被称为伪目标。它的作用就是为了纯粹的执行命令。为避免伪目标与真实目标同名,可以用.PHONY
关键字来修饰它。
如:
一些约定的伪目标
递归式推导目标
现在有如下两个C文件和对应的makefile文件:
test1.c:
void my_print(char*);
void main(){
my_print("hello world\n");
}
test2.c:
#include <stdio.h>
void my_print(char* str){
printf(str);
}
makefile:
test2.o:test2.c
gcc -w -c -o test2.o test2.c
test1.o:test1.c
gcc -w -c -o test1.o test1.c
test.bin:test1.o test2.o
gcc -w -o test.bin test1.o test2.o
all:test.bin
@echo "done"
执行make all
命令的流程如下:
- make 发现all的依赖文件test.bin不存在,就去寻址以test.bin为目标文件的规则
- 找到对应规则后,发现test.bin的依赖文件test1.o不存在,于是去找test1.o为目标文件的规则。
- 找到test1.o对应的规则后,执行
gcc -w -c -o test1.o test1.c
- 回到test.bin对应规则,发现依赖文件test2.o不存在,于是去找test2.o为目标文件的规则。
- 找到test2.o对应的规则后,执行
gcc -w -c -o test2.o test2.c
- 回到test.bin对应规则,执行
gcc -w -o test.bin test1.o test2.o
- 回到all对应的规则,执行@echo "done"
自定义变量和系统变量
自定义变量
定义变量格式:变量名=值(字符串),多个值之间用空格分开
变量引用:$(变量名)
如上节中的makefile可以改为:
test2.o:test2.c
gcc -w -c -o test2.o test2.c
test1.o:test1.c
gcc -w -c -o test1.o test1.c
objfiles = test1.o test2.o
test.bin:$(objfiles)
gcc -w -o test.bin test1.o test2.o
all:test.bin
@echo "done"
系统变量
自动化变量
自动化变量可以代表一组文件名。
以下为一些自动化:
$@ 表示规则中的目标文件名集合
$< 表示规则中依赖文件的第1个文件
$^ 表示规则中所有依赖文件的集合
$? 表示规则中,所以比目标文件mtime新的依赖文件集合
用自动化变量修改前面的makefile文件:
test2.o:test2.c
gcc -w -c -o test2.o test2.c
test1.o:test1.c
gcc -w -c -o test1.o test1.c
objfiles = test1.o test2.o
test.bin:$(objfiles)
gcc -w -o $@ $^
all:test.bin
@echo "done"
$@ 表示规则中的目标文件:test.bin
$^ 表示规则中的所以依赖文件:test1.o test2.o
规则模式
make支持字符串正则匹配
% 匹配多个非空字符
前面的mkefile可用匹配模式修改为:
%.o:%.c
gcc -w -c -o $@ $^
objfiles = test1.o test2.o
test.bin:$(objfiles)
gcc -w -o $@ $^
all:test.bin
@echo "done"