【问题标题】:Creating a robust Makefile for C++ program为 C++ 程序创建健壮的 Makefile
【发布时间】: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 机器上正常工作。我不知道这些东西是什么意思,但这个任务很快就要到期了。你能用这些更改编辑我的代码吗?
  • 你的头文件不会被包含在多个地方吗?

标签: c++ linux gcc makefile


【解决方案1】:

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

  1. 添加了一个默认的all 目标 - 最好是明确的
  2. 在所有对 g++ 的调用中使用 CXXFLAGS 环境变量
  3. 如上所述,使 main.o 依赖于 class1.hclass2.h
  4. 指定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 
      

      【讨论】:

      • 这太短了!与给出的其他解决方案相比,此实现有什么缺点吗?
      猜你喜欢
      • 2015-01-28
      • 1970-01-01
      • 1970-01-01
      • 2010-12-24
      • 2020-02-08
      • 2015-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多