make: 匹配多个扩展名的模式规则
make: pattern rule matching multiple extensions
我有几个扩展的重复模式规则(例如:cpp
和 cc
):
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
@$(CXX) $(CPPFLAGS) -I. -o $@ -c $?
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cc
@$(CXX) $(CPPFLAGS) -I. -o $@ -c $?
有没有办法让一个模式规则在两个扩展上都匹配,而不是必须有两个规则?
不,您不能合并这两个规则。先决条件都必须匹配。
但是您可以避免需要两次指定配方。
通过使用配方定义:
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 $?))
您可以为此使用 .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
,这将被忽略)。
$$(wildcard...
的 $
符号加倍,以防止在第一次扩展期间进行计算。您可以 $$(SRC_DIR)
和 $(SRC_DIR)
一样,因为在扩展此变量时(在上面的代码中)无关紧要。
我有几个扩展的重复模式规则(例如:cpp
和 cc
):
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
@$(CXX) $(CPPFLAGS) -I. -o $@ -c $?
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cc
@$(CXX) $(CPPFLAGS) -I. -o $@ -c $?
有没有办法让一个模式规则在两个扩展上都匹配,而不是必须有两个规则?
不,您不能合并这两个规则。先决条件都必须匹配。
但是您可以避免需要两次指定配方。
通过使用配方定义:
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 $?))
您可以为此使用 .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
,这将被忽略)。
$$(wildcard...
的 $
符号加倍,以防止在第一次扩展期间进行计算。您可以 $$(SRC_DIR)
和 $(SRC_DIR)
一样,因为在扩展此变量时(在上面的代码中)无关紧要。