¿Cómo puedo configurar mi makefile para compilaciones de depuración y lanzamiento?
Tengo el siguiente makefile para mi proyecto, y me gustaría configurarlo para compilaciones de liberación y depuración. En mi código, tengo un montón de #ifdef DEBUG
macros en su lugar, por lo que es simplemente una cuestión de establecer esta macro y agregar 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 release/debug builds, quiero poder escribir make
y obtener una release build o make debug
y obtener una debug build, sin comentar manualmente las cosas en el makefile.
6 answers
Puede usar Valores de variable específicos de destino. 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 usar $(CXX) o CC(CC) en todos sus comandos de compilación.
Entonces, 'make debug' tendrá banderas adicionales como-DDEBUG y-g donde como 'make' no lo hará.
En una nota al margen, puede hacer que su Makefile sea mucho más conciso como otros posts habían sugerido.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-15 05:26:40
Si por configurar release / build, quiere decir que solo necesita una configuración por makefile, entonces es simplemente una cuestión y desacoplar CC y CFLAGS:
CFLAGS=-DDEBUG
#CFLAGS=-O2 -DNDEBUG
CC=g++ -g3 -gdwarf2 $(CFLAGS)
Dependiendo de si puedes usar gnu makefile, puedes usar 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 use:
make DEBUG=0
make DEBUG=1
Si necesita controlar ambas configuraciones al mismo tiempo, creo que es mejor tener directorios de compilación, y un directorio de compilación / config.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-30 15:06:03
Esta pregunta ha aparecido a menudo cuando se busca un problema similar, por lo que siento que se justifica una solución completamente implementada. Especialmente porque yo (y asumiría que otros) he luchado juntando todas las diversas respuestas.
A continuación se muestra un Makefile de ejemplo que soporta múltiples tipos de compilación en directorios separados. El ejemplo ilustrado muestra compilaciones de depuración y liberación.
Soporta ...
- directorios de proyectos separados para compilaciones específicas
- fácil selección de una compilación de destino predeterminada
- objetivo de preparación silenciosa para crear los directorios necesarios para construir el proyecto
- banderas de configuración del compilador específicas de compilación
- El método natural de GNU Make para determinar si el proyecto requiere una reconstrucción
- reglas de patrón en lugar del sufijo obsoleto reglas
#
# 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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-29 22:14:36
Tenga en cuenta que también puede simplificar su Makefile, 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 no tienes que repetir nombres de archivo por todas partes. Cualquier .los archivos l se pasarán a través de flex y gcc, cualquiera .los archivos y pasarán a través de bison y g++, y any .archivos cpp a través de just g++.
Simplemente enumere el.o archivos que espera terminar con, y Make hará el trabajo de averiguar qué reglas pueden satisfacer las necesidades...
Para que conste:
-
$@
Las nombre del archivo de destino (el anterior a los dos puntos) -
$<
El nombre del primer (o único) archivo de prerrequisitos (el primero después de los dos puntos) -
$^
Los nombres de todos los archivos de prerrequisitos (separados por espacio) $*
La raíz (el bit que coincide con el comodín%
en la definición de la regla.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-05 23:49:21
Puede tener una variable
DEBUG = 0
Entonces puedes usar una sentencia condicional
ifeq ($(DEBUG),1)
else
endif
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-03 15:54:42
Completando las respuestas anteriores... Necesita hacer referencia a las variables que define info 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-03 16:05:01