Makefile 隐式规则匹配 - 前缀长度不影响匹配

Makefile implicit rule matching - prefix length not affecting match

在我的 gnu-make-3.81 Makefile 中,我希望定义两个隐式规则,以便更具体的第一个优先于更一般的第二个:

src/%_bar.o : src/%_bar.c
    $(CC) -Wall -Wno-unused-but-set-variable -c $^ -o $@

src/%.o : src/%.c
    $(CC) -Wall -c $^ -o $@

我遇到的问题是 foo_bar.c 代表自动生成的代码,它会触发带有 -Wall 的警告,我更愿意抑制,所以第一条规则是为了捕捉这种特殊情况。

根据make's manual

It is possible that more than one pattern rule will meet these criteria. In that case, make will choose the rule with the shortest stem (that is, the pattern that matches most specifically).

我认为对于 src/foo_bar.o 的文件名,第一条规则会生成词干 foo,第二条规则会生成 foo_bar。前者是最短的,所以我希望它适用。然而,情况似乎并非如此,第二条规则是由 make 选择并执行的。 运行 make -d 甚至没有显示与词干 foo 匹配的尝试 - 仅考虑 foo_bar

如果我进行以下更改,通过将前缀从 src/ 缩短为 sr 来故意使第二条规则的词干更长,第二条规则仍然被选​​中:

src/%_bar.o : src/%_bar.c
    $(CC) -Wall -Wno-unused-but-set-variable -c $^ -o $@

sr%.o : sr%.c
    $(CC) -Wall -c $^ -o $@

我无法将其与 make 文档相协调。

此外,如果我完全删除 src/ 前缀,则第二条规则 选择的:

src/%_bar.o : src/%_bar.c
    $(CC) -Wall -Wno-unused-but-set-variable -c $^ -o $@

%.o : %.c
    $(CC) -Wall -c $^ -o $@

虽然这解决了我的问题,但它实际上并不合适,因为它 overrides/interacts 在我需要保留的当前目录上有另一个隐式规则:

%.o : %.c
    # do something else

我的问题是为什么 make 在这种情况下会这样,这是否与文档一致?如果是这样,是否有更好的方法来指定更专业的隐式规则?

首先,请注意 GNU make 3.82 中引入了 "shortest stem" 模式匹配方法。如果您使用的是 GNU make 3.81,那么您的 make 版本使用旧方法 "first match"。如果可能的话,最好阅读发行版附带的文档,而不是网络文档,因为网络文档是针对最新版本的 GNU make 的。 GNU make 3.81 于 2006 年 4 月发布...已经很老了。

但是,您提供的示例确实按照您希望的方式工作:

src/%_bar.o : src/%_bar.c ; @echo shorter: $*

src/%.o : src/%.c ; @echo longer: $*

all: src/foo_bar.o

$ make-3.81
shorter: foo

$ make-3.82
shorter: foo

我怀疑当您在这里提问时,您使用的代码与您在真实环境中使用的代码不同。在那个环境中,您必须在 之后使用较短的模式 较长的模式,如下所示:

src/%.o : src/%.c ; @echo longer: $*

src/%_bar.o : src/%_bar.c ; @echo shorter: $*

all: src/foo_bar.o

$ make-3.81
longer: foo_bar

$ make-3.82
shorter: foo

在提问时,确保问题中的简化示例准确反映真实情况非常重要。