文章目录
1、基本结构
目标文件 : 依赖文件
<Tab键>指令指令:
<Tab键>指令具体实现
- makefile文件命名时通常是成Makefile或makefile也可以自定义
- 执行时直接make,也可以用 make -f 自定义文件名
- make只编译改动过的的代码文件,而不会完全编译
- 执行时由make工具解析,交给shell解释器执行
2、变量
2.1、变量的赋值
- 递归赋值 =
前面的变量可以通过后面的变量来赋值
$(a) 表示取变量a的值
注意避免死循环,如: fun = $(fun)
n = $(a)
a = $(b)
b =10
-->n = 10
- 直接赋值 :=
前面的变量不能通过后面的变量来赋值
n = 1
n := $(a)
a = 10
--> n = 1
- 追加赋值 +=
可以给变量追加值
n = a
n += b
-->n = a b
- 判断默认值 ?=
如果变量前面已经定义,则使用前面定义的值
n = 9
n ?= 10
-->n = 9
2.2、预定义变量,自动变量
- 常见的预定义变量
CC C编译器的名称,默认值为cc。
CFLAGS C编译器的选项
LDFLAGS C链接器的选项
CROSS_COMPILE 指定交叉编译器的前缀
AR 库文件维护程序的名称,默认值为ar
AS 汇编程序的名称,默认值为as
CPP C预编译器的名称,默认值为$(CC) –E
CXX C++编译器的名称,默认值为g++
FC FORTRAN编译器的名称,默认值为f77
ARFLAGS 库文件维护程序的选项,无默认值。
ASFLAGS 汇编程序的选项,无默认值。
CPPFLAGS C预编译的选项,无默认值。
CXXFLAGS C++编译器的选项,无默认值。
FFLAGS FORTRAN编译器的选项,无默认值
- 常见的自动变量
$< 第一个依赖文件
$^ 所有不重复的依赖文件,以空格隔开
$+ 所有的依赖文件,包含重复,以空格隔开
$@ 目标文件
$? 所有比目标文件新的依赖文件,以空格隔开
2.3、文件查找
VPATH:make在当前路径找不到源文件时会自动到VPATH指定的路径去找
VPATH = 目录a : 目录b ...
或者vpath 模式 目录a :目录b
make会依次查找目录a和目录b
. PHONY 是伪目标,为了不和真实的目标混淆
第一次make将VPATH注释掉了
3、嵌套执行
可以使用以下命令调用子目录的makefile
cd 目录 && $(MAKE)
或者:$(MAKE) -C 子目录
可以通过expoet 变量a,将a传给下层的makefile,但没法通过此方式传给上层
4、条件判断
ifeq (参数a,参数b):比较a和b的值,相同为真,相异为假
ifneq (参数a,参数b):比较a和b的值,相同为假,相异为真
ifdef 参数:参数非空为真,空为假
ifndef 参数:参数非空为假,空为真
- 判断语句和参数之间有空格
5、函数
语法:$ (函数名 参数,参数)
5.1、subst:字符串替换
$(subset 参数a,参数b,参数c)
把参数c中的和参数a相同的替换为参数b
5.2、patsubst: 模式字符串替换
$(patsubst 模式a,模式b,参数c)
把参数c中的和模式a相同的替换为模式b
5.3、wildcard:列出特定文件名
$(wildcard 目录a/模式b)
列出目录a下符合模式b的所有文件名
5.4、foreach:循环赋值
$(foreach 参数a,参数b,表达式c)
循环取出参数b的值赋值给参数a然后执行表达式c
5.5、dir/notdir:提取目录/文件名
6、gcc选项
-E : 预处理 gcc -E -o a.i a.c a.c ---> a.i
-S : 编译 gcc -S -o a.S a.i a.i ---> a.S
-c : 汇编 gcc -c -o a.o a.S a.S ---> a.o
: 链接 gcc -o build a.o a.o ---> build 默认生成ELF格式的可执行文件
-v :查看编译器版本
-I :指定头文件的路径
-L :指定依赖的路径
-o :指定生成文件的名字
-d :gdb调试的时候需要加的参数
-D :编译的时候指定宏
-Wall :打开所有警告
-On :优化,n是优化级别
补充
objcopy -O binary a.o a.bin: 去elf头生成二进制文件 a.o ----> a.bin
objdump -S a.o : 反汇编
7、多文件案例
部分参考:https://blog.csdn.net/qq_34968572/article/details/102721670