diff options
| author | Daniel Shaw <t-dansha@microsoft.com> | 2017-07-19 14:29:28 -0700 |
|---|---|---|
| committer | Daniel Shaw <t-dansha@microsoft.com> | 2017-07-24 15:21:32 -0700 |
| commit | 59389ca236b005922cf1101f66c957d2396f6371 (patch) | |
| tree | 42bbcc25b501967203c63dd55b665ec9f49a41e4 | |
| parent | 1445115906139f5c6d14bcbbacdcc0cfb543fd80 (diff) | |
| download | vcpkg-59389ca236b005922cf1101f66c957d2396f6371.tar.gz vcpkg-59389ca236b005922cf1101f66c957d2396f6371.zip | |
end to end feature pkg draft
| -rw-r--r-- | toolsrc/include/BinaryParagraph.h | 3 | ||||
| -rw-r--r-- | toolsrc/include/PackageSpec.h | 6 | ||||
| -rw-r--r-- | toolsrc/include/SourceParagraph.h | 1 | ||||
| -rw-r--r-- | toolsrc/include/vcpkg_Build.h | 23 | ||||
| -rw-r--r-- | toolsrc/include/vcpkg_Commands.h | 1 | ||||
| -rw-r--r-- | toolsrc/include/vcpkg_Dependencies.h | 34 | ||||
| -rw-r--r-- | toolsrc/src/BinaryParagraph.cpp | 15 | ||||
| -rw-r--r-- | toolsrc/src/PackageSpec.cpp | 47 | ||||
| -rw-r--r-- | toolsrc/src/commands_install.cpp | 38 | ||||
| -rw-r--r-- | toolsrc/src/commands_remove.cpp | 2 | ||||
| -rw-r--r-- | toolsrc/src/test_install_plan.cpp | 118 | ||||
| -rw-r--r-- | toolsrc/src/tests_paragraph.cpp | 20 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg_Build.cpp | 62 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg_Dependencies.cpp | 88 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg_Input.cpp | 27 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg_Parse.cpp | 12 |
16 files changed, 359 insertions, 138 deletions
diff --git a/toolsrc/include/BinaryParagraph.h b/toolsrc/include/BinaryParagraph.h index 4adde5e36..f411b3c39 100644 --- a/toolsrc/include/BinaryParagraph.h +++ b/toolsrc/include/BinaryParagraph.h @@ -14,6 +14,9 @@ namespace vcpkg BinaryParagraph(); explicit BinaryParagraph(std::unordered_map<std::string, std::string> fields); BinaryParagraph(const SourceParagraph& spgh, const Triplet& triplet); + BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, + const FeatureParagraph& fpgh, + const Triplet& triplet); std::string displayname() const; diff --git a/toolsrc/include/PackageSpec.h b/toolsrc/include/PackageSpec.h index 62b6fc9de..15b5e5b9b 100644 --- a/toolsrc/include/PackageSpec.h +++ b/toolsrc/include/PackageSpec.h @@ -1,5 +1,6 @@ #pragma once #include "PackageSpecParseResult.h" +#include "SourceParagraph.h" #include "Triplet.h" #include "vcpkg_expected.h" @@ -7,8 +8,6 @@ namespace vcpkg { struct PackageSpec { - static ExpectedT<PackageSpec, PackageSpecParseResult> from_string(const std::string& spec_as_string, - const Triplet& default_triplet); static std::string to_string(const std::string& name, const Triplet& triplet); static ExpectedT<PackageSpec, PackageSpecParseResult> from_name_and_triplet(const std::string& name, const Triplet& triplet); @@ -30,6 +29,9 @@ namespace vcpkg { PackageSpec package_spec; std::vector<std::string> features; + + static ExpectedT<FullPackageSpec, PackageSpecParseResult> from_string(const std::string& spec_as_string, + const Triplet& default_triplet); }; bool operator==(const PackageSpec& left, const PackageSpec& right); diff --git a/toolsrc/include/SourceParagraph.h b/toolsrc/include/SourceParagraph.h index e85884b51..7ddf999cc 100644 --- a/toolsrc/include/SourceParagraph.h +++ b/toolsrc/include/SourceParagraph.h @@ -60,6 +60,7 @@ namespace vcpkg std::vector<std::string> filter_dependencies(const std::vector<Dependency>& deps, const Triplet& t); + // zlib[uwp] becomes Dependency{"zlib", "uwp"} std::vector<Dependency> expand_qualified_dependencies(const std::vector<std::string>& depends); std::vector<std::string> parse_comma_list(const std::string& str); diff --git a/toolsrc/include/vcpkg_Build.h b/toolsrc/include/vcpkg_Build.h index 9a4e2baeb..c4f3e6746 100644 --- a/toolsrc/include/vcpkg_Build.h +++ b/toolsrc/include/vcpkg_Build.h @@ -95,14 +95,35 @@ namespace vcpkg::Build const Triplet& triplet, fs::path&& port_dir, const BuildPackageOptions& build_package_options) - : src(src), triplet(triplet), port_dir(std::move(port_dir)), build_package_options(build_package_options) + : src(src) + , scf(nullptr) + , triplet(triplet) + , port_dir(std::move(port_dir)) + , build_package_options(build_package_options) + , feature_list(nullptr) + { + } + + BuildPackageConfig(const SourceControlFile& src, + const Triplet& triplet, + fs::path&& port_dir, + const BuildPackageOptions& build_package_options, + const std::unordered_set<std::string>& feature_list) + : src(*src.core_paragraph) + , scf(&src) + , triplet(triplet) + , port_dir(std::move(port_dir)) + , build_package_options(build_package_options) + , feature_list(&feature_list) { } const SourceParagraph& src; + const SourceControlFile* scf; const Triplet& triplet; fs::path port_dir; const BuildPackageOptions& build_package_options; + const std::unordered_set<std::string>* feature_list; }; ExtendedBuildResult build_package(const VcpkgPaths& paths, diff --git a/toolsrc/include/vcpkg_Commands.h b/toolsrc/include/vcpkg_Commands.h index 67319f240..8348a64e4 100644 --- a/toolsrc/include/vcpkg_Commands.h +++ b/toolsrc/include/vcpkg_Commands.h @@ -77,6 +77,7 @@ namespace vcpkg::Commands namespace Remove { void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db); } namespace Update diff --git a/toolsrc/include/vcpkg_Dependencies.h b/toolsrc/include/vcpkg_Dependencies.h index ff559c0f1..e3af0fd28 100644 --- a/toolsrc/include/vcpkg_Dependencies.h +++ b/toolsrc/include/vcpkg_Dependencies.h @@ -26,12 +26,6 @@ namespace vcpkg::Dependencies Optional<SourceParagraph> source_paragraph; Optional<const SourceControlFile*> source_control_file; }; - - struct ClusterNode - { - std::vector<StatusParagraph> status_paragraphs; - Optional<const SourceControlFile*> source_paragraph; - }; } namespace vcpkg::Dependencies @@ -48,11 +42,13 @@ namespace vcpkg::Dependencies std::vector<FeatureSpec> build_edges; bool plus = false; }; - std::vector<FeatureSpec> to_feature_specs(const std::vector<std::string> depends, - const std::unordered_map<std::string, PackageSpec> str_to_spec); + std::vector<FeatureSpec> to_feature_specs(const std::vector<std::string>& depends, const Triplet& t); + struct Cluster { - ClusterNode cluster_data; + std::vector<StatusParagraph> status_paragraphs; + Optional<const SourceControlFile*> source_control_file; + PackageSpec spec; std::unordered_map<std::string, FeatureNodeEdges> edges; std::unordered_set<std::string> to_install_features; std::unordered_set<std::string> original_features; @@ -65,6 +61,13 @@ namespace vcpkg::Dependencies Cluster& operator=(const Cluster&) = delete; }; + struct ClusterPtr + { + Cluster* ptr; + }; + + bool operator==(const ClusterPtr& l, const ClusterPtr& r); + enum class InstallPlanType { UNKNOWN, @@ -181,12 +184,21 @@ namespace vcpkg::Dependencies const StatusParagraphs& status_db); } +template<> +struct std::hash<vcpkg::Dependencies::ClusterPtr> +{ + size_t operator()(const vcpkg::Dependencies::ClusterPtr& value) const + { + return std::hash<vcpkg::PackageSpec>()(value.ptr->spec); + } +}; + namespace vcpkg::Dependencies { struct GraphPlan { - Graphs::Graph<Cluster*> remove_graph; - Graphs::Graph<Cluster*> install_graph; + Graphs::Graph<ClusterPtr> remove_graph; + Graphs::Graph<ClusterPtr> install_graph; }; bool mark_plus(const std::string& feature, Cluster& cluster, diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp index e126054a8..b6f3e8a87 100644 --- a/toolsrc/src/BinaryParagraph.cpp +++ b/toolsrc/src/BinaryParagraph.cpp @@ -75,6 +75,16 @@ namespace vcpkg this->depends = filter_dependencies(spgh.depends, triplet); } + BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const FeatureParagraph& fpgh, const Triplet& triplet) + { + this->spec = PackageSpec::from_name_and_triplet(spgh.name, triplet).value_or_exit(VCPKG_LINE_INFO); + this->version = ""; + this->feature = fpgh.name; + this->description = fpgh.description; + this->maintainer = ""; + this->depends = filter_dependencies(fpgh.depends, triplet); + } + std::string BinaryParagraph::displayname() const { return this->spec.to_string(); } std::string BinaryParagraph::dir() const { return this->spec.dir(); } @@ -87,7 +97,10 @@ namespace vcpkg void serialize(const BinaryParagraph& pgh, std::string& out_str) { out_str.append("Package: ").append(pgh.spec.name()).push_back('\n'); - out_str.append("Version: ").append(pgh.version).push_back('\n'); + if (!pgh.version.empty()) + out_str.append("Version: ").append(pgh.version).push_back('\n'); + else if (!pgh.feature.empty()) + out_str.append("Feature: ").append(pgh.feature).push_back('\n'); if (!pgh.depends.empty()) { out_str.append("Depends: "); diff --git a/toolsrc/src/PackageSpec.cpp b/toolsrc/src/PackageSpec.cpp index 12217ac98..a7e5648cd 100644 --- a/toolsrc/src/PackageSpec.cpp +++ b/toolsrc/src/PackageSpec.cpp @@ -10,13 +10,47 @@ namespace vcpkg return (c == '-') || isdigit(c) || (isalpha(c) && islower(c)) || (c == '[') || (c == ']'); } - ExpectedT<PackageSpec, PackageSpecParseResult> PackageSpec::from_string(const std::string& spec_as_string, - const Triplet& default_triplet) + ExpectedT<FullPackageSpec, PackageSpecParseResult> FullPackageSpec::from_string(const std::string& spec_as_string, + const Triplet& default_triplet) { auto pos = spec_as_string.find(':'); - if (pos == std::string::npos) + auto pos_l_bracket = spec_as_string.find('['); + auto pos_r_bracket = spec_as_string.find(']'); + + FullPackageSpec f; + if (pos == std::string::npos && pos_l_bracket == std::string::npos) + { + f.package_spec = + PackageSpec::from_name_and_triplet(spec_as_string, default_triplet).value_or_exit(VCPKG_LINE_INFO); + return f; + } + else if (pos == std::string::npos) + { + if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) + { + return PackageSpecParseResult::INVALID_CHARACTERS; + } + const std::string name = spec_as_string.substr(0, pos_l_bracket); + f.package_spec = PackageSpec::from_name_and_triplet(name, default_triplet).value_or_exit(VCPKG_LINE_INFO); + f.features = parse_comma_list(spec_as_string.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); + return f; + } + else if (pos_l_bracket == std::string::npos && pos_r_bracket == std::string::npos) + { + const std::string name = spec_as_string.substr(0, pos); + const Triplet triplet = Triplet::from_canonical_name(spec_as_string.substr(pos + 1)); + f.package_spec = PackageSpec::from_name_and_triplet(name, triplet).value_or_exit(VCPKG_LINE_INFO); + } + else { - return from_name_and_triplet(spec_as_string, default_triplet); + if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket) + { + return PackageSpecParseResult::INVALID_CHARACTERS; + } + const std::string name = spec_as_string.substr(0, pos_l_bracket); + f.features = parse_comma_list(spec_as_string.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1)); + const Triplet triplet = Triplet::from_canonical_name(spec_as_string.substr(pos + 1)); + f.package_spec = PackageSpec::from_name_and_triplet(name, triplet).value_or_exit(VCPKG_LINE_INFO); } auto pos2 = spec_as_string.find(':', pos + 1); @@ -24,10 +58,7 @@ namespace vcpkg { return PackageSpecParseResult::TOO_MANY_COLONS; } - - const std::string name = spec_as_string.substr(0, pos); - const Triplet triplet = Triplet::from_canonical_name(spec_as_string.substr(pos + 1)); - return from_name_and_triplet(name, triplet); + return f; } ExpectedT<PackageSpec, PackageSpecParseResult> PackageSpec::from_name_and_triplet(const std::string& name, diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index d340a9cf8..2ce5b6c62 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -16,6 +16,8 @@ namespace vcpkg::Commands::Install using Dependencies::InstallPlanAction; using Dependencies::RequestType; using Dependencies::InstallPlanType; + using Dependencies::RemovePlanAction; + using Dependencies::RemovePlanType; InstallDir InstallDir::from_destination_root(const fs::path& destination_root, const std::string& destination_subdirectory, @@ -290,7 +292,7 @@ namespace vcpkg::Commands::Install return BuildResult::SUCCEEDED; } - if (plan_type == InstallPlanType::BUILD_AND_INSTALL) + if (plan_type == InstallPlanType::BUILD_AND_INSTALL && !g_feature_packages) { if (use_head_version) System::println("Building package %s from HEAD... ", display_name); @@ -318,7 +320,36 @@ namespace vcpkg::Commands::Install return BuildResult::SUCCEEDED; } - if (plan_type == InstallPlanType::INSTALL) + if (plan_type == InstallPlanType::BUILD_AND_INSTALL && g_feature_packages) + { + if (use_head_version) + System::println("Building package %s from HEAD... ", display_name); + else + System::println("Building package %s... ", display_name); + + const Build::BuildPackageConfig build_config{ + *action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO), + action.spec.triplet(), + paths.port_dir(action.spec), + build_package_options, + action.feature_list}; + const auto result = Build::build_package(paths, build_config, status_db); + if (result.code != Build::BuildResult::SUCCEEDED) + { + System::println(System::Color::error, Build::create_error_message(result.code, action.spec)); + return result.code; + } + 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); + System::println("Installing package %s... ", display_name); + install_package(paths, bpgh, &status_db); + System::println(System::Color::success, "Installing package %s... done", display_name); + return BuildResult::SUCCEEDED; + } + + if (plan_type == InstallPlanType::INSTALL && !g_feature_packages) { if (use_head_version && is_user_requested) { @@ -359,7 +390,8 @@ namespace vcpkg::Commands::Install // create the plan StatusParagraphs status_db = database_load_check(paths); - auto paths_port_file = Dependencies::PathsPortFile(paths); + + Dependencies::PathsPortFile paths_port_file(paths); std::vector<InstallPlanAction> install_plan = Dependencies::create_install_plan(paths_port_file, specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty"); diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp index e2b5d12a1..eabf2b9ae 100644 --- a/toolsrc/src/commands_remove.cpp +++ b/toolsrc/src/commands_remove.cpp @@ -14,7 +14,7 @@ namespace vcpkg::Commands::Remove using Dependencies::RequestType; using Update::OutdatedPackage; - static void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db) + 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()); diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp index 671b6ed67..d02af5662 100644 --- a/toolsrc/src/test_install_plan.cpp +++ b/toolsrc/src/test_install_plan.cpp @@ -13,13 +13,16 @@ namespace UnitTest1 struct PackageSpecMap { std::unordered_map<PackageSpec, SourceControlFile> map; + Triplet triplet; + PackageSpecMap(const Triplet& t) { triplet = t; } + PackageSpec get_package_spec(std::vector<std::unordered_map<std::string, std::string>>&& fields) { auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(fields)); Assert::IsTrue(m_pgh.has_value()); auto& scf = *m_pgh.get(); - auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, Triplet::X86_WINDOWS); + auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, triplet); Assert::IsTrue(spec.has_value()); map.emplace(*spec.get(), std::move(*scf.get())); return PackageSpec{*spec.get()}; @@ -32,11 +35,14 @@ namespace UnitTest1 static void features_check(Dependencies::AnyAction* install_action, std::string pkg_name, - std::vector<std::string> vec) + std::vector<std::string> vec, + const Triplet& triplet = Triplet::X86_WINDOWS) { - const auto& plan = *install_action->install_plan.get(); + const auto& plan = install_action->install_plan.value_or_exit(VCPKG_LINE_INFO); const auto& feature_list = plan.feature_list; + Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); + Assert::AreEqual(pkg_name.c_str(), (*plan.any_paragraph.source_control_file.get())->core_paragraph->name.c_str()); Assert::AreEqual(size_t(vec.size()), feature_list.size()); @@ -53,16 +59,20 @@ namespace UnitTest1 } } - static void remove_plan_check(Dependencies::AnyAction* install_action, std::string pkg_name) + static void remove_plan_check(Dependencies::AnyAction* remove_action, + std::string pkg_name, + const Triplet& triplet = Triplet::X86_WINDOWS) { - Assert::AreEqual(pkg_name.c_str(), install_action->remove_plan.get()->spec.name().c_str()); + const auto& plan = remove_action->remove_plan.value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); + Assert::AreEqual(pkg_name.c_str(), plan.spec.name().c_str()); } TEST_METHOD(basic_install_scheme) { std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = spec_map.set_package_map("a", "1.2.8", "b"); auto spec_b = spec_map.set_package_map("b", "1.3", "c"); auto spec_c = spec_map.set_package_map("c", "2.5.3", ""); @@ -81,7 +91,7 @@ namespace UnitTest1 { std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = spec_map.set_package_map("a", "1.2.8", "d"); auto spec_b = spec_map.set_package_map("b", "1.3", "d, e"); auto spec_c = spec_map.set_package_map("c", "2.5.3", "e, h"); @@ -134,7 +144,7 @@ namespace UnitTest1 {"Depends", ""}, {"Status", "install ok installed"}})); - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = spec_map.set_package_map("a", "1.2.8", "b, c, d, e, f, g, h, j, k"); auto spec_b = spec_map.set_package_map("b", "1.2.8", "c, d, e, f, g, h, j, k"); @@ -188,7 +198,7 @@ namespace UnitTest1 {"Depends", ""}, {"Status", "install ok installed"}})); - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = FullPackageSpec{spec_map.get_package_spec({ {{"Source", "a"}, {"Version", "1.3.8"}, {"Build-Depends", "b, b[beefeatureone]"}}, @@ -220,7 +230,7 @@ namespace UnitTest1 std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = FullPackageSpec{spec_map.get_package_spec( @@ -259,7 +269,7 @@ namespace UnitTest1 {"Depends", ""}, {"Status", "install ok installed"}})); - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = FullPackageSpec{ spec_map.get_package_spec( @@ -303,7 +313,7 @@ namespace UnitTest1 {"Depends", ""}, {"Status", "install ok installed"}})); - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = FullPackageSpec{ spec_map.get_package_spec( @@ -331,7 +341,7 @@ namespace UnitTest1 std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = FullPackageSpec{ spec_map.get_package_spec( @@ -366,7 +376,7 @@ namespace UnitTest1 {"Multi-Arch", "same"}, {"Depends", ""}, {"Status", "install ok installed"}})); - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = FullPackageSpec{spec_map.get_package_spec({ {{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b[core]"}}, @@ -407,7 +417,7 @@ namespace UnitTest1 {"Multi-Arch", "same"}, {"Depends", ""}, {"Status", "install ok installed"}})); - PackageSpecMap spec_map; + PackageSpecMap spec_map(Triplet::X86_WINDOWS); auto spec_a = FullPackageSpec{spec_map.get_package_spec({ {{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", ""}}, @@ -435,5 +445,83 @@ namespace UnitTest1 features_check(&install_plan[3], "x", {"core"}); features_check(&install_plan[4], "b", {"core", "1"}); } + + TEST_METHOD(basic_feature_test_8) + { + using Pgh = std::unordered_map<std::string, std::string>; + + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + status_paragraphs.push_back(std::make_unique<StatusParagraph>(Pgh{{"Package", "a"}, + {"Default-Features", ""}, + {"Version", "1.3"}, + {"Architecture", "x64-windows"}, + {"Multi-Arch", "same"}, + {"Depends", ""}, + {"Status", "install ok installed"}})); + status_paragraphs.push_back(std::make_unique<StatusParagraph>(Pgh{{"Package", "a"}, + {"Default-Features", ""}, + {"Version", "1.3"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", ""}, + {"Status", "install ok installed"}})); + + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + + auto spec_a_64 = FullPackageSpec{ + spec_map.get_package_spec( + {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}}, + {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}), + {"core"}}; + auto spec_b_64 = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, + })}; + auto spec_c_64 = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}}, + }), + {"core"}}; + + spec_map.triplet = Triplet::X86_WINDOWS; + auto spec_a_86 = FullPackageSpec{ + spec_map.get_package_spec( + {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}}, + {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}), + {"core"}}; + auto spec_b_86 = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}}, + })}; + auto spec_c_86 = FullPackageSpec{spec_map.get_package_spec({ + {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}}, + }), + {"core"}}; + + auto install_plan = + Dependencies::create_feature_install_plan(spec_map.map, + {spec_c_64, spec_a_86, spec_a_64, spec_c_86}, + StatusParagraphs(std::move(status_paragraphs))); + + /*Assert::AreEqual(size_t(8), install_plan.size()); + auto iterator_pos = [&](const PackageSpec& spec, size_t start) -> int { + auto it = std::find_if(install_plan.begin() + start, install_plan.end(), [&](auto& action) { + return action.spec == spec; + }); + Assert::IsTrue(it != install_plan.end()); + return (int)(it - install_plan.begin()); + }; + int a_64_1 = iterator_pos(spec_a_64.package_spec, 0), a_86_1 = iterator_pos(spec_a_86.package_spec, 0), + b_64 = iterator_pos(spec_b_64.package_spec, 0), b_86 = iterator_pos(spec_b_86.package_spec, 0), + c_64 = iterator_pos(spec_c_64.package_spec, 0), c_86 = iterator_pos(spec_c_86.package_spec, 0), + a_64_2 = iterator_pos(spec_a_64.package_spec, a_64_1 + 1), + a_86_2 = iterator_pos(spec_a_86.package_spec, a_86_1 + 1);*/ + + remove_plan_check(&install_plan[0], "a", Triplet::X64_WINDOWS); + remove_plan_check(&install_plan[1], "a"); + features_check(&install_plan[2], "b", {"core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[3], "a", {"one", "core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[4], "c", {"core"}, Triplet::X64_WINDOWS); + features_check(&install_plan[5], "b", {"core"}); + features_check(&install_plan[6], "a", {"one", "core"}); + features_check(&install_plan[7], "c", {"core"}); + } }; }
\ No newline at end of file diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp index 2a53cc8b4..dd9a40160 100644 --- a/toolsrc/src/tests_paragraph.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -372,25 +372,27 @@ namespace UnitTest1 TEST_METHOD(package_spec_parse) { - vcpkg::ExpectedT<vcpkg::PackageSpec, vcpkg::PackageSpecParseResult> spec = - vcpkg::PackageSpec::from_string("zlib", vcpkg::Triplet::X86_WINDOWS); + vcpkg::ExpectedT<vcpkg::FullPackageSpec, vcpkg::PackageSpecParseResult> spec = + vcpkg::FullPackageSpec::from_string("zlib", vcpkg::Triplet::X86_WINDOWS); Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error()); - Assert::AreEqual("zlib", spec.get()->name().c_str()); - Assert::AreEqual(vcpkg::Triplet::X86_WINDOWS.canonical_name(), spec.get()->triplet().canonical_name()); + Assert::AreEqual("zlib", spec.get()->package_spec.name().c_str()); + Assert::AreEqual(vcpkg::Triplet::X86_WINDOWS.canonical_name(), + spec.get()->package_spec.triplet().canonical_name()); } TEST_METHOD(package_spec_parse_with_arch) { - vcpkg::ExpectedT<vcpkg::PackageSpec, vcpkg::PackageSpecParseResult> spec = - vcpkg::PackageSpec::from_string("zlib:x64-uwp", vcpkg::Triplet::X86_WINDOWS); + vcpkg::ExpectedT<vcpkg::FullPackageSpec, vcpkg::PackageSpecParseResult> spec = + vcpkg::FullPackageSpec::from_string("zlib:x64-uwp", vcpkg::Triplet::X86_WINDOWS); Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error()); - Assert::AreEqual("zlib", spec.get()->name().c_str()); - Assert::AreEqual(vcpkg::Triplet::X64_UWP.canonical_name(), spec.get()->triplet().canonical_name()); + Assert::AreEqual("zlib", spec.get()->package_spec.name().c_str()); + Assert::AreEqual(vcpkg::Triplet::X64_UWP.canonical_name(), + spec.get()->package_spec.triplet().canonical_name()); } TEST_METHOD(package_spec_parse_with_multiple_colon) { - auto ec = vcpkg::PackageSpec::from_string("zlib:x86-uwp:", vcpkg::Triplet::X86_WINDOWS).error(); + auto ec = vcpkg::FullPackageSpec::from_string("zlib:x86-uwp:", vcpkg::Triplet::X86_WINDOWS).error(); Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec); } diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index c794b5ede..a0d690f37 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -102,6 +102,17 @@ namespace vcpkg::Build paths.get_filesystem().write_contents(binary_control_file, Strings::serialize(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) + { + 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)); + } + ExtendedBuildResult build_package(const VcpkgPaths& paths, const BuildPackageConfig& config, const StatusParagraphs& status_db) @@ -135,17 +146,36 @@ namespace vcpkg::Build const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset); const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); + std::string features; + if (g_feature_packages) + { + if (config.feature_list) + { + for (auto&& feature : *config.feature_list) + { + features.append(feature + ";"); + } + if (features.size() > 0) + { + features.pop_back(); + } + } + } + const std::wstring cmd_launch_cmake = make_cmake_cmd( cmake_exe_path, ports_cmake_script_path, - {{L"CMD", L"BUILD"}, - {L"PORT", config.src.name}, - {L"CURRENT_PORT_DIR", config.port_dir / "/."}, - {L"TARGET_TRIPLET", triplet.canonical_name()}, - {L"VCPKG_PLATFORM_TOOLSET", toolset.version}, - {L"VCPKG_USE_HEAD_VERSION", to_bool(config.build_package_options.use_head_version) ? L"1" : L"0"}, - {L"_VCPKG_NO_DOWNLOADS", !to_bool(config.build_package_options.allow_downloads) ? L"1" : L"0"}, - {L"GIT", git_exe_path}}); + { + {L"CMD", L"BUILD"}, + {L"PORT", config.src.name}, + {L"CURRENT_PORT_DIR", config.port_dir / "/."}, + {L"TARGET_TRIPLET", triplet.canonical_name()}, + {L"VCPKG_PLATFORM_TOOLSET", toolset.version}, + {L"VCPKG_USE_HEAD_VERSION", to_bool(config.build_package_options.use_head_version) ? L"1" : L"0"}, + {L"_VCPKG_NO_DOWNLOADS", !to_bool(config.build_package_options.allow_downloads) ? L"1" : L"0"}, + {L"GIT", git_exe_path}, + {L"FEATURES", features}, + }); const std::wstring command = Strings::wformat(LR"(%s && %s)", cmd_set_environment, cmd_launch_cmake); @@ -170,7 +200,21 @@ namespace vcpkg::Build { return {BuildResult::POST_BUILD_CHECKS_FAILED, {}}; } - + if (g_feature_packages) + { + if (config.feature_list) + { + for (auto&& feature : *config.feature_list) + { + 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_control_file(paths, config.src, triplet, build_info); // const fs::path port_buildtrees_dir = paths.buildtrees / spec.name; diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 90168813e..820e51b33 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -12,6 +12,8 @@ namespace vcpkg::Dependencies { + bool operator==(const ClusterPtr& l, const ClusterPtr& r) { return l.ptr == r.ptr; } + std::vector<PackageSpec> AnyParagraph::dependencies(const Triplet& triplet) const { auto to_package_specs = [&](const std::vector<std::string>& dependencies_as_string) { @@ -337,8 +339,7 @@ namespace vcpkg::Dependencies return toposort; } - std::vector<FeatureSpec> to_feature_specs(const std::vector<std::string> depends, - const std::unordered_map<std::string, PackageSpec> str_to_spec) + std::vector<FeatureSpec> to_feature_specs(const std::vector<std::string>& depends, const Triplet& triplet) { std::vector<FeatureSpec> f_specs; for (auto&& depend : depends) @@ -350,21 +351,16 @@ namespace vcpkg::Dependencies auto feature_name = depend.substr(start + 1, end - start - 1); auto package_name = depend.substr(0, start); - auto p_spec = str_to_spec.find(package_name); - if (p_spec != str_to_spec.end()) - { - auto feature_spec = FeatureSpec{p_spec->second, feature_name}; - f_specs.emplace_back(std::move(feature_spec)); - } + auto p_spec = PackageSpec::from_name_and_triplet(package_name, triplet).value_or_exit(VCPKG_LINE_INFO); + auto feature_spec = FeatureSpec{p_spec, feature_name}; + f_specs.emplace_back(std::move(feature_spec)); } else { - auto p_spec = str_to_spec.find(depend); - if (p_spec != str_to_spec.end()) - { - auto feature_spec = FeatureSpec{p_spec->second, ""}; - f_specs.emplace_back(std::move(feature_spec)); - } + auto p_spec = PackageSpec::from_name_and_triplet(depend, triplet).value_or_exit(VCPKG_LINE_INFO); + + auto feature_spec = FeatureSpec{p_spec, ""}; + f_specs.emplace_back(std::move(feature_spec)); } } return f_specs; @@ -405,7 +401,7 @@ namespace vcpkg::Dependencies mark_minus(cluster, pkg_to_cluster, graph_plan); } - graph_plan.install_graph.add_vertex(&cluster); + 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()) @@ -415,7 +411,7 @@ namespace vcpkg::Dependencies { 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); + graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); } } @@ -424,7 +420,7 @@ namespace vcpkg::Dependencies auto& depend_cluster = pkg_to_cluster[depend.spec]; mark_plus(depend.feature_name, depend_cluster, pkg_to_cluster, graph_plan); if (&depend_cluster == &cluster) continue; - graph_plan.install_graph.add_edge(&cluster, &depend_cluster); + graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster}); } return true; } @@ -434,14 +430,14 @@ namespace vcpkg::Dependencies if (cluster.will_remove) return; cluster.will_remove = true; - graph_plan.remove_graph.add_vertex(&cluster); + graph_plan.remove_graph.add_vertex({&cluster}); for (auto&& pair : cluster.edges) { auto& remove_edges_edges = pair.second.remove_edges; for (auto&& depend : remove_edges_edges) { auto& depend_cluster = pkg_to_cluster[depend.spec]; - graph_plan.remove_graph.add_edge(&cluster, &depend_cluster); + graph_plan.remove_graph.add_edge({&cluster}, {&depend_cluster}); depend_cluster.transient_uninstalled = true; mark_minus(depend_cluster, pkg_to_cluster, graph_plan); } @@ -456,40 +452,37 @@ namespace vcpkg::Dependencies const std::vector<FullPackageSpec>& specs, const StatusParagraphs& status_db) { - const auto triplet = Triplet::X86_WINDOWS; std::unordered_map<PackageSpec, Cluster> pkg_spec_to_package_node; - std::unordered_map<std::string, PackageSpec> str_to_spec; - - for (const auto& it : map) - { - str_to_spec.emplace(it.first.name(), it.first); - } for (const auto& it : map) { Cluster& node = pkg_spec_to_package_node[it.first]; + + node.spec = it.first; FeatureNodeEdges core_dependencies; - core_dependencies.build_edges = - to_feature_specs(filter_dependencies(it.second.core_paragraph->depends, triplet), str_to_spec); + auto core_depends = filter_dependencies(it.second.core_paragraph->depends, node.spec.triplet()); + core_dependencies.build_edges = to_feature_specs(core_depends, node.spec.triplet()); node.edges["core"] = std::move(core_dependencies); for (const auto& feature : it.second.feature_paragraphs) { FeatureNodeEdges added_edges; - added_edges.build_edges = to_feature_specs(filter_dependencies(feature->depends, triplet), str_to_spec); + auto depends = filter_dependencies(feature->depends, node.spec.triplet()); + added_edges.build_edges = to_feature_specs(depends, node.spec.triplet()); node.edges.emplace(feature->name, std::move(added_edges)); } - node.cluster_data.source_paragraph = &it.second; + node.source_control_file = &it.second; } - for (auto&& status_paragraph : status_db) + for (auto&& status_paragraph : get_installed_ports(status_db)) { auto& spec = status_paragraph->package.spec; auto& status_paragraph_feature = status_paragraph->package.feature; Cluster& cluster = pkg_spec_to_package_node[spec]; cluster.transient_uninstalled = false; - auto reverse_edges = to_feature_specs(status_paragraph->package.depends, str_to_spec); + auto reverse_edges = + to_feature_specs(status_paragraph->package.depends, status_paragraph->package.spec.triplet()); for (auto&& dependency : reverse_edges) { @@ -507,7 +500,7 @@ namespace vcpkg::Dependencies auto& target_node = pkg_node->second.edges[depends_name]; target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); } - cluster.cluster_data.status_paragraphs.emplace_back(*status_paragraph); + cluster.status_paragraphs.emplace_back(*status_paragraph); if (status_paragraph_feature == "") { cluster.original_features.insert("core"); @@ -528,35 +521,40 @@ namespace vcpkg::Dependencies } } - Graphs::GraphAdjacencyProvider<Cluster*> adjacency_remove_graph(graph_plan.remove_graph.adjacency_list()); + Graphs::GraphAdjacencyProvider<ClusterPtr> adjacency_remove_graph(graph_plan.remove_graph.adjacency_list()); auto remove_vertex_list = graph_plan.remove_graph.vertex_list(); auto remove_toposort = Graphs::topological_sort(remove_vertex_list, adjacency_remove_graph); - Graphs::GraphAdjacencyProvider<Cluster*> adjacency_install_graph(graph_plan.install_graph.adjacency_list()); + Graphs::GraphAdjacencyProvider<ClusterPtr> adjacency_install_graph(graph_plan.install_graph.adjacency_list()); auto insert_vertex_list = graph_plan.install_graph.vertex_list(); auto insert_toposort = Graphs::topological_sort(insert_vertex_list, adjacency_install_graph); std::vector<AnyAction> install_plan; - for (auto&& cluster : remove_toposort) + for (auto&& like_cluster : remove_toposort) { - auto scf = *cluster->cluster_data.source_paragraph.get(); + auto scf = *like_cluster.ptr->source_control_file.get(); AnyAction any_plan; any_plan.remove_plan = RemovePlanAction{ - str_to_spec[scf->core_paragraph->name], RemovePlanType::REMOVE, RequestType::AUTO_SELECTED}; + PackageSpec::from_name_and_triplet(scf->core_paragraph->name, like_cluster.ptr->spec.triplet()) + .value_or_exit(VCPKG_LINE_INFO), + RemovePlanType::REMOVE, + RequestType::AUTO_SELECTED}; install_plan.emplace_back(std::move(any_plan)); } - for (auto&& cluster : insert_toposort) + for (auto&& like_cluster : insert_toposort) { - if (!cluster->transient_uninstalled) continue; - - auto scf = *cluster->cluster_data.source_paragraph.get(); - auto& pkg_spec = str_to_spec[scf->core_paragraph->name]; - auto action = InstallPlanAction{ - pkg_spec, map.find(pkg_spec)->second, cluster->to_install_features, RequestType::AUTO_SELECTED}; + if (!like_cluster.ptr->transient_uninstalled) continue; + + auto scf = *like_cluster.ptr->source_control_file.get(); + auto pkg_spec = + PackageSpec::from_name_and_triplet(scf->core_paragraph->name, like_cluster.ptr->spec.triplet()) + .value_or_exit(VCPKG_LINE_INFO); + auto action = + InstallPlanAction{pkg_spec, *scf, like_cluster.ptr->to_install_features, RequestType::AUTO_SELECTED}; AnyAction any_plan; any_plan.install_plan = std::move(action); diff --git a/toolsrc/src/vcpkg_Input.cpp b/toolsrc/src/vcpkg_Input.cpp index fdedd5507..f4e9a07c2 100644 --- a/toolsrc/src/vcpkg_Input.cpp +++ b/toolsrc/src/vcpkg_Input.cpp @@ -12,10 +12,10 @@ namespace vcpkg::Input CStringView example_text) { const std::string as_lowercase = Strings::ascii_to_lowercase(package_spec_as_string); - auto expected_spec = PackageSpec::from_string(as_lowercase, default_triplet); + auto expected_spec = FullPackageSpec::from_string(as_lowercase, default_triplet); if (auto spec = expected_spec.get()) { - return PackageSpec{*spec}; + return PackageSpec{spec->package_spec}; } // Intentionally show the lowercased string @@ -39,26 +39,11 @@ namespace vcpkg::Input const Triplet& default_triplet, CStringView example_text) { - int left_pos = (int)full_package_spec_as_string.find('['); - if (left_pos == std::string::npos) - { - return FullPackageSpec{ - check_and_get_package_spec(full_package_spec_as_string, default_triplet, example_text)}; - } - int right_pos = (int)full_package_spec_as_string.find(']'); - if (left_pos >= right_pos) - { - System::println(System::Color::error, "Error: Argument is not formatted correctly \"%s\""); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - std::string package_spec_as_string = full_package_spec_as_string.substr(0, left_pos); - const std::string as_lowercase = Strings::ascii_to_lowercase(package_spec_as_string); - auto expected_spec = PackageSpec::from_string(as_lowercase, default_triplet); - if (auto&& spec = expected_spec.get()) + const std::string as_lowercase = Strings::ascii_to_lowercase(full_package_spec_as_string); + auto expected_spec = FullPackageSpec::from_string(as_lowercase, default_triplet); + if (auto spec = expected_spec.get()) { - return {*spec, - parse_comma_list(full_package_spec_as_string.substr(left_pos + 1, right_pos - left_pos - 1))}; + return *spec; } // Intentionally show the lowercased string diff --git a/toolsrc/src/vcpkg_Parse.cpp b/toolsrc/src/vcpkg_Parse.cpp index b63ce41a9..659af2939 100644 --- a/toolsrc/src/vcpkg_Parse.cpp +++ b/toolsrc/src/vcpkg_Parse.cpp @@ -6,18 +6,6 @@ namespace vcpkg::Parse { - static Optional<std::string> get_field(const std::unordered_map<std::string, std::string>& fields, - const std::string& fieldname) - { - auto it = fields.find(fieldname); - if (it == fields.end()) - { - return nullopt; - } - - return it->second; - } - static Optional<std::string> remove_field(std::unordered_map<std::string, std::string>* fields, const std::string& fieldname) { |
