23

我是makefile的新手。我从“使用 GNU make 管理项目”一书中学习了 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。这是正确的吗?

任何帮助都会很棒。

4

3 回答 3

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

我会接受 Artyom 关于标志的建议并使用-O.

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

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

于 2009-04-30T17:47:18.370 回答