I have duplicated pattern rules for several extensions (eg: cpp
and cc
):
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
@$(CXX) $(CPPFLAGS) -I. -o $@ -c $?
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cc
@$(CXX) $(CPPFLAGS) -I. -o $@ -c $?
Is there a way to have one pattern rule which matches on both extensions, rather than having to have two rules?
No, you can't combine the two rules. Prerequisites all have to match.
But you can avoid needing to have the recipe specified twice.
Either by using a define for the recipe:
define COMPILE
@$(CXX) $(CPPFLAGS) -I. -o $@ -c $?
endef
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(COMPILE)
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cc
$(COMPILE)
Or by using a loop and eval to define the recipes (untested I may have gotten some of the escaping wrong but I prefer the define approach anyway):
$(foreach prereq,cc cpp,$(eval $(OBJ_DIR)/%.o: $(SRC_DIR)/%.$(prereq) ; @$(CXX) $(CPPFLAGS) -I. -o $@ -c $?))
You can use .SECONDEXPANSION
for this. Here's an executable example:
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 $<
Create src/foo.cc
and src/bar.cpp
, and issue make -n
, and you'll get:
g++ -I. -o obj/foo.o -c src/foo.cc
g++ -I. -o obj/bar.o -c src/bar.cpp
If you have both foo.cc
and foo.cpp
this will behave just like the version in the question asked here (foo.cpp
will have precedence over foo.cc
, which will be ignored).
The $
signs are doubled for $$(wildcard...
to prevent evaluation during the first expansion. You could have $$(SRC_DIR)
just as well as $(SRC_DIR)
since it does not matter (in the code above) when this variable is expanded.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With