cmake 构建header/impl可选模块

ffvjumwh  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(113)

我有一个很大的遗留c++代码库,使用hpp/cpp文件中的头和实现。这需要仍然可用,以兼容旧的编译器。
示例文件

// myLib.hpp
int foo();

// myLib.cpp
#include "myLib.hpp"
int foo() { return 42; }

// main.cpp
#include "myLib.hpp"
int main() { return foo(); }

字符串
对于较新的编译器,我希望能够将特定的头文件编译成模块(例如“myModule”)。就像围绕hpp/cpp文件的 Package 器。这不应该是一个替代,因为一些依赖的翻译单元可能仍然使用#include "myLib.hpp",而其他人可能已经使用import myModule;
如果一个模块应该被构建和使用,可以通过一个CMake选项来选择,该选项被转换为一个预处理器宏,例如。

# CMakeLists.txt
option(CMAKE_USE_MODULES "Enable C++20 module usage" ON)

if(CMAKE_USE_MODULES)
    add_compile_definitions(USE_MODULES)
endif(CMAKE_USE_MODULES)


我的问题是模块接口及其实现应该如何实现?

// myLib.hpp
EXPORT int foo();

// myLib.cpp
#define EXPORT
#include "myLib.hpp"
int foo() { return 42; }

// myModule.cpp
export module myModule;
#define EXPORT export
#include "myLib.hpp"

// myModule_impl.cpp
module myModule;
#include "myLib.cpp"


其他翻译单元现在可以选择使用头或模块,例如。

// tu_alwaysHeader.cpp
#define EXPORT
#include "myLib.hpp"
int alwaysHeader() { return foo(); }

// tu_tryModuleOtherwiseHeader.cpp
#ifdef USE_MODULES
import myModule;
#else
#define EXPORT
#include "myLib.hpp"
#endif
int tryModuleOtherwiseHeader() { return foo(); }


另一个问题:CMake中的依赖关系应该如何表示?特别是myModule.cpp到myLib.hpp,myModule_impl.cpp到myLib.cpp?
godbolt上的最小示例。

xfb7svmp

xfb7svmp1#

这不应该是一个替代,因为一些依赖的翻译单元可能仍然使用#include "myLib.hpp",而其他的可能已经使用import myModule;
这是个问题
C++模块不仅仅是访问实体的一种替代方式。将实体声明/定义放在模块的范围内会改变该实体的性质。具体来说,它现在具有模块链接。
命名同一实体的两个声明必须在该实体的链接上达成一致。无论它们是在你的整个程序中声明的,而不仅仅是在一个文件中。
围绕这一点有几条规则,但它们几乎总是归结为同一件事:格式错误,不需要诊断。这意味着您的代码可以编译和链接,但接下来发生的事情是不可知的。它可能工作......直到它不工作。
一个库可以have a module and non-module build for itself。但是你必须把它们当作库的不同版本。不同的,* 不兼容的 * 版本。你程序中的所有代码都必须同意使用哪个版本。

相关问题