aboutsummaryrefslogtreecommitdiff
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
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
-rw-r--r--toolsrc/include/BinaryParagraph.h6
-rw-r--r--toolsrc/include/Paragraphs.h2
-rw-r--r--toolsrc/include/SourceParagraph.h15
-rw-r--r--toolsrc/include/StatusParagraphs.h3
-rw-r--r--toolsrc/include/vcpkg_Commands.h2
-rw-r--r--toolsrc/include/vcpkg_Dependencies.h5
-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
20 files changed, 459 insertions, 96 deletions
diff --git a/toolsrc/include/BinaryParagraph.h b/toolsrc/include/BinaryParagraph.h
index 1e12dd8a6..61e03343a 100644
--- a/toolsrc/include/BinaryParagraph.h
+++ b/toolsrc/include/BinaryParagraph.h
@@ -31,5 +31,11 @@ namespace vcpkg
std::vector<std::string> depends;
};
+ struct BinaryControlFile
+ {
+ BinaryParagraph core_paragraph;
+ std::vector<BinaryParagraph> features;
+ };
+
void serialize(const BinaryParagraph& pgh, std::string& out_str);
} \ No newline at end of file
diff --git a/toolsrc/include/Paragraphs.h b/toolsrc/include/Paragraphs.h
index 60f509266..aae46f7da 100644
--- a/toolsrc/include/Paragraphs.h
+++ b/toolsrc/include/Paragraphs.h
@@ -20,7 +20,7 @@ namespace vcpkg::Paragraphs
Parse::ParseExpected<SourceControlFile> try_load_port(const Files::Filesystem& fs, const fs::path& control_path);
- 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);
struct LoadResults
{
diff --git a/toolsrc/include/SourceParagraph.h b/toolsrc/include/SourceParagraph.h
index 7ddf999cc..fee61c3e8 100644
--- a/toolsrc/include/SourceParagraph.h
+++ b/toolsrc/include/SourceParagraph.h
@@ -15,13 +15,24 @@ namespace vcpkg
struct Triplet;
- struct Dependency
+ struct Features
{
std::string name;
+ std::vector<std::string> features;
+ };
+
+ Features parse_feature_list(const std::string& name);
+
+ struct Dependency
+ {
+ Features depend;
std::string qualifier;
+
+ std::string name() const;
+ static Dependency parse_dependency(std::string name, std::string qualifier);
};
- const std::string& to_string(const Dependency& dep);
+ const std::string to_string(const Dependency& dep);
struct FeatureParagraph
{
diff --git a/toolsrc/include/StatusParagraphs.h b/toolsrc/include/StatusParagraphs.h
index 2af177219..bf2ef2f3e 100644
--- a/toolsrc/include/StatusParagraphs.h
+++ b/toolsrc/include/StatusParagraphs.h
@@ -17,6 +17,9 @@ namespace vcpkg
const_iterator find(const PackageSpec& spec) const { return find(spec.name(), spec.triplet()); }
const_iterator find(const std::string& name, const Triplet& triplet) const;
iterator find(const std::string& name, const Triplet& triplet);
+ std::vector<std::unique_ptr<StatusParagraph>*> StatusParagraphs::find_all(const std::string& name,
+ const Triplet& triplet);
+ iterator find(const std::string& name, const Triplet& triplet, const std::string& feature);
const_iterator find_installed(const PackageSpec& spec) const
{
diff --git a/toolsrc/include/vcpkg_Commands.h b/toolsrc/include/vcpkg_Commands.h
index 8348a64e4..d5f316d69 100644
--- a/toolsrc/include/vcpkg_Commands.h
+++ b/toolsrc/include/vcpkg_Commands.h
@@ -59,7 +59,7 @@ namespace vcpkg::Commands
const fs::path& source_dir,
const InstallDir& dirs);
void install_package(const VcpkgPaths& paths,
- const BinaryParagraph& binary_paragraph,
+ const BinaryControlFile& binary_paragraph,
StatusParagraphs* status_db);
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet);
}
diff --git a/toolsrc/include/vcpkg_Dependencies.h b/toolsrc/include/vcpkg_Dependencies.h
index e3af0fd28..3fee8ef33 100644
--- a/toolsrc/include/vcpkg_Dependencies.h
+++ b/toolsrc/include/vcpkg_Dependencies.h
@@ -90,6 +90,7 @@ namespace vcpkg::Dependencies
InstallPlanAction(InstallPlanAction&&) = default;
InstallPlanAction& operator=(const InstallPlanAction&) = delete;
InstallPlanAction& operator=(InstallPlanAction&&) = default;
+ std::string displayname() const;
PackageSpec spec;
AnyParagraph any_paragraph;
@@ -205,7 +206,9 @@ namespace vcpkg::Dependencies
std::unordered_map<PackageSpec, Cluster>& pkg_to_cluster,
GraphPlan& graph_plan);
void mark_minus(Cluster& cluster, std::unordered_map<PackageSpec, Cluster>& pkg_to_cluster, GraphPlan& graph_plan);
-
+ void mark_plus_default(Cluster& cluster,
+ std::unordered_map<PackageSpec, Cluster>& pkg_to_cluster,
+ GraphPlan& 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);
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;
}