Reputation: 355
I have a binary that I need to build multiple times with different compiler flags. Therefore, I have a Makefile that states something like:
OBJECTS_A := $(addprefix $(OBJFOLDER)/, $(SOURCES:.cpp=.a.o))
OBJECTS_B := $(addprefix $(OBJFOLDER)/, $(SOURCES:.cpp=.b.o))
OBJECTS_C := $(addprefix $(OBJFOLDER)/, $(SOURCES:.cpp=.c.o))
I also define a rule to change the flags for each OBJECTS_x:
$(OBJECTS_B): DEFINES+=-D_B
$(OBJECTS_C): DEFINES+=-D_C
And this is where the problem happens: If I state the targets separately, as:
$(OBJFOLDER)/%.a.o: %.cpp
$(COMPILER) $(CFLAGS) $(INCFOLDER) $(DEFINES) -c $< -o $@
$(OBJFOLDER)/%.b.o: %.cpp
$(COMPILER) $(CFLAGS) $(INCFOLDER) $(DEFINES) -c $< -o $@
$(OBJFOLDER)/%.c.o: %.cpp
$(COMPILER) $(CFLAGS) $(INCFOLDER) $(DEFINES) -c $< -o $@
All works. However, if I merge all rules into one, only the first is evaluated:
$(OBJFOLDER)/%.a.o $(OBJFOLDER)/%.b.o $(OBJFOLDER)/%.c.o: %.cpp
$(COMPILER) $(CFLAGS) $(INCFOLDER) $(DEFINES) -c $< -o $@
What I get on a dry run is that only $(OBJFOLDER)/%.a.o objects are build, but on the linking rule each binary requires its objects (and b and c binaries fail to build, therefore).
Any ideas? Thank you!
Upvotes: 2
Views: 3995
Reputation: 136208
Another way is to create symlinks to your source files and compile those with different flags. This way the same one generic pattern rule (OBJFOLDER)/%.o: %.cpp
can build all of your targets:
OBJECTS_A := $(SOURCES:%.cpp=$(OBJFOLDER)/%.a.o)
OBJECTS_B := $(SOURCES:%.cpp=$(OBJFOLDER)/%.b.o)
OBJECTS_B := $(SOURCES:%.cpp=$(OBJFOLDER)/%.c.o)
$(OBJECTS_B): DEFINES+=-D_B
$(OBJECTS_C): DEFINES+=-D_C
%.a.cpp : %.cpp
ln -s $< $@
%.b.cpp : %.cpp
ln -s $< $@
%.c.cpp : %.cpp
ln -s $< $@
$(OBJFOLDER)/%.o: %.cpp
$(COMPILER) $(CFLAGS) $(INCFOLDER) $(DEFINES) -c -o $@ $<
Upvotes: 0
Reputation: 491
You can achieve this using secondary expansion :
.SECONDEXPANSION:
$(OBJFOLDER)/%.o: $$(basename $$*).cpp
$(COMPILER) $(CFLAGS) $(INCFOLDER) $(DEFINES) -c $< -o $@
Note that this is not a very idiomatic way of doing this, a more usual define
/ call
/ eval
combo can be used to generate rules as in your first solution :
VARIANTS=a b c
DEFINES_FOR_a=
DEFINES_FOR_b=-D_B
DEFINES_FOR_c=-D_C
define make_target =
$$(OBJFOLDER)/%.$(1).o: %.cpp
$$(COMPILER) $$(CFLAGS) $$(INCFOLDER) $$(DEFINES_FOR_$(1)) -c $$< -o $$@
endef
$(eval $(foreach variant,$(VARIANTS),$(call make_target,$(variant))))
Upvotes: 6