如何为调试和发布版本配置makefile ?

我的项目有以下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

澄清一下,当我说发布/调试构建时,我希望能够只键入make并获得发布构建或make debug并获得调试构建,而不需要手动注释掉makefile中的内容。

266570 次浏览

如果通过配置发布/构建,你的意思是每个makefile只需要一个配置,那么这只是一个解耦CC和CFLAGS的问题:

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

取决于你是否可以使用gnu makefile,你可以使用conditional来使它更漂亮,并从命令行控制它:

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


.o: .c
$(CC) -c $< -o $@ $(CFLAGS)

然后使用:

make DEBUG=0
make DEBUG=1

如果您需要同时控制两个配置,我认为最好有一个构建目录和一个构建目录/ config。

你可以有一个变量

DEBUG = 0

然后你可以使用条件语句

  ifeq ($(DEBUG),1)


else


endif

完成前面的答案。你需要引用你在命令中定义的变量info…

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更简单,在同一时间:

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将负责找出哪些规则可以满足需求……

郑重声明:

  • $@目标文件的名称(冒号之前的那个)

  • $<第一个(或唯一一个)先决条件文件的名称(冒号后的第一个文件)

  • $^所有先决条件文件的名称(空格分隔)

  • $*词干(规则定义中与%通配符匹配的位。

你可以使用目标特定的变量值。例子:

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更加简洁。

在搜索类似的问题时,这个问题经常出现,所以我觉得一个完全实现的解决方案是有必要的。特别是在我(我也会假设其他人)努力将所有不同的答案拼凑在一起之后。

下面是一个样例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中添加一些简单的内容,例如

ifeq ($(DEBUG),1)
OPTS = -g
endif

然后编译它进行调试

make DEBUG=1