【问题标题】:Makefile optimisation of multiple targets多目标的Makefile优化
【发布时间】:2015-07-15 13:27:03
【问题描述】:

因此,作为我用 C++ 制作的一些工具的一部分,我希望能够单独测试每个工具。有多个带有多个测试文件的工具,因此我想要多个可执行文件作为我的最终结果。我希望 Makefile 的魔力能让我的生活更轻松。

这是我当前的 Makefile 模板:

# Compilation
CXX = g++
CXXFLAGS = -pedantic -Wall -c # -g -Wextra

all: lbLog lbString

lbLog:
    $(CXX) $(CXXFLAGS) 'src/lbLog.cpp' -o lbLog.o
    $(CXX) 'examples/lbLog_example.cpp' lbLog.o -o 'tests/lbLog_example'
    rm lbLog.o

lbString:
    $(CXX) $(CXXFLAGS) 'src/lbString.cpp' -o lbString.o
    $(CXX) 'examples/lbString_example.cpp' lbString.o -o 'tests/lbString_example'
    rm lbString.o

预期的文件结构是

  • 驱动程序示例文件位于“/examples”(.cpp)中
  • 源/工具 (.cpp) 位于“/src”中
  • “/include”中的标题
  • 在“/tests”中输出 exe

所以问题是,是否有优化 makefile 的方法,所以我可以虚拟地“设置并忘记”?我不想希望将每个新工具都添加到 Makefile 中。因为它是如此重复的模式,所以一定有办法让它变得更聪明。

【问题讨论】:

    标签: c++ c compilation makefile


    【解决方案1】:

    这根本不是一个合适的 makefile。它没有指定 make 可以利用的任何先决条件/目标对。

    要利用 make 为你做的事情,你需要更多这样的东西:

    # Compilation
    CXX = g++
    CXXFLAGS = -pedantic -Wall -c # -g -Wextra
    
    all: tests/lbLog_example tests/lbString_example
    
    lbLog.o: src/lbLog.cpp
        $(CXX) $(CXXFLAGS) $^ -o $@    
    
    tests/lbLog_example: examples/lbLog_example.cpp lbLog.o
        $(CXX) $^ -o $@
    
    lbString.o: src/lbString.cpp
        $(CXX) $(CXXFLAGS) $^ -o $@
    
    tests/lbString_example: examples/lbString_example.cpp lbString.o
        $(CXX) $^ -o $@
    

    这告诉 make 默认构建测试可执行文件,并且测试可执行文件依赖于顶级目标文件以及如何从它们各自的源构建目标文件。现在 make 知道它需要在其先决文件更改时重建目标文件,而不是其他情况(与您的原始文件相反,它总是重新编译所有内容)。

    您甚至可以像这样使用pattern rules 清理更多内容:

    # Compilation
    CXX = g++
    CXXFLAGS = -pedantic -Wall -c # -g -Wextra
    
    all: tests/lbLog_example tests/lbString_example
    
    lb%.o: src/lb%.cpp
        $(CXX) $(CXXFLAGS) $^ -o $@
    
    tests/lb%_example: examples/lb%_example.cpp lb%.o
        $(CXX) $^ -o $@
    

    如果您允许在src 目录中构建目标文件,您也可以完全删除lb%.o: src/lb%.cpp 规则。在examples 目录中构建测试可执行文件,我相信您也可以从tests/lb%_example: examples/lb%_example.cpp lb%.o 目标中删除$(CXX) $^ -o $@ 主体,我相信这最终会得到这个(未经测试的)makefile:

    # Compilation
    CXX = g++
    CXXFLAGS = -pedantic -Wall -c # -g -Wextra
    
    all: tests/lbLog_example tests/lbString_example
    
    tests/lb%_example: examples/lb%_example.cpp lb%.o
    

    最后一点有效(假设我没问题),因为 make 带有许多 built-in rules 用于常见的构建模式。

    【讨论】:

    • 我看到了我的“makefile”和真实的东西之间的区别。这更有意义,谢谢。但我想知道,在第二个示例中,是什么使它删除了目标文件?
    • make 有处理所谓的“中间文件”的特殊规则。如果文件X 将文件Y 列为先决条件并且文件Y 将源文件Z 作为先决条件,则make 知道它可以在需要时构建Y,并且知道Y 不会如果Z 没有更改,则更改它,以便在完成后删除Y。有关这方面的更多详细信息,请参阅Chains of Implicit Rules。 (假设你的意思是为什么你会在输出的末尾看到 make "run" rm lbString.o lbLog.。顺便说一句,它并没有真正运行它,只是告诉你它做了什么。)
    【解决方案2】:

    假设您可以确定从源代码生成工具的规则,请查看以下 make 函数:

    • patsubst
    • 通配符

    【讨论】:

    • 这充其量只是答案的一部分。
    猜你喜欢
    • 2018-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-17
    • 1970-01-01
    • 1970-01-01
    • 2019-01-14
    • 1970-01-01
    相关资源
    最近更新 更多