make:模式规则匹配多个扩展

Ste*_*mer 5 c++ makefile gnu-make

我有几个扩展的重复模式规则(例如:cppcc):

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
    @$(CXX) $(CPPFLAGS) -I. -o $@ -c $?

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cc
    @$(CXX) $(CPPFLAGS) -I. -o $@ -c $?
Run Code Online (Sandbox Code Playgroud)

有没有办法让一个模式规则在两个扩展上匹配,而不是必须有两个规则?

Eta*_*ner 5

不,你不能把这两个规则结合起来.先决条件都必须匹配.

但是你可以避免需要两次指定配方.

通过使用配方的定义:

define COMPILE
@$(CXX) $(CPPFLAGS) -I. -o $@ -c $?
endef

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
        $(COMPILE)

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cc
        $(COMPILE)
Run Code Online (Sandbox Code Playgroud)

或者通过使用循环和eval来定义配方(未经测试我可能已经获得了一些转义错误但我更喜欢定义方法):

$(foreach prereq,cc cpp,$(eval $(OBJ_DIR)/%.o: $(SRC_DIR)/%.$(prereq) ; @$(CXX) $(CPPFLAGS) -I. -o $@ -c $?))
Run Code Online (Sandbox Code Playgroud)


Lou*_*uis 3

您可以用于.SECONDEXPANSION此用途。这是一个可执行的示例:

OBJ_DIR:=obj
SRC_DIR:=src

TARGETS:=obj/foo.o obj/bar.o

all: $(TARGETS)

.SECONDEXPANSION:
$(OBJ_DIR)/%.o: $$(wildcard $(SRC_DIR)/%.cpp) $$(wildcard $(SRC_DIR)/%.cc)
    @$(CXX) $(CPPFLAGS) -I. -o $@ -c $<
Run Code Online (Sandbox Code Playgroud)

创建src/foo.ccsrc/bar.cpp,并发出make -n,您将得到:

g++  -I. -o obj/foo.o -c src/foo.cc
g++  -I. -o obj/bar.o -c src/bar.cpp
Run Code Online (Sandbox Code Playgroud)

如果您两者都有foo.cc,则foo.cpp其行为就像此处提出的问题中的版本一样(foo.cpp将优先于foo.cc,后者将被忽略)。

这些$符号加倍是为了$$(wildcard...防止在第一次扩展期间进行评估。您$$(SRC_DIR)也可以这样做$(SRC_DIR),因为扩展此变量时(在上面的代码中)并不重要。

  • 我不知道你怎么想,但这对我来说就像黑魔法,过去 30 年我一直断断续续地使用“make”。 (4认同)