-
Notifications
You must be signed in to change notification settings - Fork 37.7k
build: add a depends dependency provider #32595
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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/32595. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsNo conflicts as of last run. |
Opened in draft for feedback on approach. There is also a bypass for the boost package (in cmake/module/AddBoostIfNeeded.cmake) which I'd like to get working with the dependency provider ideally. Note that this also bumps the minimum cmake version to 3.24. |
Can you elaborate on this? Currently, CMake configured with a depends toolchain, should never look outside depends (doing so would be a bug). What are the stronger guarantees? |
Right, perhaps I didn't use the best wording here. When using the toolchain I have not found us pulling in extraneous deps from outside of depends, but have encountered us missing dependencies from inside of depends, e.g. in my original issue. By using a dependency provider and intercepting calls to This is what I termed "stronger guarantees", perhaps misleadingly! |
The windows job fails as currently we activate the dependency provider automatically based on whether a(ny) toolchain is in use. This works fine for depends, but doesn't make sense on windows where the vcpkg toolchain is used, without depends. The idea for doing it this way was to try and avoid users having to pass two flags in order to build from depends -- a toolchain and a dependency-provider -- but perhaps this is necessary after all... I do recall reading somewhere in cmake docs that choice of dependency provider should always be left to the user too, so I suppose doing it this way would fit with that. |
b1a0b66
to
7bdf1af
Compare
Pushed an update which now only activates the dependency provider when using the depends toolchain. This will hopefully appease the windows CI job, as well as making more sense in general and being more expected behaviour. |
Thank you for working on a dependency provider! I think core should provide two dependency providers, which will give users three different ways to build:
At the moment, the dependency provider points to prebuilt depends. Alternatively, the dependency provider could take the responsibility of building depends at the moment they are requested. This would make the current, Makefile based depends system an implementation detail that can be ported piece by piece to CMake. |
Thanks for the feedback @purpleKarrot. I like the sound of your approach here myself and will be happy to adapt to it. I think i'll start off by targetting 3.:
...without the optionl "auto-build depends" functionality. This is close to what I have here already (and solves my immediate personal itch regarding building using depends on NixOS). I would appreciate your input though on one more aspect of this; namely the (dev) UX involved with the 3 options. Option 1 would not see any UX changes. Option 2 would require dev to specify the "fallback provider" file with a Option 3 would require the dev to specify both a Option 3 in particular feels a little clunky to me (as a cmake novice), as I'd expect the toolchain to "contain everything needed to build". But I am guessing this can be abstracted away with a Does my understanding above sound roughly logical to you? If so I can make the changes later this week. |
I can't tell from this if you are saying to use depends to "fill in" any missing system packages, or, if all the required system packages aren't available, we would switch to using depends (unclear if that is actually desirable). Certainly a NACK on mixing and matching the two. |
Yes. The idea is to provide an approach to build core with minimal effort. If you NACK mixing system packages with vendored dependencies, are you saying that nobody will ever want that, or that nobody should ever want that? |
I think I'm also not currently aware of a platform that we support, where the dependencies needed to compile Core, aren't available via the system package manager; one used to be our specific version of BDB There's also some nuance around how this would function, are you imaging it all integrated into into CMake, so depends is no-longer a stand alone system? Otherwise, we need logic in CMake, to detect if the depends requirements (curl, compilers, patch, binutils etc) are actually installed / usable (i.e otherwise the fallback would fail because curl isn't installed, probably leaving the user wondering why it's trying to download stuff), as well as making sure that build flags / compiler selection are all passed through to depends (i.e if the user is trying to build with Clang & libc++, then any tools / flags need to be forwarded to the depends compilation). I'm also just not sure that if a dependency is missing, downloading and compiling something is even the best behaviour. Maybe the user just forgot to apt install it, and will do so when CMake fails to configure? |
a20f62c
to
4d568f9
Compare
OK I reworked this a little so that it works as described in top comment. The overview is that the provider must be manually specified with The toolchain remains usable (as today) without the provider being specified. |
https://cirrus-ci.com/task/5352790488252416?logs=ci#L1675: [09:31:48.288] Extracting freetype...
[09:31:48.316] /ci_container_base/depends/sources/freetype-2.11.0.tar.xz: OK
[09:31:48.562] Preprocessing freetype...
[09:31:48.575] Configuring freetype...
[09:31:48.656] CMake Error at CMakeLists.txt:100 (cmake_minimum_required):
[09:31:48.656] Compatibility with CMake < 3.5 has been removed from CMake.
[09:31:48.656]
[09:31:48.656] Update the VERSION argument <min> value. Or, use the <min>...<max> syntax
[09:31:48.656] to tell CMake that the project requires at least <min> but has been updated
[09:31:48.656] to work with policies introduced by <max> or earlier.
[09:31:48.656]
[09:31:48.656] Or, add -DCMAKE_POLICY_VERSION_MINIMUM=3.5 to try configuring anyway.
[09:31:48.656]
[09:31:48.656]
[09:31:48.656] -- Configuring incomplete, errors occurred! |
ci/test/01_base_install.sh
Outdated
@@ -32,6 +32,18 @@ if [ -n "${APT_LLVM_V}" ]; then | |||
) | |||
fi | |||
|
|||
# Fetch newer cmake on Ubuntu 22.04 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure. The CI in this repo is probably the wrong place for fragile nightly tests. At a minimum, it would be good to pin the version. My preference would be to just use bookworm, see https://github.com/bitcoin/bitcoin/pull/32595/files#r2106854007
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to be clear, you mean switching the native_previous_releases job from ubuntu:22.04
to debian:bookworm
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, on bookworm (+ gcc12) we seem to fail on a new error: https://github.com/bitcoin/bitcoin/pull/32595/checks?check_run_id=44008178986 which I haven't looked into much yet
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fail on a new error:
This looks similar to what we are already working around in the native fuzz valgrind task, so it seems fine to use the same workaround here (-Wno-error=array-bounds
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My preference would be to keep at least one CI with the min required gcc version. Albeit I am not aware of any changes that would affect us, compared to gcc-12, it seems inconsistent to bump it early before bumping the minimum required.
4d568f9
to
05b9e17
Compare
05b9e17
to
62525d0
Compare
62525d0
to
3ac4ac9
Compare
This has a few advantages over the old method of simply copying headers: - Installs proper cmake files which can be picked up by our buildsystem - Only installs necessary headers, not all of boost Co-authored-by: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com>
The `FindBoost` module has been removed by policy CMP0167.
3ac4ac9
to
2e2d658
Compare
Ubuntu 22.04 supplies cmake 3.22 which is below our minimum version. - Switch to bookworm for cmake 3.25. - Set FORTIFY_SOURCE=2, as level 3 creates a wraning on this platform.
2e2d658
to
e350162
Compare
After depends have been built, print out the required flags needed to use the dependency provider along with the existing --toolchain message. Include configure output showing active toolchain and dependency provider information.
e350162
to
9347fdb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this, @willcl-ark ! I got nerd sniped on this and ended up learning a bunch about CMake, toolchains, and dependency providers.
As written now, I don't think this PR actually solves #32428, so per #32428 (comment), I do think for nix / nixos specifically we'd be better off going the simple route for now, and then continuing to work on this PR as a more comprehensive solution.
set(${package_name}_INCLUDE_DIR "${DEPENDS_DIR}/include" CACHE PATH "" FORCE) | ||
set(${package_name}_INCLUDEDIR "${DEPENDS_DIR}/include" CACHE PATH "" FORCE) | ||
set(${package_name}_LIBRARY_DIR "${DEPENDS_DIR}/lib" CACHE PATH "" FORCE) | ||
find_package(${package_name} ${ARGN} BYPASS_PROVIDER) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAICT, this doesn't quite do what we want. Ideally, we'd want to completely override find_package
's behaviour with our own custom logic, but this just sets some variables before calling the built-in find package (hence the BYPASS_PROVIDER
argument).
I noticed this because Qt was failing to build inside depends due to it still reaching out to the system installed Qt in my nix environment. To get around this, I was able to patch qt.mk
with:
--- a/depends/packages/qt.mk
+++ b/depends/packages/qt.mk
@@ -158,6 +158,11 @@ $(package)_config_env_darwin := OBJC="$$($(package)_cc)"
$(package)_config_env_darwin += OBJCXX="$$($(package)_cxx)"
$(package)_cmake_opts := -DCMAKE_PREFIX_PATH=$(host_prefix)
+$(package)_cmake_opts += -DCMAKE_FIND_ROOT_PATH=$(host_prefix)
+$(package)_cmake_opts += -DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY
+$(package)_cmake_opts += -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY
+$(package)_cmake_opts += -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY
+$(package)_cmake_opts += -DCMAKE_SYSTEM_PREFIX_PATH=$(host_prefix)
$(package)_cmake_opts += -DQT_FEATURE_cxx20=ON
$(package)_cmake_opts += -DQT_ENABLE_CXX_EXTENSIONS=OFF
ifneq ($(V),)
.. but that at least indicated to me that this approach is not doing what we'd expect. What we want is to fully restrict CMake to only use what is in depends, even if system packages are installed. To confirm this, I tried a nix build with libevent installed in the system packages, and the did a depends build with NO_LIBEVENT=1
and the final build of bitcoind did not fail and instead mixed the system libevent with the vendored dependencies.
I'm still reading up on dependency providers and find_package, so I don't have a concrete solution to propose, but my intuition so far says we'd be better of completely overriding find_package
with our own logic, instead of using find_package
with BYPASS_PROVIDER
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. Currently this provider is only configuring the correct directories dynamically on find_package()
calls, then "bypassing" fully over-riding find_package()
. So essentially it's more of a "configuration & passthrough provider".
I'm going to close this for now (could mark as up for grabs?) as a) this doesn't achieve any increased hermetic properties as it stands, and b) I agree with the comments in #32428 that we should implement a simple fix for Nix users first, with the aim of introducing a more full-featured provider in the future.
(This was actually my preferred approach, hence me including just such a patch in the original issue comment in #32428 (comment)
@@ -63,6 +63,10 @@ created. To use it during configuring Bitcoin Core: | |||
|
|||
cmake -B build --toolchain depends/x86_64-pc-linux-gnu/toolchain.cmake | |||
|
|||
To additionally use the depends [dependency provider](https://cmake.org/cmake/help/v3.24/guide/using-dependencies/index.html): | |||
|
|||
cmake -B build --toolchain depends/x86_64-pc-linux-gnu/toolchain.cmake -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=depends/x86_64-pc-linux-gnu/dependency_provider.cmake |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of my depth here, but one question I had while reading up on this was if we have a dependency provider, do we still need a toolchain?
Fixes: #32428
This PR adds a dependency provider to depends builds.
Currently the depends toolchain appears to rely on certain assumptions [citation needed] to find packages correctly. It does largely do this correctly, however NixOS sets some environment variables which interfere with this and cause builds from depends to fail, due to attempting to link system packages.
We can reproduce this interferrence by running a NixOS container and loading system packages using a flake:
A dependency provider allows the overriding of
cmake
'sfind_package()
therefore giving total control over where dependencies come from in a build.This achieves two things:
CMAKE_PREFIX_PATH
breaking builds (i.e. 32428)This provider must be specified along with the toolchain, with an invocation of the type:
To-do
cmake
, even after we installcmake
4.0.2. Fixed by using bookworm, gcc-12 and-Wno-error=array-bounds
in the previous releases job.