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

时间:2015-01-14 21:14:04

标签: 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 $?

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

2 个答案:

答案 0 :(得分:5)

不,你不能将这两个规则结合起来。所有必须匹配的先决条件。

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

使用配方的定义:

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

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

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

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

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

答案 1 :(得分: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 $<

创建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

如果您同时拥有foo.ccfoo.cpp,则其行为与此处提出的问题中的版本相同(foo.cpp将优先于foo.cc,这将被忽略)。

$的{​​{1}}符号加倍,以防止在第一次扩展期间进行评估。您可以$$(wildcard...$$(SRC_DIR)一样,因为扩展此变量时(在上面的代码中)无关紧要。