最后我设法解决了上面的几乎任务。
以下说明适用于 Windows 64 位、LLVM 12.0 版本的最新 CLang(您可以在此处获取)和最新的 MSVC Community Build Tools 2019 v16.9.4(您可以从此处获取)。
我解决的任务不是完全针对标头单元,而是针对标头模块,它们的行为几乎相同,它们的用法没有区别。
玩具示例文件如下:
module.modulemap:
module mod {
requires cplusplus17
header "mod.hpp"
export *
}
模组.hpp:
#include <iostream>
使用.cpp:
import mod;
int main() {
std::cout << "Hello, world!" << std::endl;
}
我使用了接下来的 3 个命令:
clang++.exe -cc1 module.modulemap -o prebuilt/mod.pcm -emit-module -fmodules -fmodule-name=mod -std=c++20 ^
-internal-isystem "d:\\bin2\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.28.29910\\include" ^
-internal-isystem "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.19041.0\\ucrt" ^
-debug-info-kind=limited -fms-extensions -fms-compatibility -fms-compatibility-version=19.28 -xc++ ^
-fmath-errno -fexceptions -fcxx-exceptions -triple x86_64-pc-windows-msvc || exit /b
clang++.exe -cc1 -emit-obj use.cpp -fmodule-file=prebuilt/mod.pcm -std=c++20 ^
-internal-isystem "d:\\bin2\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.28.29910\\include" ^
-internal-isystem "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.19041.0\\ucrt" ^
-debug-info-kind=limited -fms-extensions -fms-compatibility -fms-compatibility-version=19.28 -xc++ ^
-fmath-errno -fexceptions -fcxx-exceptions -triple x86_64-pc-windows-msvc || exit /b
clang++.exe use.o -o use.exe || exit /b
这一切都没有错误。您可以看到包含标准库目录的完整路径,这些路径特定于我的系统。这是必需的,因为在我使用的命令中,我使用-cc1
了启用低级 CLang 前端而不是简化驱动程序的选项,这个前端需要很多低级选项才能工作。
您可以通过执行获得所有选项clang++ -### use.cpp
,这将转储以控制系统所需的所有选项。
以上命令只能在-cc1
前端使用,驱动不支持模块映射文件。
实际上,在第二个命令上面的这三个命令中,可以简化,编译目标文件不需要低级前端。但是只有在第一个命令具有命令获得的默认参数的情况下才能简化clang -###
,那么第二个命令可以简写为clang++ use.cpp -o use.o -c -std=c++20 -fmodule-file=prebuilt/mod.pcm
。
这些命令的结果use.o
是在几分之一秒内编译。众所周知,iostream
编译需要大量时间。非常快速的编译use.o
意味着我们正确使用了模块并提高了我们的速度。
为什么我首先想要标题单元?为了能够升级我的旧代码,只需使用导入自动替换常规的旧式包含,从而大大缩短编译时间。这种更换仅适用于接头单元或接头模块。据我所知,常规模块无法导出其他完整标题。
有关模块的更多说明,请参阅 CLang 的Modules Doc和CommandLine Doc。