cmake: Check user-defined APPEND_*FLAGS variables early#32367
Conversation
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code Coverage & BenchmarksFor details see: https://corecheck.dev/bitcoin/bitcoin/pulls/32367. 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. |
43ccbb1 to
990067f
Compare
990067f to
eb2a943
Compare
janb84
left a comment
There was a problem hiding this comment.
ACK eb2a943
- PR fixes #32323 (reproduced on main, checked it was solved by this PR) ✅
- Code review looks good to me. Adds a new macro with additional checks and some optimisations.✅ (There is one reference to
enable_languages()in secp256k1 but that is separate and not relevant to this PR )
Details
Main:
Configure with faulty flag:
cmake -B build -DAPPEND_CXXFLAGS="-ftrivial-auto-var-init"
expected config BREAK
Configure with correct flag:
cmake -B build -DAPPEND_CXXFLAGS="-ftrivial-auto-var-init=zero"
not expected: STILL BREAKS
This PR:
Configure with faulty flag
cmake -B build -DAPPEND_CXXFLAGS="-ftrivial-auto-var-init"
expected BREAK
Configure with correct flag
cmake -B build -DAPPEND_CXXFLAGS="-ftrivial-auto-var-init=zero"
config WORKS
BrandonOdiwuor
left a comment
There was a problem hiding this comment.
ACK eb2a943
Confirmed that the new bitcoincore_enable_language(...) macro properly validates user-defined APPEND_*FLAGS early via check_source_compiles(...), fixing #32323 by catching bad flags during enable_language(...), and removing the need a clean build directory.
(system: macOS 15.6)
(commit: eb2a943)

|
@hebasto was this drafted for any particular reason? |
eb2a943 to
98b5edf
Compare
Rebased and undrafted. |
This change introduces the `bitcoincore_enable_language()` macro to wrap CMake’s `enable_language()` command, applying Bitcoin Core-specific settings and checks.
This change is required for the following commit.
This change improves usability in cases where the user provides `APPEND_*` variables that are incompatible with the compiler for some reason.
98b5edf to
cd9367c
Compare
|
Rebased to resolve conflicts. |
|
What you are observing here is the so-called intervention spiral. You want to improve one aspect of cmake's builtin behavior, there are unintended side effects, you add a workaround, which have side effects of their own and you need to add more workarounds until the whole system is complex beyond recognition. The simple approach would be to respect user provided compile flags. Period. A project that does not modify user provided compile flags does not need any additional mechanism to let the user "append" flags and it also does not need a custom way to enable languages. We should go back to the scratch board and discuss what that original intervention was that pulled in all those other workarounds. |
What about something like #31843 (https://gitlab.kitware.com/cmake/cmake/-/issues/26757), where the mechanism for the user to pass the flags they want ( |
|
The release notes for 29.0 contain:
CMake does not use the |
We extensively debated the introduction during the migration. The |
CMake doesn't put the user supplied flags, last on the link line, meaning they are overriden by CMakes own PIC/PIE flags. So in this case, the user flags are effectively ignored by CMake. |
Migrating from Autotools to CMake presented several challenges. Perhaps the most significant was that, over the years, users relied on the fact that any user-provided flags override whatever is set by the build system. This is generally not the case with CMake. Another minor issue is that CMake does not support |
Those are links to the actual commits that introduced them. Is there a way to reason about the "extensive debate" that led to their introduction? Are they intended as temporary workarounds, long term technical debt, features that should be upstreamed, ... ?
CMake does not add any PIC/PIE flags by default. It is the project's configuration that causes the additional flags. The precedence rules (file flags > target flags > directory flags > project flags > env flags) make sense. We are in agreement that CMake#26757 is an issue, but we could just as well simply not use CMake's default build type bitcoin/cmake/module/ProcessConfigurations.cmake Lines 81 to 85 in ff7cdf6 |
If by this you mean, apply the flags we want, manually by default (required because we are shipping with hardening by default), and in a way that user applied flags can override them, then sure, that could be an option (not clear how involved that is). Especially given we are already working around bugs in CMake PIE logic anyways, i.e: https://gitlab.kitware.com/cmake/cmake/-/issues/26463 (fixed in https://gitlab.kitware.com/cmake/cmake/-/merge_requests/10034). |
I can't answer those questions, but my understanding is that the feature is needed, because it is not possible otherwise to say: "Thanks for setting all the compiler options in the Bitcoin Core build system, which seem like sane defaults, but I really want to force this one myself, and I know what I am doing". E.g. Maybe this is similar to the |
Here lies an important detail. The precedence rules are: "file flags > target flags > directory flags > project flags > env flags". The Conventions and personal preferences such as compiler warnings, optimization settings, hardening, etc. are better placed in toolchain files, CI scripts, presets, etc. Keeping these concerns out of
Ideally, toolchains and CI scripts should live in a separate repo. Consider stress-testing them on a large, complex CMake project like VTK. If they work there, they will probably work anywhere. |
I strongly believe we need to provide an out-of-the-box option for regular (non-programmer) users to build Bitcoin Core from source using default flags that ensure the safety of their funds. If doing so requires them to pass an additional Another case I'm curious about is more developer-specific. Let's say I'm testing the code under the assumption that SSE4.1 is unavailable. On master branch, I can currently run the following: cmake -B build -DAPPEND_CXXFLAGS="-mno-sse4.1"How would this be achieved in your proposed alternative? |
I can totally see that point. Though,
|
For situations like this, a top level just buildIn the cxxflags := "-Wall -Wextra " + env_var_or_default("CXXFLAGS", "")
[private]
configure:
cmake -B build -S . -DCMAKE_CXX_FLAGS="{{cxxflags}}"
build target="all": configure
cmake --build build --target {{target}}
test pattern="": build
ctest --test-dir build -R "{{pattern}}" --output-on-failure
CXXFLAGS="-mno-sse4.1" just test |
Will it worK? |
Try it. Throw the above |
This results in |
and cmake -B build -S . -DCMAKE_CXX_FLAGS="-Wall -Wextra -mno-sse4.1"so the flag is appended. Did you want to remove it instead? |
The expected behavior is as follows: |
I see, you want We can search for the existence of Qt and based on the result we can enable building of the GUI. Or, we can provide an option whether the GUI should be built and based on that setting, we make the existence of Qt a requirement. In the same sense, we should check for SIMD capabilities and based on the result provide options to use them. Or, provide the options unconditionally and based on the setting make the capability a requirement. But relying on Also, it requires custom procedural logic like |
|
🐙 This pull request conflicts with the target branch and needs rebase. |

For the purpose of checks performed by the build system, we strive to handle user-defined
APPEND_*FLAGSin the same way as flags provided by other standard means. In particular, they are considered when thetry_compile()command is used.However, these flags are not considered during
enable_language()command invocation due to design limitations, which might cause issues, such as #32323.This PR addresses the issue by introducing an additional compiler check that does consider the user-defined
APPEND_*FLAGS.Fixes #32323: