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

Fix default features control by top level manifest #1331

Merged
merged 6 commits into from
Apr 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions azure-pipelines/end-to-end-tests-dir/manifests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ function feature {
}

$vcpkgJson = @{
'name' = 'toplevel-spec';
'default-features' = @( 'default-fail' );
'features' = @{
'default-fail' = feature 'vcpkg-fail-if-depended-upon';
Expand All @@ -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' )
};
}
}

Expand Down Expand Up @@ -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";
Expand Down
37 changes: 21 additions & 16 deletions src/vcpkg/dependencies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1331,29 +1331,31 @@ 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)
{
}

void add_override(const std::string& name, const Version& v);

void solve_with_roots(View<Dependency> dep, const PackageSpec& toplevel);
void solve_with_roots(View<Dependency> dep);

ExpectedL<ActionPlan> finalize_extract_plan(const PackageSpec& toplevel,
UnsupportedPortAction unsupported_port_action);
ExpectedL<ActionPlan> 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;

Expand Down Expand Up @@ -1592,10 +1594,14 @@ namespace vcpkg
Optional<VersionedPackageGraph::PackageNode&> 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;
}

Expand Down Expand Up @@ -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);
Expand All @@ -1670,19 +1675,19 @@ namespace vcpkg
m_overrides.emplace(name, v);
}

void VersionedPackageGraph::solve_with_roots(View<Dependency> deps, const PackageSpec& toplevel)
void VersionedPackageGraph::solve_with_roots(View<Dependency> 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;
}
Expand All @@ -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())
{
Expand Down Expand Up @@ -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<ActionPlan> VersionedPackageGraph::finalize_extract_plan(
const PackageSpec& toplevel, UnsupportedPortAction unsupported_port_action)
UnsupportedPortAction unsupported_port_action)
{
if (!m_errors.empty())
{
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
}
}
Loading