¿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.

Author: nbro, 2009-07-03

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.

 160
Author: David Lin,
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.

 37
Author: David Cournapeau,
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)
 33
Author: ffhaddad,
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.

 23
Author: Stobor,
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
 2
Author: Tiberiu,
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
 1
Author: Stobor,
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