¿Cómo puedo configurar mi makefile para depurar y las versiones de lanzamiento?
Pregunta
Tengo el siguiente makefile para mi proyecto, y me gustaría configurarlo para la liberación y versiones de depuración. En mi código, tengo un montón de macros #ifdef DEBUG
en su lugar, por lo que es simplemente una cuestión de establecer esta macro y la adición de las banderas -g3 -gdwarf2
a los compiladores. ¿Cómo puedo hacer esto?
$(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
Solo para aclarar, cuando digo liberación / versiones de depuración, quiero ser capaz de simplemente escribir make
y obtener una versión de lanzamiento o make debug
y obtener una versión de depuración, sin comentar manualmente las cosas en el makefile.
Solución
Puede utilizar valores de las variables específicas de la diana . Ejemplo:
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
Recuerde que debe utilizar $ (CXX) o $ (CC) en todos sus comandos de compilación.
A continuación, 'hacer debug' tendrá banderas adicionales como -DDEBUG y -g donde como 'hacer' no lo hará.
En una nota lateral, usted puede hacer su Makefile mucho más concisa como habían sugerido otros mensajes.
Otros consejos
Si por la liberación de configuración / construcción, que quiere decir que sólo necesita un config por makefile, entonces es simplemente una cuestión y desacoplamiento CC y CFLAGS:
CFLAGS=-DDEBUG
#CFLAGS=-O2 -DNDEBUG
CC=g++ -g3 -gdwarf2 $(CFLAGS)
En función de si se puede utilizar makefile GNU, puede utilizar condicional para hacer esto un poco más elegante, y controlarlo desde la línea de comandos:
DEBUG ?= 1
ifeq ($(DEBUG), 1)
CFLAGS =-DDEBUG
else
CFLAGS=-DNDEBUG
endif
.o: .c
$(CC) -c $< -o $@ $(CFLAGS)
y luego usar:
make DEBUG=0
make DEBUG=1
Si necesita controlar ambas configuraciones, al mismo tiempo, creo que es mejor tener directorios de construcción, y una carpeta de compilación / config.
Esta cuestión ha aparecido con frecuencia en la búsqueda de un problema similar, así que me siento una solución totalmente implementado está garantizado. Sobre todo porque yo (y yo supongo que otros) han luchado reconstruyendo todas las diversas respuestas juntos.
A continuación se muestra un Makefile que soporta múltiples tipos de construcción en directorios separados. El ejemplo ilustrado muestra de depuración y liberación construye.
Soporta ...
- directorios de proyectos específicos separados para construye
- selección fácil de construir un destino predeterminado
- target preparación silenciosa para crear los directorios necesarios para la construcción del proyecto
- construir específica banderas de configuración del compilador
- método natural GNU de Marca de determinar si el proyecto requiere una reconstrucción
- reglas de patrón en lugar de las reglas de sufijo obsoletos
#
# Compiler 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)
Tenga en cuenta que también puede hacer su Makefile más simple, al mismo tiempo:
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
Ahora usted no tiene que repetir los nombres de archivos por todo el lugar. Cualquier archivo .L se van pasando a través de la flexión y gcc, los archivos .y se van pasando a través de bisontes y g ++, y cualquier archivo .cpp través acaba g ++.
Basta con enumerar los archivos .o que espera terminar con, y hacer va a hacer el trabajo de averiguar qué reglas se pueden satisfacer las necesidades ...
para el registro:
-
$@
El nombre del archivo de destino (el que antes de que el colon) -
$<
El nombre de la primera (o única) prerrequisito archivo (el primero uno después del colon) -
$^
Los nombres de todos los archivos de prerrequisitos (separadas por espacios) -
$*
El tallo (el bit que coincide con el comodín%
en la definición de la regla.
puede tener una variable
DEBUG = 0
A continuación, se puede utilizar una sentencia condicional
ifeq ($(DEBUG),1)
else
endif
Completar las respuestas de antes ... Es necesario hacer referencia a las variables que se definen información en sus comandos ...
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