【发布时间】:2014-12-10 16:55:16
【问题描述】:
考虑以下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 之后的附加先决条件在其他地方被分解,通常是由工具生成的完全独立的依赖生成文件,可以完全删除,而不会影响从头开始进行完整构建的能力。
问题是:我们怎样才能只获得主要先决条件的列表,而不包括次要先决条件?
这应该可以通过通用方式实现,无需任何硬编码。例如,如果我将一些配方行定义为宏,它们可以在多个规则中重复使用。
define RULE_BODY
@printf "the primary prerequisites of target %s are %s\n" $@ [what goes here?]
endef
%.o: %.c
$(call RULE_BODY)
我不想为此向 RULE_BODY 传递参数,因为它应该“只知道”,就像它知道目标和总先决条件一样。
请注意,模式规则的使用是一个红鲱鱼:我们可以将%.o: %.c 替换为foo.o: foo.c。
【问题讨论】:
-
这种区别只存在于您的脑海中。 Make 没有这样的区别。
-
@EtanReisner 感谢您的意见。在我看来,区别在
Makefile的语法中进行了编码,因为模式规则%.o: %.c的右侧是%.c,并且仅匹配foo.c,而不匹配foo.h。在某些时候,程序知道这一点。所以,它不仅在我的脑海里。 -
您正在假设一种非常特定的方式来编写makefile,并且只有特定类型的模式规则。您也没有考虑 make 结合先决条件的方式。我并不是建议让无法知道这种区别。我我建议 make 不会保存此信息,并且不会像您一样考虑这种区别。
-
我同意构建使用与新鲜使用先决条件的想法是一个潜在有用的想法(尽管使用可能仅限于像这样的编译案例)但这种区别在 make 中并不存在.唯一的先决条件类型区分是针对仅订单的先决条件,这些先决条件不能满足您的要求。
-
@EtanReisner 你能通过引用 GNU make 源代码来支持这一点吗?如果做不到,知道这将是有用的。我必须为此写一个补丁吗?说一个新的自动变量,如
$~或其他什么?我知道 o-o 先决条件并使用过它们。补丁不会那么有用,因为它必须被上游化,并且它会产生对前沿 GNU Make 的依赖。在 3.81 中工作的东西会很好。没有人愿意发布一个需要最新 gmake 的开源程序,该程序必须从 GNU ftp 服务器获得并从头开始构建。 :)