build: Add a compiler minimum version check#34580
build: Add a compiler minimum version check#34580polespinasa wants to merge 2 commits intobitcoin:masterfrom
Conversation
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please copy-paste ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
78088b3 to
109049c
Compare
cfb5e3f to
a902bd9
Compare
|
Concept ACK |
|
https://github.com/bitcoin/bitcoin/actions/runs/21985815150/job/63519602237?pr=34580#step:9:434: + eval 'CMAKE_ARGS=(-DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DBUILD_BENCH=ON -DBUILD_FUZZ_BINARY=ON -DCMAKE_INSTALL_PREFIX=/Users/runner/work/bitcoin/bitcoin/repo_archive/ci/scratch/out -Werror=dev --preset=dev-mode -DWITH_USDT=OFF -DREDUCE_EXPORTS=ON -DCMAKE_EXE_LINKER_FLAGS='\''-Wl,-stack_size -Wl,0x80000'\'' )'
++ CMAKE_ARGS=(-DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DBUILD_BENCH=ON -DBUILD_FUZZ_BINARY=ON -DCMAKE_INSTALL_PREFIX=/Users/runner/work/bitcoin/bitcoin/repo_archive/ci/scratch/out -Werror=dev --preset=dev-mode -DWITH_USDT=OFF -DREDUCE_EXPORTS=ON -DCMAKE_EXE_LINKER_FLAGS='-Wl,-stack_size -Wl,0x80000')
+ cmake -S /Users/runner/work/bitcoin/bitcoin/repo_archive -B /Users/runner/work/bitcoin/bitcoin/repo_archive/ci/scratch/build-aarch64-apple-darwin24.6.0 -DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DBUILD_BENCH=ON -DBUILD_FUZZ_BINARY=ON -DCMAKE_INSTALL_PREFIX=/Users/runner/work/bitcoin/bitcoin/repo_archive/ci/scratch/out -Werror=dev --preset=dev-mode -DWITH_USDT=OFF -DREDUCE_EXPORTS=ON '-DCMAKE_EXE_LINKER_FLAGS=-Wl,-stack_size -Wl,0x80000'
-- The CXX compiler identification is AppleClang 16.0.0.16000026
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Error at CMakeLists.txt:86 (message):
Clang >= 17.0 required.
-- Configuring incomplete, errors occurred! |
CMakeLists.txt
Outdated
|
|
||
| if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") | ||
| if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS MIN_CLANG_VERSION) | ||
| message(FATAL_ERROR "Clang >= ${MIN_CLANG_VERSION} required.") |
There was a problem hiding this comment.
Would be useful to print also the detected compiler version. E.g. if it is detected wrong or the user thinks they have clang 17, it is not the best experience to get a message like "minimum is 17".
There was a problem hiding this comment.
The detected compiler version is already printed by CMake
There was a problem hiding this comment.
The compiler version is printed by CMake in the first line of the output, and the error appears in line ~6. I don't think there's a need to repeat the version number.
AppleClang 16.0.0.16000026 is based on LLVM 17.0.6, which is OK. That's another reason to test compiler features, not versions. |
Yea. This was my initial feedback (in IRC) as well. |
|
I'm tending to Concept~0 here. We should be checking features, not version strings that might have exceptions, or be brittle to match against. This might also make it more difficult to test with weird compiler/standard library pairings. |
|
If you want to extract the clang feature check, it is currently in |
|
For GCC, I think it is some ranges/view stuff in the kernel tests. The gcc-12 fix from fa3854e was actually backported to gcc-11, so in theory one could use gcc11.3 just fine, if disabling the kernel tests. |
|
I agree that it is more robust to check for features instead of compiler versions. However, then Further, if we check for features, e.g. Maybe use a wording like "Need a compiler with support for feature1, feature2, etc, like clang 17 or gcc 12.1" in both |
|
I think bitcoin/doc/release-notes-empty-template.md Lines 35 to 43 in 35e6444 Of course, anyone is free to use whatever compiler/OS they want (at their own risk). It should be trivial to replace
Why not? Maybe the error message can be improved to say "Your current compiler with the current version failed to compile foobar. You may try the next major version of this compiler, or a different supported and tested compiler, according to doc/dependencies.md"
Seems fine as well, but I don't think there is a need to keep the build system features check in sync with dependencies.md. I think it is enough to have the features check in the build system only. |
|
So, check for features and print a message like "your compiler does not support xyz, Bitcoin Core has been tested to compile with clang >=17 ..."? |
a902bd9 to
62559d0
Compare
|
Just opened as ready to review to make the CI run and see if the change avoid crashing for Apple. $ git diff a902bd955cba72c618269b0481fe6f9d5e23801e..62559d00bdbfa3dd38016d7e7a13df83bba54f0d
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5636f641a0..00676a2ed2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -81,7 +81,7 @@ set(MIN_MSVC_VERSION 19.50)
# VS 18.x uses 19.50-19.59 as MSVC version values
# https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html
-if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS MIN_CLANG_VERSION)
message(FATAL_ERROR "Clang >= ${MIN_CLANG_VERSION} required.")
endif()
|
62559d0 to
4515584
Compare
|
I've been researching a bit on how to do the features check and I think is not as trivial as I initially thought. Disclaimer: It's the first time I actually play with CMake files so I don't actually know at all how it works. I've used AI to help me generating the features check CMake file. From the different options I've seen and tried this approach is the only one that actually worked. To summarize the solution, cmake will try to compile a piece of code that uses the feature we need. If compilation fails, it returns an error marking the missing feature. I don't know if there's another cleaner way to check these features. If there is not, I am not sure at all that checking features is a good option, maybe the work to maintaing this extra code and updating it it is not worth at all and just checking compiler versions should be good enough. At the end the version check that this PR proposes is not restrictive on which compiler to use. It just forces the users, in case they use one of the three "main" compilers that we recommend, to use at least the older known supported version, but it will not fail if a user tries to use a different compiler. The check will just not apply. Updating that version number should be easy and not much extra work to do in a PR like #33555 and probably is not something that will happen regularly. Personally if the work to maintain the feature check is considered to be ok and not a big deal I think keeping both approaches, version check (for easy verbose) + feature check (for other compilers) is not a bad idea. The last commit (760b8c2) adds a feature check following what we have in Note: This output appears like this because I dropped the three version check commits before compiling, if the whole PR is tested it will first exit because of the Clang version check. To reach this state without dropping commits, a compiler different from GCC, Clang or MSVC that does not implement CTAD should be used. Other approaches that I tested and don't work are using To clarify the personal motivation for this PR again; this was open after me having an error when building and not understanding why (see IRC logs). As a user not really familiar with compilers and CMake, the output being something like Again I am not really familiar with CMake and maybe I am missing some cleaner way to do this feature check, help, and approach ideas are more than welcome :) |
4515584 to
737682b
Compare
This doesn't force users to use a specific compiler, only forces to, if you used Clang, GCC or MSVC, use at least the older required version. But users can still use weird compilers and this checks will be skipped. |
737682b to
760b8c2
Compare
I've already provided my feedback in #34580 (comment), but I haven't seen a reply so far, so I am not sure what else I can do here? |
@maflcko in order to address the feedback features check was implemented too. The order of the commits was also changed to make it easy to only review the features check. Feel free to only review the first two commits and NACK or ignore the last three. If there's consensus among the reviewers, I will be happy to drop the last commits (version check). |
1ccc075 to
2bff5f1
Compare
|
Force pushed to fix two small comments: $ git diff 91e64c95116d4d1ca3f7176a9d83dcc339c4481b..eca0c31c130c3deb68acd98325580052950981b5
diff --git a/cmake/module/CheckCXXFeatures.cmake b/cmake/module/CheckCXXFeatures.cmake
index c1f91d79d8..9ebb769104 100644
--- a/cmake/module/CheckCXXFeatures.cmake
+++ b/cmake/module/CheckCXXFeatures.cmake
@@ -2,6 +2,8 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://opensource.org/license/mit/.
+include_guard(GLOBAL)
+
#Checks for C++ features required to compile Bitcoin Core.
include(CheckCXXSourceCompiles)
@@ -30,7 +32,7 @@ function(check_cxx_features)
message(FATAL_ERROR
"Compiler lacks Class Template Argument Deduction (CTAD) for aggregates.\n"
"This C++ feature is required for src/util/overloaded.h.\n"
- "Recomended compiler versions:\n"
+ "Recommended compiler versions:\n"
" - GCC >= ${MIN_GCC_VERSION}\n"
" - Clang >= ${MIN_CLANG_VERSION}\n"
" - MSVC >= ${MIN_MSVC_VERSION}" |
BrandonOdiwuor
left a comment
There was a problem hiding this comment.
Approach ACK eca0c31.
I support doing compiler feature checks against hard-coded minimum compiler version checks.
Was also able to successfully compile with GCC version 11.5 against the stated 12.1 MIN_GCC_VERSION
The check_cxx_features function is able to catch old compiler versions just fine
2bff5f1 to
eca0c31
Compare
|
Given the feedback and lack of support for version check, I force pushed to drop the version check and keep only the feature checks. |
|
Looks like the version checking commit is still here? |
eca0c31 to
27d4859
Compare
@fanquake The version check was dropped. The first commit only sets some variables used for suggesting versions to the user in case the feature check is not passed. I have just updated the commit message to make it more clear. |
CMakeLists.txt
Outdated
| set(MIN_GCC_VERSION 12.1) | ||
| # VS 18.x uses 19.50-19.59 as MSVC version values | ||
| # https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html | ||
| set(MIN_MSVC_VERSION 19.50) |
There was a problem hiding this comment.
I think this should just use the wording and version from doc/build-windows-msvc.md. Otherwise this will just be extra steps to convert manually each time, for no benefit? Also, this is only used once, so it seems easier to just inline it in the single place that needs it?
There was a problem hiding this comment.
Or just refer to the md directly, to avoid creating a silent conflict with #31507, and given that the md needs to be followed anyway.
There was a problem hiding this comment.
I changed the version numbers by the documentation path so the user can go and check.
27d4859 to
bc45354
Compare
bc45354 to
ac1ccc5
Compare
|
Force pushed to solve some nits. Also changed the output from printing the recommended version to print the path to the compiler requirements documentation. This way we avoid the need to update the value if the requirements change and avoid silent conflicts with other PRs #31507 |
| " - GCC -> ${MIN_GCC_DOCS}\n" | ||
| " - Clang -> ${MIN_CLANG_DOCS}\n" | ||
| " - MSVC -> ${MIN_MSVC_DOCS}\n" | ||
| ) |
There was a problem hiding this comment.
nit, feel free to ignore: since the MIN_..._DOCS variables are used in just one place and will not be changed frequently (they do not contain version numbers anymore), might as well just cite the docs here, e.g.
" - GCC -> doc/dependencies.md#compiler\n"
There was a problem hiding this comment.
If touching again I will move the variable inside CheckCXXFeatures.cmake, but keep them as variables in case more checks are added.
Adds a compiler features check. If failed, it returns a fatal error.
This early stop at configure time will avoid contributors losing time trying to fix compilation errors because of not fitting the requirements.
Example of the output for GCC:
Version requirement satisfied:
Version requirement not satisfied:
Example of the output for Clang:
Version requirement satisfied:
Version requirement not satisfied:
Edit: The first version of the PR was to check hardcoded compiler versions. See previous PR description for context here.
Details
Adds a compiler minimum version check. If failed, it returns a fatal error.
This early stop at configure time will avoid contributors losing time trying to fix compilation errors because of not fitting the requirements.
Example of the output for GCC:
Version requirement satisfied:
Version requirement not satisfied:
Example of the output for Clang:
Version requirement satisfied:
Version requirement not satisfied:
<\detail>