我怎样才能configuration我的生成文件的debugging和发布版本?
我有我的项目以下的生成文件,我想configuration它的发布和debugging版本。 在我的代码中,我有很多#ifdef DEBUG
macros,所以只需要设置这个macros并将-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
只是为了澄清,当我说发布/debugging构build时,我希望能够键入make
并获得一个发布版本或make debug
并得到一个debugging版本,而无需手动注释在makefile中的东西。
您可以使用特定于目标的variables值 。 例:
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更加简洁,像其他职位build议。
如果通过configure release / build,你的意思是每个makefile只需要一个configuration,那么这只是一个简单的问题,并且解耦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
如果你需要同时控制两个configuration,我认为最好是有构build目录和一个构build目录/configuration。
这个问题在寻找类似问题时经常出现,所以我觉得有一个完全实现的解决scheme是有必要的。 尤其是因为我(我会假设其他人)一直在努力拼凑所有各种答案。
下面是一个示例Makefile,它支持多个构buildtypes在不同的目录中。 所示的例子显示了debugging版本和发布版本。
支持…
- 单独的项目目录为特定版本
- 轻松select默认目标版本
- 无声的准备目标来创build项目所需的目录
- 编译特定的编译器configuration标志
- GNU Make确定项目是否需要重build的自然方法
- 模式规则而不是过时的后缀规则
# # 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更简单,同时:
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将确定哪些规则可以满足需求。
作为logging:
-
$@
目标文件的名称(冒号前面的那个) -
$<
第一个(或唯一的)必备文件的名称(冒号后的第一个) -
$^
所有先决条件文件的名称(空格分隔) -
$*
词干(在规则定义中与%
通配符匹配的位。
我同意@davidlin,使用目标特定的variables来为每个configuration设置不同的标志。 但是,您可能还希望将输出文件放在不同的目录中,以便您可以构build不同的configuration,而无需重build所有内容。 用@ davidlin的例子,你可以这样做:
debug: CONFIG=debug debug: executable executable: output/$(CONFIG)/myprog # Always use "$@" when referring to the target file. output/$(CONFIG)/myprog: ... $(CXX) ... -o $@
你可以有一个variables
DEBUG = 0
那么你可以使用一个条件语句
ifeq ($(DEBUG),1) else endif
从早期完成答案…您需要引用您在命令中定义信息的variables…
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
ifeq (DEBUG, 1)
应该replace为ifeq ($(DEBUG), 1)
。