diff options
Diffstat (limited to 'toolsrc/src')
| -rw-r--r-- | toolsrc/src/BinaryParagraph.cpp | 4 | ||||
| -rw-r--r-- | toolsrc/src/SourceParagraph.cpp | 83 | ||||
| -rw-r--r-- | toolsrc/src/commands_installation.cpp | 11 | ||||
| -rw-r--r-- | toolsrc/src/lib.cpp | 40 | ||||
| -rw-r--r-- | toolsrc/src/tests_dependencies.cpp | 39 | ||||
| -rw-r--r-- | toolsrc/src/tests_paragraph.cpp (renamed from toolsrc/src/test.cpp) | 50 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg_Checks.cpp | 3 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg_Dependencies.cpp | 8 | ||||
| -rw-r--r-- | toolsrc/src/vcpkglib_helpers.cpp | 33 |
9 files changed, 196 insertions, 75 deletions
diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp index 6dceb66d9..ad85a1f8a 100644 --- a/toolsrc/src/BinaryParagraph.cpp +++ b/toolsrc/src/BinaryParagraph.cpp @@ -56,7 +56,7 @@ namespace vcpkg Checks::check_exit(multi_arch == "same", "Multi-Arch must be 'same' but was %s", multi_arch); std::string deps = details::remove_optional_field(&fields, BinaryParagraphOptionalField::DEPENDS); - this->depends = details::parse_depends(deps); + this->depends = parse_depends(deps); } BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const triplet& target_triplet) @@ -65,7 +65,7 @@ namespace vcpkg this->version = spgh.version; this->description = spgh.description; this->maintainer = spgh.maintainer; - this->depends = spgh.depends; + this->depends = filter_dependencies(spgh.depends, target_triplet); } std::string BinaryParagraph::displayname() const diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 6f25dbded..bdf15a737 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -2,6 +2,7 @@ #include "vcpkglib_helpers.h" #include "vcpkg_System.h" #include "vcpkg_Maps.h" +#include "triplet.h" namespace vcpkg { @@ -44,7 +45,7 @@ namespace vcpkg this->maintainer = details::remove_optional_field(&fields, SourceParagraphOptionalField::MAINTAINER); std::string deps = details::remove_optional_field(&fields, SourceParagraphOptionalField::BUILD_DEPENDS); - this->depends = details::parse_depends(deps); + this->depends = expand_qualified_dependencies(parse_depends(deps)); if (!fields.empty()) { @@ -60,4 +61,84 @@ namespace vcpkg exit(EXIT_FAILURE); } } + + std::vector<dependency> vcpkg::expand_qualified_dependencies(const std::vector<std::string>& depends) + { + auto convert = [&](const std::string& depend_string) -> dependency { + auto pos = depend_string.find(' '); + if (pos == std::string::npos) + return{ depend_string, "" }; + // expect of the form "\w+ \[\w+\]" + dependency dep; + dep.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, "" }; + } + dep.qualifier = depend_string.substr(pos + 2, depend_string.size() - pos - 3); + return dep; + }; + + std::vector<vcpkg::dependency> ret; + + for (auto&& depend_string : depends) + { + ret.push_back(convert(depend_string)); + } + + return ret; + } + + std::vector<std::string> parse_depends(const std::string& depends_string) + { + if (depends_string.empty()) + { + return{}; + } + + std::vector<std::string> out; + + size_t cur = 0; + do + { + auto pos = depends_string.find(',', cur); + if (pos == std::string::npos) + { + out.push_back(depends_string.substr(cur)); + break; + } + out.push_back(depends_string.substr(cur, pos - cur)); + + // skip comma and space + ++pos; + if (depends_string[pos] == ' ') + { + ++pos; + } + + cur = pos; + } while (cur != std::string::npos); + + return out; + } + + std::vector<std::string> filter_dependencies(const std::vector<vcpkg::dependency>& deps, const triplet& t) + { + std::vector<std::string> ret; + for (auto&& dep : deps) + { + if (dep.qualifier.empty() || t.canonical_name().find(dep.qualifier) != std::string::npos) + { + ret.push_back(dep.name); + } + } + return ret; + } + + std::ostream & operator<<(std::ostream & os, const dependency & p) + { + os << p.name; + return os; + } } diff --git a/toolsrc/src/commands_installation.cpp b/toolsrc/src/commands_installation.cpp index 022b87139..f6aeafa02 100644 --- a/toolsrc/src/commands_installation.cpp +++ b/toolsrc/src/commands_installation.cpp @@ -138,7 +138,16 @@ namespace vcpkg const package_spec spec = Input::check_and_get_package_spec(args.command_arguments.at(0), default_target_triplet, example.c_str()); Input::check_triplet(spec.target_triplet(), paths); - std::unordered_set<package_spec> unmet_dependencies = Dependencies::find_unmet_dependencies(paths, spec, status_db); + + // Explicitly load and use the portfile's build dependencies when resolving the build command (instead of a cached package's dependencies). + auto first_level_deps = get_unmet_package_build_dependencies(paths, spec, status_db); + std::vector<package_spec> first_level_deps_specs; + for (auto&& dep : first_level_deps) + { + first_level_deps_specs.push_back(package_spec::from_name_and_triplet(dep, spec.target_triplet()).get_or_throw()); + } + + std::unordered_set<package_spec> unmet_dependencies = Dependencies::find_unmet_dependencies(paths, first_level_deps_specs, status_db); if (!unmet_dependencies.empty()) { System::println(System::color::error, "The build command requires all dependencies to be already installed."); diff --git a/toolsrc/src/lib.cpp b/toolsrc/src/lib.cpp index 45b73ee07..3c844ac3f 100644 --- a/toolsrc/src/lib.cpp +++ b/toolsrc/src/lib.cpp @@ -209,29 +209,33 @@ static void install_and_write_listfile(const vcpkg_paths& paths, const BinaryPar // TODO: Refactoring between this function and install_package std::vector<std::string> vcpkg::get_unmet_package_dependencies(const vcpkg_paths& paths, const package_spec& spec, const StatusParagraphs& status_db) { - std::vector<std::unordered_map<std::string, std::string>> pghs; - { - const fs::path packages_dir_control_file_path = paths.package_dir(spec) / "CONTROL"; + const fs::path packages_dir_control_file_path = paths.package_dir(spec) / "CONTROL"; - auto control_contents_maybe = Files::get_contents(packages_dir_control_file_path); - if (auto control_contents = control_contents_maybe.get()) + auto control_contents_maybe = Files::get_contents(packages_dir_control_file_path); + if (auto control_contents = control_contents_maybe.get()) + { + std::vector<std::unordered_map<std::string, std::string>> pghs; + try + { + pghs = parse_paragraphs(*control_contents); + } + catch (std::runtime_error) { - try - { - pghs = parse_paragraphs(*control_contents); - } - catch (std::runtime_error) - { - } - Checks::check_exit(pghs.size() == 1, "Invalid control file at %s", packages_dir_control_file_path.string()); - return BinaryParagraph(pghs[0]).depends; } + Checks::check_exit(pghs.size() == 1, "Invalid control file at %s", packages_dir_control_file_path.string()); + return BinaryParagraph(pghs[0]).depends; } + return get_unmet_package_build_dependencies(paths, spec, status_db); +} + +std::vector<std::string> vcpkg::get_unmet_package_build_dependencies(const vcpkg_paths& paths, const package_spec& spec, const StatusParagraphs& status_db) +{ const fs::path ports_dir_control_file_path = paths.port_dir(spec) / "CONTROL"; auto control_contents_maybe = Files::get_contents(ports_dir_control_file_path); if (auto control_contents = control_contents_maybe.get()) { + std::vector<std::unordered_map<std::string, std::string>> pghs; try { pghs = parse_paragraphs(*control_contents); @@ -240,7 +244,7 @@ std::vector<std::string> vcpkg::get_unmet_package_dependencies(const vcpkg_paths { } Checks::check_exit(pghs.size() == 1, "Invalid control file at %s", ports_dir_control_file_path.string()); - return SourceParagraph(pghs[0]).depends; + return filter_dependencies(SourceParagraph(pghs[0]).depends, spec.target_triplet()); } Checks::exit_with_message("Could not find package named %s", spec); @@ -252,11 +256,11 @@ void vcpkg::install_package(const vcpkg_paths& paths, const BinaryParagraph& bin spgh.package = binary_paragraph; spgh.want = want_t::install; spgh.state = install_state_t::half_installed; - for (const std::string& dependency : spgh.package.depends) + for (auto&& dep : spgh.package.depends) { - if (status_db.find_installed(dependency, spgh.package.spec.target_triplet()) == status_db.end()) + if (status_db.find_installed(dep, spgh.package.spec.target_triplet()) == status_db.end()) { - std::abort(); + Checks::unreachable(); } } write_update(paths, spgh); diff --git a/toolsrc/src/tests_dependencies.cpp b/toolsrc/src/tests_dependencies.cpp new file mode 100644 index 000000000..bce1cab0e --- /dev/null +++ b/toolsrc/src/tests_dependencies.cpp @@ -0,0 +1,39 @@ +#include "CppUnitTest.h" +#include "SourceParagraph.h" +#include "triplet.h" + +#pragma comment(lib,"version") +#pragma comment(lib,"winhttp") + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +using namespace vcpkg; + +namespace UnitTest1 +{ + TEST_CLASS(DependencyTests) + { + public: + TEST_METHOD(parse_depends_one) + { + auto v = expand_qualified_dependencies(parse_depends("libA [windows]")); + Assert::AreEqual(size_t(1), v.size()); + Assert::AreEqual("libA", v[0].name.c_str()); + Assert::AreEqual("windows", v[0].qualifier.c_str()); + } + + TEST_METHOD(filter_depends) + { + auto deps = expand_qualified_dependencies(parse_depends("libA [windows], libB, libC [uwp]")); + auto v = filter_dependencies(deps, triplet::X64_WINDOWS); + Assert::AreEqual(size_t(2), v.size()); + Assert::AreEqual("libA", v[0].c_str()); + Assert::AreEqual("libB", v[1].c_str()); + + auto v2 = filter_dependencies(deps, triplet::ARM_UWP); + Assert::AreEqual(size_t(2), v.size()); + Assert::AreEqual("libB", v2[0].c_str()); + Assert::AreEqual("libC", v2[1].c_str()); + } + }; +} diff --git a/toolsrc/src/test.cpp b/toolsrc/src/tests_paragraph.cpp index fc49b362d..b06359b90 100644 --- a/toolsrc/src/test.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -48,7 +48,7 @@ namespace UnitTest1 Assert::AreEqual("m", pgh.maintainer.c_str()); Assert::AreEqual("d", pgh.description.c_str()); Assert::AreEqual(size_t(1), pgh.depends.size()); - Assert::AreEqual("bd", pgh.depends[0].c_str()); + Assert::AreEqual("bd", pgh.depends[0].name.c_str()); } TEST_METHOD(SourceParagraph_Two_Depends) @@ -60,8 +60,8 @@ namespace UnitTest1 }); Assert::AreEqual(size_t(2), pgh.depends.size()); - Assert::AreEqual("z", pgh.depends[0].c_str()); - Assert::AreEqual("openssl", pgh.depends[1].c_str()); + Assert::AreEqual("z", pgh.depends[0].name.c_str()); + Assert::AreEqual("openssl", pgh.depends[1].name.c_str()); } TEST_METHOD(SourceParagraph_Three_Depends) @@ -73,17 +73,37 @@ namespace UnitTest1 }); Assert::AreEqual(size_t(3), pgh.depends.size()); - Assert::AreEqual("z", pgh.depends[0].c_str()); - Assert::AreEqual("openssl", pgh.depends[1].c_str()); - Assert::AreEqual("xyz", pgh.depends[2].c_str()); + Assert::AreEqual("z", pgh.depends[0].name.c_str()); + Assert::AreEqual("openssl", pgh.depends[1].name.c_str()); + Assert::AreEqual("xyz", pgh.depends[2].name.c_str()); } + TEST_METHOD(SourceParagraph_Construct_Qualified_Depends) + { + vcpkg::SourceParagraph pgh({ + { "Source", "zlib" }, + { "Version", "1.2.8" }, + { "Build-Depends", "libA [windows], libB [uwp]" } + }); + + Assert::AreEqual("zlib", pgh.name.c_str()); + Assert::AreEqual("1.2.8", pgh.version.c_str()); + Assert::AreEqual("", pgh.maintainer.c_str()); + Assert::AreEqual("", pgh.description.c_str()); + Assert::AreEqual(size_t(2), pgh.depends.size()); + Assert::AreEqual("libA", pgh.depends[0].name.c_str()); + Assert::AreEqual("windows", pgh.depends[0].qualifier.c_str()); + Assert::AreEqual("libB", pgh.depends[1].name.c_str()); + Assert::AreEqual("uwp", pgh.depends[1].qualifier.c_str()); + } + + TEST_METHOD(BinaryParagraph_Construct_Minimum) { vcpkg::BinaryParagraph pgh({ {"Package", "zlib"}, {"Version", "1.2.8"}, - {"Architecture", "a"}, + {"Architecture", "x86-windows"}, {"Multi-Arch", "same"}, }); @@ -91,7 +111,7 @@ namespace UnitTest1 Assert::AreEqual("1.2.8", pgh.version.c_str()); Assert::AreEqual("", pgh.maintainer.c_str()); Assert::AreEqual("", pgh.description.c_str()); - Assert::AreEqual("a", pgh.spec.target_triplet().canonical_name().c_str()); + Assert::AreEqual("x86-windows", pgh.spec.target_triplet().canonical_name().c_str()); Assert::AreEqual(size_t(0), pgh.depends.size()); } @@ -100,7 +120,7 @@ namespace UnitTest1 vcpkg::BinaryParagraph pgh({ {"Package", "s"}, {"Version", "v"}, - {"Architecture", "a"}, + {"Architecture", "x86-windows"}, {"Multi-Arch", "same"}, {"Maintainer", "m"}, {"Description", "d"}, @@ -119,7 +139,7 @@ namespace UnitTest1 vcpkg::BinaryParagraph pgh({ {"Package", "zlib"}, {"Version", "1.2.8"}, - {"Architecture", "a"}, + {"Architecture", "x86-windows"}, {"Multi-Arch", "same"}, {"Depends", "a, b, c"}, }); @@ -253,7 +273,7 @@ namespace UnitTest1 vcpkg::BinaryParagraph pgh({ {"Package", "zlib"}, {"Version", "1.2.8"}, - {"Architecture", "a"}, + {"Architecture", "x86-windows"}, {"Multi-Arch", "same"}, }); ss << pgh; @@ -262,7 +282,7 @@ namespace UnitTest1 Assert::AreEqual(size_t(4), pghs[0].size()); Assert::AreEqual("zlib", pghs[0]["Package"].c_str()); Assert::AreEqual("1.2.8", pghs[0]["Version"].c_str()); - Assert::AreEqual("a", pghs[0]["Architecture"].c_str()); + Assert::AreEqual("x86-windows", pghs[0]["Architecture"].c_str()); Assert::AreEqual("same", pghs[0]["Multi-Arch"].c_str()); } @@ -272,7 +292,7 @@ namespace UnitTest1 vcpkg::BinaryParagraph pgh({ {"Package", "zlib"}, {"Version", "1.2.8"}, - {"Architecture", "a"}, + {"Architecture", "x86-windows"}, {"Description", "first line\n second line"}, {"Maintainer", "abc <abc@abc.abc>"}, {"Depends", "dep"}, @@ -284,7 +304,7 @@ namespace UnitTest1 Assert::AreEqual(size_t(7), pghs[0].size()); Assert::AreEqual("zlib", pghs[0]["Package"].c_str()); Assert::AreEqual("1.2.8", pghs[0]["Version"].c_str()); - Assert::AreEqual("a", pghs[0]["Architecture"].c_str()); + Assert::AreEqual("x86-windows", pghs[0]["Architecture"].c_str()); Assert::AreEqual("same", pghs[0]["Multi-Arch"].c_str()); Assert::AreEqual("first line\n second line", pghs[0]["Description"].c_str()); Assert::AreEqual("dep", pghs[0]["Depends"].c_str()); @@ -296,7 +316,7 @@ namespace UnitTest1 vcpkg::BinaryParagraph pgh({ {"Package", "zlib"}, {"Version", "1.2.8"}, - {"Architecture", "a"}, + {"Architecture", "x86-windows"}, {"Multi-Arch", "same"}, {"Depends", "a, b, c"}, }); diff --git a/toolsrc/src/vcpkg_Checks.cpp b/toolsrc/src/vcpkg_Checks.cpp index db6c03480..453ba81fd 100644 --- a/toolsrc/src/vcpkg_Checks.cpp +++ b/toolsrc/src/vcpkg_Checks.cpp @@ -8,6 +8,9 @@ namespace vcpkg {namespace Checks void unreachable() { System::println(System::color::error, "Error: Unreachable code was reached"); +#ifndef NDEBUG + std::abort(); +#endif exit(EXIT_FAILURE); } diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 54b37cd11..0e45b28dd 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -57,11 +57,9 @@ namespace vcpkg { namespace Dependencies return build_dependency_graph(paths, specs, status_db).find_topological_sort(); } - std::unordered_set<package_spec> find_unmet_dependencies(const vcpkg_paths& paths, const package_spec& spec, const StatusParagraphs& status_db) + std::unordered_set<package_spec> find_unmet_dependencies(const vcpkg_paths& paths, const std::vector<package_spec>& specs, const StatusParagraphs& status_db) { - const Graphs::Graph<package_spec> dependency_graph = build_dependency_graph(paths, {spec}, status_db); - std::unordered_set<package_spec> key_set = Maps::extract_key_set(dependency_graph.adjacency_list()); - key_set.erase(spec); - return key_set; + const Graphs::Graph<package_spec> dependency_graph = build_dependency_graph(paths, specs, status_db); + return Maps::extract_key_set(dependency_graph.adjacency_list()); } }} diff --git a/toolsrc/src/vcpkglib_helpers.cpp b/toolsrc/src/vcpkglib_helpers.cpp index 3d14d4b06..61dc4f4cc 100644 --- a/toolsrc/src/vcpkglib_helpers.cpp +++ b/toolsrc/src/vcpkglib_helpers.cpp @@ -45,37 +45,4 @@ namespace vcpkg {namespace details return value; } - std::vector<std::string> parse_depends(const std::string& depends_string) - { - if (depends_string.empty()) - { - return {}; - } - - std::vector<std::string> out; - - size_t cur = 0; - do - { - auto pos = depends_string.find(',', cur); - if (pos == std::string::npos) - { - out.push_back(depends_string.substr(cur)); - break; - } - out.push_back(depends_string.substr(cur, pos - cur)); - - // skip comma and space - ++pos; - if (depends_string[pos] == ' ') - { - ++pos; - } - - cur = pos; - } - while (cur != std::string::npos); - - return out; - } }} |
