We last increased the minimum CMake version from 3.13.4 to 3.20 in June 2023 after this RFC in October 2022. Now’s the time to do that again. This proposal proposes requiring CMake 3.28.3 3.30 or more recent for LLVM 23, see the rationale below.
The primary motivation is that libc++ needs to start building its dylib with support for C++26 language features, and the easiest way to do that is to set the C++ Standard via e.g. CXX_STANDARD 26, as shown in this PR. That requires a newer CMake than our current minimum. It’s also a good idea, generally speaking, to keep the minimum CMake version reasonably up to date for good build system hygiene. Based on the last RFC, I think that is pretty uncontroversial.
Our general RFC process for these updates usually focuses around selecting the minimum version based on the current LTS releases of Linux, so I’ll do that below (based on a mix of this table and asking Google):
LTS Release
Default CMake version
CentOS Stream 9
3.31.8
CentOS Stream 10
3.31.8
Debian 11
3.18.4
Debian 12
3.25.1
Debian 13
3.31.6
Debian 14
4.2.3
Ubuntu 20.04 LTS
3.16.3
Ubuntu 22.04 LTS
3.22.1
Ubuntu 24.04 LTS
3.28.3
FreeBSD 13-STABLE
3.31.10
FreeBSD 14-STABLE
3.31.10
NetBSD 9.x
3.16.1
NetBSD 10.x
4.1.1 (not certain?)
Most (if not all) distributions support updating to newer versions of CMake by downloading a binary package.
Based on the table above, I think that CMake 3.28.3 3.30 is a reasonable requirement, and it meets the requirements for libc++.
The proposed update process is based on what we did last time:
Immediately: Issue a CMake warning when the version is less than 3.28.3 3.30.
Immediately: Notify all build bot owners.
Two weeks after the warning: Make the warning into an error, iterate on fixing broken build bots (likely reverting back to a warning and trying again until everything works).
Once the error sticks (and so all bots have been updated), send a message indicating the end of the migration.
This proposal intentionally uses an aggressive timeline for upgrading from a warning to an error: my experience is that nobody sees warnings, so adding a warning is close to doing nothing. Leaving a lot of time between the warning and the error is, IMO, just wasting time that could be spent actually pushing the migration forward. I also want to prevent the effort from lingering for too long since I know I won’t have bandwidth to push this for months.
Thoughts welcome!
Louis
Edits: Changed the RFC to propose moving to CMake 3.30 instead of CMake 3.28.3 in response to Petr Hosek’s comment.
Note that while C++26 support was introduced in CMake 3.25, it wasn’t fully implemented until 3.30 so if C++26 support is the main motivation, upgrading to 3.28 won’t be sufficient for all host compilers.
The only reason libc++ is pursuing this is indeed C++26 support. However, as explained by Petr, it seems like we would actually need to move to CMake 3.30 for that to work properly on all compilers we support.
I wasn’t aware of that, thanks for catching it! This indeed means that libc++ would need to move to CMake 3.30 instead.
There is surprisingly little activity on this thread. There’s quite a few likes on the original post that can likely be interpreted as support for the proposal, though.
@boomanaiden154-1 Do you see a problem with moving to CMake 3.30 on the Debian 12 build bots?
The downside of 3.30 is that it’s quite bleeding edge, and for example not available even in the most recent Ubuntu LTS.
That shouldn’t necessarily stop us, but I do wonder if libc++ wouldn’t be better off just handling this itself? I think there is going to be an unavoidable recurring tension here where libc++ wants to specify a very recent standards version, which has only recently gained cmake support. Especially with libc++s very tight host compiler requirements, handling this yourself is probably something like 15 lines of code, and then you’re free from the shackles of cmake.
As far as I can see, that particular linked change (Verifying connection...) isn’t something that would mandate requiring 3.30 for libc++.
It would only mean that if you build libc++ with GCC, with CMake 3.28, it would be built in C++23 mode rather than in C++26. For the CI environment, I’d presume you’d have a new enough CMake, which would end up building in C++26 mode even with GCC.
Increasing the required CMake version for the whole of llvm-project (requiring a version not available even in the latest LTS distros), for that particular case only, feels excessive.
That seems surprising. CMake 3.30 was released over a year ago, they are now at CMake 4.3. But I agree this makes it a lot harder for people to migrate to that version if it’s not easily available.
Yeah, that might be the right call. I’m trying that out in the latest iteration of my PR.
Well, if we claim support for some GCC version and some CMake version, but then building libc++ with these GCC and CMake fails with a compiler error due to -std=c++23 being passed when -std=c++26 would need to be passed, I think that’s problem. It might not manifest in our CI if we actually use a newer version of CMake, but it’s technically still a bug and I’d rather not introduce it knowingly.
I’ll see if we can remove the libc++ dependency on a newer CMake and what that requires. If so, while I still think it would be healthy for LLVM to bump, we might not have to do it right now, or we might be able to bump to a less recent version. If not, we might want to explore alternative solutions.
I did some additional digging to figure out whether libc++ can be decoupled from the CMake version to set the version of the Standard it uses, and the answer is that we do need at least CMake 3.28 for that to work. I don’t know why, but CMake will automatically pass -std=<...> based on the CMAKE_CXX_STANDARD and that conflicts with any attempt from libc++ to set its own -std=c++26 flag. This doesn’t happen with CMake 3.28 based on my testing.
Given this, I think we should probably bump to at least CMake 3.28, and probably 3.30 since that will allow us to actually set the flag the right way instead of relying on a hack, without requiring more work from people who need to update CMake.
Edit: After more testing (see post below), I think it’s actually CMake 3.30 that is required. CMake 3.28 doesn’t work when you rebuild after the initial configuration.
FWIW, we’ve recently decided to upgrade the minimum CMake version to 3.26 in IREE due to the Python SABIModule support for our Python bindings. If we bump to >=3.26, we could clean up a little bit of conditional code in the upstream MLIR bindings.
If we decide to go with CMake 3.30, we could wait until the release of Ubuntu 26.04 LTS—which is a little over a month out—at which point every major Linux distribution will have an LTS release with CMake newer than 3.30 (and Kitware maintains an APT repository for older LTS releases).
Would be nice to match this with AWS and Azure’s versions of ubuntu-latest, fedora-latest, etc. in their builders, as there are quite a lot of projects using LLVM that build using their free builders. Potentially the LTS versions too, being adopted there.
Do I understand correctly that you are both setting CMAKE_CXX_STANDARDand trying to pass -std=c++26 explicitly via target_compile_options?
If so, why are you setting CMAKE_CXX_STANDARD if you’re already passing the option explicitly?
I just went ahead and built cmake 3.20 just to double check that it indeed does not pass any -std= option as long as CMAKE_CXX_STANDARD (or the CXX_STANDARD target property) is not set.
Well, CMAKE_CXX_STANDARD is already set by default. I tried setting it to 26 instead of 23 (the status quo), but that’s invalid with older versions of CMake. I also tried to unset it entirely, but somehow -std=gnu++17 still gets passed when using older CMakes, which overrides my explicit setting of -std=c++26. In fact, what happens is really really weird, and it only happens under the bootstrapping build. When you first build libc++ via the bootstrapping build, it “works”, in the sense that unsetting CMAKE_CXX_STANDARD takes effect. However, when you then try to build again (e.g. just re-run ninja install-runtimes), CMake re-configures and nowCMAKE_CXX_STANDARD is back to 17, which overrides our explicit -std=c++26. I’ve been trying with various CMake versions over the course of the last two days:
CMake version
Works on first build?
Works on rebuild?
3.24.4
3.25.3
3.28.6
3.30.5
So it seems like something quite strange is happening here, and it also feels like this is all very brittle. If something was wrong with the bootstrapping build, presumably it would be wrong with all CMake versions.
In all cases, it seems like we basically need to upgrade to 3.30 for things to work, and if we do that, we’ll be able to use the clean approach with set_target_properties.
I feel like there’s almost no limit to the number of external things we can try to sync with. Honestly, I don’t know what to make of that. After investigation, it turns out that this migration is blocking actual libc++ patches from landing (or from landing in their optimal form). I’d really like to get this unblocked sooner rather than later, and I feel like it’s probably better in the long term if we get into the habit of updating these tools on a regular basis (instead of just always waiting for all the baselines to magically update tools for us).
I’m just stabbing in the dark here, but my suspicion would be interaction with cached variables? It looks like we commonly define CMAKE_CXX_STANDARD as a cached variable, which means that unset(CMAKE_CXX_STANDARD) is going to just unset the localCMAKE_CXX_STANDARD variable, in which case cmake will fall back to the cached one.
So possibly you need unset(CMAKE_CXX_STANDARD CACHE) (or maybe both, not sure).
I thought about that too, I did check all of the above variations with unset(CACHE{CMAKE_CXX_STANDARD}) (which is the documented syntax) and that didn’t help.
Edit: Crap. The unset(CACHE{CMAKE_CXX_STANDARD}) syntax was added in CMake 4.2, so my testing for that variation didn’t work.. Jeez. Let me try again.
It turns out that this is correct, unsetting it from the cache does fix the problem. I’ve landed the patch that unblocks libc++ adopting a newer standard.
So, for now, there is no incentive for libc++ to push for a CMake upgrade. I would encourage the infrastructure working group to perhaps perform these updates systematically at some cadence. I’ll update the RFC saying that I am not pursuing it anymore. Seems like I can’t edit the original post anymore.