Skip to content

Modernize CMake Buildsystem - #10936

Draft
jschmidt-icinga wants to merge 18 commits into
masterfrom
modernize-cmake
Draft

jschmidt-icinga wants to merge 18 commits into
masterfrom
modernize-cmake

Conversation

@jschmidt-icinga

@jschmidt-icinga jschmidt-icinga commented Jul 8, 2026 •

Copy link
Copy Markdown
Contributor

This modernizes several aspects of our build-system.

Features

  • Properly defined dependency graph between project targets and imported targets, using find modules and linking object libraries instead of lists of include directories and linker commands.
    • This means now CMake's own unity builds with configurable batch size work.
  • mkclass now operates directly on the library targets and .ti files are now added to targets directly instead of the generated -ti.hpp headers.
    • This also adds additional targets for generated files, which allows better parallelization (remote doesn't have to wait for base etc.). Prior to this PR this made unity builds actually slow down the build in some cases, whereas now they are always faster for fresh builds (See the build time measurements below).
  • CMake's codegen target now works and includes all generated files, which allows to generate all code needed to build the project, but without actually building anything (except mkclass). This is a prerequisite for checking the source tree with clang-tidy or other linters and static analyzers in their own GHAs.
  • I added CMake Presets for a number of development and build configurations based on release type (Debug/Release), compiler (GCC/Clang), generator (Ninja/Makefiles) and LTO (on/off).
    • You can list them with cmake --list-presets and set up a build dir with for example cmake --preset debug-clang-ninja.
    • Currently I've opted to give all of them the same binaryDir (<src>/build), so it will overwrite an existing build directory everytime the preset is switched. To set different build dirs, just add -B <dir> after --preset <foo>.
    • IDEs will probably pick up on these and offer you nice drop-downs or selection menus for the different configurations.
    • I tried to stay CMake 3.20 (the version presets were added) compatible, but some features might not work on older versions, which is why I didn't use them in the CI after all.
  • All CMAKE_C_FLAGS /CMAKE_CXX_FLAGS not immediately required to build correctly are moved out of the CMakeLists.txt and into the presets. This includes all warnings and optimization flags, which should be left for the user to decide on.
    • This means that these variables can now be correctly overridden by either setting the CFLAGS/CXXFLAGS or CMake variables at configure time. This works additively with the flags set in the presets for maximum flexibility.
  • Systemd is now detected if no preference is specified. Setting USE_SYSTEMD:BOOL to ON will still REQUIRE systemd to be present and to OFF will still disable systemd support even if it's present.

Build times

I've measured the build times between master and this PR, both with and without Unity builds turned on:

Jobs 1 2 4 8
master (unity) 6m 9s 4m 3s 3m 56s 3m 48s
this PR (unity) 6m 22s 2m 39s 1m 49s 1m 30s
master (separate) 8m 25s 4m 31s 2m 59s
this PR (separate) 8m 14s 4m 26s 2m 38s

You can see that the new unity builds in combination with the generated header targets scale a lot better with the number of jobs.

Caveats and Future Considerations

There's still a couple things left over after this PR:

  • Improving the way the version string is generated: Already done by Get version string from git-describe, git-archive or CMake config #10573 (which will probably need a rebase if this PR is merged first)
  • Looking at the install()-related commands and variables.
  • Fixing/Verifying cross-compilation: I see no reason why it wouldn't already work, as long as a toolchain file sets CMAKE_CROSSCOMPILING_EMULATOR so mkclass and test discovery can run, but I didn't test this yet.
  • Precompiled headers might be worth a look. If we can get ccache going again in the GitHub CI that might actually be faster on the average build than unity builds.
  • There is a circular dependency between lib/base and lib/config which should be resolved long-term, most likely by further splitting up both of these modules and abstracting out common dependencies.
  • The last item points to a larger issue of how all lib modules basically sit in the same include path (headers and source files). Fixing this requires moving lots of files around, which is the reason why I haven't done this in this PR. If we want to make this nicer we would need to coordinate this.

Testing

I've tested this on my own system with a variety of configurations (essentially the CMake Presets provided). Also I've tested on FreeBSD and OpenBSD systems to verify the additional find modules I've added.

Closes #10404, closes #10777.

@cla-bot cla-bot Bot added the cla/signed label Jul 8, 2026
@jschmidt-icinga
jschmidt-icinga force-pushed the modernize-cmake branch 14 times, most recently from 6b21e50 to 0f6b36c Compare July 14, 2026 15:26
@jschmidt-icinga
jschmidt-icinga force-pushed the modernize-cmake branch 4 times, most recently from 3d8202c to 91bce12 Compare July 23, 2026 08:00
@jschmidt-icinga
jschmidt-icinga force-pushed the modernize-cmake branch 2 times, most recently from e20a1a9 to f8aa552 Compare July 23, 2026 10:43
@jschmidt-icinga jschmidt-icinga changed the title (WIP) Modernize CMake Buildsystem Modernize CMake Buildsystem Jul 23, 2026
@jschmidt-icinga
jschmidt-icinga force-pushed the modernize-cmake branch 3 times, most recently from 1da63ab to 6ee8b7c Compare July 28, 2026 09:22
@jschmidt-icinga
jschmidt-icinga marked this pull request as ready for review July 30, 2026 09:59
@Al2Klimov

Copy link
Copy Markdown
Member

@jschmidt-icinga
jschmidt-icinga force-pushed the modernize-cmake branch 2 times, most recently from 20a4186 to cdeda60 Compare August 5, 2026 08:54
Base automatically changed from mac-gha to master August 5, 2026 11:28
@jschmidt-icinga
jschmidt-icinga force-pushed the modernize-cmake branch 2 times, most recently from 47bb3ae to b117c99 Compare August 6, 2026 08:45
The Boost::thread CMake target depends on it. Actually it's
needed only on *suse*:15.*, but can't harm having it on the
other GHAs too.
This is required for the CMake unity builds because unlike mkunity it does
not guarantee the order that source files are included, which would
otherwise require that a source file that includes `i2-base.hpp` comes
first, so `win32.hpp`, which set these flags is at the very start of
each unity build file.

This would otherwise cause syntax errors like `C2589` when C++ constructs
like `std::min()` or `std::numeric_limits<T>::max()` are used because
`windows.h` without `NOMINMAX` defined will define `min()` and `max()`
macros.
We should not have function definitions in CMakeLists.txt.
The old form is deprecated and less clear.

Also removes a an old block that used to support old MSVC versions
that don't have the override keyword.
@jschmidt-icinga
jschmidt-icinga force-pushed the modernize-cmake branch 3 times, most recently from 02131f3 to c3d83b5 Compare September 25, 2026 09:06
Autodetection can still be overridden by setting USE_SYSTEMD:BOOL
to `ON` or `OFF` when the build dir is configured.
Most of this wasn't used anywhere except for determining atomics
support. There was even a (severely broken) `check_cxx_source_compiles`
snippet already in place, which is what you are supposed to do to
detect if atomics support requires a library independently of the
processor architecture.

This fixes the snippet and uses it for a proper check to determine
support, with and without library.
This effectively removes manual treatment for the AIX/OpenBSD/SunPro etc. systems.

At least on OpenBSD it has been verified that CMake just does this correctly. On the
other system we'll be relying on the same thing, only that it remains untested for now
(I'm not sure anyone ever tested the original code on these systems either).
Some options don't fit into presets, because they're required to
build the project.

There's also a few linker flags we just set without explanation.
Most lib/* targets don't actually depend on other lib/* targets,
they depend on their generated files. If that dependency is expressed
correctly, it turns out all those targets can easily be built in
parallel.
CMake 3.31 onwards support this natively, but since it isn't much
additional work, I also added a custom target for use on lower
CMake versions.
I would have prefered to use presets here right away, but since
Debian 11 is still on CMake 3.18, with presets being introduced
in 3.19, it makes no sense to use them for everything but Debian 11
at this point. We can still migrate to presets once Debian 11 is
removed.

TODO: Disable unity builds on a single target like on master
@jschmidt-icinga
jschmidt-icinga force-pushed the modernize-cmake branch 2 times, most recently from 1fbfd56 to e243dd1 Compare October 1, 2026 14:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Modernize CMake build-system Use CMake unity builds instead of custom implementation

2 participants