如何在 CLang C++ 下 compile/use header 单元模块?
How to compile/use header unit modules under CLang C++?
文档中说 CLang 中的模块支持是部分的。我在最近发布的 LLVM 12.0.Windows 64 位下使用 CLang。
我成功地使用了常规模块(您通过 import modulename;
导入)。
但我还没有设法创建和使用 header 单元模块,那些你通过 import "header.hpp";
导入的模块。你能用例子建议如何做到这一点吗?
为了尝试 header 个单位,我创建了下一个玩具文件:
hello.hpp:
#include <vector>
use.cpp:
import "hello.hpp";
int main() {
std::vector<int> v(123);
}
然后我成功(我希望)将header单元hello.hpp
编译成PCM文件:
clang++ -std=c++20 -Xclang -emit-header-module -I. hello.hpp -o hello.pcm
命令 运行 没有错误并生成了 hello.pcm
。如果你上面的 运行 命令没有 -o
标志然后文件
hello.hpp.gch
已创建。
然后我尝试编译use.cpp
,但是没有成功,不知为何它无法识别我的header单元and/or找不到对应的hello.pcm
。我想我缺少一些特殊标志,这些标志向编译器显示它是 header 单元。使用了下一个命令:
clang++ -std=c++20 -fprebuilt-module-path=. -fmodule-file=hello.hpp=hello.pcm -I. use.cpp
编译错误:
use.cpp:1:8: error: header file "hello.hpp" (aka './hello.hpp') cannot be imported because it is not known to be a header unit
import "hello.hpp";
^
在 MSVC 下,我成功地使用了常规模块和 header 单元模块。但不是在 CLang 中。你能帮我吗?或者告诉我可能还不支持 CLang header 单位。
最后我设法解决了上面几乎所有的任务。
以下说明适用于 Windows 64 位、来自 LLVM 12.0 版本的最新 CLang(您可以获得 here) and most recent MSVC Community Build Tools 2019 v16.9.4 (which you can get from here)。
注。这个答案只针对CLang,我也写了similar answer for MSVC.
我解决的任务不完全是 header 个单元,而是 header 个模块,它们的行为几乎相同,它们的用法没有区别。
下面的玩具示例文件:
module.modulemap:
module mod {
requires cplusplus17
header "mod.hpp"
export *
}
mod.hpp:
#include <iostream>
use.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 前端而不是简化的 driver,这个前端需要很多 low-level 选项才能工作。
您只需执行 clang++ -### use.cpp
即可获得所有选项,这将转储到控制台系统所需的所有选项。
以上命令只能用于-cc1
前端,driver不支持模块映射文件。
其实上面那3个命令中第二个命令可以简化,编译object文件不需要low-levelfront-end。但它只能在第一个命令具有通过 clang -###
命令获得的默认参数的情况下进行简化,然后第二个命令可以是 short-written 为 clang++ use.cpp -o use.o -c -std=c++20 -fmodule-file=prebuilt/mod.pcm
.
这些命令的结果是 use.o
在几分之一秒内编译完成。众所周知,iostream
需要大量的时间来编译。 use.o
的快速编译意味着我们正确使用了模块并提高了速度。
为什么我首先想要 header 个单位?为了能够升级我的旧代码,只需通过自动替换常规 old-style 包含导入,即可大大缩短编译时间。此替换仅适用于 header 个单元或 header 个模块。据我所知,常规模块无法导出其他完整 header。
有关模块的更多说明,请参阅 CLang 的 Modules Doc and CommandLine Doc。
文档中说 CLang 中的模块支持是部分的。我在最近发布的 LLVM 12.0.Windows 64 位下使用 CLang。
我成功地使用了常规模块(您通过 import modulename;
导入)。
但我还没有设法创建和使用 header 单元模块,那些你通过 import "header.hpp";
导入的模块。你能用例子建议如何做到这一点吗?
为了尝试 header 个单位,我创建了下一个玩具文件:
hello.hpp:
#include <vector>
use.cpp:
import "hello.hpp";
int main() {
std::vector<int> v(123);
}
然后我成功(我希望)将header单元hello.hpp
编译成PCM文件:
clang++ -std=c++20 -Xclang -emit-header-module -I. hello.hpp -o hello.pcm
命令 运行 没有错误并生成了 hello.pcm
。如果你上面的 运行 命令没有 -o
标志然后文件
hello.hpp.gch
已创建。
然后我尝试编译use.cpp
,但是没有成功,不知为何它无法识别我的header单元and/or找不到对应的hello.pcm
。我想我缺少一些特殊标志,这些标志向编译器显示它是 header 单元。使用了下一个命令:
clang++ -std=c++20 -fprebuilt-module-path=. -fmodule-file=hello.hpp=hello.pcm -I. use.cpp
编译错误:
use.cpp:1:8: error: header file "hello.hpp" (aka './hello.hpp') cannot be imported because it is not known to be a header unit
import "hello.hpp";
^
在 MSVC 下,我成功地使用了常规模块和 header 单元模块。但不是在 CLang 中。你能帮我吗?或者告诉我可能还不支持 CLang header 单位。
最后我设法解决了上面几乎所有的任务。
以下说明适用于 Windows 64 位、来自 LLVM 12.0 版本的最新 CLang(您可以获得 here) and most recent MSVC Community Build Tools 2019 v16.9.4 (which you can get from here)。
注。这个答案只针对CLang,我也写了similar answer for MSVC.
我解决的任务不完全是 header 个单元,而是 header 个模块,它们的行为几乎相同,它们的用法没有区别。
下面的玩具示例文件:
module.modulemap:
module mod {
requires cplusplus17
header "mod.hpp"
export *
}
mod.hpp:
#include <iostream>
use.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 前端而不是简化的 driver,这个前端需要很多 low-level 选项才能工作。
您只需执行 clang++ -### use.cpp
即可获得所有选项,这将转储到控制台系统所需的所有选项。
以上命令只能用于-cc1
前端,driver不支持模块映射文件。
其实上面那3个命令中第二个命令可以简化,编译object文件不需要low-levelfront-end。但它只能在第一个命令具有通过 clang -###
命令获得的默认参数的情况下进行简化,然后第二个命令可以是 short-written 为 clang++ use.cpp -o use.o -c -std=c++20 -fmodule-file=prebuilt/mod.pcm
.
这些命令的结果是 use.o
在几分之一秒内编译完成。众所周知,iostream
需要大量的时间来编译。 use.o
的快速编译意味着我们正确使用了模块并提高了速度。
为什么我首先想要 header 个单位?为了能够升级我的旧代码,只需通过自动替换常规 old-style 包含导入,即可大大缩短编译时间。此替换仅适用于 header 个单元或 header 个模块。据我所知,常规模块无法导出其他完整 header。
有关模块的更多说明,请参阅 CLang 的 Modules Doc and CommandLine Doc。