Как настроить мой файл для отладки и выпуска?
У меня есть следующий 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)
.