chronos
chronos

Reputation: 355

Makefile multiple targets from same source file, with different flags

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

Answers (2)

Maxim Egorushkin
Maxim Egorushkin

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

A. Monti
A. Monti

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

Related Questions