Finally I managed to solve almost task above.
Instructions below are for Windows 64-bit, most recent CLang from LLVM 12.0 release (which you can get here) and most recent MSVC Community Build Tools 2019 v16.9.4 (which you can get from here).
Note. This answer is for CLang only, I also wrote similar answer for MSVC.
I solved task not exactly for header units but for header modules, which behave almost same, there is no difference in their usage.
Toy example files below:
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;
}
I used next 3 commands:
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
which all worked without errors. You can see that there are full paths to include directories of standard library, these paths are specific to my system. This is needed because in commands I used -cc1
option which enabled to use low level CLang front end instead of simplified driver, this front end needs a lot of low-level options to work.
You can get all options just by doing clang++ -### use.cpp
, this will dump to console all options that are needed for your system.
Commands above can be used with -cc1
front end only, driver doesn't support module map file.
Actually among those 3 commands above second command can be simplified, compiling object file doesn't need low-level front-end. But it can be simplified only in the case if 1st command has default params obtained by clang -###
command, then 2nd command can be short-written as clang++ use.cpp -o use.o -c -std=c++20 -fmodule-file=prebuilt/mod.pcm
.
Result of these commands is that use.o
is compiled within a fraction of a second. It is known that iostream
takes a lot of time to compile. Very fast compilation of use.o
means that we used modules correctly and boosted our speed.
Why I wanted header units in the first place? To be able to upgrade my old code, just by automated replacing regular old-style includes with imports, to greatly improve compilation time. This replacement is only possible with header units or header modules. Regular modules can't export other full header as I know.
For further instructions regarding modules see CLang's Modules Doc and CommandLine Doc.