From 87adc3f47d5327558b92b6e6925f1706047f7acd Mon Sep 17 00:00:00 2001 From: Kai Pastor Date: Sat, 20 Apr 2024 03:06:49 +0200 Subject: [PATCH] Fix default features control by top level manifest (#1331) --- .../end-to-end-tests-dir/manifests.ps1 | 75 +++++++++++++++++++ src/vcpkg/dependencies.cpp | 37 +++++---- 2 files changed, 96 insertions(+), 16 deletions(-) diff --git a/azure-pipelines/end-to-end-tests-dir/manifests.ps1 b/azure-pipelines/end-to-end-tests-dir/manifests.ps1 index 5e66eca742..f8fd585022 100644 --- a/azure-pipelines/end-to-end-tests-dir/manifests.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/manifests.ps1 @@ -14,6 +14,7 @@ function feature { } $vcpkgJson = @{ + 'name' = 'toplevel-spec'; 'default-features' = @( 'default-fail' ); 'features' = @{ 'default-fail' = feature 'vcpkg-fail-if-depended-upon'; @@ -29,6 +30,11 @@ $vcpkgJson = @{ 'default-features' = $False; 'features' = @( 'success' ) }; + 'no-default-features-3' = feature @{ + 'name' = 'toplevel-spec'; + 'default-features' = $False; + 'features' = @( 'no-default-features-1' ) + }; } } @@ -78,6 +84,75 @@ Throw-IfFailed Write-Trace "test manifest features: no-default-features, features = [no-default-features-2]" Run-Vcpkg install @noDefaultFeatureArgs --x-feature=no-default-features-2 Throw-IfFailed +Write-Trace "test manifest features: no-default-features, features = [no-default-features-1,no-default-features-3]" +Run-Vcpkg install @noDefaultFeatureArgs --x-feature=no-default-features-1 --x-feature=no-default-features-3 +Throw-IfFailed +Write-Trace "test manifest features: no-default-features, features = [no-default-features-3]" +Run-Vcpkg install @noDefaultFeatureArgs --x-feature=no-default-features-3 +Throw-IfFailed + +$vcpkgJson = @{ + 'default-features' = @( 'default-fail' ); + 'features' = @{ + 'default-fail' = feature 'vcpkg-fail-if-depended-upon'; + 'copied-feature' = feature 'vcpkg-empty-port' + 'multiple-dep-1' = feature 'vcpkg-empty-port' + 'multiple-dep-2' = feature 'vcpkg-empty-port' + 'no-default-features-1' = feature @{ + 'name' = 'vcpkg-default-features-fail'; + 'default-features' = $False; + }; + 'no-default-features-2' = feature @{ + 'name' = 'vcpkg-default-features-fail-require-other-feature'; + 'default-features' = $False; + 'features' = @( 'success' ) + }; + } +} + +Set-Content -Path "$manifestDir/vcpkg.json" ` + -Value (ConvertTo-Json -Depth 5 -InputObject $vcpkgJson) ` + -Encoding Ascii -NoNewline + +Write-Trace "test nameless manifest features: default-features, features = []" +Run-Vcpkg install @manifestDirArgs +Throw-IfNotFailed + +Write-Trace "test nameless manifest features: no-default-features, features = []" +Run-Vcpkg install @manifestDirArgs --x-no-default-features +Throw-IfFailed +Write-Trace "test nameless manifest features: default-features, features = [core]" +Run-Vcpkg install @manifestDirArgs --x-feature=core +Throw-IfFailed +# test having both +Write-Trace "test nameless manifest features: no-default-features, features = [core]" +Run-Vcpkg install @manifestDirArgs --x-no-default-features --x-feature=core +Throw-IfFailed + +Write-Trace "test nameless manifest features: no-default-features, features = [default-fail]" +Run-Vcpkg install @manifestDirArgs --x-no-default-features --x-feature=default-fail +Throw-IfNotFailed +Write-Trace "test nameless manifest features: default-features, features = [core, default-fail]" +Run-Vcpkg install @manifestDirArgs --x-feature=core --x-feature=default-fail +Throw-IfNotFailed + +Write-Trace "test nameless manifest features: no-default-features, features = [copied-feature]" +Run-Vcpkg install @noDefaultFeatureArgs --x-feature=copied-feature +Throw-IfFailed +Write-Trace "test nameless manifest features: no-default-features, features = [copied-feature, copied-feature]" +Run-Vcpkg install @noDefaultFeatureArgs --x-feature=copied-feature --x-feature=copied-feature +Throw-IfFailed + +Write-Trace "test nameless manifest features: no-default-features, features = [multiple-dep-1, multiple-dep-2]" +Run-Vcpkg install @noDefaultFeatureArgs --x-feature=multiple-dep-1 --x-feature=multiple-dep-2 +Throw-IfFailed + +Write-Trace "test nameless manifest features: no-default-features, features = [no-default-features-1]" +Run-Vcpkg install @noDefaultFeatureArgs --x-feature=no-default-features-1 +Throw-IfFailed +Write-Trace "test nameless manifest features: no-default-features, features = [no-default-features-2]" +Run-Vcpkg install @noDefaultFeatureArgs --x-feature=no-default-features-2 +Throw-IfFailed $vcpkgJson = @{ 'name' = "manifest-test"; diff --git a/src/vcpkg/dependencies.cpp b/src/vcpkg/dependencies.cpp index c4edad36e0..ca640508f9 100644 --- a/src/vcpkg/dependencies.cpp +++ b/src/vcpkg/dependencies.cpp @@ -1331,12 +1331,14 @@ namespace vcpkg const IBaselineProvider& base_provider, const IOverlayProvider& oprovider, const CMakeVars::CMakeVarProvider& var_provider, + const PackageSpec& toplevel, Triplet host_triplet, const Path& packages_dir) : m_ver_provider(ver_provider) , m_base_provider(base_provider) , m_o_provider(oprovider) , m_var_provider(var_provider) + , m_toplevel(toplevel) , m_host_triplet(host_triplet) , m_packages_dir(packages_dir) { @@ -1344,16 +1346,16 @@ namespace vcpkg void add_override(const std::string& name, const Version& v); - void solve_with_roots(View dep, const PackageSpec& toplevel); + void solve_with_roots(View dep); - ExpectedL finalize_extract_plan(const PackageSpec& toplevel, - UnsupportedPortAction unsupported_port_action); + ExpectedL finalize_extract_plan(UnsupportedPortAction unsupported_port_action); private: const IVersionedPortfileProvider& m_ver_provider; const IBaselineProvider& m_base_provider; const IOverlayProvider& m_o_provider; const CMakeVars::CMakeVarProvider& m_var_provider; + const PackageSpec& m_toplevel; const Triplet m_host_triplet; const Path m_packages_dir; @@ -1592,10 +1594,14 @@ namespace vcpkg Optional VersionedPackageGraph::require_package(const PackageSpec& spec, const std::string& origin) { + // Implicit defaults are disabled if spec is requested from top-level spec. + const bool default_features_mask = origin != m_toplevel.name(); + auto it = m_graph.find(spec); if (it != m_graph.end()) { it->second.origins.insert(origin); + it->second.default_features &= default_features_mask; return *it; } @@ -1650,9 +1656,8 @@ namespace vcpkg } } - // Implicit defaults are disabled if spec has been mentioned at top-level. + it->second.default_features = default_features_mask; // Note that if top-level doesn't also mark that reference as `[core]`, defaults will be re-engaged. - it->second.default_features = !Util::Maps::contains(m_user_requested, spec); it->second.requested_features.insert(FeatureNameCore.to_string()); require_scfl(*it, it->second.scfl, origin); @@ -1670,19 +1675,19 @@ namespace vcpkg m_overrides.emplace(name, v); } - void VersionedPackageGraph::solve_with_roots(View deps, const PackageSpec& toplevel) + void VersionedPackageGraph::solve_with_roots(View deps) { - auto dep_to_spec = [&toplevel, this](const Dependency& d) { - return PackageSpec{d.name, d.host ? m_host_triplet : toplevel.triplet()}; + auto dep_to_spec = [this](const Dependency& d) { + return PackageSpec{d.name, d.host ? m_host_triplet : m_toplevel.triplet()}; }; auto specs = Util::fmap(deps, dep_to_spec); - specs.push_back(toplevel); + specs.push_back(m_toplevel); Util::sort_unique_erase(specs); for (auto&& dep : deps) { if (!dep.platform.is_empty() && - !dep.platform.evaluate(m_var_provider.get_or_load_dep_info_vars(toplevel, m_host_triplet))) + !dep.platform.evaluate(m_var_provider.get_or_load_dep_info_vars(m_toplevel, m_host_triplet))) { continue; } @@ -1692,7 +1697,7 @@ namespace vcpkg m_roots.push_back(DepSpec{std::move(spec), dep.constraint, dep.features}); } - m_resolve_stack.push_back({toplevel, deps}); + m_resolve_stack.push_back({m_toplevel, deps}); while (!m_resolve_stack.empty()) { @@ -1798,7 +1803,7 @@ namespace vcpkg // This function is called after all versioning constraints have been resolved. It is responsible for // serializing out the final execution graph and performing all final validations. ExpectedL VersionedPackageGraph::finalize_extract_plan( - const PackageSpec& toplevel, UnsupportedPortAction unsupported_port_action) + UnsupportedPortAction unsupported_port_action) { if (!m_errors.empty()) { @@ -1905,7 +1910,7 @@ namespace vcpkg for (auto&& root : m_roots) { - auto x = push(root, toplevel.name()); + auto x = push(root, m_toplevel.name()); if (!x.has_value()) { return std::move(x).error(); @@ -2005,13 +2010,13 @@ namespace vcpkg const CreateInstallPlanOptions& options) { VersionedPackageGraph vpg( - provider, bprovider, oprovider, var_provider, options.host_triplet, options.packages_dir); + provider, bprovider, oprovider, var_provider, toplevel, options.host_triplet, options.packages_dir); for (auto&& o : overrides) { vpg.add_override(o.name, o.version); } - vpg.solve_with_roots(deps, toplevel); - return vpg.finalize_extract_plan(toplevel, options.unsupported_port_action); + vpg.solve_with_roots(deps); + return vpg.finalize_extract_plan(options.unsupported_port_action); } }