如何从命令行编译/使用 MSVC 中的头单元?

问题描述

例如我有以下玩具文件

mod.hpp

#include <iostream>

use.cpp

import "mod.hpp";

int main() {
    std::cout << "Hello,World!" << std::endl;
}

但是如果你像 cl use.cpp /std:c++latest 一样编译它,我就会得到错误

error C7612: Could not find header unit for 'mod.hpp'

如何在 MSVC 中创建/使用标题单元?

注意:我现在正在制作跨平台/交叉编译器项目。这意味着我希望能够在 Windows 和 Linux 上的 MSVC/CLang/GCC 中编译相同的源代码。对我来说,将特定于 MSVC 的扩展名设为 .ixx/.cppm 毫无意义,这就是我在本例中使用 .hpp/.cpp 的原因。更重要的是,我根本没有制作 .vcxproj/.sln 文件,我只考虑在 MSVC 中编译的低级命令行调用

这个问题是我提出来的,只是为了和现成的解决方分享我的答案。

解决方法

要创建预编译头单元发出下一个命令:

cl /EHsc /std:c++latest /exportHeader mod.hpp

此命令创建 mod.hpp.ifc 文件,这是一个预编译的头单元模块。 Here 是关于 /exportHeader 标志的文档。

然后使用标题单元发出命令:

cl /EHsc /std:c++latest use.cpp /headerUnit mod.hpp=mod.hpp.ifc

关于 /headerUnit 的文档是 here/headerUnit 接受参数 header-filename=ifc-filename。在最终程序编译并输出上面的命令之后:

Hello,World!

通过这种方式,您可以预编译任何标头,包括像 import <iostream>; 这样的标准标头。

对于上面的命令,我使用了以下文件:

mod.hpp

#include <iostream>

use.cpp

import "mod.hpp";

int main() {
    std::cout << "Hello,World!" << std::endl;
}