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

[vcpkg] Implement Default-Features #2697

Merged
merged 15 commits into from
Feb 15, 2018

Conversation

Squareys
Copy link
Contributor

@Squareys Squareys commented Jan 31, 2018

Hi @ras0219-msft !

As discussed on #2687, I am giving the implementation of default features a shot.

I have been playing around with a solution for the default features, trying to make it "feel clean". To make communication about the code easier, here's my WIP.

All feedback is greatly apprechiated. In case the "default" feature is to intrusive, I will start over based on your suggestion (already had this implemented at the time of the suggestion though, so might as well see what you think of this.)

Thanks!
Jonathan Hale

FeatureNodeEdges default_dependencies; // dependencies of "default" feature package
default_dependencies.build_edges =
filter_dependencies_to_specs(scf.core_paragraph->default_features, out_cluster.spec.triplet());
out_cluster.edges.emplace("default", std::move(default_dependencies));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ras0219-msft This and the following location are they key diffs that make me believe this could be a valid solution.

@ras0219-msft
Copy link
Contributor

From #2687 (comment):

>vcpkg install z0 // z0 depends on x0[core]
// should install defaults of x0 and z0 <- this the hard part

>vcpkg install x1[core,y]
>vcpkg install z1 // z1 depends on x1[core]
// should not install defaults of x1, but should install defaults of z1

>vcpkg install z2 x2[core,y] // z2 depends on x2[core]
// should not install defaults of x2, but should install defaults of z2

>vcpkg install x3[core,y]
>vcpkg upgrade
// should not install defaults of x3

>vcpkg install z4 x4 // z4 depends on x4[core]
// should install defaults of both x4 and z4

>vcpkg install z6[core,w] // z6 depends on x6[core]
// should not install defaults of z6 but should install defaults of x6

>vcpkg install x7[core,y]
>vcpkg install x7
// should install defaults of x7

The "idea" behind defaults is to represent what an uninformed user would think of the library. For example, let's take libarchive. You can actually build libarchive with essentially no compression algorithms (and it's pretty useless like that). But every compression algorithm should arguably listed as a separate feature.

Then, if my library depends on libarchive, but I don't need any particular compression algorithm, I should arguably depend on libarchive[core].

In the above configuration, if a user runs vcpkg install mylibrary, she might be missing some significant functionality out of the box but has no idea what libarchive is or why she should care. She just wants to write her program and saw that my library could do X, Y, and Z.

This might be combatted by duplicating every feature from libarchive into my package and making a suitable set be default, but that seems like a pretty terrible approach at scale.

Alternatively, we can recognize libarchive as a library that the user is "uninformed" of and install the defaults in the pursuit of producing a capable result by default. This is the approach I believe we should take.

Another example of where we apply this "informed" vs "uninformed" dynamic is when passing --head. Only the libraries listed on the install line are built using the latest upstream sources; the transitive dependencies are built using the latest stable as usual, because a failure in some random dependency 5 levels deep that you've never heard of is a poor experience ;p

@Squareys
Copy link
Contributor Author

Squareys commented Feb 1, 2018

@ras0219-msft Thanks for putting so much effort into clarifying that!

One idea regarding that:
@mosra was able to convince me, that this is indeed sufficient and allowing package maintainers to specifiy default packages for its dependent packages is not really that useful.

I'm leaving the below, but it is not relevant anymore.


Could it possibly be even better to let you, the developer of the library (call it "archive++") that depends on libarchive, decide on what features the user of your library would expect?
This would split a feature package dependency into "Minimally required dependencies" and "default dependencies".

To illustrate what I mean, this could be an example CONTROL for archive++:

# archive++/CONTROL
Source: archive++
Version: 0.1.0
Build-Depends: libarchive[core]
Build-Depends-Default: libarchive[gzip,lzma]
Description: One up on the libarchive library
Default-Features: quantum-compression, zero-byte-compression

Feature: quantum-compression
Build-Depends: qpp[core]
Build-Depends-Default: qpp[openmp]
Description: Compress a file onto a Qubyte.

[...]

This would still "hide" the dependency from an uninformed user and make it useable, but give the control over that to the package maintainer rather than the maintainer of the dependent package. And as an "inexperienced vcpkg user", I would not expect a dependency foo[core] to be installed as foo.
In cargo this seems to be handled with a flag to disable default features, which is done in vcpkg by explicitly specifying "core". But now this explicit specification would be overwritten by installing the default after all. Assume you actually do just depend on "core", there would be no way of specifying that currently, which is why this doesn't feel quite right.

I am happy to implement as proposed anyway, if you considered the above but don't find that problematic. It would probably make it even more complicated to implement, anyway.

@Squareys Squareys force-pushed the default-features branch 2 times, most recently from 134600b to d645c63 Compare February 2, 2018 14:29
@Squareys
Copy link
Contributor Author

Squareys commented Feb 2, 2018

@ras0219-msft If possible, some (very brief) feedback on the commits I just added would be apprechiated:

I implemented a first test in 26395fb0c4bd1dc55f1d515ff35e200c7421ad2f (and added documentation to everything I came across to aid my understanding). The test actually runs fine, I am usure why, as I didn't find default features implemented in any way yet, but maybe there is something already?

I am having slight difficulties understanding the remove_plan_check part. I guess that "remove" action is used to force a rebuild of the package when the features change?

Thanks in advance!

@ras0219-msft
Copy link
Contributor

I am having slight difficulties understanding the remove_plan_check part. I guess that "remove" action is used to force a rebuild of the package when the features change?

Yep! When we detect a package needs to be rebuilt, it manifests as a RemovePlanAction followed later by an InstallPlanAction. In your test, you had added an already-installed-package (that's what the statusparagraphs tracks) as well as a new package definition (that's what the PackageSpecMap tracks).

I didn't look too closely, but create_feature_install_plan determined that you needed a package rebuilt in that context, so it was reinstalling the same features that already were installed (1 and core).

I've taken the liberty to reduce the test down to what I think you wanted originally -- now there are no installed packages and a single portfile with Default-Features: 1. This results in only a single step in the "plan": an InstallPlanAction which currently doesn't have feature 1 selected (but it should!). Please feel free to revert the commit if it's not helpful :).

and added documentation to everything I came across to aid my understanding

Those are great, thank you very much 👍 !

@Squareys
Copy link
Contributor Author

Squareys commented Feb 2, 2018

@ras0219-msft That is super helpful, thank you very much!

Squareys and others added 9 commits February 3, 2018 16:16
Signed-off-by: Squareys <squareys@googlemail.com>
…sing

Signed-off-by: Squareys <squareys@googlemail.com>
Signed-off-by: Squareys <squareys@googlemail.com>
Signed-off-by: Squareys <squareys@googlemail.com>
Signed-off-by: Squareys <squareys@googlemail.com>
Signed-off-by: Squareys <squareys@googlemail.com>
Signed-off-by: Squareys <squareys@googlemail.com>
Signed-off-by: Squareys <squareys@googlemail.com>
@Squareys
Copy link
Contributor Author

Squareys commented Feb 3, 2018

@ras0219-msft The implemented tests now run successfully.

How should the following two cases be handled:

> vcpkg install x1
// x1 adds a feature to its "default features" list
> vcpkg upgrade
// Currently no way of telling that the user originally requested the default features
// Should this install the added default feature?

> vcpkg install a1[core] // depends on b1[core]
// b1 default features are installed
// b1 adds a feature to their default list
> vcpkg upgrade
// Should this install the added default feature of b1?

I believe tested that the latter would install the new default package with the current implementation, as it only adds features of user-requested packages to the "don't install defaults" list.

The former could be solved with a RequestType::USER_REQUESTED_DEFAULTS or something, in case that is supposed to install the new feature.

Signed-off-by: Squareys <squareys@googlemail.com>
@Squareys Squareys changed the title [WIP] Implement Default-Features [vcpkg] Implement Default-Features Feb 4, 2018
@Squareys
Copy link
Contributor Author

Squareys commented Feb 5, 2018

@ras0219-msft Pinging, just in case you missed the above message, no hurry.

@ras0219-msft
Copy link
Contributor

ras0219-msft commented Feb 6, 2018

I suppose an interesting question would be:

> vcpkg install a1[core]
// a1 adds a default feature
> vcpkg upgrade
// should this install the new default feature of a1?

I almost feel like it should, since this scenario is most likely mapping to "We're making something optional that was not optional before, so you should act like you've had it installed all along.".

Therefore, by the same logic, I think both of your above scenarios should also install new default packages.

This is a really good point, thanks for bringing it up!


Just to possibly clarify more: I think the logic should be "when rebuilding a package in a way that doesn't express explicit immediate desire to not install default features, any new default features should be added."

@Squareys
Copy link
Contributor Author

Squareys commented Feb 6, 2018

@ras0219-msft Alright, that makes sense, but sounds tricky to implement. Is there a way to tell what changed in a CONTROL/SourceFile since the last upgrade?

@ras0219-msft
Copy link
Contributor

Sorry for the delay!

The StatusParagraph/BinaryParagraph for the previously installed package should probably record the Default-Features, so that could be diff'd with the new list.

Signed-off-by: Squareys <squareys@googlemail.com>
Further down the line to create_feature_install_plan.

Signed-off-by: Squareys <squareys@googlemail.com>
Signed-off-by: Squareys <squareys@googlemail.com>
Signed-off-by: Squareys <squareys@googlemail.com>
@Squareys
Copy link
Contributor Author

@ras0219-msft Should be done!

If you need me to make any adjustments or changes/add some more tests, I'm happy to do so!

@ras0219-msft ras0219-msft merged commit 425d07e into microsoft:master Feb 15, 2018
@ras0219-msft
Copy link
Contributor

Thanks so much, these changes are awesome in every way (comments, tests, and functionality, oh my)!

@Squareys
Copy link
Contributor Author

Thanks for merging! 👍 And thank you for all the feedback, help and clarifications.
It was fun working on this with you!

Squareys added a commit to Squareys/vcpkg that referenced this pull request Feb 16, 2018
When a package dependency was not found (has no source control file),
install would exit with "Value was null" when trying to install its default
features, as the dependency would be marked erroneously as found in this
case.

Signed-off-by: Squareys <squareys@googlemail.com>
ras0219-msft pushed a commit that referenced this pull request Feb 16, 2018
When a package dependency was not found (has no source control file),
install would exit with "Value was null" when trying to install its default
features, as the dependency would be marked erroneously as found in this
case.

Signed-off-by: Squareys <squareys@googlemail.com>
ras0219-msft pushed a commit that referenced this pull request Feb 17, 2018
* Add libgta

Libgta is a portable library that implements the Generic Tagged Array (GTA)
file format.

Signed-off-by: Hiroshi Miura <miurahr@linux.com>

* [libgta] turn off document build and doxygen dependency

Signed-off-by: Hiroshi Miura <miurahr@linux.com>

* [libgta] add build-dependency

- bzip2, zlib and liblzma

Signed-off-by: Hiroshi Miura <miurahr@linux.com>

* [libgta] remove dlls when static build

Signed-off-by: Hiroshi Miura <miurahr@linux.com>

* Fix typo

* [libgta] update CONTROL

add lf at end of file.

* libmupdf version bump

* [qt5-base] Use system freetype.

* [opencv] Fix UWP and ARM

* [hdf5] Always use config mode for HDF5

* [opencv] Fixup -- apply patch added in previous commit

* [abseil] Add *.inc files. Fixes #2718

* [abseil] Update to 2018-2-5

* Fix for Issue #2729

Allows PowerShell to change the name of the downloaded directory correctly.

* vcpkgRemoveItem: nullcheck

* [cpprestsdk] Update to 2.10.2

* Adding Torch's TH library (#2737)

Adding Torch's TH library

* [flatbuffers] Fixes #2735

* sobjectizer updated to v.5.5.21

* [nghttp2] Enable static builds

* [nghttp2]: update to 1.30.0 (#2739)

* [nghttp2]: update to 1.30.0

* [nghttp2] Enable static builds

* Add epsilon library port

Signed-off-by: Hiroshi Miura <miurahr@linux.com>

* [vcpkg-configure-cmake] Use ninja to configure in parallel (#2712)

* [curl] Add nghttp2.lib to dependencies of curl

* [vtk] Fix breaking change in find_package(HDF5)

* Merge findFileRecursivelyUp into VcpkgPowershellUtils

* [vcpkgInvokeCommandClean] Don't use -encodedCommand.

Instead, use -Command with the appropriate number of escaped quotes
(which ended up being 3)

* [blosc] Update to 1.13.5

static-install-fix.patch no longer required (upstream contains the patched version).
Resolves build error with VS 15.6 in static builds

* [cgal] Avoid using absolute paths in cmake config file

* Update CHANGELOG and bump version to v0.0.104

* [qt5-base][qtdeploy] Deploy plugin dependencies to the executable's folder.

* Add libgeotiff port

Signed-off-by: Hiroshi Miura <miurahr@linux.com>

* [libgeotiff] fix install directory for cmake configurations

Signed-off-by: Hiroshi Miura <miurahr@linux.com>

* fix tiff detection error when static build

* [libgeotiff] remove installed dlls when static build

* [libgeotiff] update description

* [chipmunk] 7.0.2 initial.

* [recast] 1.5.1 initial.

* [tinydir] 1.2.3 initial.

* [mman] git-f5ff813 initial.

* Update Catch to 2.1.2 (#2763)

* [vcpkg-ci] Delete intermediate build folders even on unsuccesful builds

* [folly] Workaround bug for VS 15.6

* [pcre] fix space issue and add mirror (fix #2751)

* [realsense2] Update to v2.10.0

Update realsense2 port to librealsense v2.10.0.

* [libevent] Fix generated libevent targets files

* fixed typo in warning message (#2773)

* [blaze] update to Blaze 3.3

* [lmdb] Fix possible whitespace problem

* Fix date issue

* add qt5-quickcontrols2

* add qt5-quickcontrols port

* add qt5-graphicaleffects

* change compile order to debug first, fix #2767 (#2785)

* [liblzma] Add usage information

* [ffmpeg] Allow static builds of ffmpeg (#2783)

ffmpeg creates static .a libraries, so change the suffix to .lib

* [ffmpeg] Bump version for PR #2783

* [aubio] Update to handle static FFMPEG

* Copy local dependencies for library targets (#2787)

* Fix for issue #2786

* [vcpkg-cmake-toolchain] Only applocal dependencies for shared libraries

* [uriparser] Update to 0.8.5

* [vcpkg] Implement Default-Features (#2697)

* [vcpkg] Add Default-Feature to make_status_pgh utility function

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Parse "Default-Features" as dependencies and add test for parsing

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Document some methods and structures

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Add install_default_features_test

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Change install_default_features_test to not have preinstalled package

* [vcpkg] Test install behaviour of default features

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Implement default features

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Test default features upgrade behavior

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Implement upgrade with default features

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Test behaviour of upgrade with default features in dependencies

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Make upgrade install new default features

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Move collecting of packages for which to prevent defaults

Further down the line to create_feature_install_plan.

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Fix core missing from default features and potential inf loop

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Rename, fix and move some tests

Signed-off-by: Squareys <squareys@googlemail.com>

* Updated boost license to 1.66.0 (#2795)

I was a bit confused to see a reference to "1.65.1" while I was installing 1.66.0, but it turns out this URL is just not updated. This updates it.

* [vcpkg-find-acquire-program] Add mirror for NASM. Fixes #2777.

* update cuda requirement to 9.0, fixes #2791 (#2802)

* update cuda requirement to 9.0, fixes #2791

* [cuda] Restore sample version blob

* [vcpkg] http_proxy and https_proxy should be lowercase (#2815)

Pacman of Msys understands only lowercase environment variables
http_proxy and https_proxy.

* [vcpkg] Add find/find_installed/is_installed for FeatureSpec

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Fix build command for packages that depend of features

Signed-off-by: Squareys <squareys@googlemail.com>

* [liblo] Initial port (#2821)

* [portaudio] Added ASIO support to build

* Update libpng to 1.6.34

* [liblo] Initial port

* Revert "Update libpng to 1.6.34"

This reverts commit ede0bb9.

* Revert "[liblo] Initial port"

This reverts commit bb819eb.

* [liblo] Initial port

* [liblo] Use vcpkg_from_github() and vcpkg_fixup_cmake_targets()

* [liblo] Fix SHA512

* [openvr] update to 1.0.13 (#2809)

* [ebml] Initial port. (#2812)

* [vcpkg] Fix bug with missing dependencies introduced in #2697 (#2819)

When a package dependency was not found (has no source control file),
install would exit with "Value was null" when trying to install its default
features, as the dependency would be marked erroneously as found in this
case.

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Avoid using s::status_known() -- it does not do what you think it does

* [jansson] Update to 2.11 (#2820)

* [aws-sdk-cpp] update to 1.3.58 (#2810)

* [mkl] Add port MKL (#2806)

* [corrade,magnum,-plugins,-extras,-integration] Update to latest and support feature packages (#2687)

[corrade,magnum,-plugins,-extras,-integration] Update to latest and support feature packages

* [jbig2dec][libmupdf] Extract jbig2dec, remove remaining vendored 3rdparty
@ras0219-msft
Copy link
Contributor

Just wanted to drop back by to say that Default-Features are working great in all my uses so far :)

https://github.com/Microsoft/vcpkg/blob/dev/roschuma/opencv-rework/ports/opencv/CONTROL

@Squareys
Copy link
Contributor Author

Very happy to hear that, thanks! :D

strega-nil pushed a commit to strega-nil/vcpkg that referenced this pull request May 5, 2021
* [vcpkg] Add Default-Feature to make_status_pgh utility function

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Parse "Default-Features" as dependencies and add test for parsing

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Document some methods and structures

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Add install_default_features_test

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Change install_default_features_test to not have preinstalled package

* [vcpkg] Test install behaviour of default features

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Implement default features

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Test default features upgrade behavior

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Implement upgrade with default features

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Test behaviour of upgrade with default features in dependencies

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Make upgrade install new default features

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Move collecting of packages for which to prevent defaults

Further down the line to create_feature_install_plan.

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Fix core missing from default features and potential inf loop

Signed-off-by: Squareys <squareys@googlemail.com>

* [vcpkg] Rename, fix and move some tests

Signed-off-by: Squareys <squareys@googlemail.com>
strega-nil pushed a commit to strega-nil/vcpkg that referenced this pull request May 5, 2021
microsoft#2819)

When a package dependency was not found (has no source control file),
install would exit with "Value was null" when trying to install its default
features, as the dependency would be marked erroneously as found in this
case.

Signed-off-by: Squareys <squareys@googlemail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants