Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
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)
Comment thread
autoantwort marked this conversation as resolved.
Outdated
{
using std::end;
return find(cont, std::forward<V>(v)) != end(cont);
Comment thread
autoantwort marked this conversation as resolved.
Outdated
}

template<class Container, class Pred>
auto find_if(Container&& cont, Pred pred)
{
Expand Down
24 changes: 17 additions & 7 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 @@ -62,7 +63,7 @@ namespace vcpkg
{
FeatureSpec(const PackageSpec& spec, const std::string& feature) : m_spec(spec), m_feature(feature) { }

const std::string& name() const { return m_spec.name(); }
const std::string& port() const { return m_spec.name(); }
const std::string& feature() const { return m_feature; }
Triplet triplet() const { return m_spec.triplet(); }

Expand All @@ -73,16 +74,16 @@ namespace vcpkg

bool operator<(const FeatureSpec& other) const
{
if (name() < other.name()) return true;
if (name() > other.name()) return false;
if (port() < other.port()) return true;
if (port() > other.port()) return false;
if (feature() < other.feature()) return true;
if (feature() > other.feature()) return false;
return triplet() < other.triplet();
}

bool operator==(const FeatureSpec& other) const
{
return triplet() == other.triplet() && name() == other.name() && feature() == other.feature();
return triplet() == other.triplet() && port() == other.port() && feature() == other.feature();
}

bool operator!=(const FeatureSpec& other) const { return !(*this == other); }
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
2 changes: 1 addition & 1 deletion include/vcpkg/statusparagraphs.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace vcpkg
/// <summary>Find the StatusParagraph for given feature spec.</summary>
/// <param name="spec">Feature specification to find the status paragraph for</param>
/// <returns>Iterator for found spec</returns>
const_iterator find(const FeatureSpec& spec) const { return find(spec.name(), spec.triplet(), spec.feature()); }
const_iterator find(const FeatureSpec& spec) const { return find(spec.port(), spec.triplet(), spec.feature()); }

/// <summary>Find a StatusParagraph by name, triplet and feature.</summary>
/// <param name="name">Package name</param>
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,7 +218,8 @@ 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,
Expand All @@ -227,7 +228,7 @@ static ExpectedS<Dependencies::ActionPlan> create_versioned_install_plan(
deps,
overrides,
toplevel,
Test::ARM_UWP,
host_triplet,
Dependencies::UnsupportedPortAction::Error);
}

Expand Down Expand Up @@ -1535,6 +1536,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
2 changes: 1 addition & 1 deletion src/vcpkg/build.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1215,7 +1215,7 @@ namespace vcpkg::Build
{
for (const FeatureSpec& fspec : kv.second)
{
if (!(status_db.is_installed(fspec) || fspec.name() == name))
if (!(status_db.is_installed(fspec) || fspec.port() == name))
{
missing_fspecs.emplace_back(fspec);
}
Expand Down
Loading