带有发布和调试版本的简单makefile - 最佳实践

时间:2009-04-27 04:11:14

标签: c++ makefile g++

我是makefiles的新手。我从“使用GNU make管理项目”一书中学习了makefile创建和其他相关概念。 makefile现在准备好了,我需要确保我创建的那个是好的。这是makefile

#Main makefile which does the build

#makedepend flags
DFLAGS = 

#Compiler flags
#if mode variable is empty, setting debug build mode
ifeq ($(mode),release)
   CFLAGS = -Wall
else
   mode = debug
   CFLAGS = -g -Wall
endif

CC = g++
PROG = fooexe

#each module will append the source files to here
SRC := main.cpp

#including the description
include bar/module.mk
include foo/module.mk

OBJ := $(patsubst %.cpp, %.o, $(filter %.cpp,$(SRC)))

.PHONY:all
all: information fooexe

information:
ifneq ($(mode),release)
ifneq ($(mode),debug)
    @echo "Invalid build mode." 
    @echo "Please use 'make mode=release' or 'make mode=debug'"
    @exit 1
endif
endif
    @echo "Building on "$(mode)" mode"
    @echo ".........................."

#linking the program
fooexe: $(OBJ)
    $(CC) -o $(PROG) $(OBJ)

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

depend:
    makedepend -- $(DFLAGS) -- $(SRC)

.PHONY:clean
clean:
    find . -name "*.o" | xargs rm -vf
    rm -vf fooexe

问题

  1. 上面给出的makefile适用于发布和调试版本。但它的格式是否正确?或者你看到有什么缺陷吗?
  2. 上面的makefile在使用 make 调用时默认调试构建。对于发布版本,需要 make mode = release 。这是正确的做法吗?
  3. 提供给g ++的调试和发布编译器标志是否正确?对于调试,我使用 -g -Wall ,对于发布,只需 -Wall 。这是对的吗?
  4. 任何帮助都会很棒。

3 个答案:

答案 0 :(得分:13)

  1. 这是一种合理的格式。它与GNU Make特别相关,但如果您选择在每个平台上使用GNU Make,那么这是一个相对较小的问题。
    • 如果存在缺陷,那么最终可能会链接在调试模式下构建的目标文件以创建最终版本。
    • 有些人可能认为'mode = release'选项是非标准的;他们是对的,但我没有一个标准的选择。你只需要知道你的约定可能不适合每个人(但它没有 - 它只需要适合你和你的用户)。
  2. 默认情况下构建调试版本可能是明智的 - 并且比默认构建版本构建更明智。
  3. 删除发布版本的-g标志并不会自动坏,但如果您的代码产生核心转储,则如果程序文件包含调试信息,则更容易构成核心转储的头部或尾部。调试信息的主要成本是程序文件中不需要加载到系统内存中的额外部分 - 运行时成本很小。
    • 您应该考虑是否在其中包含优化标志。使用GCC工具集,您可以同时使用-g-O。调试优化代码更加困难,但它可以为您提供(通常很重要的)性能优势。

答案 1 :(得分:11)

我建议采用以下模式:

for debugger: -O0 -g -Wall
for development and internal release: -O2 -g -Wall
for release outside the company: -O2 -Wall

理由:

  • 在“生产模式”中开发和测试代码非常重要。你可以找到 在某些情况下,代码在优化模式下没有优化崩溃的情况下工作,因为 您的代码中的错误。 (相信我发生了很多事情) - 所以使用-O2
  • 在大多数情况下,即使使用优化代码,您仍然可以很好地调试,因此请添加-g。但是,如果在这种模式下很难找到错误,您可以使用-O0编译调试器
  • 只有在代码中包含调试信息时遇到问题,才应删除-g。在生产环境中使用-g代码是个好主意,因为如果某些内容崩溃,您可以获得更多信息。

答案 2 :(得分:3)

我会采用Artyom关于旗帜的建议并使用-O

我的主要建议是将默认模式设为“发布”。公司外部的任何用户都不会知道您的make mode=release约定,其中99.99%会希望将其构建用于发布。

我喜欢你在所有模式中都有-Wall。如果你想变得非常迂腐...... -Wall -std=c++98 -pedantic -Wextra -Wconversion是一个好的开始。如果你坚持使用g ++,那么-std = c ++ 98可能就没有必要了,但如果你有任何可移植性的幻想,你就会想要它。