1. 编译工具及构建工具介绍
直接使用gcc对代码进行编译,这对简单的工程是可以的,但当我们遇到复杂的工程时,每次用gcc等编译工具去操作就会显得很低效。因此make工具就出现了,make的出现是为了解决手动编译和链接大型工程的问题,它可以避免重复的工作,提高效率,保证正确性。make工具就根据makefile中的命令进行编译和链接的。
但是当工程非常大的时候,手写makefile也是非常麻烦的,如果换了个平台makefile又要重新修改,因此更高级的一些构建系统或者工具工具像cmake、qmake、ninja和auto make就出现了,它们可以根据一些配置文件来自动化编译和链接软件项目。
2. Makefile的规则
a.基本规则
b. 伪目标
如果一个目标和一个实际文件同名,那么make会认为该目标已经是最新的,不需要重新生成,也不会执行其命令。通过将目标声明为伪目标,可以避免这种情况,强制执行其命令。
c. 变量赋值和预定义变量
Makefile中的变量赋值运算符有四种,分别是 = := ?= +=
= 表示延迟展开赋值,即变量的值是在使用时才确定,可能会受到后面的赋值影响。例如,VAR_A = A,VAR_B = $(VAR_A) B,VAR_A = AA,那么最后VAR_B的值是AA B,而不是A B。
:= 表示直接赋值
?: 表示条件赋值,即只有当变量没有被赋值时,才使用等号后面的值作为变量的值。例如,VAR ?=new_value,如果VAR在之前没有被赋值,那么VAR的值就为new_value,否则保持原来的值不变。
+= 表示追加赋值,即将等号后面的值追加到变量原来的值之后,形成一个新的值。例如,VAR +=new_value,如果VAR在之前没有被赋值,那么VAR的值就为new_value,如果VAR在之前被赋值为old_value,那么VAR的值就为old_value new_value
d. $符的其他用法:
$^ 表示所有的依赖文件
$@ 表示生成的目标文件
$< 代表第一个依赖文件
e.注释和换行符
# 进行一行注释
\ 作为续行符
f.常见函数
(1)wildcard通配符:
Makefile中的wildcard是一个函数,返回与通配符匹配的文件列表。
ECO = $(wildcard Class/*.c)
debug :
@echo $(ECO)
结果:Class/A.c Class/B.c
(2)shell
$(shell<cmd><args>)
(3)patsubst替换函数:
(4)subst替换函数
Makefile
CC = gcc
CC += -g
# 查找当前目录以及当前目录子目录下的所有.c文件
SRC := $(shell find . -name "*.c")
# 生成目标文件列表
TARGET := $(patsubst %.c,%,$(subst src,obj,$(SRC)))
# 提取目标文件所在目录
TARGET_DIR = $(dir $(TARGET))
debug:
@echo $(SRC)
@echo $(EQT)
@echo $(TARGET)
$(TARGET): $(SRC)
# 创建目标文件目录
mkdir -p $(TARGET_DIR)
# 编译生成目标文件
$(CC) -o $@ $<
# 编译所有目标文件
compile: $(TARGET)
# 清理目标文件夹
clean:
@rm obj -rf
(5) dir函数
功能:dir函数是一个用于从文件名序列中提取目录部分的函数
$(dir NAMES...)
(6) suffix函数
功能:从文件名序列中取出各个文件名的后缀。
ECO = $(suffix beep.c hello.o)
debug :
@echo $(ECO)
结果:.c .o
(7) basename函数
功能:从文件名序列中取出各个文件名的前缀部分。
ECO = $(basename beep.c hello.o)
debug :
@echo $(ECO)
结果:beep hello
(8) addsuffix函数
功能:把后缀加到每个单词后面。
Echo = $(addsuffix .c,foo bar)
debug:
@echo $(Echo)
结果:fool.c bar.c
(9) addprefix函数
功能:把前缀加到中的每个单词前面
Echo = $(addprefix src/,foo bar)
debug:
@echo $(Echo)
结果:src/foo src/bar
(10) foreach函数
#(foreach <var>,<list>,<test>)
#把list中使用空格分割的单词依次取出并赋值给变量var,然后执行text表达式
INCLODE := /usr/include/ /usr/local/include
I_FLAGS := $(foreach var,$(INCLODE),-I$(var))
debug :
@echo $(I_FLAGS)
结果:-I/usr/include/ -I/usr/local/include
(11) 条件判断语言
ifeq(arg1,arg2)
#arg1 arg2 相等执行这里的语句
else
#arg1 arg2 不相等执行这里的语句
endif
infeq(arg1,arg2)
#arg1 arg2 不相等执行这里的语句
else
#arg1 arg2 相等执行这里的语句
endif
ifdef var
#如果定义了var,执行这里的内容
else
#如果没定义var,执行这里的内容
endif
ifndef var
#如果没定义了var,执行这里的内容
else
#如果定义var,执行这里的内容
endif