我最初有两个隐含的规则(为了清楚起见,简化了):
%$(EXESUFFIX) : %.c $(CC) -o $* $< %$(EXESUFFIX) : %.cpp $(CXX) -o $* $<
但问题是,在OS X和Linux上,$(EXESUFFIX)
是空白的,这导致规则匹配错误的东西。所以我尝试使用静态模式规则,如下所示:
$(EXECS) : %$(EXESUFFIX) : %.c $(CC) -o $* $< $(EXECS) : %$(EXESUFFIX) : %.cpp $(CXX) -o $* $<
其中$(EXECS)
是目标,因此没有扩展。但是现在,正在为以. cpp结尾的源运行顶级规则。我该如何解决这个问题?
有关完整示例:
Makefile:
EXESUFFIX = EXECS = test $(EXECS) : %$(EXESUFFIX) : %.c $(CC) -o $* $< $(EXECS) : %$(EXESUFFIX) : %.cpp $(CXX) -o $* $<
测试.cpp:
#include <stdio.h> int main(int argc, char *argv[]){ printf("Hello World\n"); return 0; }
这会打印出错误:
Makefile:8: warning: overriding commands for target `test' Makefile:5: warning: ignoring old commands for target `test' make: *** No rule to make target `test.c', needed by `test'. Stop.
你链接的GNU Make手册很清楚静态规则和隐式规则的区别。
4.12.2静态模式规则与隐式规则
静态模式规则与定义为模式规则的隐式规则有许多共同之处
隐式规则可以应用于与其模式匹配的任何目标,但仅当目标没有另行指定的配方时,并且仅当可以找到先决条件时,它才适用。如果有多个隐式规则适用,则只有一个规则适用;选择取决于规则的顺序。
相反,静态模式规则适用于您在规则中指定的目标的精确列表。它不能适用于任何其他目标,它总是适用于指定的每个目标。如果有两个相互冲突的规则,并且都有食谱,那就是错误。
我建议在C和C程序之间拆分您的可执行文件,并为每个程序定义独立的规则。
我无法重现您的错误,但这在GNUake 3.81中有效:
%$(EXESUFFIX) : %.c
$(CC) -o $* $<
%$(EXESUFFIX) : %.cpp
$(CXX) -o $* $<
使用两个不同的规则来满足相同的目标对于普通模式规则是合法的,但对于静态模式规则则不合法。