【问题标题】:Simple makefile with release and debug builds - Best practices带有发布和调试版本的简单 makefile - 最佳实践
【发布时间】:2010-10-21 23:45:15
【问题描述】:

我是 makefile 的新手。我从“使用 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. 当使用 make 调用时,上面的 makefile 默认会调试构建。对于发布版本,make mode=release 是必需的。这是正确的方法吗?
  3. 提供给 g++ 的调试和发布编译器标志是否正确?对于调试,我使用 -g -Wall,对于发布,只使用 -Wall。对吗?

任何帮助都会很棒。

【问题讨论】:

  • 您是否计划发布您的软件源代码,包括 Makefile?或者你只是运送二进制文件? IE。除了您和您​​的团队之外,其他人会看到和使用这个 Makefile 吗?
  • 是的。我将发布源代码,因为这将是一个开源项目。

标签: c++ makefile g++


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

【讨论】:

  • “如果有缺陷,您最终可能会链接在调试模式下构建的目标文件以创建最终构建”。我不清楚那个说法。在进行发布构建之前,我将清理所有现有的目标文件并进行发布构建。这样我才能获得正确的发布文件链接。那样可以么?感谢您的回答。
  • 假设你运行'make',然后编辑一个源文件,然后运行'make mode=release';大多数目标文件都是在调试模式下编译的,即使它是“发布”版本。如果正如您所暗示的那样,您执行“make mode=release clean all”,那么您应该很好。这就是为什么我没有说“这是一个缺陷”;我指出这可能是一个需要注意的问题。 (此外,没有一个简单的解决方案 - 您需要一个更复杂的构建跟踪器来记录目标文件的创建方式,包括编译器选项。有关示例,请参见 'ccache' ccache.samba.org。)
【解决方案2】:

我建议以下模式:

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,因为如果发生崩溃,您可以获得更多信息。

【讨论】:

    【解决方案3】:

    我会听取 Artyom 关于标志的建议并使用-O

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

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

    【讨论】:

      猜你喜欢
      • 2012-11-09
      • 1970-01-01
      • 1970-01-01
      • 2014-05-01
      • 1970-01-01
      • 2012-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多