为 C++ 程序创建健壮的 Makefile

Posted

技术标签:

【中文标题】为 C++ 程序创建健壮的 Makefile【英文标题】:Creating a robust Makefile for C++ program 【发布时间】:2016-03-21 22:00:34 【问题描述】:

考虑以下微不足道的 Makefile。请注意,有两个类,每个类都有对应的 .h 和 .cpp 文件。

output: main.o class1.o class2.o
    g++ main.o class1.o class2.o -o output

main.o: main.cpp
    g++ -c main.cpp

class1.o: class1.cpp class1.h
    g++ -c class1.cpp

class2.o: class2.cpp class2.h
    g++ -c class2.cpp

clean:
    rm *.o output 

这个 Makefile 是否健壮?我怎样才能使它更健壮?有人可以提供这个 Makefile 的更强大的版本吗?它将在 64 位 Red Hat Linux 或 CentOS 机器上运行。

如果重要,我正在使用:

-gcc --version 4.8.4(来自 GNU 编译器集合)

-GDB版本:GNU gdb (Ubuntu 7.7.1 -0ubuntu5~14.04.2) 7.7.1

【问题讨论】:

您对“健壮”的理解是什么? Makefile 有一些缺陷(例如,无法设置强制和可选标志,没有自动依赖跟踪,没有 VPATH 构建)。 如果你使用 CMake,为什么还要有 Makefile?! @Biffen - 我必须在没有 CMake 的情况下将应用程序发送给其他人。 @ensc - 更强大 == 将在我的教授 Linux 机器上正常工作。我不知道这些东西是什么意思,但这个任务很快就要到期了。你能用这些更改编辑我的代码吗? 你的头文件不会被包含在多个地方吗? 【参考方案1】:

我不认为你原来的 makefile 离题太远了。我刚刚做了一些补充:

    添加了一个默认的all 目标 - 最好是明确的 在所有对 g++ 的调用中使用 CXXFLAGS 环境变量 如上所述,使 main.o 依赖于 class1.hclass2.h 指定cleanPHONY 目标只是为了安全起见,如果您添加名为clean 的构建工件

ALL := output

all : $(ALL) 

output: main.o class1.o class2.o
    g++ $(CXXFLAGS) main.o class1.o class2.o -o output

main.o: main.cpp class1.h class2.h
    g++ $(CXXFLAGS) -c main.cpp

class1.o: class1.cpp class1.h
    g++ $(CXXFLAGS) -c class1.cpp

class2.o: class2.cpp class2.h
    g++ $(CXXFLAGS) -c class2.cpp

.PHONY : clean

clean:
    rm *.o output 

【讨论】:

【参考方案2】:

我会写一些类似的东西

CXX = g++
# mandatory build flags
AM_CXXFLAGS = -Wall -W -std=gnu++11
# optional build flags
CXXFLAGS = -O2 -Werror

# mandatory link flags
AM_LDFLAGS = -Wl,-as-neeeded

output: main.o class1.o class2.o
    $CXX $AM_LDFLAGS $LDFLAGS $(filter %.o,$^) -o $@

%: %.cpp
    $CXX $AM_CXXFLAGS $CXXFLAGS $< -c -o $@

class1.o: class1.cpp class1.h
class2.o: class2.cpp class2.h

*FLAGS 遵循 automake 表示法:AM_* 表示强制标志,普通标志包含本地设置(例如调试或优化)。

通常也应该使用带有预处理器标志 (-I ...) 的 AM_CPPFLAGSCPPFLAGS,但我在这里省略了它们

output 目标可能也需要 $LIBS,此处已省略

依赖跟踪更加棘手,没有实现;您将不得不在这里使用-dM 编译器选项...

当您的程序仅包含列出的 5 个文件时,您可以编写

output_SOURCES = main.c class1.c class2.c class1.h class2.h

output: $output_SOURCES
        $CXX $AM_CXXFLAGS $CXXFLAGS $AM_LDFLAGS $LDFLAGS $(filter %.cpp,$^) -o $@ $LIBS

直接。

编辑:

对于自动依赖跟踪,你可以写

DEPGENFLAGS = \
    -MD -MF $@D/.$@F.d -MT '$@'

%: %.cpp
    $CXX $DEPGENFLAGS $AM_CXXFLAGS $CXXFLAGS $< -c -o $@

-include .deps.main.o.d
-include .deps.class1.o.d
-include .deps.class2.o.d

【讨论】:

【参考方案3】:

我怎样才能使它更健壮?

使用隐式规则,保持简单。

LDLIBS+=-lstdc++
output: main.o class1.o class2.o

clean:
    rm *.o output 

【讨论】:

这太短了!与给出的其他解决方案相比,此实现有什么缺点吗?

以上是关于为 C++ 程序创建健壮的 Makefile的主要内容,如果未能解决你的问题,请参考以下文章

C++ 断言

使用 const 提高函数的健壮性

如何在 C++ 中实现强大的数据持久层?

C++异常处理:掌握高效健壮代码的秘密武器

异常

健壮程序之--SQL优化