变量、规则与内置函数
1)变量
随着软件项目的变大、变复杂,源文件也越来越多,如果采用前面的方式写 makefile 文件,将会使 makefile也变得复杂而难于维护。
通过 make 支持的变量定义、规则和内置函数,可以写出通用性较强的 makefile 文件,使得同一个 makefile 文件能够适应不同的项目。
变量: 用来代替一个文本字符串
定义变量的 2 种方法:
变量名=变量值 递规变量展开(几个变量共享一个值) //不常用
变量名:=变量值 简单变量展开(类似于 C++的赋值) //通常采用这种形式
使用变量的一般方法:
$(变量名)=??? //赋值
???=$(变量名) //引用
例: 前面的那个可以写为:TEST_file1文件夹。
OBJS:=test.o add.o
EXE:=test.exe
$(EXE):$(OBJS)
gcc -o $(EXE) $(OBJS)
test.o:test.c
gcc -c test.c
add.o:add.c
gcc -c add.c
.PHONY:rebuild clean
rebuild:clean $(EXE)
clean:
rm -rf $(EXE) $(OBJS)
变量分为:用户自定义变量,自动变量,预定义变量,环境变量。
上面的例子就是用户自定义变量。
(1)自动变量
指在使用的时候,自动用特定的值替换。
常用的变量
$@ 当前规则的目标文件
$< 当前规则的第一个依赖文件
$^ 当前规则的所有依赖文件,以逗号分隔
$? 规则中日期新于目标文件的所有相关文件列表,逗号分隔
$(@D) 目标文件的目录名部分,若$@为”add/add.c,则$(@D)为add
$(@F) 目标文件的文件名部分,若$@为”add/add.c,则$(@F)为add.c
示例: 用自动变量:TEST_file2文件夹。
OBJS:=test.o add.o
EXE:=test.exe
$(EXE):$(OBJS)
gcc -o $@ $^
test.o:test.c
gcc -c $^
add.o:add.c
gcc -c $^
.PHONY:rebuild clean
rebuild:clean $(EXE)
clean:
rm -rf $(EXE) $(OBJS)
(2)预定义变量 查看环境变量export
内部事先定义好的变量,但是它的值是固定的,并且有些的值是为空的。
变量 描述
AS 汇编程序,默认为 as
CC c 编译器默认为 cc
CPP c 预编译器,默认为$(CC) -E
CXX c++编译器,默认为 g++
RM 删除,默认为 rm -f
ARFLAGS 库选项,无默认
ASFLAGS 汇编选项,无默认
CFLAGS c 编译器选项,无默认
CPPFLAGS c 预编译器选项,无默认
CXXFLAGS c++编译器选项,无默认
根据内部变量,可以将 makefile 改写为:TEST_file3文件夹。
OBJS:=test.o add.o
EXE:=test.exe
$(EXE):$(OBJS)
$(CC) -o $@ $^
test.o:test.c
$(CC) -c $^
add.o:add.c
$(CC) -c $^
.PHONY:rebuild clean
rebuild:clean $(EXE)
clean:
$(RM) $(EXE) $(OBJS)
2)规则
分为: 普通规则, 隐含规则,模式规则。
(1)隐含规则: TEST_file4文件夹。
例如:*.o 文件自动依赖*.c 或*.cc 文件,所以可以省略 main.o:main.c 等。
OBJS:=test.o add.o
EXE:=test.exe
$(EXE):$(OBJS)
$(CC) -o $@ $^
.PHONY:rebuild clean
rebuild:clean $(EXE)
clean:
$(RM) $(EXE) $(OBJS)
(2)模式规则
通过匹配模式找字符串,%匹配 1 或多个任意字符串。
%.o: %.cpp 任何目标文件的依赖文件是与目标文件同名的并且扩展名为.cpp 的文件。
OBJS := main.o fun.o
main.exe : $(OBJS)
gcc $^ -o $@
%.o: %.cpp #模式通配
gcc -o $@ -c $^
另外还可以指定将*.o、 *.exe、 *.a、 *.so 等编译到指定的目录中:
DIR:=./Debug/
EXE:=main.exe
OBJS:=main.o
$(DIR)$(EXE):$(DIR)$(OBJS)
gcc -o $@ $< -L./ -lfunc
$(DIR)main.o:main.c
gcc -o $@ -c $^
.PHONY:rebuild clean
rebuild:clean $(DIR)$(EXE)
clean:
rm -rf $(DIR)*.o $(DIR)*.exe
注意: 当 OBJS 里面有多项的时候,此时(DIR)(DIR)(DIR)(OBJS)只能影响到 OBJS 中第一个,后面的全部无效,因此需要全部列出来。
3)函数
(1)搜索文件函数wildcard
搜索当前目录下的文件名,展开成一列所有符合由其参数描述的文件名,文件间以空格间隔。
SOURCES = $(wildcard *.cpp)
//把当前目录下所有'.cpp'文件存入变量 SOURCES 里。
(2)字符串替换函数patsubst
格式:$(patsubst 要查找的子串,替换后的目标子串,源字符串)。
将源字符串(以空格分隔)中的所有要查找的子串替换成目标子串。
如:
OBJS = $(patsubst %.cpp,%.o,$(SOURCES))
把 SOURCES 中'.cpp' 替换为'.o' ,然后把替换后的字符串存入变量 OBJS。
(3)加前缀函数addprefix
格式:$(addprefix 前缀,源字符串)
该函数把第二个参数列表的每一项前缀上第一个参数值。