By Paul Dreik 2023-10-15
I use the defacto standard cmake for building C++. Build times in C++ is one of the pain points.
One thing I do often is to verify all commits build and pass unit test properly. A full build (including configure, build and running the unit test) must therefore be as fast as possible.
I use ccache and other tricks, I strongly recommend checking out this excellent 2023 talk by Vittorio Romeo.
Cmake has profiling capability built in.
cmake -B /tmp/blah -S /path/to/source --profiling-output blaha.json --profiling-format=google-trace
Then I used chrome (not Debian chromium, it does
not work) to display the file, using the
chrome://tracing/
feature.
I immediately found that I used
check_cxx_source_compiles
to check for the existence of a
specific boost feature. The particular header is very heavy. I tried
using CHECK_INCLUDE_FILE_CXX
to save time, but no significant improvement.
I instead used the following trick:
check_cxx_source_compiles(
"#if __has_include(<boost/x/y/z.hpp>)
int main() { }
#endif" HAS_BOOST_FEATURE)
This trick requires the C++17 feature __has_include. Luckily, I have a pretty high minimum compiler version in this project.
This saved two seconds from the configure time.
This is based on the information from this Craig Scott blog entry.
I use the excellent ninja build tool. It generates a log, which can be used to understand the build process.
cmake -B /tmp/blah -S /path/to/source -GNinja
cmake --build /tmp/blah
There is now a .ninja_log file to work with. For some reason, it has an extra newline at the end which must be removed before fed to the next tool.
Get the tool from here.
Then just run
./ninjatracing.py .ninja_log >cmake_build_trace_full.json
and open the json file in chrome. I could verify that there are no significant bottlenecks in my build, but there are some heavy files.
One thing I noticed is that the end of my build was blocked on a single item. If the builder had known the compile/link time for each step, it could have planned better and started the long running things first. It would be a cool thing if the build could take timings from it’s last build (which often is pretty accurate prediction) and optimize the build order.