내 프로젝트에 다음과 같은 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
명확히하기 위해 릴리스 / 디버그 빌드를 말할 때 makefile의 내용을 수동으로 주석 처리하지 않고 make
릴리스 빌드를 입력 하고 make debug
디버그 빌드를 얻을 수 있기를 원합니다 .
답변
대상별 변수 값을 사용할 수 있습니다 . 예:
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’에는 ‘make’가 아닌 -DDEBUG 및 -g와 같은 추가 플래그가 있습니다.
참고로, 다른 게시물에서 제안한 것처럼 Makefile을 훨씬 간결하게 만들 수 있습니다.
답변
이 질문은 비슷한 문제를 검색 할 때 자주 나타 났으므로 완전히 구현 된 솔루션이 필요하다고 생각합니다. 특히 나는 (그리고 다른 사람들을 가정 할 것이므로) 모든 다양한 답을 하나로 묶는 데 어려움을 겪었다.
다음은 별도의 디렉토리에서 여러 빌드 유형을 지원하는 샘플 Makefile입니다. 그림은 디버그 및 릴리스 빌드를 보여줍니다.
지원 …
- 특정 빌드를위한 별도의 프로젝트 디렉토리
- 기본 대상 빌드를 쉽게 선택
- 프로젝트 준비에 필요한 디렉토리를 작성하기위한 자동 준비 대상
- 빌드 특정 컴파일러 구성 플래그
- 프로젝트를 다시 빌드해야하는지 결정하는 GNU Make의 자연스러운 방법
- 더 이상 사용되지 않는 접미사 규칙이 아닌 패턴 규칙
#
# 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)
답변
릴리스 / 빌드를 구성한다고해서 makefile 당 하나의 구성 만 필요하면 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 $@ $(CFLAGS)
다음을 사용하십시오.
make DEBUG=0
make DEBUG=1
두 구성을 동시에 제어 해야하는 경우 빌드 디렉토리와 하나의 빌드 디렉토리 / 구성을 갖는 것이 좋습니다.
답변
동시에 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 $@ $^ $(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가 어떤 규칙이 요구를 충족시킬 수 있는지 알아내는 작업을 수행합니다 …
기록을 위해 :
-
$@
대상 파일의 이름 (콜론 앞의 이름) -
$<
첫 번째 (또는 유일한) 전제 조건 파일의 이름 (콜론 다음의 첫 번째 파일) -
$^
모든 전제 조건 파일 이름 (공백으로 구분) -
$*
스템 (%
규칙 정의에서 와일드 카드 와 일치하는 비트)
답변
당신은 변수를 가질 수 있습니다
DEBUG = 0
그런 다음 조건문을 사용할 수 있습니다
ifeq ($(DEBUG),1)
else
endif
답변
이전 답변을 완료하는 중 … 명령에서 정보를 정의하는 변수를 참조해야합니다 …
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
답변
Makefile에 간단한 것과 같은 것을 추가 할 수도 있습니다.
ifeq ($(DEBUG),1)
OPTS = -g
endif
그런 다음 디버깅을 위해 컴파일하십시오.
make DEBUG=1