aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/src
diff options
context:
space:
mode:
authorDaniel Shaw <t-dansha@microsoft.com>2017-07-25 21:29:31 -0700
committerRobert Schumacher <roschuma@microsoft.com>2017-08-16 15:10:50 -0700
commit307b761df4197bf9cf1b69652808530e6219a868 (patch)
tree40dc026ac1522df8268865703e1182b9036a029b /toolsrc/src
parentbd7cd7f56d5d9fdfeb1f57810a2ea77bf4d7e31a (diff)
downloadvcpkg-307b761df4197bf9cf1b69652808530e6219a868.tar.gz
vcpkg-307b761df4197bf9cf1b69652808530e6219a868.zip
partial end to end feature packages hdf5
added vcpkg feature package support to other commands remove comments change qualifier bracket to parens added features to qualified dependencies
Diffstat (limited to 'toolsrc/src')
-rw-r--r--toolsrc/src/BinaryParagraph.cpp12
-rw-r--r--toolsrc/src/Paragraphs.cpp16
-rw-r--r--toolsrc/src/SourceParagraph.cpp57
-rw-r--r--toolsrc/src/StatusParagraphs.cpp26
-rw-r--r--toolsrc/src/commands_depends.cpp2
-rw-r--r--toolsrc/src/commands_install.cpp200
-rw-r--r--toolsrc/src/commands_remove.cpp27
-rw-r--r--toolsrc/src/commands_search.cpp2
-rw-r--r--toolsrc/src/test_install_plan.cpp50
-rw-r--r--toolsrc/src/tests_dependencies.cpp2
-rw-r--r--toolsrc/src/tests_paragraph.cpp28
-rw-r--r--toolsrc/src/vcpkg_Build.cpp46
-rw-r--r--toolsrc/src/vcpkg_Dependencies.cpp52
-rw-r--r--toolsrc/src/vcpkglib.cpp2
14 files changed, 431 insertions, 91 deletions
diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp
index 49e9d58e5..9abd388b9 100644
--- a/toolsrc/src/BinaryParagraph.cpp
+++ b/toolsrc/src/BinaryParagraph.cpp
@@ -87,7 +87,17 @@ namespace vcpkg
this->depends = filter_dependencies(fpgh.depends, triplet);
}
- std::string BinaryParagraph::displayname() const { return this->spec.to_string(); }
+ std::string BinaryParagraph::displayname() const
+ {
+ if (this->feature == "")
+ {
+ return this->spec.name() + "[core]:" + this->spec.triplet().to_string();
+ }
+ else
+ {
+ return this->spec.name() + "[" + this->feature + "]:" + this->spec.triplet().to_string();
+ }
+ }
std::string BinaryParagraph::dir() const { return this->spec.dir(); }
diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp
index 3749e919e..3a30f66a3 100644
--- a/toolsrc/src/Paragraphs.cpp
+++ b/toolsrc/src/Paragraphs.cpp
@@ -3,6 +3,7 @@
#include "ParagraphParseResult.h"
#include "Paragraphs.h"
#include "vcpkg_Files.h"
+#include "vcpkg_Util.h"
using namespace vcpkg::Parse;
@@ -226,14 +227,21 @@ namespace vcpkg::Paragraphs
return error_info;
}
- Expected<BinaryParagraph> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec)
+ Expected<BinaryControlFile> try_load_cached_control_package(const VcpkgPaths& paths, const PackageSpec& spec)
{
- Expected<std::unordered_map<std::string, std::string>> pghs =
- get_single_paragraph(paths.get_filesystem(), paths.package_dir(spec) / "CONTROL");
+ Expected<std::vector<std::unordered_map<std::string, std::string>>> pghs =
+ get_paragraphs(paths.get_filesystem(), paths.package_dir(spec) / "CONTROL");
if (auto p = pghs.get())
{
- return BinaryParagraph(*p);
+ BinaryControlFile bcf;
+ bcf.core_paragraph = BinaryParagraph(p->front());
+ p->erase(p->begin());
+
+ bcf.features =
+ Util::fmap(*p, [&](auto&& raw_feature) -> BinaryParagraph { return BinaryParagraph(raw_feature); });
+
+ return bcf;
}
return pghs.error();
diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp
index a37567f3a..2aab7c572 100644
--- a/toolsrc/src/SourceParagraph.cpp
+++ b/toolsrc/src/SourceParagraph.cpp
@@ -152,18 +152,61 @@ namespace vcpkg
return std::move(control_file);
}
+ Features parse_feature_list(const std::string& name)
+ {
+ Features f;
+ int end = (int)name.find(']');
+ if (end != std::string::npos)
+ {
+ int start = (int)name.find('[');
+
+ auto feature_name_list = name.substr(start + 1, end - start - 1);
+ f.name = name.substr(0, start);
+ f.features = parse_comma_list(feature_name_list);
+ }
+ else
+ {
+ f.name = name;
+ }
+ return f;
+ }
+
+ Dependency Dependency::parse_dependency(std::string name, std::string qualifier)
+ {
+ Dependency dep;
+ dep.qualifier = qualifier;
+ dep.depend = parse_feature_list(name);
+ return dep;
+ }
+
+ std::string Dependency::name() const
+ {
+ std::string str = this->depend.name;
+ if (this->depend.features.empty()) return str;
+
+ str += "[";
+ for (auto&& s : this->depend.features)
+ {
+ str += s + ",";
+ }
+ str.pop_back();
+ str += "]";
+ return str;
+ }
+
std::vector<Dependency> vcpkg::expand_qualified_dependencies(const std::vector<std::string>& depends)
{
return Util::fmap(depends, [&](const std::string& depend_string) -> Dependency {
auto pos = depend_string.find(' ');
- if (pos == std::string::npos) return {depend_string, ""};
+ if (pos == std::string::npos) return Dependency::parse_dependency(depend_string, "");
// expect of the form "\w+ \[\w+\]"
Dependency dep;
- dep.name = depend_string.substr(0, pos);
+
+ dep.depend.name = depend_string.substr(0, pos);
if (depend_string.c_str()[pos + 1] != '(' || depend_string[depend_string.size() - 1] != ')')
{
// Error, but for now just slurp the entire string.
- return {depend_string, ""};
+ return Dependency::parse_dependency(depend_string, "");
}
dep.qualifier = depend_string.substr(pos + 2, depend_string.size() - pos - 3);
return dep;
@@ -210,13 +253,17 @@ namespace vcpkg
{
if (dep.qualifier.empty() || t.canonical_name().find(dep.qualifier) != std::string::npos)
{
- ret.push_back(dep.name);
+ ret.emplace_back(dep.name());
}
}
return ret;
}
- const std::string& to_string(const Dependency& dep) { return dep.name; }
+ const std::string to_string(const Dependency& dep)
+ {
+ std::string name = dep.name();
+ return name;
+ }
ExpectedT<Supports, std::vector<std::string>> Supports::parse(const std::vector<std::string>& strs)
{
diff --git a/toolsrc/src/StatusParagraphs.cpp b/toolsrc/src/StatusParagraphs.cpp
index 27f3c30a2..02ee61f75 100644
--- a/toolsrc/src/StatusParagraphs.cpp
+++ b/toolsrc/src/StatusParagraphs.cpp
@@ -27,6 +27,30 @@ namespace vcpkg
});
}
+ std::vector<std::unique_ptr<StatusParagraph>*> StatusParagraphs::find_all(const std::string& name,
+ const Triplet& triplet)
+ {
+ std::vector<std::unique_ptr<StatusParagraph>*> spghs;
+ for (auto&& p : *this)
+ {
+ if (p->package.spec.name() == name && p->package.spec.triplet() == triplet)
+ {
+ spghs.emplace_back(&p);
+ }
+ }
+ return spghs;
+ }
+
+ StatusParagraphs::iterator StatusParagraphs::find(const std::string& name,
+ const Triplet& triplet,
+ const std::string& feature)
+ {
+ return std::find_if(begin(), end(), [&](const std::unique_ptr<StatusParagraph>& pgh) {
+ const PackageSpec& spec = pgh->package.spec;
+ return spec.name() == name && spec.triplet() == triplet && pgh->package.feature == feature;
+ });
+ }
+
StatusParagraphs::const_iterator StatusParagraphs::find_installed(const std::string& name,
const Triplet& triplet) const
{
@@ -43,7 +67,7 @@ namespace vcpkg
{
Checks::check_exit(VCPKG_LINE_INFO, pgh != nullptr, "Inserted null paragraph");
const PackageSpec& spec = pgh->package.spec;
- auto ptr = find(spec.name(), spec.triplet());
+ auto ptr = find(spec.name(), spec.triplet(), pgh->package.feature);
if (ptr == end())
{
paragraphs.push_back(std::move(pgh));
diff --git a/toolsrc/src/commands_depends.cpp b/toolsrc/src/commands_depends.cpp
index 2d1fb658b..b04af5282 100644
--- a/toolsrc/src/commands_depends.cpp
+++ b/toolsrc/src/commands_depends.cpp
@@ -46,7 +46,7 @@ namespace vcpkg::Commands::DependInfo
for (auto&& source_control_file : source_control_files)
{
const SourceParagraph& source_paragraph = *source_control_file->core_paragraph;
- auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name; });
+ auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name(); });
System::println("%s: %s", source_paragraph.name, s);
}
diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp
index 2ce5b6c62..2965d9025 100644
--- a/toolsrc/src/commands_install.cpp
+++ b/toolsrc/src/commands_install.cpp
@@ -211,10 +211,10 @@ namespace vcpkg::Commands::Install
}
}
- void install_package(const VcpkgPaths& paths, const BinaryParagraph& binary_paragraph, StatusParagraphs* status_db)
+ void install_package(const VcpkgPaths& paths, const BinaryControlFile& bcf, StatusParagraphs* status_db)
{
- const fs::path package_dir = paths.package_dir(binary_paragraph.spec);
- const Triplet& triplet = binary_paragraph.spec.triplet();
+ const fs::path package_dir = paths.package_dir(bcf.core_paragraph.spec);
+ const Triplet& triplet = bcf.core_paragraph.spec.triplet();
const std::vector<StatusParagraphAndAssociatedFiles> pgh_and_files = get_installed_files(paths, *status_db);
const SortedVector<std::string> package_files =
@@ -234,7 +234,7 @@ namespace vcpkg::Commands::Install
System::println(System::Color::error,
"The following files are already installed in %s and are in conflict with %s",
triplet_install_path.generic_string(),
- binary_paragraph.spec);
+ bcf.core_paragraph.spec);
System::print("\n ");
System::println(Strings::join("\n ", intersection));
System::println("");
@@ -242,27 +242,42 @@ namespace vcpkg::Commands::Install
}
StatusParagraph source_paragraph;
- source_paragraph.package = binary_paragraph;
+ source_paragraph.package = bcf.core_paragraph;
source_paragraph.want = Want::INSTALL;
source_paragraph.state = InstallState::HALF_INSTALLED;
- for (auto&& dep : source_paragraph.package.depends)
- {
- if (status_db->find_installed(dep, source_paragraph.package.spec.triplet()) == status_db->end())
- {
- Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
+
write_update(paths, source_paragraph);
status_db->insert(std::make_unique<StatusParagraph>(source_paragraph));
+ std::vector<StatusParagraph> features_spghs;
+ for (auto&& feature : bcf.features)
+ {
+ features_spghs.emplace_back();
+
+ StatusParagraph& feature_paragraph = features_spghs.back();
+ feature_paragraph.package = feature;
+ feature_paragraph.want = Want::INSTALL;
+ feature_paragraph.state = InstallState::HALF_INSTALLED;
+
+ write_update(paths, feature_paragraph);
+ status_db->insert(std::make_unique<StatusParagraph>(feature_paragraph));
+ }
+
const InstallDir install_dir = InstallDir::from_destination_root(
- paths.installed, triplet.to_string(), paths.listfile_path(binary_paragraph));
+ paths.installed, triplet.to_string(), paths.listfile_path(bcf.core_paragraph));
install_files_and_write_listfile(paths.get_filesystem(), package_dir, install_dir);
source_paragraph.state = InstallState::INSTALLED;
write_update(paths, source_paragraph);
status_db->insert(std::make_unique<StatusParagraph>(source_paragraph));
+
+ for (auto&& feature_paragraph : features_spghs)
+ {
+ feature_paragraph.state = InstallState::INSTALLED;
+ write_update(paths, feature_paragraph);
+ status_db->insert(std::make_unique<StatusParagraph>(feature_paragraph));
+ }
}
using Build::BuildResult;
@@ -312,8 +327,8 @@ namespace vcpkg::Commands::Install
}
System::println("Building package %s... done", display_name);
- const BinaryParagraph bpgh =
- Paragraphs::try_load_cached_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO);
+ const BinaryControlFile bpgh =
+ Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO);
System::println("Installing package %s... ", display_name);
install_package(paths, bpgh, &status_db);
System::println(System::Color::success, "Installing package %s... done", display_name);
@@ -322,10 +337,11 @@ namespace vcpkg::Commands::Install
if (plan_type == InstallPlanType::BUILD_AND_INSTALL && g_feature_packages)
{
+ const std::string display_name_feature = action.displayname();
if (use_head_version)
- System::println("Building package %s from HEAD... ", display_name);
+ System::println("Building package %s from HEAD... ", display_name_feature);
else
- System::println("Building package %s... ", display_name);
+ System::println("Building package %s... ", display_name_feature);
const Build::BuildPackageConfig build_config{
*action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO),
@@ -339,13 +355,13 @@ namespace vcpkg::Commands::Install
System::println(System::Color::error, Build::create_error_message(result.code, action.spec));
return result.code;
}
- System::println("Building package %s... done", display_name);
+ System::println("Building package %s... done", display_name_feature);
- const BinaryParagraph bpgh =
- Paragraphs::try_load_cached_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO);
- System::println("Installing package %s... ", display_name);
- install_package(paths, bpgh, &status_db);
- System::println(System::Color::success, "Installing package %s... done", display_name);
+ const BinaryControlFile bcf =
+ Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO);
+ System::println("Installing package %s... ", display_name_feature);
+ install_package(paths, bcf, &status_db);
+ System::println(System::Color::success, "Installing package %s... done", display_name_feature);
return BuildResult::SUCCEEDED;
}
@@ -357,7 +373,9 @@ namespace vcpkg::Commands::Install
System::Color::warning, "Package %s is already built -- not building from HEAD", display_name);
}
System::println("Installing package %s... ", display_name);
- install_package(paths, action.any_paragraph.binary_paragraph.value_or_exit(VCPKG_LINE_INFO), &status_db);
+ install_package(paths,
+ BinaryControlFile{action.any_paragraph.binary_paragraph.value_or_exit(VCPKG_LINE_INFO)},
+ &status_db);
System::println(System::Color::success, "Installing package %s... done", display_name);
return BuildResult::SUCCEEDED;
}
@@ -365,11 +383,27 @@ namespace vcpkg::Commands::Install
Checks::unreachable(VCPKG_LINE_INFO);
}
+ static void print_plan(const std::vector<const InstallPlanAction*> rebuilt_plans,
+ const std::vector<const InstallPlanAction*> new_plans)
+ {
+ const std::string rebuilt_string = Strings::join("\n", rebuilt_plans, [](const InstallPlanAction* p) {
+ return Dependencies::to_output_string(p->request_type, p->displayname());
+ });
+
+ const std::string new_string = Strings::join("\n", new_plans, [](const InstallPlanAction* p) {
+ return Dependencies::to_output_string(p->request_type, p->displayname());
+ });
+
+ if (rebuilt_plans.size() > 0) System::println("The following packages will be rebuilt:\n%s", rebuilt_string);
+ if (new_plans.size() > 0) System::println("The following packages will be installed:\n%s", new_string);
+ }
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
{
static const std::string OPTION_DRY_RUN = "--dry-run";
static const std::string OPTION_USE_HEAD_VERSION = "--head";
static const std::string OPTION_NO_DOWNLOADS = "--no-downloads";
+ static const std::string OPTION_RECURSE = "--recurse";
// input sanitization
static const std::string example =
@@ -383,14 +417,130 @@ namespace vcpkg::Commands::Install
Input::check_triplet(spec.triplet(), paths);
const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments(
- {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS});
+ {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS, OPTION_RECURSE});
const bool dryRun = options.find(OPTION_DRY_RUN) != options.cend();
const bool use_head_version = options.find(OPTION_USE_HEAD_VERSION) != options.cend();
const bool no_downloads = options.find(OPTION_NO_DOWNLOADS) != options.cend();
+ const bool isRecursive = options.find(OPTION_RECURSE) != options.cend();
// create the plan
StatusParagraphs status_db = database_load_check(paths);
+ if (g_feature_packages)
+ {
+ const std::vector<FullPackageSpec> full_specs = Util::fmap(args.command_arguments, [&](auto&& arg) {
+ return Input::check_and_get_full_package_spec(arg, default_triplet, example);
+ });
+
+ std::unordered_map<PackageSpec, SourceControlFile> scf_map;
+ auto all_ports = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports);
+ for (auto&& port : all_ports.paragraphs)
+ {
+ auto pkg_spec = PackageSpec::from_name_and_triplet(port->core_paragraph->name, default_triplet)
+ .value_or_exit(VCPKG_LINE_INFO);
+ scf_map[pkg_spec] = std::move(*port);
+ }
+ std::vector<Dependencies::AnyAction> action_plan =
+ Dependencies::create_feature_install_plan(scf_map, full_specs, status_db);
+ // install plan will be empty if it is already installed - need to change this at status paragraph part
+ Checks::check_exit(
+ VCPKG_LINE_INFO, !action_plan.empty(), "Install plan cannot be empty for feature packages");
+
+ const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version),
+ Build::to_allow_downloads(!no_downloads)};
+
+ std::vector<const RemovePlanAction*> remove_plans;
+
+ std::vector<const InstallPlanAction*> rebuilt_plans;
+ std::vector<const InstallPlanAction*> new_plans;
+
+ // removal will happen before install
+ for (auto&& action : action_plan)
+ {
+ if (auto install_action = action.install_plan.get())
+ {
+ auto it = Util::find_if(
+ remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; });
+ if (it != remove_plans.end())
+ {
+ rebuilt_plans.emplace_back(install_action);
+ }
+ else
+ {
+ new_plans.emplace_back(install_action);
+ }
+ }
+ else if (auto remove_action = action.remove_plan.get())
+ {
+ remove_plans.emplace_back(remove_action);
+ }
+ }
+
+ print_plan(rebuilt_plans, new_plans);
+
+ if (remove_plans.size() > 0 && !isRecursive)
+ {
+ System::println(System::Color::warning,
+ "If you are sure you want to rebuild the above packages, run the command with the "
+ "--recurse option");
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
+
+ // execute the plan
+ for (const Dependencies::AnyAction& any_action : action_plan)
+ {
+ if (auto install_action = any_action.install_plan.get())
+ {
+ const BuildResult result =
+ perform_install_plan_action(paths, *install_action, install_plan_options, status_db);
+ if (result != BuildResult::SUCCEEDED)
+ {
+ System::println(Build::create_user_troubleshooting_message(install_action->spec));
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
+ }
+ else if (auto remove_action = any_action.remove_plan.get())
+ {
+ static const std::string OPTION_PURGE = "--purge";
+ static const std::string OPTION_NO_PURGE = "--no-purge";
+
+ const bool alsoRemoveFolderFromPackages = options.find(OPTION_NO_PURGE) == options.end();
+ if (options.find(OPTION_PURGE) != options.end() && !alsoRemoveFolderFromPackages)
+ {
+ // User specified --purge and --no-purge
+ System::println(System::Color::error, "Error: cannot specify both --no-purge and --purge.");
+ System::print(example);
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
+ const std::string display_name = remove_action->spec.to_string();
+ switch (remove_action->plan_type)
+ {
+ case RemovePlanType::NOT_INSTALLED:
+ System::println(System::Color::success, "Package %s is not installed", display_name);
+ break;
+ case RemovePlanType::REMOVE:
+ System::println("Removing package %s... ", display_name);
+ Commands::Remove::remove_package(paths, remove_action->spec, &status_db);
+ System::println(System::Color::success, "Removing package %s... done", display_name);
+ break;
+ case RemovePlanType::UNKNOWN:
+ default: Checks::unreachable(VCPKG_LINE_INFO);
+ }
+
+ if (alsoRemoveFolderFromPackages)
+ {
+ System::println("Purging package %s... ", display_name);
+ Files::Filesystem& fs = paths.get_filesystem();
+ std::error_code ec;
+ fs.remove_all(paths.packages / remove_action->spec.dir(), ec);
+ System::println(System::Color::success, "Purging package %s... done", display_name);
+ }
+ }
+ }
+
+ Checks::exit_success(VCPKG_LINE_INFO);
+ }
+
Dependencies::PathsPortFile paths_port_file(paths);
std::vector<InstallPlanAction> install_plan =
Dependencies::create_install_plan(paths_port_file, specs, status_db);
diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp
index eabf2b9ae..e480f02dd 100644
--- a/toolsrc/src/commands_remove.cpp
+++ b/toolsrc/src/commands_remove.cpp
@@ -17,13 +17,19 @@ namespace vcpkg::Commands::Remove
void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db)
{
auto& fs = paths.get_filesystem();
- StatusParagraph& pkg = **status_db->find(spec.name(), spec.triplet());
+ auto spghs = status_db->find_all(spec.name(), spec.triplet());
+ auto core_pkg = **status_db->find(spec.name(), spec.triplet(), "");
- pkg.want = Want::PURGE;
- pkg.state = InstallState::HALF_INSTALLED;
- write_update(paths, pkg);
+ for (auto&& spgh : spghs)
+ {
+ StatusParagraph& pkg = **spgh;
+ if (pkg.state != InstallState::INSTALLED) continue;
+ pkg.want = Want::PURGE;
+ pkg.state = InstallState::HALF_INSTALLED;
+ write_update(paths, pkg);
+ }
- auto maybe_lines = fs.read_lines(paths.listfile_path(pkg.package));
+ auto maybe_lines = fs.read_lines(paths.listfile_path(core_pkg.package));
if (auto lines = maybe_lines.get())
{
@@ -80,11 +86,16 @@ namespace vcpkg::Commands::Remove
}
}
- fs.remove(paths.listfile_path(pkg.package));
+ fs.remove(paths.listfile_path(core_pkg.package));
}
- pkg.state = InstallState::NOT_INSTALLED;
- write_update(paths, pkg);
+ for (auto&& spgh : spghs)
+ {
+ StatusParagraph& pkg = **spgh;
+ if (pkg.state != InstallState::HALF_INSTALLED) continue;
+ pkg.state = InstallState::NOT_INSTALLED;
+ write_update(paths, pkg);
+ }
}
static void print_plan(const std::map<RemovePlanType, std::vector<const RemovePlanAction*>>& group_by_plan_type)
diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp
index fee99a5db..f12c25fb6 100644
--- a/toolsrc/src/commands_search.cpp
+++ b/toolsrc/src/commands_search.cpp
@@ -39,7 +39,7 @@ namespace vcpkg::Commands::Search
s.append(Strings::format("%s;", name));
for (const Dependency& d : source_paragraph.depends)
{
- const std::string dependency_name = replace_dashes_with_underscore(d.name);
+ const std::string dependency_name = replace_dashes_with_underscore(d.name());
s.append(Strings::format("%s -> %s;", name, dependency_name));
}
}
diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp
index d02af5662..347998723 100644
--- a/toolsrc/src/test_install_plan.cpp
+++ b/toolsrc/src/test_install_plan.cpp
@@ -347,13 +347,13 @@ namespace UnitTest1
spec_map.get_package_spec(
{{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", ""}},
{{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", "b[1]"}},
- {{"Feature", "2"}, {"Description", "the first feature for a"}, {"Build-Depends", "b[2]"}},
- {{"Feature", "3"}, {"Description", "the first feature for a"}, {"Build-Depends", "a[2]"}}}),
+ {{"Feature", "2"}, {"Description", "the second feature for a"}, {"Build-Depends", "b[2]"}},
+ {{"Feature", "3"}, {"Description", "the third feature for a"}, {"Build-Depends", "a[2]"}}}),
{"3"}};
auto spec_b = FullPackageSpec{spec_map.get_package_spec({
{{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}},
- {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}},
- {{"Feature", "2"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}},
+ {{"Feature", "1"}, {"Description", "the first feature for b"}, {"Build-Depends", ""}},
+ {{"Feature", "2"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}},
})};
auto install_plan = Dependencies::create_feature_install_plan(
@@ -434,7 +434,7 @@ namespace UnitTest1
{"1"}};
auto install_plan = Dependencies::create_feature_install_plan(
- spec_map.map, {spec_b, spec_x}, StatusParagraphs(std::move(status_paragraphs)));
+ spec_map.map, {spec_b}, StatusParagraphs(std::move(status_paragraphs)));
Assert::AreEqual(size_t(5), install_plan.size());
remove_plan_check(&install_plan[0], "x");
@@ -523,5 +523,45 @@ namespace UnitTest1
features_check(&install_plan[6], "a", {"one", "core"});
features_check(&install_plan[7], "c", {"core"});
}
+
+ TEST_METHOD(default_features_test)
+ {
+ using Pgh = std::unordered_map<std::string, std::string>;
+
+ std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
+
+ PackageSpecMap spec_map(Triplet::X86_WINDOWS);
+
+ auto spec_a = FullPackageSpec{
+ spec_map.get_package_spec(
+ {{{"Source", "a"}, {"Version", "1.3"}, {"Default-Features", "1, 2"}, {"Build-Depends", ""}},
+ {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", "b[2]"}},
+ {{"Feature", "2"}, {"Description", "the second feature for a"}, {"Build-Depends", ""}},
+ {{"Feature", "3"}, {"Description", "the third feature for a"}, {"Build-Depends", ""}}}),
+ {""}};
+ auto spec_b = FullPackageSpec{
+ spec_map.get_package_spec({
+ {{"Source", "b"}, {"Version", "1.3"}, {"Default-Features", "1, 2"}, {"Build-Depends", ""}},
+ {{"Feature", "1"}, {"Description", "the first feature for b"}, {"Build-Depends", "c[1]"}},
+ {{"Feature", "2"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}},
+ }),
+ {""}};
+
+ auto spec_c = FullPackageSpec{
+ spec_map.get_package_spec({
+ {{"Source", "c"}, {"Version", "1.3"}, {"Default-Features", "2"}, {"Build-Depends", ""}},
+ {{"Feature", "1"}, {"Description", "the first feature for c"}, {"Build-Depends", ""}},
+ {{"Feature", "2"}, {"Description", "the second feature for c"}, {"Build-Depends", ""}},
+ }),
+ {""}};
+
+ auto install_plan = Dependencies::create_feature_install_plan(
+ spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs)));
+
+ Assert::AreEqual(size_t(3), install_plan.size());
+ features_check(&install_plan[0], "c", {"core", "1", "2"});
+ features_check(&install_plan[1], "b", {"core", "1", "2"});
+ features_check(&install_plan[2], "a", {"core", "1", "2"});
+ }
};
} \ No newline at end of file
diff --git a/toolsrc/src/tests_dependencies.cpp b/toolsrc/src/tests_dependencies.cpp
index 7a49bdbd0..26cc1e22c 100644
--- a/toolsrc/src/tests_dependencies.cpp
+++ b/toolsrc/src/tests_dependencies.cpp
@@ -17,7 +17,7 @@ namespace UnitTest1
{
auto v = expand_qualified_dependencies(parse_comma_list("libA (windows)"));
Assert::AreEqual(size_t(1), v.size());
- Assert::AreEqual("libA", v[0].name.c_str());
+ Assert::AreEqual("libA", v[0].depend.name.c_str());
Assert::AreEqual("windows", v[0].qualifier.c_str());
}
diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp
index af4b55498..3f2760c22 100644
--- a/toolsrc/src/tests_paragraph.cpp
+++ b/toolsrc/src/tests_paragraph.cpp
@@ -60,7 +60,7 @@ namespace UnitTest1
Assert::AreEqual("m", pgh->core_paragraph->maintainer.c_str());
Assert::AreEqual("d", pgh->core_paragraph->description.c_str());
Assert::AreEqual(size_t(1), pgh->core_paragraph->depends.size());
- Assert::AreEqual("bd", pgh->core_paragraph->depends[0].name.c_str());
+ Assert::AreEqual("bd", pgh->core_paragraph->depends[0].name().c_str());
Assert::AreEqual(size_t(1), pgh->core_paragraph->supports.size());
Assert::AreEqual("x64", pgh->core_paragraph->supports[0].c_str());
}
@@ -77,8 +77,8 @@ namespace UnitTest1
auto& pgh = *m_pgh.get();
Assert::AreEqual(size_t(2), pgh->core_paragraph->depends.size());
- Assert::AreEqual("z", pgh->core_paragraph->depends[0].name.c_str());
- Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name.c_str());
+ Assert::AreEqual("z", pgh->core_paragraph->depends[0].name().c_str());
+ Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name().c_str());
}
TEST_METHOD(SourceParagraph_Three_Depends)
@@ -93,9 +93,9 @@ namespace UnitTest1
auto& pgh = *m_pgh.get();
Assert::AreEqual(size_t(3), pgh->core_paragraph->depends.size());
- Assert::AreEqual("z", pgh->core_paragraph->depends[0].name.c_str());
- Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name.c_str());
- Assert::AreEqual("xyz", pgh->core_paragraph->depends[2].name.c_str());
+ Assert::AreEqual("z", pgh->core_paragraph->depends[0].name().c_str());
+ Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name().c_str());
+ Assert::AreEqual("xyz", pgh->core_paragraph->depends[2].name().c_str());
}
TEST_METHOD(SourceParagraph_Three_Supports)
@@ -131,9 +131,9 @@ namespace UnitTest1
Assert::AreEqual("", pgh->core_paragraph->maintainer.c_str());
Assert::AreEqual("", pgh->core_paragraph->description.c_str());
Assert::AreEqual(size_t(2), pgh->core_paragraph->depends.size());
- Assert::AreEqual("libA", pgh->core_paragraph->depends[0].name.c_str());
+ Assert::AreEqual("libA", pgh->core_paragraph->depends[0].name().c_str());
Assert::AreEqual("windows", pgh->core_paragraph->depends[0].qualifier.c_str());
- Assert::AreEqual("libB", pgh->core_paragraph->depends[1].name.c_str());
+ Assert::AreEqual("libB", pgh->core_paragraph->depends[1].name().c_str());
Assert::AreEqual("uwp", pgh->core_paragraph->depends[1].qualifier.c_str());
}
@@ -411,6 +411,18 @@ namespace UnitTest1
Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec);
}
+ TEST_METHOD(package_spec_feature_parse_with_arch)
+ {
+ vcpkg::ExpectedT<vcpkg::FullPackageSpec, vcpkg::PackageSpecParseResult> spec =
+ vcpkg::FullPackageSpec::from_string("zlib[feature]:x64-uwp", vcpkg::Triplet::X86_WINDOWS);
+ Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error());
+ Assert::AreEqual("zlib", spec.get()->package_spec.name().c_str());
+ Assert::IsTrue(spec.get()->features.size() == 1);
+ Assert::AreEqual("feature", spec.get()->features.front().c_str());
+ Assert::AreEqual(vcpkg::Triplet::X64_UWP.canonical_name(),
+ spec.get()->package_spec.triplet().canonical_name());
+ }
+
TEST_METHOD(utf8_to_utf16)
{
auto str = vcpkg::Strings::to_utf16("abc");
diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp
index a0d690f37..124efb7f2 100644
--- a/toolsrc/src/vcpkg_Build.cpp
+++ b/toolsrc/src/vcpkg_Build.cpp
@@ -88,29 +88,37 @@ namespace vcpkg::Build
return Strings::wformat(LR"("%s" %s %s %s 2>&1)", toolset.vcvarsall.native(), arch, target, tonull);
}
- static void create_binary_control_file(const VcpkgPaths& paths,
- const SourceParagraph& source_paragraph,
+ static void create_binary_feature_control_file(const SourceParagraph& source_paragraph,
+ const FeatureParagraph& feature_paragraph,
+ const Triplet& triplet,
+ BinaryControlFile& bcf)
+ {
+ BinaryParagraph bpgh(source_paragraph, feature_paragraph, triplet);
+ bcf.features.emplace_back(std::move(bpgh));
+ }
+
+ static void create_binary_control_file(const SourceParagraph& source_paragraph,
const Triplet& triplet,
- const BuildInfo& build_info)
+ const BuildInfo& build_info,
+ BinaryControlFile& bcf)
{
- BinaryParagraph bpgh = BinaryParagraph(source_paragraph, triplet);
+ BinaryParagraph bpgh(source_paragraph, triplet);
if (auto p_ver = build_info.version.get())
{
bpgh.version = *p_ver;
}
- const fs::path binary_control_file = paths.packages / bpgh.dir() / "CONTROL";
- paths.get_filesystem().write_contents(binary_control_file, Strings::serialize(bpgh));
+ bcf.core_paragraph = std::move(bpgh);
}
- static void create_binary_feature_control_file(const VcpkgPaths& paths,
- const SourceParagraph& source_paragraph,
- const FeatureParagraph& feature_paragraph,
- const Triplet& triplet,
- const BuildInfo& build_info)
+ static void write_binary_control_file(const VcpkgPaths& paths, BinaryControlFile bcf)
{
- BinaryParagraph bpgh = BinaryParagraph(source_paragraph, feature_paragraph, triplet);
- const fs::path binary_control_file = paths.packages / bpgh.dir() / "CONTROL";
- paths.get_filesystem().write_contents(binary_control_file, Strings::serialize(bpgh));
+ std::string start = Strings::serialize(bcf.core_paragraph);
+ for (auto&& feature : bcf.features)
+ {
+ start += "\n" + Strings::serialize(feature);
+ }
+ const fs::path binary_control_file = paths.packages / bcf.core_paragraph.dir() / "CONTROL";
+ paths.get_filesystem().write_contents(binary_control_file, start);
}
ExtendedBuildResult build_package(const VcpkgPaths& paths,
@@ -196,6 +204,10 @@ namespace vcpkg::Build
auto build_info = read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec));
const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info);
+ BinaryControlFile bcf;
+
+ create_binary_control_file(config.src, triplet, build_info, bcf);
+
if (error_count != 0)
{
return {BuildResult::POST_BUILD_CHECKS_FAILED, {}};
@@ -209,13 +221,13 @@ namespace vcpkg::Build
for (auto&& f_pgh : config.scf->feature_paragraphs)
{
if (f_pgh->name == feature)
- create_binary_feature_control_file(
- paths, *config.scf->core_paragraph, *f_pgh, triplet, build_info);
+ create_binary_feature_control_file(*config.scf->core_paragraph, *f_pgh, triplet, bcf);
}
}
}
}
- create_binary_control_file(paths, config.src, triplet, build_info);
+
+ write_binary_control_file(paths, bcf);
// const fs::path port_buildtrees_dir = paths.buildtrees / spec.name;
// delete_directory(port_buildtrees_dir);
diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp
index 820e51b33..c84ca73f3 100644
--- a/toolsrc/src/vcpkg_Dependencies.cpp
+++ b/toolsrc/src/vcpkg_Dependencies.cpp
@@ -101,6 +101,25 @@ namespace vcpkg::Dependencies
this->plan_type = InstallPlanType::UNKNOWN;
}
+ std::string InstallPlanAction::displayname() const
+ {
+ if (this->feature_list.empty())
+ {
+ return this->spec.to_string();
+ }
+ else
+ {
+ std::string features;
+ for (auto&& feature : this->feature_list)
+ {
+ features += feature + ",";
+ }
+ features.pop_back();
+
+ return this->spec.name() + "[" + features + "]:" + this->spec.triplet().to_string();
+ }
+ }
+
bool InstallPlanAction::compare_by_name(const InstallPlanAction* left, const InstallPlanAction* right)
{
return left->spec.name() < right->spec.name();
@@ -319,9 +338,9 @@ namespace vcpkg::Dependencies
? RequestType::USER_REQUESTED
: RequestType::AUTO_SELECTED;
- Expected<BinaryParagraph> maybe_bpgh = Paragraphs::try_load_cached_package(paths, spec);
- if (auto bpgh = maybe_bpgh.get())
- return ExportPlanAction{spec, {nullopt, *bpgh, nullopt}, request_type};
+ Expected<BinaryControlFile> maybe_bpgh = Paragraphs::try_load_cached_control_package(paths, spec);
+ if (auto bcf = maybe_bpgh.get())
+ return ExportPlanAction{spec, {nullopt, bcf->core_paragraph, nullopt}, request_type};
auto maybe_scf = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec));
if (auto scf = maybe_scf.get())
@@ -366,6 +385,20 @@ namespace vcpkg::Dependencies
return f_specs;
}
+ void mark_plus_default(Cluster& cluster,
+ std::unordered_map<PackageSpec, Cluster>& pkg_to_cluster,
+ GraphPlan& graph_plan)
+ {
+ mark_plus("core", cluster, pkg_to_cluster, graph_plan);
+ if (auto scf = cluster.source_control_file.get())
+ {
+ for (auto&& default_feature : (*scf)->core_paragraph->default_features)
+ {
+ mark_plus(default_feature, cluster, pkg_to_cluster, graph_plan);
+ }
+ }
+ }
+
bool mark_plus(const std::string& feature,
Cluster& cluster,
std::unordered_map<PackageSpec, Cluster>& pkg_to_cluster,
@@ -404,21 +437,12 @@ namespace vcpkg::Dependencies
graph_plan.install_graph.add_vertex({&cluster});
auto& tracked = cluster.to_install_features;
tracked.insert(updated_feature);
- if (tracked.find("core") == tracked.end() && tracked.find("") == tracked.end())
- {
- cluster.to_install_features.insert("core");
- for (auto&& depend : cluster.edges["core"].build_edges)
- {
- auto& depend_cluster = pkg_to_cluster[depend.spec];
- mark_plus(depend.feature_name, depend_cluster, pkg_to_cluster, graph_plan);
- graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster});
- }
- }
for (auto&& depend : cluster.edges[updated_feature].build_edges)
{
auto& depend_cluster = pkg_to_cluster[depend.spec];
mark_plus(depend.feature_name, depend_cluster, pkg_to_cluster, graph_plan);
+ mark_plus_default(depend_cluster, pkg_to_cluster, graph_plan);
if (&depend_cluster == &cluster) continue;
graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster});
}
@@ -448,6 +472,7 @@ namespace vcpkg::Dependencies
mark_plus(original_feature, cluster, pkg_to_cluster, graph_plan);
}
}
+
std::vector<AnyAction> create_feature_install_plan(const std::unordered_map<PackageSpec, SourceControlFile>& map,
const std::vector<FullPackageSpec>& specs,
const StatusParagraphs& status_db)
@@ -515,6 +540,7 @@ namespace vcpkg::Dependencies
for (auto&& spec : specs)
{
Cluster& spec_cluster = pkg_spec_to_package_node[spec.package_spec];
+ mark_plus_default(spec_cluster, pkg_spec_to_package_node, graph_plan);
for (auto&& feature : spec.features)
{
mark_plus(feature, spec_cluster, pkg_spec_to_package_node, graph_plan);
diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp
index 6b180b532..428ae090d 100644
--- a/toolsrc/src/vcpkglib.cpp
+++ b/toolsrc/src/vcpkglib.cpp
@@ -191,7 +191,7 @@ namespace vcpkg
for (const std::unique_ptr<StatusParagraph>& pgh : status_db)
{
- if (pgh->state != InstallState::INSTALLED)
+ if (pgh->state != InstallState::INSTALLED || pgh->package.feature != "")
{
continue;
}