Search code examples
makefilebuildtargets

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!


Solution

  • 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))))