如何让对.tpp模板实现文件的修改在Makefile中触发重新编译?
我正在使用 .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.hpp 和 MRE.tpp 被列为依赖项,
因此当任意一个文件改变时,Make将重新编译 TestMRE.o。
然而,它们并未出现在编译命令中,
因为模板实现文件(.tpp)是通过 .hpp 被 .cpp 包含的。
在链接命令中使用 $^ 会错误地把 MRE.tpp 传递给编译器,因此链接规则必须只显式列出对象文件。
现在修改 MRE.tpp 将正确触发重新编译,程序输出:
最终信息
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。