This is mostly a set of disconnected ramblings.
We build a precompiled header to accelerate the build at present.
We need at least some headers because C++ modules don't handle macros, and properly attaching attributes to something without macros is hell.
The macros are large and represent a lot of state as do our third-party library dependencies that are also header-based.
It'd be nice to cache the startup of the compiler right after it has parsed all of that information. This is precisely what a precompiled header does.
This leads to some conflicts between cmake
and clangd
.
We also want to minimize the amount of time we spend editing files that are included in the pch to optimize build time.
This is also in tension with wanting robust documentation.
When using CMake (at least as of 3.30.5) it wants to control the assembly of your precompiled header.
To wit, it makes it awkward when you edit any file from your project that is included by the precompiled header that isn't named in your CMakeLists.txt
, and simply complaints that you should rebuild your PCH, rather than incurring any data dependency for the PCH as a resource. I'd rather write a C++ header than keep thrashing my CMake build.
I let CMake build its own precompiled header by naming the same headers listed below in the precompiled headers in src/CMakeLists.txt
.
Unfortunately Clangd
(at least as of 19.1) on the other seems to have issues with using precompiled headers and C++ modules. Notably, it expects module
to be absolutely first thing in a source file, but I have no way to get "ahead" of the PCH to say 'module;' before the PCH spews out a wall of included text.
So for now, I'm exploring being able to build with and without precompiled headers.
All external headers used anywhere in the project more than once should be bundled into the PCH. You can do this by including that file transitively from one of:
The intent is that since prelude.hpp contains all the files used by the PCH you can #include
that at the top of a source file in the module;
section once in the top of each source file and let it be filtered out via #pragma once
and your code will work either way with no import changes.
Eventually, if we want the non-PCH mode to be as fast as possible, it should adopt a 'least import' practice, but as it only exists to satisfy clangd
I'm punting on this for now.
I prefer the clarity of the code with no headers cluttering the top of each file.
The code doesn't care about your documentation. So in theory we should consider doing out of line documentation for headers (and other modules), lest we induce false data dependencies on the documentation, and needlessly recompile.
This is especially true for the precompiled header, but partially true for the rest of our code as well.
Why? Splitting docs from code gives us the option to detect documentation-only patches in CI and skipping compilation, only building documentaiton, creating a nice culture of rapid turnaround for documentation improvements.
So we should probably pull out long multi-paragraph writings into the ./pub/ folder and use \ref
tags or \copydoc
to bring them inline in the documentation where needed.