我怎样才能configuration我的生成文件的debugging和发布版本?

我有我的项目以下的生成文件,我想configuration它的发布和debugging版本。 在我的代码中,我有很多#ifdef DEBUGmacros,所以只需要设置这个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)