Is there a simple way to apply a single recipe to multiple pattern rules?
Consider this directory structure
|- src
| - file1.cpp
|- test
| - file2.cpp
| - file3.cpp
| - metrics
| - file4.cpp
| - file5.cpp
I would like to write a single pattern rule to compile all the .cpp files in the test directory. Here is what I have right now:
$(OBJS)/%.o: test/%.cpp
@mkdir -p $(OBJS)
g++ $(FLAGS) $(CPPFLAGS) -c $< -o $@
$(OBJS)/%.o: test/metrics/%.cpp
@mkdir -p $(OBJS)
g++ $(FLAGS) $(CPPFLAGS) -I test -c $< -o $@
TEST_CPP := $(wildcard test/*.cpp) $(wildcard test/**/*.cpp)
TEST_OBJ := $(addprefix $(OBJS)/,$(notdir $(TEST_CPP:.cpp=.o)))
$(BIN)/testRunner: $(TEST_OBJ)
@mkdir -p $(BIN)
g++ $(FLAGS) $(CPPFLAGS) $^ $(LIBS) -o $@
I would like to avoid repeating the recipe for the object files. I imagine the solution would look something like this:
$(OBJS)/%.o: test/%.cpp
$(OBJS)/%.o: test/metrics/%.cpp
@mkdir -p $(OBJS)
g++ $(FLAGS) $(CPPFLAGS) -c $< -o $@
(At the moment, the objs directory is flat; but, I don't have a problem duplicating the source directory structure if that simplifies the makefile.)
There is no way to do what you want. The closest you can get is to put the recipe into a variable and use that same variable in each recipe, like this:
define BUILD_O
@mkdir -p $(OBJS)
g++ $(FLAGS) $(CPPFLAGS) -c $< -o $@
endef
$(OBJS)/%.o : test/%.cpp
$(BUILD_O)
$(OBJS)/%.o : test/metrics/%.cpp
$(BUILD_O)
As an alternative to that, because you want all your objects to go into the same directory but find sources from different directories, you could use VPATH instead and write just a single pattern rule, like this:
VPATH = test test/metrics
$(OBJS)/%.o : %.cpp
@mkdir -p $(@D)
g++ $(FLAGS) $(CPPFLAGS) -c $< -o $@
I strongly urge you to rework your makefiles to use the standard variable names, though; use $(CXX)
, not g++
, for the C++ compiler name and $(CXXFLAGS)
, not $(FLAGS)
, for the C++ compiler options.
EDIT
If you need to customize flags, then the normal way to do this is either through target-specific variables, or through constructed macro names
Target-specific variables would look like this:
test: $(test_targets)
test: FLAGS += -Dtest
production: $(production_targets)
production: FLAGS += -Dproduction
then when you run make test
you'll get the -Dtest
added; when you run make production
you'll get the -Dproduction
added. There are issues here though: if you run make myfoo.o
then you won't get these added (see the documentation).
Constructed macro names would look like this:
test_FLAGS = -Dtest
production_FLAGS = -Dproduction
rootdir = $(firstword $(subst /, ,$1))
VPATH = test test/metrics production production/widgets
$(OBJS)/%.o : %.cpp
@mkdir -p $(@D)
g++ $(FLAGS) $(CPPFLAGS) $($(call rootdir,$(<D))_FLAGS) -c $< -o $@
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