Skip to content

[CMake] Don't override find_package() for builtins#22604

Open
guitargeek wants to merge 2 commits into
root-project:masterfrom
guitargeek:issue-8633
Open

[CMake] Don't override find_package() for builtins#22604
guitargeek wants to merge 2 commits into
root-project:masterfrom
guitargeek:issue-8633

Conversation

@guitargeek

@guitargeek guitargeek commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Targeted changes to make the find_package override unnecessary (more detail in inline comments and commit messages).

Closes #8633.

🤖 Done with the help of AI, which suggested an initial solution that I refined.

@guitargeek guitargeek self-assigned this Jun 14, 2026
@guitargeek guitargeek requested a review from bellenot as a code owner June 14, 2026 13:38
@guitargeek guitargeek added in:Build System clean build Ask CI to do non-incremental build on PR labels Jun 14, 2026
@guitargeek guitargeek changed the title [CMake] Don't override find_package() for builtins [CMake] Don't override find_package() for builtins Jun 14, 2026
@github-actions

github-actions Bot commented Jun 14, 2026

Copy link
Copy Markdown

Test Results

    19 files      19 suites   3d 2h 15m 34s ⏱️
 3 865 tests  3 812 ✅   4 💤 49 ❌
65 141 runs  64 887 ✅ 205 💤 49 ❌

For more details on these failures, see this check.

Results for commit cbcfc58.

♻️ This comment has been updated with latest results.

Comment thread builtins/zlib/CMakeLists.txt Outdated
Comment on lines +83 to +84
set(ZLIB_INCLUDE_DIR ${ZLIB_INCLUDE_DIR} CACHE PATH "Path to the builtin zlib headers" FORCE)
set(ZLIB_LIBRARY ${ROOT_ZLIB_LIBRARY} CACHE FILEPATH "Path to the builtin zlib library" FORCE)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
set(ZLIB_INCLUDE_DIR ${ZLIB_INCLUDE_DIR} CACHE PATH "Path to the builtin zlib headers" FORCE)
set(ZLIB_LIBRARY ${ROOT_ZLIB_LIBRARY} CACHE FILEPATH "Path to the builtin zlib library" FORCE)
set(ZLIB_INCLUDE_DIR ${ZLIB_INCLUDE_DIR} PARENT_SCOPE)
set(ZLIB_LIBRARY ${ROOT_ZLIB_LIBRARY} PARENT_SCOPE)

for consistency with above?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I'll try! As long as FindPNG (which does find_package(ZLIB) internally) picks up the builtin ZLIB we're good. We just need to set the right variables so find_package(ZLIB) knows ZLIB is already there, and it will not look for it again and find the system ZLIB.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, indeed it both works. The FindPNG -> find_package(ZLIB) happens in SearchInstalledSoftware, which is the parent scope. So setting these variables in the PARENT_SCOPE is indeed good enough. The global cache would only be needed if we frigger find_package(ZLIB) in arbitrary places, but that's not the case.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for doing it only in the parent scope. The cache is already full enough, and it should (in theory) be settable by the user to show ROOT the path to a different zlib.
(I doubt that this applies here, because the builtin is on when this code runs, but staying out of the cache if we can looks reasonable to me.)

@ferdymercury ferdymercury left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, just a minor nitpick

Comment thread builtins/zlib/CMakeLists.txt Outdated
Comment on lines +78 to +84
# Pre-seed the singular variables FindZLIB.cmake consumes (its REQUIRED_VARS:
# ZLIB_INCLUDE_DIR via find_path(), ZLIB_LIBRARY via its if(NOT ZLIB_LIBRARY)
# guard), so a real find_package(ZLIB) short-circuits the system search and
# reuses the builtin ZLIB::ZLIB target above. Setting this variable in the
# PARENT_SCOPE is sufficient, because that's SearchInstalledSoftware.cmake
# where also the other find_package(ZLIB) calls happen (indirectly via
# FindPNG). So a CACHE entry is not required.

@hageboeck hageboeck Jun 16, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about:

# The following variables can be set by users to override the behaviour of FindZLIB.cmake,
# so packages executing their own find_package(ZLIB) will find the builtin library.
# We use this to direct the zlib search of FindPNG to the builtin.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! Since we all agree here that we don't want the CACHE entry, the comment can be less defensive and shortened.

Comment thread interpreter/CMakeLists.txt Outdated
Comment on lines +25 to +29
# When ROOT provides zlib/zstd as builtins, disable them in the bundled LLVM so it
# cannot discover and link the *system* copy (mixing two versions in one process).
# We cannot point LLVM at the builtins instead: it probes them with a configure-time
# compile/link check, but the builtin libraries are only produced later by their
# ExternalProject, so the check would always fail.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, but does it still manage to use those libraries if they are disabled?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should! Let's verify this by setting LLVM_ENABLE_ZSTD and LLVM_ENABLE_ZLIB to FORCE_ON (LLVMs equivalent to our fail-on-missing that I just learned about 🙂 ):

https://github.com/root-project/root/blob/master/interpreter/llvm-project/llvm/cmake/config-ix.cmake#L179C8-L179C24

builtins/zstd defined the imported ZSTD::ZSTD target but never tied it to
the BUILTIN_ZSTD ExternalProject that actually produces libzstd.a. As a
result a parallel or targeted build (e.g. building only the Core target)
could try to link the archive before it exists. Add the dependency edge,
consistent with what builtins/zlib already does for BUILTIN_ZLIB.

🤖 Done by AI.
ROOT redefined the global find_package() command to no-op for its
builtins, so that sub-projects added later (notably the bundled LLVM)
and transitive find modules (e.g. FindPNG -> find_package(ZLIB)) would
reuse ROOT's builtin imported targets instead of re-discovering a system
copy. This relied on undocumented CMake behaviour and recursed
infinitely under tools that override find_package() themselves, such as
vcpkg (root-project#8633).

The override only ever did real work for ZLIB and zstd: every other name
in ROOT_BUILTINS was unnecessary (no find_package() consumer
downstream). Both are now handled directly, so the override and the
ROOT_BUILTINS list can be removed.

This makes ROOT compatible with vcpkg and other dependency providers
without changing behaviour: in builtin builds LLVM is still built without
zlib/zstd, and a system build is unaffected since find_package() is no
longer shadowed.

Closes root-project#8633.

🤖 Done with the help of AI, which suggested an initial solution that I
refined.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🤖AI-Assisted clean build Ask CI to do non-incremental build on PR in:Build System

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Don't replace CMake's find_package

4 participants