LV120-命令包
在 Makefile 中,如果出现一些重复的命令序列,我们可以将这些命令定义成一个可重用的命令包(也称为命令模板)。这样可以提高 Makefile 的可读性和维护性。
一、命令包简介
1. 命令包的定义
定义命令包的语法以 define 开始,以 endef 结束,如:
makefile
define run-yacc
yacc $(firstword $^)
mv y.tab.c $@
endef这里,run-yacc 是这个命令包的名字,不要与 Makefile 中的变量重名。在 define 和 endef 之间的多行内容就是命令序列。这个命令包中的第一个命令是运行 Yacc 程序,因为 Yacc 程序总是生成 y.tab.c 的文件,所以第二行的命令就是把这个文件重命名。
2. 命令包的使用
我们放到一个示例中来看看:
makefile
foo.c : foo.y
$(run-yacc)我们可以看到,要使用这个命令包,我们就像使用变量一样。在这个命令包的使用中,命令包 run-yacc 中的 $^ 就是 foo.y,$@ 就是 foo.c。Make 在执行命令包时,命令包中的每个命令会被依次独立执行。
3. 命令包的特点
(1)变量替换:命令包中的变量在使用时会自动替换为实际值(如 $^、$@ 等自动化变量)。
(2)命令独立执行:命令包中的每个命令都会被独立执行,就像写在目标规则中的命令一样。
(3)可重用性:可以多次在不同的规则中使用同一个命令包。
4. 注意事项
(1)变量名冲突:命令包名称不能与 Makefile 中的变量名重名。
(2)自动化变量:命令包中的自动化变量(如 $^、$@)在使用时会被自动替换为对应的实际值。
(3)命令执行:命令包中的每个命令都会被独立执行,具有与规则中直接书写的命令相同的语义。
(4)缩进规则:命令包内部的命令必须按照 Makefile 的缩进规则进行缩进(使用 Tab 键)。
二、实际应用示例
下面是一个更复杂的命令包示例,展示了如何在多个规则中复用命令序列:
makefile
# 定义一个编译C文件的命令包
define compile-c
$(CC) $(CFLAGS) -c $< -o $@
endef
# 定义一个链接目标文件的命令包
define link-binary
$(CC) $(LDFLAGS) $^ -o $@
endef
# 使用命令包
main: main.o utils.o
$(link-binary)
main.o: main.c
$(compile-c)
utils.o: utils.c
$(compile-c)在这个例子中,我们定义了两个命令包:
compile-c:用于编译C源文件为目标文件link-binary:用于链接目标文件生成可执行文件
这样可以避免重复书写相似的编译和链接命令。