请看以下
除了
这体现在我们的
Makefile
示例:.SUFFIXES:
.SUFFIXES: .c.o
.PHONY: all
all: foo.o
foo.o: foo.h bar.h xyzzy.h
%.o: %.c
@printf "prerequisites of %s are %s\n" $@ "$^"
除了
foo.o
,所有文件都存在,输出结果为:prerequisites of foo.o are foo.c foo.h bar.h xyzzy.h
正确地说,自动变量$^
会为我们提供所有的前置条件,包括从其他规则中得到的依赖项。
让我们把规则本身给出的前置条件称为主要前提,而来自其他依赖项的前置条件称为次要前提。
上面,主要前提是:
foo.c
而次要的则为:
foo.h bar.h xyzzy.h
类别很重要,因为主要的前提条件是规则实际使用的对象,这些对象需要用于构建程序。次要的前提条件仅涉及增量构建的正确触发,而不涉及完整构建。即使我们删除依赖关系线,从头开始进行完整构建也将起作用:
foo.o: foo.h bar.h xyzzy.h
这体现在我们的
Makefile
结构中。我们通常不会编写这样的规则:Makefiles
。foo.o: foo.c foo.h bar.h xyzzy.h
# commands
在foo.c
之后的额外前提条件被拆分到其他地方,通常是一个完全独立的依赖关系makefile中,该makefile由工具生成,并且可以完全删除,而不会影响从头开始进行完整构建的能力。
问题是:我们如何仅获得主要先决条件的列表,而不包括次要先决条件?
这应该可以以一种通用的方式完成,而没有任何硬编码。例如,如果我定义了一些作为宏的配方行,它们可以在多个规则中重复使用。
define RULE_BODY
@printf "the primary prerequisites of target %s are %s\n" $@ [what goes here?]
endef
%.o: %.c
$(call RULE_BODY)
我不希望将参数传递给RULE_BODY,因为它应该“自己知道”,就像它知道目标和全部先决条件一样。
请注意,使用模式规则是一个红鲱鱼:我们可以用foo.o: foo.c
替换%.o: %.c
。
$~
或其他什么?我知道关于o-o先决条件并已经使用过它们。一个补丁可能没有那么有用,因为它必须被上游采纳,并且它会在GNU Make的最新版本中创建依赖性。在3.81中工作的东西会很好。没有人想要发布一个需要从GNU ftp服务器获取并从头构建的最新gmake的开源程序。 :) - Kazfoo.o: $(DEPS_$*)
,那么这将需要进行二次扩展(我认为),但如果你不这样做,那么你的定义可以使用$(DEPS_$*)
来从$^
中过滤出次要先决条件。是的,我假设$^
在这些情况下不能“只是”做你想要的事情? - Etan Reisner