meson
meson copied to clipboard
Shared precompiled header
I have C++ project organized as few libraries. All of them use the same precompiled header. Currently meson precompiles this header for each invocation of library() call. Is there any way to precompile this header only once, and after that just share it among all library() calls?
That is not supported ATM. The problem is that if any compiler flag changes, the PCH file is no longer guaranteed to be valid.
Also, this will be backend dependent. I don't think you can easily re-use a precompiled header across multiple VS projects in a solution, but I'll gladly review a PR implementing this.
pch as a build target can be valuable since for compilers like clang that support chained pch, meson is better to support something like:
clang++ -x c++-header header1.h -o header1.h.pch
clang++ -x c++-header header2.h -o header2.h.pch -include-pch header1.h.pch
Where header2.h includes header1.h . In case where multiple subprojects have commonly shared headers, the shared part can be in header1 and the rest to header2 and huge build time can potentially be saved.
True that pch outputs are sensitive to compiler flags. When having pch as a build target, it should be very easy for meson to figure this out as configuration error - so this should not be an issue with meson design.
This affects us in Lix, since we have a lot of libraries and we have little reason to not simply use the same PCH across all our libraries. It looks like we would save about 40 cpu-seconds by this being fixed, which is about 5% of our current build time. We could get more build-time savings by doing any other optimization, so this is not a huge priority for us but it would be nice.
Probably it would be possible in the backend to take a list of all pch files and figure out which ones are called with the same flags, then merge rules.
Anyone want to look into implementing this?
@eli-schwartz Recent experiments in one of my projects (which involves many plugins which are separate .so files, but have the exact same flags for compilation) show that this could save up to 20% of compile-times so I am interested in looking into this, I have some experience with Python but unfortunately never looked into meson's codebase. Do you have some hints as to what has to happen broadly / which parts of the code I should look and hook into for this to be made possible?
Also, this will be backend dependent. I don't think you can easily re-use a precompiled header across multiple VS projects in a solution
https://devblogs.microsoft.com/cppblog/shared-pch-usage-sample-in-visual-studio/
pch as a build target can be valuable since for compilers like clang that support chained pch, meson is better to support something like:
clang++ -x c++-header header1.h -o header1.h.pch clang++ -x c++-header header2.h -o header2.h.pch -include-pch header1.h.pch
That would be awesome. Usually you need 1 core PCH for STL and then module layers on top.
Is there any workaround to share PCHs?
btw CMake has PCH sharing.
But they still don't support the clang mode that really gives the full PCH boost:
https://gitlab.kitware.com/cmake/cmake/-/issues/21133
-fpch-instantiate-templates is required to get any real gains with templates.
And -fpch-codegen -fpch-debuginfo enables something similar to what msvc does, saving a lot on codegen.
There's also a much better way of doing pch that clang and msvc use. The posted pch approach prepends the AST from the pch to each .o file. So the linker then has to throw all that out.
The better way to to build a pch module. This prepends much less, but requires a .o of the compiled pch module to be linked in with the exe. MSVC has a "use" vs. "compile" setting for the pch.
I just added basic support for this in muon (bdbb74c). It lets you use a build target that is a static library with a <lang>_pch kwarg as the value for a matching <lang>_pch kwarg. muon will re-use the pch in this case. Currently pch chaining using this method doesn't work, but it should be easy to add. Perhaps meson could consider adopting this?