0%

Makefile中自动变量与隐晦规则

代码变成可执行文件,叫做编译(compile);先编译这个还是先编译那个(即编译的安排),叫做构建(build)。Make是最常用的构建工具,诞生于1977年,主要用于C语言的项目。

一、自动变量

      makefile中的自动变量实质上是对一类变量的简写,当我们在模式规则中对这类变量处理的时候可以直接使用自动变量简化makefile代码的编写。自动变量包括如目标文件,依赖文件等,常用的自动变量:

  1. $@指代当前目标,就是Make命令当前构建的那个目标。

    • makefile内容如下
    1
    2
    test:
    @echo $@
    • 执行make得到结果test,即目标本身
  2. $<指代第一个前置条件。

    • makefile内容如下
1
2
3
4
5
6
test.txt: source.txt result.txt
@echo $<
source.txt:
@echo "this is a test" > source.txt
result.txt:
@echo "this is also a test" > result.txt
  • 执行makemake test.txt得到结果source.txt
  1. $^指代所有前置条件,之间以空格分隔。
    • makefile内容如下
1
2
3
4
5
6
test.txt: source.txt result.txt
@echo $^
source.txt:
@echo "this is a test" > source.txt
result.txt:
@echo "this is also a test" > result.txt
  • 执行makemake test.txt得到结果source.txt result.txt
  1. $+表示所有依赖文件的集合(不去重),$^会去重。

  2. $?指代比目标更新的所有前置条件,之间以空格分隔。

  3. $*指代匹配符%匹配到的部分。

  4. $(@D)$(@F)分别指向$@的目录名(相对路径)和文件名。

  5. $(<D)$(<F)分别指向$<的目录名(相对路径)和文件名。

二、隐晦规则

      使用makefile隐晦规则可以省去为每一个类似的规则生成都去写类似的规则,makefile会自动推导依赖文件,并根据隐含规则推导出生成当前目标的命令。

  1. 不使用隐晦规则
1
2
3
4
5
6
7
8
target: a.o b.o c.o
g++ -o $@ $^ $(LIB) $(INC) $(LINKER)
a.o: a.c
g++ -c $(CFLAGS) -o a.o a.c
b.o: b.c
g++ -c $(CFLAGS) -o b.o b.c
c.o: c.c
g++ -c $(CFLAGS) -o c.o c.c
  1. 使用隐晦规则
1
2
3
4
5
6
SOURCE := $(shell find ./ -type f -name *.c)
OBJECTS := $(patsubst *.c,*.o,$(SOURCE))
target : $(OBJECTS)
g++ -o $@ $^ $(LIB) $(INC) $(LINKER)
%.o:%.c
$(CC) -c $(CFLAGS) -o $@ $<

执行过程:

makefile中首先声明了变量SOURCEOBJECTS分别代表当前文件夹下的.c.o文件集合。目标target依赖所有的目标文件.o,即a.o,b.o,c.o。当需要依赖a.omakefile会根据隐晦规则自动推导出生成a.o文件的命令g++ -c $(CFLAGS) -o a.o a.c生成a.o,同理会根据隐晦规则生成b.o、c.o,三个.o文件生成后再根据上述规则生成target

三、参考

  1. 参考一

  2. 参考二