我正在尝试制作一个 makefile,而不必手动输入我的所有目标。
我有一个与该函数同名的几乎每个函数的文件,然后是另一个同名的文件,后跟“_test”,其中包含尝试使用该函数的主要方法(不是超级严格,但我不需要完整的单元测试)。
我的 Makefile 看起来像这样:
CFLAGS = -g -Wall
TARGETS = add_tag tag_known
$(TARGETS) : $(addsuffix _test.o, $@) [email protected]
$(CC) $(CFLAGS) -o $(addsuffix _test, $@) $(addsuffix _test.o, $@) [email protected]
%.o : %.c
$(CC) $(CFLAGS) -c $< -o $@
clean :
rn -f *.o $(TARGETS) $(addsuffix _test, $(TARGETS))
除了第一个目标之外,一切正常。要求 $(addsuffix _test.o, $@) 等,看起来它们只是评估空字符串,这会导致 C 编译器抛出错误。
这行不通:
$(TARGETS) : $(addsuffix _test.o, $@) [email protected]
如果您检查
$@
等自动变量的文档,您会发现它们仅在规则配方的上下文中设置。它们在配方之外没有任何价值(在本例中,在先决条件列表中)。
您可以为此使用模式规则:
% : %.o %_test.o
$(CC) $(CFLAGS) -o $@ $^
或者,可能更好,使用静态模式规则:
$(TARGETS) : % : %.o %_test.o
$(CC) $(CFLAGS) -o $@ $^
请注意:
-o $(addsuffix _test, $@)
总是 (*) 错误。每个配方都应该创建目标的确切名称(即
$@
)而不是其他文件。如果你的规则在于 make 关于它的作用,那么 make 会变得非常混乱。
(*) 就像任何事情一样,在极少数情况下这会很有用。
这里的问题是自动变量(在本例中为
$@
)不能在规则的先决条件列表中使用https://www.gnu.org/software/make/manual/html_node/Automatic-Variables .html
此外,无法在规则的先决条件列表中直接访问它们。一个常见的错误是尝试在先决条件列表中使用 $@;这是行不通的。
但从好的方面来说,您可以通过多种方式解决这个问题!一种方法是“二次扩张”。如果您有兴趣,我链接的文档会更深入地介绍这一点。我个人很难理解大量使用二次扩展的 makefile,因此我会引导您进行我能想到的另一个修复,即根据
TARGETS
变量定义第一个目标的先决条件,如下所示只是工作:
$(TARGETS) : $(addsuffix _test.o, $(TARGETS)) $(addsuffix .o, $(TARGETS))
$(CC) $(CFLAGS) -o $(addsuffix _test, $@) $(addsuffix _test.o, $@) [email protected]