Skip to content
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

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

ras0219-msft
Copy link
Collaborator

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.

@prmerger-automator
Copy link

@ras0219-msft : Thanks for your contribution! The author(s) have been notified to review your proposed change.

@learn-build-service-prod
Copy link
Contributor

Learn Build status updates of commit 957875c:

✅ Validation status: passed

File Status Preview URL Details
vcpkg/contributing/maintainer-guide.md ✅Succeeded View

For more details, please refer to the build report.

For any questions, please:

Comment on lines +279 to +296
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()

Copy link
Contributor

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.

Copy link
Collaborator Author

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".

Copy link
Contributor

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.

Copy link
Contributor

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?

@AugP
Copy link
Collaborator

AugP commented Aug 13, 2024

Converting to draft for now - @ras0219-msft feel free to re-open when this is ready for review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants