Skip to content
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
2 changes: 2 additions & 0 deletions include/vcpkg/cmakevars.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ namespace vcpkg::CMakeVars
virtual Optional<const std::unordered_map<std::string, std::string>&> get_dep_info_vars(
const PackageSpec& spec) const = 0;

const std::unordered_map<std::string, std::string>& get_or_load_dep_info_vars(const PackageSpec& spec) const;

virtual Optional<const std::unordered_map<std::string, std::string>&> get_tag_vars(
const PackageSpec& spec) const = 0;

Expand Down
16 changes: 14 additions & 2 deletions include/vcpkg/dependencies.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ namespace vcpkg

namespace vcpkg::Dependencies
{
enum class UnsupportedPortAction : bool
{
Warn,
Error,
};

enum class RequestType
{
UNKNOWN,
Expand Down Expand Up @@ -118,6 +124,7 @@ namespace vcpkg::Dependencies
std::vector<RemovePlanAction> remove_actions;
std::vector<InstallPlanAction> already_installed;
std::vector<InstallPlanAction> install_actions;
std::vector<std::string> warnings;
};

enum class ExportPlanType
Expand Down Expand Up @@ -159,10 +166,14 @@ namespace vcpkg::Dependencies
struct CreateInstallPlanOptions
{
CreateInstallPlanOptions(Graphs::Randomizer* r, Triplet t) : randomizer(r), host_triplet(t) { }
CreateInstallPlanOptions(Triplet t) : host_triplet(t) { }
CreateInstallPlanOptions(Triplet t, UnsupportedPortAction action = UnsupportedPortAction::Error)
: host_triplet(t), unsupported_port_action(action)
{
}

Graphs::Randomizer* randomizer = nullptr;
Triplet host_triplet;
UnsupportedPortAction unsupported_port_action;
};

std::vector<RemovePlanAction> create_remove_plan(const std::vector<PackageSpec>& specs,
Expand Down Expand Up @@ -201,7 +212,8 @@ namespace vcpkg::Dependencies
const std::vector<Dependency>& deps,
const std::vector<DependencyOverride>& overrides,
const PackageSpec& toplevel,
Triplet host_triplet);
Triplet host_triplet,
UnsupportedPortAction unsupported_port_action);

void print_plan(const ActionPlan& action_plan, const bool is_recursive = true, const Path& builtin_ports_dir = {});
}
1 change: 1 addition & 0 deletions include/vcpkg/sourceparagraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ namespace vcpkg
std::string name;
std::vector<std::string> description;
std::vector<Dependency> dependencies;
PlatformExpression::Expr supports_expression;

Json::Object extra_info;

Expand Down
118 changes: 110 additions & 8 deletions src/vcpkg-test/dependencies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,15 @@ static ExpectedS<Dependencies::ActionPlan> create_versioned_install_plan(
const std::vector<DependencyOverride>& overrides,
const PackageSpec& toplevel)
{
return Dependencies::create_versioned_install_plan(
provider, bprovider, s_empty_mock_overlay, var_provider, deps, overrides, toplevel, Test::ARM_UWP);
return Dependencies::create_versioned_install_plan(provider,
bprovider,
s_empty_mock_overlay,
var_provider,
deps,
overrides,
toplevel,
Test::ARM_UWP,
Dependencies::UnsupportedPortAction::Error);
}

namespace vcpkg::Dependencies
Expand All @@ -235,8 +242,15 @@ namespace vcpkg::Dependencies
const std::vector<DependencyOverride>& overrides,
const PackageSpec& toplevel)
{
return vcpkg::Dependencies::create_versioned_install_plan(
provider, bprovider, oprovider, var_provider, deps, overrides, toplevel, Test::ARM_UWP);
return vcpkg::Dependencies::create_versioned_install_plan(provider,
bprovider,
oprovider,
var_provider,
deps,
overrides,
toplevel,
Test::ARM_UWP,
Dependencies::UnsupportedPortAction::Error);
}
}

Expand Down Expand Up @@ -1714,13 +1728,20 @@ TEST_CASE ("version install self features", "[versionplan]")
check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}, {"x", "y"});
}

static auto create_versioned_install_plan(MockVersionedPortfileProvider& vp,
MockBaselineProvider& bp,
std::vector<Dependency> deps,
MockCMakeVarProvider& var_provider)
{
return create_versioned_install_plan(vp, bp, var_provider, deps, {}, toplevel_spec());
}

static auto create_versioned_install_plan(MockVersionedPortfileProvider& vp,
MockBaselineProvider& bp,
std::vector<Dependency> deps)
{
MockCMakeVarProvider var_provider;

return create_versioned_install_plan(vp, bp, var_provider, deps, {}, toplevel_spec());
return create_versioned_install_plan(vp, bp, deps, var_provider);
}

TEST_CASE ("version install nonexisting features", "[versionplan]")
Expand Down Expand Up @@ -1963,7 +1984,7 @@ TEST_CASE ("version overlay ports", "[versionplan]")
Dependency{"a", {}, {}, {Constraint::Type::Minimum, "1", 1}},
},
{
DependencyOverride{"a", {"2", 0}},
DependencyOverride{"a", "2", 0},
},
toplevel_spec()));

Expand All @@ -1980,11 +2001,92 @@ TEST_CASE ("version overlay ports", "[versionplan]")
Dependency{"a"},
},
{
DependencyOverride{"a", {"2", 0}},
DependencyOverride{"a", "2", 0},
},
toplevel_spec()));

REQUIRE(install_plan.size() == 1);
check_name_and_version(install_plan.install_actions[0], "a", {"overlay", 0});
}
}

TEST_CASE ("respect supports expression", "[versionplan]")
{
using namespace PlatformExpression;
const auto supports_expression =
parse_platform_expression("windows", MultipleBinaryOperators::Deny).value_or_exit(VCPKG_LINE_INFO);
MockBaselineProvider bp;
bp.v["a"] = {"1", 0};

MockVersionedPortfileProvider vp;
vp.emplace("a", {"1", 0}).source_control_file->core_paragraph->supports_expression = supports_expression;
vp.emplace("a", {"1", 1});
MockCMakeVarProvider var_provider;
var_provider.dep_info_vars[{"a", toplevel_spec().triplet()}]["VCPKG_CMAKE_SYSTEM_NAME"] = "";
auto install_plan = create_versioned_install_plan(vp, bp, {{"a", {}}}, var_provider);
CHECK(install_plan.has_value());
var_provider.dep_info_vars[{"a", toplevel_spec().triplet()}]["VCPKG_CMAKE_SYSTEM_NAME"] = "Linux";
install_plan = create_versioned_install_plan(vp, bp, {{"a", {}}}, var_provider);
CHECK_FALSE(install_plan.has_value());
SECTION ("override")
{
// override from non supported to supported version
MockOverlayProvider oprovider;
install_plan = Dependencies::create_versioned_install_plan(
vp, bp, oprovider, var_provider, {Dependency{"a"}}, {DependencyOverride{"a", "1", 1}}, toplevel_spec());
CHECK(install_plan.has_value());
// override from supported to non supported version
bp.v["a"] = {"1", 1};
install_plan = Dependencies::create_versioned_install_plan(
vp, bp, oprovider, var_provider, {Dependency{"a"}}, {DependencyOverride{"a", "1", 0}}, toplevel_spec());
CHECK_FALSE(install_plan.has_value());
}
}

TEST_CASE ("respect supports expressions of features", "[versionplan]")
{
using namespace PlatformExpression;
MockBaselineProvider bp;
bp.v["a"] = {"1", 0};

MockVersionedPortfileProvider vp;
auto a_x = std::make_unique<FeatureParagraph>();
a_x->name = "x";
a_x->supports_expression =
parse_platform_expression("windows", MultipleBinaryOperators::Deny).value_or_exit(VCPKG_LINE_INFO);
vp.emplace("a", {"1", 0}).source_control_file->feature_paragraphs.push_back(std::move(a_x));
a_x = std::make_unique<FeatureParagraph>();
a_x->name = "x";
vp.emplace("a", {"1", 1}).source_control_file->feature_paragraphs.push_back(std::move(a_x));

MockCMakeVarProvider var_provider;
var_provider.dep_info_vars[{"a", toplevel_spec().triplet()}]["VCPKG_CMAKE_SYSTEM_NAME"] = "";
auto install_plan = create_versioned_install_plan(vp, bp, {{"a", {"x"}}}, var_provider);
CHECK(install_plan.has_value());
var_provider.dep_info_vars[{"a", toplevel_spec().triplet()}]["VCPKG_CMAKE_SYSTEM_NAME"] = "Linux";
install_plan = create_versioned_install_plan(vp, bp, {{"a", {"x"}}}, var_provider);
CHECK_FALSE(install_plan.has_value());
SECTION ("override")
{
// override from non supported to supported version
MockOverlayProvider oprovider;
install_plan = Dependencies::create_versioned_install_plan(vp,
bp,
oprovider,
var_provider,
{Dependency{"a", {"x"}}},
{DependencyOverride{"a", "1", 1}},
toplevel_spec());
CHECK(install_plan.has_value());
// override from supported to non supported version
bp.v["a"] = {"1", 1};
install_plan = Dependencies::create_versioned_install_plan(vp,
bp,
oprovider,
var_provider,
{Dependency{"a", {"x"}}},
{DependencyOverride{"a", "1", 0}},
toplevel_spec());
CHECK_FALSE(install_plan.has_value());
}
}
9 changes: 8 additions & 1 deletion src/vcpkg-test/manifests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,8 @@ TEST_CASE ("manifest construct maximum", "[manifests]")
]
},
"zuko": {
"description": ["son of the fire lord", "firebending 師父"]
"description": ["son of the fire lord", "firebending 師父"],
"supports": "!(windows & arm)"
}
}
})json");
Expand All @@ -654,6 +655,7 @@ TEST_CASE ("manifest construct maximum", "[manifests]")
REQUIRE(pgh.core_paragraph->dependencies[0].name == "bd");
REQUIRE(pgh.core_paragraph->default_features.size() == 1);
REQUIRE(pgh.core_paragraph->default_features[0] == "df");
REQUIRE(pgh.core_paragraph->supports_expression.is_empty());

REQUIRE(pgh.feature_paragraphs.size() == 2);

Expand All @@ -679,6 +681,11 @@ TEST_CASE ("manifest construct maximum", "[manifests]")
REQUIRE(pgh.feature_paragraphs[1]->description.size() == 2);
REQUIRE(pgh.feature_paragraphs[1]->description[0] == "son of the fire lord");
REQUIRE(pgh.feature_paragraphs[1]->description[1] == "firebending 師父");
REQUIRE(!pgh.feature_paragraphs[1]->supports_expression.is_empty());
REQUIRE_FALSE(pgh.feature_paragraphs[1]->supports_expression.evaluate(
{{"VCPKG_CMAKE_SYSTEM_NAME", ""}, {"VCPKG_TARGET_ARCHITECTURE", "arm"}}));
REQUIRE(pgh.feature_paragraphs[1]->supports_expression.evaluate(
{{"VCPKG_CMAKE_SYSTEM_NAME", ""}, {"VCPKG_TARGET_ARCHITECTURE", "x86"}}));

REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning));
}
Expand Down
12 changes: 12 additions & 0 deletions src/vcpkg/cmakevars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ namespace vcpkg::CMakeVars
load_tag_vars(install_package_specs, port_provider, host_triplet);
}

const std::unordered_map<std::string, std::string>& CMakeVarProvider::get_or_load_dep_info_vars(
const PackageSpec& spec) const
{
auto maybe_vars = get_dep_info_vars(spec);
if (!maybe_vars.has_value())
{
load_dep_info_vars({&spec, 1});
maybe_vars = get_dep_info_vars(spec);
}
return maybe_vars.value_or_exit(VCPKG_LINE_INFO);
}

namespace
{
struct TripletCMakeVarProvider : CMakeVarProvider
Expand Down
18 changes: 13 additions & 5 deletions src/vcpkg/commands.upgrade.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ namespace vcpkg::Commands::Upgrade

static constexpr StringLiteral OPTION_NO_DRY_RUN = "no-dry-run";
static constexpr StringLiteral OPTION_KEEP_GOING = "keep-going";
static constexpr StringLiteral OPTION_ALLOW_UNSUPPORTED_PORT = "allow-unsupported";

static constexpr std::array<CommandSwitch, 2> INSTALL_SWITCHES = {{
static constexpr std::array<CommandSwitch, 3> INSTALL_SWITCHES = {{
{OPTION_NO_DRY_RUN, "Actually upgrade"},
{OPTION_KEEP_GOING, "Continue installing packages on failure"},
{OPTION_ALLOW_UNSUPPORTED_PORT, "Instead of erroring on an unsupported port, continue with a warning."},
}};

const CommandStructure COMMAND_STRUCTURE = {
Expand All @@ -52,6 +54,9 @@ namespace vcpkg::Commands::Upgrade

const bool no_dry_run = Util::Sets::contains(options.switches, OPTION_NO_DRY_RUN);
const KeepGoing keep_going = to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING));
const auto unsupported_port_action = Util::Sets::contains(options.switches, OPTION_ALLOW_UNSUPPORTED_PORT)
? Dependencies::UnsupportedPortAction::Warn
: Dependencies::UnsupportedPortAction::Error;

BinaryCache binary_cache{args};
StatusParagraphs status_db = database_load_check(paths);
Expand Down Expand Up @@ -88,7 +93,7 @@ namespace vcpkg::Commands::Upgrade
var_provider,
Util::fmap(outdated_packages, [](const Update::OutdatedPackage& package) { return package.spec; }),
status_db,
{host_triplet});
{host_triplet, unsupported_port_action});
}
else
{
Expand Down Expand Up @@ -165,12 +170,15 @@ namespace vcpkg::Commands::Upgrade

if (to_upgrade.empty()) Checks::exit_success(VCPKG_LINE_INFO);

action_plan =
Dependencies::create_upgrade_plan(provider, var_provider, to_upgrade, status_db, {host_triplet});
action_plan = Dependencies::create_upgrade_plan(
provider, var_provider, to_upgrade, status_db, {host_triplet, unsupported_port_action});
}

Checks::check_exit(VCPKG_LINE_INFO, !action_plan.empty());

for (const auto& warning : action_plan.warnings)
{
print2(Color::warning, warning, '\n');
}
// Set build settings for all install actions
for (auto&& action : action_plan.install_actions)
{
Expand Down
Loading