Как настроить мой файл для отладки и выпуска?

У меня есть следующий makefile для моего проекта, и я бы хотел настроить его для выпуска и отладки. В моем коде у меня есть много макросов #ifdef DEBUG, поэтому просто вопрос об установке этого макроса и добавлении флагов -g3 -gdwarf2 к компиляторам. Как я могу это сделать?

$(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

Просто, чтобы уточнить, когда я говорю о выпуске/debug-сборках, я хочу иметь возможность просто набирать make и получать сборку релизов или make debug и получать отладочную сборку без ручного комментирования вещей в make файле.

Ответ 1

Вы можете использовать значения переменных для конкретных целей. Пример:

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

Не забудьте использовать $(CXX) или $(CC) во всех ваших компилируемых командах.

Затем "make debug" будет иметь дополнительные флаги, такие как -DDEBUG и -g, где "make" не будет.

С другой стороны, вы можете сделать свой Makefile намного более лаконичным, как предполагали другие сообщения.

Ответ 2

Если с помощью configure release/сборки вы имеете в виду, что вам нужен только один конфиг для make файла, тогда это просто вопрос и развязка CC и CFLAGS:

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

В зависимости от того, можно ли использовать файл gnu makefile, вы можете использовать условный код, чтобы сделать это немного более интересным и управлять им из командной строки:

DEBUG ?= 1
ifeq ($(DEBUG), 1)
    CFLAGS =-DDEBUG
else
    CFLAGS=-DNDEBUG
endif

.o: .c
    $(CC) -c $< -o [email protected] $(CFLAGS)

а затем используйте:

make DEBUG=0
make DEBUG=1

Если вам нужно одновременно управлять обеими конфигурациями, я считаю, что лучше иметь каталоги сборки и один каталог /config сборки.

Ответ 3

Этот вопрос часто возникал при поиске аналогичной проблемы, поэтому я считаю, что полностью реализованное решение оправдано. Тем более, что я (и я предполагал, что другие) боролся с тем, чтобы собрать все разные ответы.

Ниже приведен пример файла Makefile, который поддерживает несколько типов сборки в отдельных каталогах. В показанном примере показаны сборки отладки и выпуска.

Поддержка...

  • отдельные каталоги проектов для конкретных построек
  • простой выбор целевой сборки по умолчанию
  • тихая предварительная цель для создания каталогов, необходимых для создания проекта
  • флаги конфигурации компилятора, специфичные для сборки
  • GNU Сделать естественный метод определения, требует ли проект перестроить
  • правила шаблонов, а не устаревшие правила суффикса

#
# 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 [email protected] $<

#
# Release rules
#
release: $(RELEXE)

$(RELEXE): $(RELOBJS)
    $(CC) $(CFLAGS) $(RELCFLAGS) -o $(RELEXE) $^

$(RELDIR)/%.o: %.c
    $(CC) -c $(CFLAGS) $(RELCFLAGS) -o [email protected] $<

#
# Other rules
#
prep:
    @mkdir -p $(DBGDIR) $(RELDIR)

remake: clean all

clean:
    rm -f $(RELEXE) $(RELOBJS) $(DBGEXE) $(DBGOBJS)

Ответ 4

Обратите внимание, что вы также можете сделать свой Makefile более простым, в то же время:

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 [email protected] $^ $(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

Теперь вам не нужно повторять имена файлов повсюду. Любые файлы .l будут переданы через flex и gcc, любые файлы .y будут переданы через bison и g++, а любые файлы .cpp через g++.

Просто перечислите файлы .o, которые вы ожидаете, и Make сделают работу по выяснению, какие правила могут удовлетворить потребности...

для записи:

  • [email protected] Имя целевого файла (один перед двоеточием)

  • $< Имя первого (или только) обязательного файла (первый после двоеточия)

  • $^ Имена всех необходимых файлов (разделенных пробелами)

  • $* Шток (бит, который соответствует шаблону % в определении правила.

Ответ 5

Я согласен с @davidlin, используйте целевые переменные для установки разных флагов для каждой конфигурации. Тем не менее, вы, вероятно, также захотите разместить ваши выходные файлы в отдельных каталогах, чтобы вы могли создавать разные конфигурации без восстановления всего. Используя пример @davidlin, вы можете сделать:

debug: CONFIG=debug

debug: executable

executable: output/$(CONFIG)/myprog

# Always use "[email protected]" when referring to the target file.
output/$(CONFIG)/myprog: ... 
        $(CXX) ... -o [email protected]

Ответ 6

у вас может быть переменная

DEBUG = 0

то вы можете использовать условный оператор

  ifeq ($(DEBUG),1)

  else

  endif

Ответ 7

Завершение ответов ранее... Вам нужно ссылаться на переменные, которые вы определяете в своих командах...

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

Ответ 8

ifeq (DEBUG, 1) следует заменить на ifeq ($(DEBUG), 1).