Comment puis-je configurer mon makefile pour les versions de débogage et de publication?

J’ai le fichier makefile suivant pour mon projet et j’aimerais le configurer pour les versions release et debug. Dans mon code, j’ai beaucoup de macros #ifdef DEBUG en place, il suffit donc de définir cette macro et d’append les -g3 -gdwarf2 aux compilateurs. Comment puis-je faire ceci?

 $(CC) = g++ -g3 -gdwarf2 $(cc) = gcc -g3 -gdwarf2 all: executable executable: CommandParser.tab.o CommandParser.yy.o Command.o g++ -g -o output CommandParser.yy.o CommandParser.tab.o Command.o -lfl CommandParser.yy.o: CommandParser.l flex -o CommandParser.yy.c CommandParser.l gcc -g -c CommandParser.yy.c CommandParser.tab.o: CommandParser.y bison -d CommandParser.y g++ -g -c CommandParser.tab.c Command.o: Command.cpp g++ -g -c Command.cpp clean: rm -f CommandParser.tab.* CommandParser.yy.* output *.o 

Juste pour clarifier, quand je dis que les versions release / debug, je veux juste pouvoir taper make et obtenir une version build ou make debug et obtenir une version de débogage, sans commenter manuellement les choses dans le makefile.

Vous pouvez utiliser des valeurs de variable spécifiques à la cible . Exemple:

 CXXFLAGS = -g3 -gdwarf2 CCFLAGS = -g3 -gdwarf2 all: executable debug: CXXFLAGS += -DDEBUG -g debug: CCFLAGS += -DDEBUG -g debug: executable executable: CommandParser.tab.o CommandParser.yy.o Command.o $(CXX) -o output CommandParser.yy.o CommandParser.tab.o Command.o -lfl CommandParser.yy.o: CommandParser.l flex -o CommandParser.yy.c CommandParser.l $(CC) -c CommandParser.yy.c 

N’oubliez pas d’utiliser $ (CXX) ou $ (CC) dans toutes vos commandes de compilation.

Ensuite, “make debug” aura des drapeaux supplémentaires comme -DDEBUG et -g où “make” ne le sera pas.

Sur une note de côté, vous pouvez rendre votre Makefile beaucoup plus concis, comme d’autres postes l’ont suggéré.

Si par configure release / build, vous voulez dire que vous n’avez besoin que d’une seule configuration par makefile, alors il s’agit simplement de découpler les CC et les CFLAGS:

 CFLAGS=-DDEBUG #CFLAGS=-O2 -DNDEBUG CC=g++ -g3 -gdwarf2 $(CFLAGS) 

Selon que vous pouvez utiliser le makefile de gnu, vous pouvez utiliser le conditionnel pour le rendre un peu plus sophistiqué, et le contrôler à partir de la ligne de commande:

 DEBUG ?= 1 ifeq ($(DEBUG), 1) CFLAGS =-DDEBUG else CFLAGS=-DNDEBUG endif .o: .c $(CC) -c $< -o $@ $(CFLAGS) 

puis utilisez:

 make DEBUG=0 make DEBUG=1 

Si vous devez contrôler les deux configurations en même temps, je pense qu'il est préférable d'avoir des répertoires de construction et un répertoire de compilation / config.

Cette question est souvent apparue lors de la recherche d’un problème similaire. Je pense donc qu’une solution complète est justifiée. Surtout que (et je suppose que j’en assumerais d’autres) j’ai eu du mal à rassembler toutes les différentes réponses ensemble.

Vous trouverez ci-dessous un exemple de Makefile qui prend en charge plusieurs types de construction dans des répertoires distincts. L’exemple illustré montre les versions de débogage et de publication.

Les soutiens …

  • répertoires de projets distincts pour des builds spécifiques
  • sélection facile d’une cible par défaut
  • cible de préparation silencieuse pour créer des répertoires nécessaires à la construction du projet
  • indicateurs de configuration du compilateur spécifiques à la construction
  • La méthode naturelle de GNU Make pour déterminer si le projet nécessite une reconstruction
  • règles de modèle plutôt que les règles de suffixe obsolètes

 # # Comstackr flags # CC = gcc CFLAGS = -Wall -Werror -Wextra # # Project files # SRCS = file1.c file2.c file3.c file4.c OBJS = $(SRCS:.c=.o) EXE = exefile # # Debug build settings # DBGDIR = debug DBGEXE = $(DBGDIR)/$(EXE) DBGOBJS = $(addprefix $(DBGDIR)/, $(OBJS)) DBGCFLAGS = -g -O0 -DDEBUG # # Release build settings # RELDIR = release RELEXE = $(RELDIR)/$(EXE) RELOBJS = $(addprefix $(RELDIR)/, $(OBJS)) RELCFLAGS = -O3 -DNDEBUG .PHONY: all clean debug prep release remake # Default build all: prep release # # Debug rules # debug: $(DBGEXE) $(DBGEXE): $(DBGOBJS) $(CC) $(CFLAGS) $(DBGCFLAGS) -o $(DBGEXE) $^ $(DBGDIR)/%.o: %.c $(CC) -c $(CFLAGS) $(DBGCFLAGS) -o $@ $< # # Release rules # release: $(RELEXE) $(RELEXE): $(RELOBJS) $(CC) $(CFLAGS) $(RELCFLAGS) -o $(RELEXE) $^ $(RELDIR)/%.o: %.c $(CC) -c $(CFLAGS) $(RELCFLAGS) -o $@ $< # # Other rules # prep: @mkdir -p $(DBGDIR) $(RELDIR) remake: clean all clean: rm -f $(RELEXE) $(RELOBJS) $(DBGEXE) $(DBGOBJS) 

Notez que vous pouvez également simplifier votre Makefile en même temps:

 DEBUG ?= 1 ifeq (DEBUG, 1) CFLAGS =-g3 -gdwarf2 -DDEBUG else CFLAGS=-DNDEBUG endif CXX = g++ $(CFLAGS) CC = gcc $(CFLAGS) EXECUTABLE = output OBJECTS = CommandParser.tab.o CommandParser.yy.o Command.o LIBRARIES = -lfl all: $(EXECUTABLE) $(EXECUTABLE): $(OBJECTS) $(CXX) -o $@ $^ $(LIBRARIES) %.yy.o: %.l flex -o $*.yy.c $< $(CC) -c $*.yy.c %.tab.o: %.y bison -d $< $(CXX) -c $*.tab.c %.o: %.cpp $(CXX) -c $< clean: rm -f $(EXECUTABLE) $(OBJECTS) *.yy.c *.tab.c 

Maintenant, vous n'avez pas à répéter les noms de fichiers partout. Tous les fichiers .l seront transmis via flex et gcc, tous les fichiers .y seront transmis via bison et g ++, et tous les fichiers .cpp via g ++.

Il suffit de lister les fichiers .o auxquels vous vous attendez et Make fera le travail pour déterminer quelles règles peuvent satisfaire les besoins ...

pour le compte rendu:

  • $@ Le nom du fichier cible (celui précédant les deux points)

  • $< Le nom du premier (ou du seul) fichier prérequirejs (le premier après les deux points)

  • $^ Les noms de tous les fichiers prérequirejs (espace séparé)

  • $* Le radical (le bit qui correspond au caractère générique % dans la définition de la règle.

vous pouvez avoir une variable

 DEBUG = 0 

alors vous pouvez utiliser une déclaration conditionnelle

  ifeq ($(DEBUG),1) else endif 

Compléter les réponses de plus tôt … Vous devez référencer les variables que vous définissez dans vos commandes …

 DEBUG ?= 1 ifeq (DEBUG, 1) CFLAGS =-g3 -gdwarf2 -DDEBUG else CFLAGS=-DNDEBUG endif CXX = g++ $(CFLAGS) CC = gcc $(CFLAGS) all: executable executable: CommandParser.tab.o CommandParser.yy.o Command.o $(CXX) -o output CommandParser.yy.o CommandParser.tab.o Command.o -lfl CommandParser.yy.o: CommandParser.l flex -o CommandParser.yy.c CommandParser.l $(CC) -c CommandParser.yy.c CommandParser.tab.o: CommandParser.y bison -d CommandParser.y $(CXX) -c CommandParser.tab.c Command.o: Command.cpp $(CXX) -c Command.cpp clean: rm -f CommandParser.tab.* CommandParser.yy.* output *.o