我有多个扩展程序的重复模式规则(例如:cpp
和cc
):
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
@$(CXX) $(CPPFLAGS) -I. -o $@ -c $?
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cc
@$(CXX) $(CPPFLAGS) -I. -o $@ -c $?
有没有办法让一个模式规则在两个扩展名上匹配,而不是必须有两个规则?
答案 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.cc
和src/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.cc
和foo.cpp
,则其行为与此处提出的问题中的版本相同(foo.cpp
将优先于foo.cc
,这将被忽略)。
$
的{{1}}符号加倍,以防止在第一次扩展期间进行评估。您可以$$(wildcard...
与$$(SRC_DIR)
一样,因为扩展此变量时(在上面的代码中)无关紧要。