如何让对.tpp模板实现文件的修改在Makefile中触发重新编译?

编程语言 2026-07-10

我正在使用 .tpp 文件来存放模板实现。

然而,修改一个 .tpp 文件不会触发重新编译,因为Make不会从 .tpp 源代码生成一个 .o 文件。

不过,这些改动会影响包含相应的 .hpp.cpp 文件的编译。

.tpp 文件发生变化时,如何让Make重新编译?

最小可复现示例

MRE.hpp

#pragma once
#include <iostream>

template <typename T>
class MRE {
    T a;
public:
    void write(std::ostream&);
};

#include "MRE.tpp"

MRE.tpp

template <typename T>
void MRE<T>::write(std::ostream& os) {
    os << "initial message";
}

TestMRE.cpp

#include "MRE.hpp"

int main() {
    MRE<int> m;
    m.write(std::cout);
    std::cout << std::endl;
}

Initial Makefile

TestMRE: TestMRE.o
    $(CXX) $(CXXFLAGS) $^ -o $@

%.o: %.cpp %.hpp
    $(CXX) $(CXXFLAGS) -c $< -o $@

Observed behavior

运行程序会输出:

初始信息

我把 "initial message" 改成 "final message",在 MRE.tpp 中。

运行make会输出:

make: 'TestMRE' 已是最新状态。

再次运行程序仍然输出:

初始信息

解决方案

.tpp 文件添加为对象文件的依赖:

# MRE.tpp is included by MRE.hpp, so it must be a dependency
# but must NOT be compiled directly.
TestMRE.o: TestMRE.cpp MRE.hpp MRE.tpp
    $(CXX) $(CXXFLAGS) -c TestMRE.cpp -o TestMRE.o

在这里,MRE.hppMRE.tpp 被列为依赖项,
因此当任意一个文件改变时,Make将重新编译 TestMRE.o

然而,它们并未出现在编译命令中,
因为模板实现文件(.tpp)是通过 .hpp.cpp 包含的。

在链接命令中使用 $^ 会错误地把 MRE.tpp 传递给编译器,因此链接规则必须只显式列出对象文件。

现在修改 MRE.tpp 将正确触发重新编译,程序输出:
最终信息

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章