Skip to content

Commit

Permalink
Manifest mode: Don't enable default features for host dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
autoantwort committed Aug 29, 2021
1 parent 0e8fa97 commit aff1f89
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 25 deletions.
7 changes: 7 additions & 0 deletions include/vcpkg/base/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,13 @@ namespace vcpkg::Util
return std::find(begin(cont), end(cont), v);
}

template<class Container, class V>
auto contains(Container&& cont, V&& v)
{
using std::end;
return find(cont, v) != end(cont);
}

template<class Container, class Pred>
auto find_if(Container&& cont, Pred pred)
{
Expand Down
16 changes: 13 additions & 3 deletions include/vcpkg/packagespec.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <vcpkg/base/expected.h>
#include <vcpkg/base/json.h>
#include <vcpkg/base/optional.h>
#include <vcpkg/base/util.h>

#include <vcpkg/platform-expression.h>
#include <vcpkg/triplet.h>
Expand Down Expand Up @@ -149,21 +150,30 @@ namespace vcpkg

struct Dependency
{
// Remove when support for MSVC v140 is dropped.
Dependency(std::string n = {},
std::vector<std::string> f = {},
PlatformExpression::Expr expr = {},
DependencyConstraint dc = {},
bool h = false)
: name(std::move(n)), features(std::move(f)), platform(std::move(expr)), constraint(std::move(dc)), host(h)
: name(std::move(n))
, features(std::move(f))
, platform(std::move(expr))
, constraint(std::move(dc))
, host(h)
, default_features(Util::contains(features, "core") ? DefaultFeatures::No : DefaultFeatures::DontCare)
{
}
std::string name;
std::vector<std::string> features;
PlatformExpression::Expr platform;
DependencyConstraint constraint;
bool host = false;

enum class DefaultFeatures
{
Yes,
No,
DontCare
} default_features = DefaultFeatures::DontCare;
Json::Object extra_info;

friend bool operator==(const Dependency& lhs, const Dependency& rhs);
Expand Down
140 changes: 137 additions & 3 deletions src/vcpkg-test/dependencies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ T unwrap(ExpectedS<T> e)

static void check_name_and_version(const Dependencies::InstallPlanAction& ipa,
StringLiteral name,
Versions::Version v,
const Versions::Version& v,
std::initializer_list<StringLiteral> features = {})
{
CHECK(ipa.spec.name() == name);
Expand Down Expand Up @@ -218,10 +218,11 @@ static ExpectedS<Dependencies::ActionPlan> create_versioned_install_plan(
const CMakeVars::CMakeVarProvider& var_provider,
const std::vector<Dependency>& deps,
const std::vector<DependencyOverride>& overrides,
const PackageSpec& toplevel)
const PackageSpec& toplevel,
const Triplet host_triplet = Test::ARM_UWP)
{
return Dependencies::create_versioned_install_plan(
provider, bprovider, s_empty_mock_overlay, var_provider, deps, overrides, toplevel, Test::ARM_UWP);
provider, bprovider, s_empty_mock_overlay, var_provider, deps, overrides, toplevel, host_triplet);
}

namespace vcpkg::Dependencies
Expand Down Expand Up @@ -1521,6 +1522,139 @@ TEST_CASE ("version install transitive default features", "[versionplan]")
check_name_and_version(install_plan.install_actions[1], "b", {"1", 0});
}

TEST_CASE ("version dont install default features when host", "[versionplan]")
{
MockVersionedPortfileProvider vp;

auto a_x = make_fpgh("x");
auto& a_scf = vp.emplace("a", {"1", 0}, Scheme::Relaxed).source_control_file;
a_scf->core_paragraph->default_features.emplace_back("x");
a_scf->feature_paragraphs.push_back(std::move(a_x));

MockCMakeVarProvider var_provider;

MockBaselineProvider bp;
bp.v["a"] = {"1", 0};

SECTION ("only one host dependency ")
{
auto install_plan = unwrap(create_versioned_install_plan(
vp, bp, var_provider, {Dependency{"a", {}, {}, {}, true}}, {}, toplevel_spec()));
REQUIRE(install_plan.size() == 1);
check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}, {});
}
SECTION ("only one host dependency, default-features = true")
{
Dependency dep{"a", {}, {}, {}, true};
dep.default_features = Dependency::DefaultFeatures::Yes;
auto install_plan = unwrap(create_versioned_install_plan(vp, bp, var_provider, {dep}, {}, toplevel_spec()));
REQUIRE(install_plan.size() == 1);
check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}, {"x"});
}
SECTION ("triplet = host triplet")
{
auto install_plan = unwrap(
create_versioned_install_plan(vp,
bp,
var_provider,
{Dependency{"a", {}, {}, {}, true}, Dependency{"a", {}, {}, {}, false}},
{},
toplevel_spec(),
toplevel_spec().triplet()));
REQUIRE(install_plan.size() == 1);
check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}, {"x"});
}
SECTION ("triplet = host triplet, default-features = false")
{
auto install_plan = unwrap(
create_versioned_install_plan(vp,
bp,
var_provider,
{Dependency{"a", {}, {}, {}, true}, Dependency{"a", {"core"}, {}, {}, false}},
{},
toplevel_spec(),
toplevel_spec().triplet()));
REQUIRE(install_plan.size() == 1);
check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}, {});
}
}

TEST_CASE ("'default-features': true vs 'default-features': true", "[versionplan]")
{
MockVersionedPortfileProvider vp;

auto a_x = make_fpgh("x");
auto& a_scf = vp.emplace("a", {"1", 0}, Scheme::Relaxed).source_control_file;
a_scf->core_paragraph->default_features.emplace_back("x");
a_scf->feature_paragraphs.push_back(std::move(a_x));

MockCMakeVarProvider var_provider;

MockBaselineProvider bp;
bp.v["a"] = {"1", 0};

SECTION ("default-features = true, host = true")
{
Dependency dep_host{"a", {}, {}, {}, true};
dep_host.default_features = Dependency::DefaultFeatures::Yes;
Dependency dep_normal{"a", {}, {}, {}, false};
dep_normal.default_features = Dependency::DefaultFeatures::No;
auto install_plan = unwrap(create_versioned_install_plan(
vp, bp, var_provider, {dep_host, dep_normal}, {}, toplevel_spec(), toplevel_spec().triplet()));
REQUIRE(install_plan.size() == 1);
check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}, {"x"});
}
SECTION ("default-features = true, host = false")
{
Dependency dep_host{"a", {}, {}, {}, true};
dep_host.default_features = Dependency::DefaultFeatures::No;
Dependency dep_normal{"a", {}, {}, {}, false};
dep_normal.default_features = Dependency::DefaultFeatures::Yes;
auto install_plan = unwrap(create_versioned_install_plan(
vp, bp, var_provider, {dep_host, dep_normal}, {}, toplevel_spec(), toplevel_spec().triplet()));
REQUIRE(install_plan.size() == 1);
check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}, {"x"});
}
}

TEST_CASE ("version dont install default features when host (transitive)", "[versionplan]")
{
MockVersionedPortfileProvider vp;
MockBaselineProvider bp;
const auto create_port = [&](auto name) -> auto&
{
auto a_x = make_fpgh("x");
auto& a_scf = vp.emplace(name, {"1", 0}, Scheme::Relaxed).source_control_file;
a_scf->core_paragraph->default_features.emplace_back("x");
a_scf->feature_paragraphs.push_back(std::move(a_x));
bp.v[name] = {"1", 0};
return a_scf;
};
// every port has a default feature x; Dependencies a -> b, b -> c, c -> d
// we request a host dependency to "a" and a normal one to "c" while triplet = host-triplet
// => a and b should have no default features, c and d should have a default feature
create_port("a")->core_paragraph->dependencies.emplace_back("b");
create_port("b")->core_paragraph->dependencies.emplace_back("c");
create_port("c")->core_paragraph->dependencies.emplace_back("d");
create_port("d");

MockCMakeVarProvider var_provider;

auto install_plan =
unwrap(create_versioned_install_plan(vp,
bp,
var_provider,
{Dependency{"a", {}, {}, {}, true}, Dependency{"c", {}, {}, {}, false}},
{},
toplevel_spec(),
toplevel_spec().triplet()));
REQUIRE(install_plan.size() == 4);
check_name_and_version(install_plan.install_actions[0], "d", {"1", 0}, {"x"});
check_name_and_version(install_plan.install_actions[1], "c", {"1", 0}, {"x"});
check_name_and_version(install_plan.install_actions[2], "b", {"1", 0}, {});
check_name_and_version(install_plan.install_actions[3], "a", {"1", 0}, {});
}

static PlatformExpression::Expr parse_platform(StringView l)
{
return unwrap(PlatformExpression::parse_platform_expression(l, PlatformExpression::MultipleBinaryOperators::Deny));
Expand Down
Loading

0 comments on commit aff1f89

Please sign in to comment.