Makefile:具有非显式输出文件名的隐式规则会破坏规则匹配
Makefile: implicit rule with non-explicit output file name breaks rule matching
我现在的情况是我希望对多种文件类型进行全部预处理(如果它们的名称表明)。
例如:
main.c # gets compiled normally by %.c rule
somethingelse.c.m4 # gets preprocessed, then dealt with by %.c rule
somethingother.h.m4 # gets preprocessed (then included by .c files)
我尝试了什么:
%: %.m4
m4 "$<" > "$@"
但我收到错误消息:
make: *** No rule to make target 'somethingelse.o', needed by 'a.out'. Stop.
如您所见,这在规则 after the m4
中失败了。
很确定它无法确定曾经有一个 .c
文件从此隐式规则生成,因此无法匹配 %.o: %.c
文件。
这当然有效:
%.c: %.c.m4
m4 "$<" > "$@"
%.h: %.h.m4
m4 "$<" > "$@"
但是在添加案例时它变得相当重复而且很快。
有什么方法可以让它与匹配这些文件的单个规则一起工作吗?
在有人告诉我 C 预处理器之前:这里的 .c
/.h
文件只是一个“众所周知”/“最小”的例子,实际上我正在处理各种自定义文件格式,但适用完全相同的逻辑和“隐式规则链接”情况。
Pretty sure it can't figure out that there'd ever be a .c file generated from this implicit rule, thus is unable to match the %.o: %.c one.
不,我认为答案更简单。每 the manual,
for performance reasons make
will not consider non-terminal
match-anything rules (i.e., ‘%:’) when searching for a rule to build a
prerequisite of an implicit rule
这正是你的情况。 somethingelse.c
文件未明确命名为任何规则的目标或先决条件;它仅被视为隐含规则的先决条件。您的 match-anything 规则不是最终规则,因此甚至不考虑构建该文件。
说明书对terminal vs. non-terminal match-anything rules说的比较多,但这里相关的要点是:
- 通过使用双冒号(而不是单个冒号)将目标与先决条件分开,终端匹配任何规则与非终端规则区别开来,并且
- 只有当所有先决条件都存在时,终端规则才适用。
所有先决条件都存在的要求对于问题中出现的情况不是问题,我发现切换到终端匹配任何规则都可以解决问题。例如,这个完整的 Makefile ...
OBJECTS = main.o somethingelse.o
foo: $(OBJECTS)
$(CC) -o $@ $^
%:: %.m4
m4 $< > $@
... 为我工作,从合适的 main.c
和 somethingelse.c.m4
.
构建 foo
我现在的情况是我希望对多种文件类型进行全部预处理(如果它们的名称表明)。
例如:
main.c # gets compiled normally by %.c rule
somethingelse.c.m4 # gets preprocessed, then dealt with by %.c rule
somethingother.h.m4 # gets preprocessed (then included by .c files)
我尝试了什么:
%: %.m4
m4 "$<" > "$@"
但我收到错误消息:
make: *** No rule to make target 'somethingelse.o', needed by 'a.out'. Stop.
如您所见,这在规则 after the m4
中失败了。
很确定它无法确定曾经有一个 .c
文件从此隐式规则生成,因此无法匹配 %.o: %.c
文件。
这当然有效:
%.c: %.c.m4
m4 "$<" > "$@"
%.h: %.h.m4
m4 "$<" > "$@"
但是在添加案例时它变得相当重复而且很快。
有什么方法可以让它与匹配这些文件的单个规则一起工作吗?
在有人告诉我 C 预处理器之前:这里的 .c
/.h
文件只是一个“众所周知”/“最小”的例子,实际上我正在处理各种自定义文件格式,但适用完全相同的逻辑和“隐式规则链接”情况。
Pretty sure it can't figure out that there'd ever be a .c file generated from this implicit rule, thus is unable to match the %.o: %.c one.
不,我认为答案更简单。每 the manual,
for performance reasons
make
will not consider non-terminal match-anything rules (i.e., ‘%:’) when searching for a rule to build a prerequisite of an implicit rule
这正是你的情况。 somethingelse.c
文件未明确命名为任何规则的目标或先决条件;它仅被视为隐含规则的先决条件。您的 match-anything 规则不是最终规则,因此甚至不考虑构建该文件。
说明书对terminal vs. non-terminal match-anything rules说的比较多,但这里相关的要点是:
- 通过使用双冒号(而不是单个冒号)将目标与先决条件分开,终端匹配任何规则与非终端规则区别开来,并且
- 只有当所有先决条件都存在时,终端规则才适用。
所有先决条件都存在的要求对于问题中出现的情况不是问题,我发现切换到终端匹配任何规则都可以解决问题。例如,这个完整的 Makefile ...
OBJECTS = main.o somethingelse.o
foo: $(OBJECTS)
$(CC) -o $@ $^
%:: %.m4
m4 $< > $@
... 为我工作,从合适的 main.c
和 somethingelse.c.m4
.
foo