-
Notifications
You must be signed in to change notification settings - Fork 73
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
Add maintainer guide entry on CMake variants and expand on "only-one-variant" #176
base: main
Are you sure you want to change the base?
Conversation
@ras0219-msft : Thanks for your contribution! The author(s) have been notified to review your proposed change. |
Learn Build status updates of commit 957875c: ✅ Validation status: passed
For more details, please refer to the build report. For any questions, please:
|
If a buildsystem patch is required for [Choose either static or shared binaries](#only-static-or-shared), you can also resolve [Provide all CMake variant targets](#provide-cmake-variants) by introducing stubs that have the original variant's [`EXPORT_NAME`](https://cmake.org/cmake/help/latest/prop_tgt/EXPORT_NAME.html). These stubs can be introduced as part of the same patch hunk. | ||
|
||
```cmake | ||
add_library(contoso SHARED contoso.c) | ||
add_library(contoso_static STATIC contoso.c) | ||
|
||
if(BUILD_SHARED_LIBS) | ||
set_target_properties(contoso_static PROPERTIES EXCLUDE_FROM_ALL 1) | ||
add_library(contoso_static_stub INTERFACE) | ||
set_target_properties(contoso_static_stub PROPERTIES EXPORT_NAME contoso_static INTERFACE_LINK_LIBRARIES contoso) | ||
install(TARGETS contoso contoso_static_stub EXPORT ContosoTargets) | ||
else() | ||
set_target_properties(contoso PROPERTIES EXCLUDE_FROM_ALL 1) | ||
add_library(contoso_stub INTERFACE) | ||
set_target_properties(contoso_stub PROPERTIES EXPORT_NAME contoso INTERFACE_LINK_LIBRARIES contoso_static) | ||
install(TARGETS contoso_stub contoso_static EXPORT ContosoTargets) | ||
endif() | ||
|
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.
I am against providing stubs. It up to upstream if they want to provide a library type agnostic target or not. So fix it upstream and not in vcpkg.
There is also an argument where this can lead to logical errors downstream. Where a consumer might check
if(TARGET EXISTS dep_static)
*** do something affecting my project which is wrong for dynamic dep ***
endif()
or the other way around.
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.
There is also an argument where this can lead to logical errors downstream.
I would be very interested in any concrete project you can point to where this causes problematic behavior. I don't think it's realistic for something like this to key off of the existence of the target, since the target's existence is wildly uncontrolled on different systems. For example, based on whether the "upstream" project was built with both or even find_package()
order.
I just don't think it's realistic that this will cause problems -- which makes me very curious if you have concrete examples!
I am against providing stubs. It up to upstream if they want to provide a library type agnostic target or not. So fix it upstream and not in vcpkg.
In a vacuum I agree, but the alternative here simply causes too much of a maintenance burden. Too many downstream projects assume one thing or the other and will break if only the static variant is available, or perhaps if only the shared variant is available for the dependency and we're asking that library to build statically.
Furthermore, this is a huge drop in adoption friction for existing applications that we don't control and can't fix. It's the difference between vcpkg being a drop-in replacement versus "The build breaks and I need to do an unknown amount of work to investigate".
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.
I'm mildly in support of @Neumann-A's position. The proposal decorates unofficial targets with official names, and it promotes lock-in. It doesn't only break (rare) target tests, but also looking up target properties (and such uses do exist).
Most adoption friction won't go away because the packages simply look for the dependency in a different way. Projects which only look for one variant indicate that the other variant isn't supported/tested. And vcpkg doesn't run the packages's test suites either.
And the usage heuristics will make uninformed proposals in both cases.
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.
I just don't think it's realistic that this will cause problems -- which makes me very curious if you have concrete examples!
I think netcdf-c once added H5_BUILD_DYNAMICALLY
(or similar) if it detected the hdf5 shared target leading to linker errors if it was a static build. Has been a long time since then.
Furthermore, this is a huge drop in adoption friction for existing applications that we don't control and can't fix
Don't fight battle you don't have to fight. Simply, this is not a problem for vcpkg to solve. vcpkg is a collection of build recipes somehow glued together and made to work. If upstream doesn't provide easy usage let them not provide easy usage and let people complain about it. If people complain about vcpkg not providing easy usage for X just delegate to upstream and close the issue. Otherwise upstream is never going to learn how to provide proper usage. There needs to be a learning experience for upstream since otherwise vcpkg will have to deal with build scripts which will silently get worse over time since vcpkg magically "fixes all the problems". It doesn't hurt adoption of vcpkg if it is clearly communicated and argued that X is to blame and vcpkg doesn't have any stakes in fixing X usage problems. If it hurts someones adoption it should hurts X adoption rate and vcpkg should amplify that instead of trying to fix it so that upstream has a stronger incentive to fix it.
I mean vcpkg once tried to supply vendored CMakeLists.txt
for everything and how well did that work in the end? The less vcpkg has to maintain the better.
A patch to fix static/shared targets in a downstream user is in general more transparent for an experienced user than hacking the targets upstream. It also fits better in the patching policy of vcpkg. Since hacking shared/static targets will never be merged upstream.
but also looking up target properties
That is another nail in the casket of this idea. shared targets on windows are expected to have IMPORTED_LOCATION
and IMPORTED_IMPLIB_LOCATION
set and at least VTK
is checking one of those.
It's the difference between vcpkg being a drop-in replacement versus "The build breaks and I need to do an unknown amount of work to investigate".
This implicitly assumes that the user didn't do its due diligent and hacked together their build scripts with implicit wrong assumptions. This is really not the case vcpkg should consider..... vcpkg generally works if users use cmake correctly and take care of the imported targets. Otherwise, there needs to be some kind of learning experience which needs to be paid in time.
Also about how many ports are we actually speaking about here? HDF5, zstd, another port I forgot?
Converting to draft for now - @ras0219-msft feel free to re-open when this is ready for review. |
This PR expands the existing "Choose either static or shared binaries" section with updated techniques and concrete examples.
This PR additionally adds a new maintainer guideline, "Provide all CMake variant targets," with remediation instructions.