我有两个不同的操作系统环境:CentOS6 和 CentOS7。
CentOS6 GNU make版本是3.81
CentOS7 GNU make版本为3.82
我的Makefile如下
%o : %c
$(CC) -c $(CPFLAGS) -I. $(INCDIR) $< -o $@
3.81 效果很好。
但是3.82不会执行命令
$(CC) -c $(CPFLAGS) -I. $(INCDIR) $< -o $@
似乎只执行其默认命令
%o : %c
我在终端上看到的内容,将像这样展开 ===> gcc c -o main.o main.c
经过一些测试,我确信这条线 $(CC) -c $(CPFLAGS) -I。 $(INCDIR) $< -o $@ will NEVER be executed.
Google搜索后,我用另一种语法格式重写
.c.o:
$(CC) -c $(CPFLAGS) -I. $(INCDIR) $< -o $@
这有效! $(CC) -c $(CPFLAGS) -I。 $(INCDIR) $< -o $@ will execute!!!
我阅读了 3.82 发行说明,但没有得到任何有关此问题的线索。
你能帮我解释一下原因吗?
我不认为这是由不同的 GNU make 版本引起的。
谢谢!!!
当你说:
似乎只执行其默认命令
%o : %c
这是不正确的。从 C 源文件构建目标文件的默认规则不是
%o : %c
,而是 %.o : %.c
。这里的差异(添加的 .
)可能看起来很小,但这就是您看到的行为的原因。
由于默认规则是
%.o : %.c
,当您使用%o : %c
定义自己的规则时,这是一个完全不同的规则:它不会替换现有规则,它是一个新规则除了现有规则之外.
所以现在有two模式规则可用于从 C 源文件构建目标文件。 make 如何决定使用哪一个? GNU Make 3.81 和 GNU Make 3.82 之间的选择算法发生了变化。
在 GNU Make 3.81 及更早版本中,始终选择“第一个定义的规则”(其中默认规则被认为是最后定义的)。这意味着您的规则%o: %c
已被选择。
(与%
匹配的部分)最短的规则(我们的选择是选择最具体的规则)。如果我们想从 foo.o
构建
foo.c
,那么在默认规则中,词干是 foo
,而在您的替代规则中,默认是 foo.
(对于与字符串 %o
词干匹配的模式 foo.o
) --匹配%
的部分--是foo.
).由于内置规则的主干(foo
为 3 个字符长)比模式规则的主干(foo.
为 4 个字符长)短,因此内置规则
更具体,所以它将被选择。如果您希望 makefile 适用于所有版本,那么您应该使用 same 模式而不是不同的模式来 replace
内置规则,而不是创建 extra 规则;将您的规则写为:
%.o : %.c
$(CC) -c $(CPFLAGS) -I. $(INCDIR) $< -o $@
它适用于所有版本的 GNU Make。
您的规则无论如何都不是很好,因为省略
.
意味着该规则将匹配任何以
o
结尾的目标文件(不仅仅是
.o
)以及任何以 c
结尾的先决条件(不仅仅是 .c
)。