我解决了你的任务。以下是执行此操作的说明。我在 Win 10 64 位上使用 LLVM 12.0 的当前版本(取自 here)中的 CLang 执行此操作,我还安装了 MSVC 2019 v16.9.4 社区(取自 here)。
首先创建以下文件:
module.modulemap:
module std_mod {
requires cplusplus17
header "std_mod.hpp"
export *
}
std_mod.hpp:
#include <iostream>
#include <map>
#include <set>
#include <vector>
使用.cpp:
import std_mod;
int main() {
std::cout << "Hello, World!" << std::endl;
}
在上面的文件std_mod.hpp 中,您可以放置您需要的任何标准头文件。您应该将您在所有项目中使用的所有可能的 STD 标头都放入,以便能够在任何地方共享相同的预编译 STD 模块。
然后执行命令:
clang++ -### use.cpp -c -std=c++20 -m64 -g -O3 >use.txt 2>&1
在这里,您可以使用项目所需的任何选项,而不是 -std=c++20 -m64 -g -O3。每个预编译模块都应具有与其他 .cpp 文件相同的编译选项,以便能够链接到最终二进制文件中。
上面的命令将产生use.txt,其中包含您需要复制的选项。在此选项中,您应该删除 -emit-obj 选项、-o 选项(及其后的路径),同时删除 use.cpp。然后添加到这个命令选项字符串module.modulemap -o std_mod.pcm -emit-module -fmodules -fmodule-name=std_mod。在我的系统上,我得到了以下结果命令:
"D:\\bin\\llvm\\bin\\clang++.exe" "-cc1" module.modulemap -o std_mod.pcm -emit-module -fmodules -fmodule-name=std_mod "-triple" "x86_64-pc-windows-msvc19.28.29914" "-mincremental-linker-compatible" "--mrelax-relocations" "-disable-free" "-disable-llvm-verifier" "-discard-value-names" "-main-file-name" "use.cpp" "-mrelocation-model" "pic" "-pic-level" "2" "-mframe-pointer=none" "-fmath-errno" "-fno-rounding-math" "-mconstructor-aliases" "-munwind-tables" "-target-cpu" "x86-64" "-tune-cpu" "generic" "-gno-column-info" "-gcodeview" "-debug-info-kind=limited" "-resource-dir" "D:\\bin\\llvm\\lib\\clang\\12.0.0" "-internal-isystem" "D:\\bin\\llvm\\lib\\clang\\12.0.0\\include" "-internal-isystem" "d:\\bin2\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.28.29910\\include" "-internal-isystem" "d:\\bin2\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.28.29910\\atlmfc\\include" "-internal-isystem" "D:\\Windows Kits\\10\\Include\\10.0.19041.0\\ucrt" "-internal-isystem" "D:\\Windows Kits\\10\\include\\10.0.19041.0\\shared" "-internal-isystem" "D:\\Windows Kits\\10\\include\\10.0.19041.0\\um" "-internal-isystem" "D:\\Windows Kits\\10\\include\\10.0.19041.0\\winrt" "-O3" "-std=c++20" "-fdeprecated-macro" "-fdebug-compilation-dir" "D:\\t\\t4" "-ferror-limit" "19" "-fno-use-cxa-atexit" "-fms-extensions" "-fms-compatibility" "-fms-compatibility-version=19.28.29914" "-fdelayed-template-parsing" "-fno-implicit-modules" "-fcxx-exceptions" "-fexceptions" "-vectorize-loops" "-vectorize-slp" "-faddrsig" "-x" "c++"
如您所见,此命令包含包含的完整路径,它们是必需的。执行上面的命令,它会产生std_mod.pcm,你可以在你的项目中使用相同的编译选项。
为什么需要上面的长命令?因为只有通过-cc1 命令才能使用.modulemap 文件,该命令执行低级CLang 前端而不是简化的CLang 驱动程序(驱动程序没有-cc1 选项)。这个低级的前端可以做很多驱动程序做不到的技巧。
现在你可以通过下一个命令编译你的最终程序use.cpp,它执行import std_mod;:
clang++ use.cpp -o use.exe -std=c++20 -m64 -g -O3 -fmodule-file=std_mod.pcm
看到我添加了-fmodule-file=std_mod.pcm - 每个导入的模块都需要这样的选项。作为替代方案,您可以使用 -fprebuilt-module-path=<directory> 指定搜索所有预构建模块的位置。
不久前,我还创建了关于如何在 CLang 中使用标头制作模块的问答 here。
有关模块的更多说明,请参阅 CLang 的 Modules Doc 和 CommandLine Doc。
附言。为什么我在上面实施了相当长的解决方案?因为至少在 Windows 的 CLang 下一个简单的程序
import <iostream>;
int main() {}
无法编译,它显示use.cpp:1:8: error: header file <iostream> (aka 'd:\bin2\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\include\iostream') cannot be imported because it is not known to be a header unit。所以至少在 Win 上需要一个特殊的解决方案,import <header-name>; 的解决方案在这里不起作用。
所有通过import <header>; 或import "header"; 语法导入的头文件都应该有特殊的已编译头文件单元模块放置在特殊文件夹中以便能够使用。并且在 Win STD 标头上没有相应的已编译标头单元模块。同样在花了很多时间之后,我没有在 CLang 中找到如何在 Win 上创建这些所谓的标头单元的方法。只有上面的解决方案解决了我将标头作为模块导入的任务。