¿Cómo puedo configurar mi makefile para depurar y las versiones de lanzamiento?

StackOverflow https://stackoverflow.com/questions/1079832

  •  22-08-2019
  •  | 
  •  

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.

¿Fue útil?

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top