2017-02-16 1 views
0

J'ai un binaire que j'ai besoin de construire plusieurs fois avec différents drapeaux de compilateur. Par conséquent, j'ai un Makefile qui dit quelque chose comme:Makefile cibles multiples à partir du même fichier source, avec différents drapeaux

OBJECTS_A := $(addprefix $(OBJFOLDER)/, $(SOURCES:.cpp=.a.o)) 
OBJECTS_B := $(addprefix $(OBJFOLDER)/, $(SOURCES:.cpp=.b.o)) 
OBJECTS_C := $(addprefix $(OBJFOLDER)/, $(SOURCES:.cpp=.c.o)) 

Je définis aussi une règle de changer les drapeaux pour chaque OBJECTS_x:

$(OBJECTS_B): DEFINES+=-D_B 
$(OBJECTS_C): DEFINES+=-D_C 

Et c'est là le problème se produit: Si je déclare la cibles séparément, en tant que:

$(OBJFOLDER)/%.a.o: %.cpp 
    $(COMPILER) $(CFLAGS) $(INCFOLDER) $(DEFINES) -c $< -o [email protected] 

$(OBJFOLDER)/%.b.o: %.cpp 
    $(COMPILER) $(CFLAGS) $(INCFOLDER) $(DEFINES) -c $< -o [email protected] 

$(OBJFOLDER)/%.c.o: %.cpp 
    $(COMPILER) $(CFLAGS) $(INCFOLDER) $(DEFINES) -c $< -o [email protected] 

Toutes les œuvres. Cependant, si je fusionne toutes les règles en une seule, seule la première est évaluée:

$(OBJFOLDER)/%.a.o $(OBJFOLDER)/%.b.o $(OBJFOLDER)/%.c.o: %.cpp 
    $(COMPILER) $(CFLAGS) $(INCFOLDER) $(DEFINES) -c $< -o [email protected] 

Ce que je reçois sur une marche à sec est que seulement $ (objFolder) /% objets ao sont construits, mais la règle de liaison. chaque binaire requiert ses objets (et les binaires b et c échouent donc à construire).

Des idées? Merci!

+0

Une règle de modèle avec plusieurs modèles cibles signifie exactement comme vous avez vécu: il attend un appel de la recette pour construire _tous_ les cibles . Il est utilisé lorsqu'un programme crée plusieurs fichiers de sortie. Voir https://www.gnu.org/software/make/manual/html_node/Pattern-Intro.html (dernier paragraphe) – MadScientist

Répondre

3

Vous pouvez y parvenir en utilisant secondary expansion:

.SECONDEXPANSION: 
$(OBJFOLDER)/%.o: $$(basename $$*).cpp 
     $(COMPILER) $(CFLAGS) $(INCFOLDER) $(DEFINES) -c $< -o [email protected] 

Notez que ce n'est pas une façon très idiomatiques de le faire, un plus combo d'habitude define/call/eval peut être utilisé pour générer des règles dans votre premier 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 [email protected] 

endef 

$(eval $(foreach variant,$(VARIANTS),$(call make_target,$(variant)))) 
+0

Pourquoi les affectations de variables spécifiques à la cible ne fonctionneront-elles plus? – MadScientist

+0

Mon mauvais, ça marche parfaitement bien, j'ai édité la réponse –

0

Une autre méthode consiste à créer des liens symboliques vers vos fichiers source et de compiler ceux avec des indicateurs différents. De cette façon, la même règle de modèle générique (OBJFOLDER)/%.o: %.cpp peut construire toutes vos cibles:

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 $< [email protected] 

%.b.cpp : %.cpp 
    ln -s $< [email protected] 

%.c.cpp : %.cpp 
    ln -s $< [email protected] 

$(OBJFOLDER)/%.o: %.cpp 
    $(COMPILER) $(CFLAGS) $(INCFOLDER) $(DEFINES) -c -o [email protected] $<