-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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
[vcpkg] Controlling top-level find_package #27950
base: master
Are you sure you want to change the base?
Conversation
FTR: The tracing part can be removed anytime without consequence. |
This seems to do something similar to #27606 and I like the idea behind this change. I don't understand how "bad" (i.e. without |
Still has the problem of consecutive calls being wrongly required.
I like the trace however. |
True, but I haven't seen this pattern very often. (And your example even ends with
I admit it isn't always as nice. The find_modules will insert extra output in many cases. But tracing remains possible. And in particular, you can grep for
I can't give such an example because this is out of scope (if I understand at all what you mean). Continuing my comment from #27606, the top-level packages should refer to direct dependencies. |
All qt6 ports do that. Component based lookup is also a possibilty |
Does the indentation reflect transitive dependencies?
In the output above I would consider
bad because the configure step wouldn't fail if |
@dg0yt Could you please solve the conflict? Thank you! |
83fe9bd
to
f7f08f0
Compare
This is exactly the kind of pattern the |
FTR there is another broken pattern: using
|
Ping. |
@BillyONeal Can the team look at this proposal? It would simplify to resolve unguarded function calls as noted in #29070 (comment). The next step might be to make |
We do want something like this but haven't had time to seriously look yet :(. Thanks! |
@BillyONeal Do you maybe now have time to do it? :) |
I don't expect it to happen in this planning cycle because getting a good answer to the tools situation, possibly solving the alternatives problem, and some artifacts stuff blowing up in important partners' faces are all higher priority things. I think Neumann-A had a starting point on what it would look like. (Different toolchain file that uses the new cmake dependency provider thingy they added a version or two ago) |
Oh I got confused as to what this was actually doing. Still not sure on priority of it vs. those other bits I mentioned. |
I guess you mean |
# Conflicts: # docs/users/buildsystems/cmake-integration.md
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.
Stupid question about this feature:
I understand the use case for disabling find_package only at the top level, as that helps to workaround ports doing 'optional dependencies' without transitively blocking things.
I'm not sure I understand why requiring find_package only at the top level makes sense though: if portfile.cmake
is going to ask that it be REQUIRED
, it had better be making sure that the dependency is present, meaning REQUIRED
should be OK everywhere.
Is there some use case I'm missing where it should be REQUIRED only at top level?
Would you be happy with naming this VCPKG_LOCK_TOP_LEVEL_FIND_PACKAGE_Xxx
or similar?
LOCK
to clearly say that this is going to enforce what the result is. Alternately:ENFORCE
?TOP_LEVEL
to clearly say that the critical difference is that this only affects the top level answer. But I could also see the argument that it should just always work like this so it shouldn't have theTOP_LEVEL
part?
Still has the problem of consecutive calls being wrongly required.
find_package(<Pkg> CONFIG) <- allowed to fail. find_package(<Pkg> REQUIRED)
I like the trace however.
I think it's fair that this feature is an improvement vs. the status quo and that projects which break from this pattern can use patches? Or is there something about this pattern uniquely broken by @dg0yt 's feature not also broken with CMAKE_Xxx_FIND_PACKAGE_Yyy
?
if(z_vcpkg_find_package_backup_id EQUAL "1") | ||
if(VCPKG_FIND_PACKAGE_${z_vcpkg_find_package_package_name}) | ||
# Avoid CMake warning when both REQUIRED and CMAKE_REQUIRE_FIND_PACKAGE_<Pkg> are used | ||
if(NOT "REQUIRED" IN_LIST z_vcpkg_find_package_${z_vcpkg_find_package_backup_id}_ARGN) |
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.
Stupid question: Why is "REQUIRED"
in quotes but z_vcpkg_find_package_${z_vcpkg_find_package_backup_id}_ARGN
not?
# Avoid CMake warning when both REQUIRED and CMAKE_REQUIRE_FIND_PACKAGE_<Pkg> are used | ||
if(NOT "REQUIRED" IN_LIST z_vcpkg_find_package_${z_vcpkg_find_package_backup_id}_ARGN) | ||
list(APPEND z_vcpkg_find_package_${z_vcpkg_find_package_backup_id}_backup_vars "CMAKE_REQUIRE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}") | ||
set(z_vcpkg_find_package_${z_vcpkg_find_package_backup_id}_backup_CMAKE_REQUIRE_FIND_PACKAGE_${z_vcpkg_find_package_package_name} "${CMAKE_REQUIRE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}}") |
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.
Stupid question: How does this do the right thing if CMAKE_REQUIRE_FIND_PACKAGE_Blah is undefined? It looks like the backup/restore thingy below would make it be empty string instead?
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.
Yeah I think this is wrong and it should be:
set(z_vcpkg_find_package_${z_vcpkg_find_package_backup_id}_backup_CMAKE_REQUIRE_FIND_PACKAGE_${z_vcpkg_find_package_package_name} "${CMAKE_REQUIRE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}}") | |
if(DEFINED "CMAKE_REQUIRE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}") | |
set(z_vcpkg_find_package_${z_vcpkg_find_package_backup_id}_backup_CMAKE_REQUIRE_FIND_PACKAGE_${z_vcpkg_find_package_package_name} "${CMAKE_REQUIRE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}}") | |
endif() |
Ditto below for the 'disable' arm
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.
Also, should we always backup and restore both the REQUIRED
and DISABLE
one? So that
-DCMAKE_DISABLE_FIND_PACKAGE_Blah=1 -DVCPKG_FIND_PACKAGE_Blah=1
chooses in favor of the VCPKG_
one. Or maybe we should just make such a case an error?
if(z_vcpkg_find_package_backup_id EQUAL "1") | ||
if(VCPKG_FIND_PACKAGE_${z_vcpkg_find_package_package_name}) |
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.
if(z_vcpkg_find_package_backup_id EQUAL "1") | |
if(VCPKG_FIND_PACKAGE_${z_vcpkg_find_package_package_name}) | |
if(z_vcpkg_find_package_backup_id EQUAL "1") | |
# This is the top-level find_package call | |
if(VCPKG_FIND_PACKAGE_${z_vcpkg_find_package_package_name}) |
elseif(DEFINED VCPKG_FIND_PACKAGE_${z_vcpkg_find_package_package_name}) | ||
list(APPEND z_vcpkg_find_package_${z_vcpkg_find_package_backup_id}_backup_vars "CMAKE_DISABLE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}") | ||
set(z_vcpkg_find_package_${z_vcpkg_find_package_backup_id}_backup_CMAKE_DISABLE_FIND_PACKAGE_${z_vcpkg_find_package_package_name} "${CMAKE_DISABLE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}}") | ||
set(CMAKE_DISABLE_FIND_PACKAGE_${z_vcpkg_find_package_package_name} 1) |
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.
It seems like this would result in the value being still disabled in transitive find_package
calls? What clears this when we're down a level?
Oh, Bill is an idiot:
set(CMAKE_DISABLE_FIND_PACKAGE_${z_vcpkg_find_package_package_name} 1) | |
# We don't need to worry about clearing this for transitive users because | |
# once this top level find_package is disabled, we immediately will return | |
# not found and not try to visit transitive dependencies in the first place. | |
set(CMAKE_DISABLE_FIND_PACKAGE_${z_vcpkg_find_package_package_name} 1) |
I think the case is in your post: We have no control over And the transitive code comes from other ports (= dependencies) or CMake. It changes independently. What builds now might fail when a dependency is updated. Maintainers of independent ports generally do not like to fix dependent ports. It is better to not increase coupling. |
If this PR gets a chance now, I can try to add a unit test. |
Makes sense.
The PR is getting a chance now :). The holdup has always been that we only had one reviewer who was confident enough in this CMake surgery to do a real review of something like this but he is rarely available to do reviews like that since he has manager-y things to do (that being @ras0219-msft ). In the last couple of years I think I finally understand this area well enough to review it. |
@ras0219-msft is concerned that this exposes a 'new feature' to people who aren't using vcpkg at all and wants these to only do something when they are inside a port somehow. Copying out the command line from |
Also I withdraw requesting "TOP_LEVEL" in the name but I would still like "LOCK". I can make that change if you want... |
It doesn't depend on building ports, it depends on using the vcpkg toolchain.
If you can do it now, it might speed it up. I will avoid pushes until July 14. |
Based on recent changes to
vcpkg.cmake
, this PR adds two behaviours which I was looking for in the past, both related to being able to control (automatic) dependencies with regard to installation order.Tracing find_package
Merged as #27982.
Controlling top-level find_package
Some projects enable behaviours automatically based on results of top-level
find_package
calls. To implement port feature control without patching, maintainers useCMAKE_REQUIRE_FIND_PACKAGE_<Pkg>
and/orCMAKE_DISABLE_FIND_PACKAGE_<Pkg>
. However, these variable maybe used as a pair, and they affect nested requirements.The second commit adds variable (template)
CMAKE_FIND_PACKAGE_<Pkg>
whichfind_package(<Pkg>)
required if true,find_package(<Pkg>)
disabled if false,CMAKE_FIND_PACKAGE_<Pkg>=ON
meetsfind_package(<Pkg> REQUIRED)
.This variable can be used easily with
vcpkg_check_features
.Hints can be printed when tracing is enabled.
Example output
From gdal with
-DVCPKG_TRACE_FIND_PACKAGE=ON -DVCPKG_FIND_PACKAGE_CryptoPP=0 -DVCPKG_FIND_PACKAGE_PROJ=1 -DVCPKG_FIND_PACKAGE_TIFF=0
:NB: The nested
find_package(TIFF)
is not affected byVCPKG_FIND_PACKAGE_TIFF=0
.(FTR port gdal shouldn't use
VCPKG_FIND_PACKAGE_<Pkg>
because it has proper feature control.)Use cases