diff options
| author | Robert Schumacher <roschuma@microsoft.com> | 2018-02-25 10:13:57 -0800 |
|---|---|---|
| committer | Robert Schumacher <roschuma@microsoft.com> | 2018-02-25 10:40:28 -0800 |
| commit | 8b97ae2dc14672ca83a5a7dc8f1d62af99234476 (patch) | |
| tree | 68a40d1832b70b6e241b5b5d6213798f3253d688 | |
| parent | 99d30fa105c9f6b8fe70417fc72fcbf9bfb16dfa (diff) | |
| download | vcpkg-8b97ae2dc14672ca83a5a7dc8f1d62af99234476.tar.gz vcpkg-8b97ae2dc14672ca83a5a7dc8f1d62af99234476.zip | |
[vcpkg] Fix "just-in-time" requirements calculation
| -rw-r--r-- | toolsrc/include/vcpkg/base/util.h | 9 | ||||
| -rw-r--r-- | toolsrc/include/vcpkg/build.h | 5 | ||||
| -rw-r--r-- | toolsrc/include/vcpkg/commands.h | 1 | ||||
| -rw-r--r-- | toolsrc/include/vcpkg/dependencies.h | 6 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg/build.cpp | 117 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg/commands.hash.cpp | 10 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg/dependencies.cpp | 8 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg/statusparagraphs.cpp | 10 |
8 files changed, 112 insertions, 54 deletions
diff --git a/toolsrc/include/vcpkg/base/util.h b/toolsrc/include/vcpkg/base/util.h index 6c05a3a9e..5e07b240a 100644 --- a/toolsrc/include/vcpkg/base/util.h +++ b/toolsrc/include/vcpkg/base/util.h @@ -127,6 +127,15 @@ namespace vcpkg::Util std::sort(begin(cont), end(cont)); } + template<class Range> + void sort_unique_erase(Range& cont) + { + using std::begin; + using std::end; + std::sort(begin(cont), end(cont)); + cont.erase(std::unique(begin(cont), end(cont)), end(cont)); + } + template<class Range1, class Range2> bool all_equal(const Range1& r1, const Range2& r2) { diff --git a/toolsrc/include/vcpkg/build.h b/toolsrc/include/vcpkg/build.h index 7ef7d6516..f560dbf57 100644 --- a/toolsrc/include/vcpkg/build.h +++ b/toolsrc/include/vcpkg/build.h @@ -12,6 +12,7 @@ #include <array> #include <map> +#include <set> #include <vector> namespace vcpkg::Build @@ -125,7 +126,7 @@ namespace vcpkg::Build const Triplet& triplet, fs::path&& port_dir, const BuildPackageOptions& build_package_options, - const std::unordered_set<std::string>& feature_list) + const std::set<std::string>& feature_list) : scf(src) , triplet(triplet) , port_dir(std::move(port_dir)) @@ -138,7 +139,7 @@ namespace vcpkg::Build const Triplet& triplet; fs::path port_dir; const BuildPackageOptions& build_package_options; - const std::unordered_set<std::string>& feature_list; + const std::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 31c750b38..4027e12f4 100644 --- a/toolsrc/include/vcpkg/commands.h +++ b/toolsrc/include/vcpkg/commands.h @@ -120,6 +120,7 @@ namespace vcpkg::Commands namespace Hash { void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths); + std::string get_file_hash(fs::path const& cmake_exe_path, fs::path const& path, std::string const& hash_type); } template<class T> diff --git a/toolsrc/include/vcpkg/dependencies.h b/toolsrc/include/vcpkg/dependencies.h index de68d06e9..6e02e4efd 100644 --- a/toolsrc/include/vcpkg/dependencies.h +++ b/toolsrc/include/vcpkg/dependencies.h @@ -39,12 +39,12 @@ namespace vcpkg::Dependencies InstallPlanAction(const PackageSpec& spec, InstalledPackageView&& spghs, - const std::unordered_set<std::string>& features, + const std::set<std::string>& features, const RequestType& request_type); InstallPlanAction(const PackageSpec& spec, const SourceControlFile& scf, - const std::unordered_set<std::string>& features, + const std::set<std::string>& features, const RequestType& request_type); std::string displayname() const; @@ -57,7 +57,7 @@ namespace vcpkg::Dependencies InstallPlanType plan_type; RequestType request_type; Build::BuildPackageOptions build_options; - std::unordered_set<std::string> feature_list; + std::set<std::string> feature_list; }; enum class RemovePlanType diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index c169a778e..ff7554b78 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -66,7 +66,8 @@ namespace vcpkg::Build::Command Build::CleanBuildtrees::NO, Build::CleanPackages::NO}; - const std::unordered_set<std::string> features_as_set(full_spec.features.begin(), full_spec.features.end()); + std::set<std::string> features_as_set(full_spec.features.begin(), full_spec.features.end()); + features_as_set.emplace("core"); const Build::BuildPackageConfig build_config{ *scf, spec.triplet(), fs::path{port_dir}, build_package_options, features_as_set}; @@ -260,56 +261,93 @@ namespace vcpkg::Build paths.get_filesystem().write_contents(binary_control_file, start); } - static ExtendedBuildResult do_build_package(const VcpkgPaths& paths, - const BuildPackageConfig& config, - const StatusParagraphs& status_db) + static std::vector<FeatureSpec> compute_required_feature_specs(const BuildPackageConfig& config, + const StatusParagraphs& status_db) { - const PackageSpec spec = PackageSpec::from_name_and_triplet(config.scf.core_paragraph->name, config.triplet) - .value_or_exit(VCPKG_LINE_INFO); - const Triplet& triplet = config.triplet; + + auto dep_strings = + Util::fmap_flatten(config.feature_list, [&](std::string const& feature) -> std::vector<std::string> { + if (feature == "core") + { + return filter_dependencies(config.scf.core_paragraph->depends, triplet); + } + + auto it = + Util::find_if(config.scf.feature_paragraphs, + [&](std::unique_ptr<FeatureParagraph> const& fpgh) { return fpgh->name == feature; }); + Checks::check_exit(VCPKG_LINE_INFO, it != config.scf.feature_paragraphs.end()); + + return filter_dependencies(it->get()->depends, triplet); + }); + + auto dep_fspecs = FeatureSpec::from_strings_and_triplet(dep_strings, triplet); + Util::sort_unique_erase(dep_fspecs); + + // expand defaults + std::vector<FeatureSpec> ret; + for (auto&& fspec : dep_fspecs) { - std::vector<FeatureSpec> missing_specs; - for (auto&& dep : filter_dependencies(config.scf.core_paragraph->depends, triplet)) + if (fspec.feature().empty()) { - auto dep_specs = FeatureSpec::from_strings_and_triplet({dep}, triplet); - for (auto&& feature : dep_specs) + // reference to default features + auto it = status_db.find_installed(fspec.spec()); + if (it == status_db.end()) + { + // not currently installed, so just leave the default reference so it will fail later + ret.push_back(fspec); + } + else { - if (!status_db.is_installed(feature)) - { - missing_specs.push_back(std::move(feature)); - } + ret.push_back(FeatureSpec{fspec.spec(), "core"}); + for (auto&& default_feature : it->get()->package.default_features) + ret.push_back(FeatureSpec{fspec.spec(), default_feature}); } } - // Fail the build if any dependencies were missing - if (!missing_specs.empty()) + else { - return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(missing_specs)}; + ret.push_back(fspec); } } + Util::sort_unique_erase(ret); + + return ret; + } + + static ExtendedBuildResult do_build_package(const VcpkgPaths& paths, + const BuildPackageConfig& config, + const StatusParagraphs& status_db) + { + auto& fs = paths.get_filesystem(); + const Triplet& triplet = config.triplet; + + const PackageSpec spec = + PackageSpec::from_name_and_triplet(config.scf.core_paragraph->name, triplet).value_or_exit(VCPKG_LINE_INFO); + + std::vector<FeatureSpec> required_fspecs = compute_required_feature_specs(config, status_db); + + // Find all features that aren't installed. This destroys required_fspecs. + Util::unstable_keep_if(required_fspecs, + [&](FeatureSpec const& fspec) { return !status_db.is_installed(fspec); }); + + if (!required_fspecs.empty()) + { + return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(required_fspecs)}; + } const fs::path& cmake_exe_path = paths.get_cmake_exe(); const fs::path& git_exe_path = paths.get_git_exe(); const fs::path ports_cmake_script_path = paths.ports_cmake; + const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); - std::string features; + std::string features = Strings::join(";", config.feature_list); + std::string all_features; - if (GlobalState::feature_packages) + for (auto& feature : config.scf.feature_paragraphs) { - for (auto&& feature : config.feature_list) - { - features.append(feature + ";"); - } - if (!features.empty()) - { - features.pop_back(); - } - for (auto& feature : config.scf.feature_paragraphs) - { - all_features.append(feature->name + ";"); - } + all_features.append(feature->name + ";"); } const Toolset& toolset = paths.get_toolset(pre_build_info); @@ -351,7 +389,7 @@ namespace vcpkg::Build } } - const BuildInfo build_info = read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); + const BuildInfo build_info = read_build_info(fs, paths.build_info_file_path(spec)); const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); auto bcf = create_binary_control_file(*config.scf.core_paragraph, triplet, build_info); @@ -360,16 +398,13 @@ namespace vcpkg::Build { return BuildResult::POST_BUILD_CHECKS_FAILED; } - if (GlobalState::feature_packages) + for (auto&& feature : config.feature_list) { - for (auto&& feature : config.feature_list) + for (auto&& f_pgh : config.scf.feature_paragraphs) { - for (auto&& f_pgh : config.scf.feature_paragraphs) - { - if (f_pgh->name == feature) - bcf->features.push_back( - create_binary_feature_control_file(*config.scf.core_paragraph, *f_pgh, triplet)); - } + if (f_pgh->name == feature) + bcf->features.push_back( + create_binary_feature_control_file(*config.scf.core_paragraph, *f_pgh, triplet)); } } diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index fa3d80f27..767a1bf26 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -7,7 +7,7 @@ namespace vcpkg::Commands::Hash { - static void do_file_hash(fs::path const& cmake_exe_path, fs::path const& path, std::string const& hash_type) + std::string get_file_hash(fs::path const& cmake_exe_path, fs::path const& path, std::string const& hash_type) { const std::string cmd_line = Strings::format( R"("%s" -E %ssum %s)", cmake_exe_path.u8string(), Strings::ascii_to_lowercase(hash_type), path.u8string()); @@ -27,7 +27,7 @@ namespace vcpkg::Commands::Hash auto hash = output.substr(0, start); Util::erase_remove_if(hash, isspace); - System::println(hash); + return hash; } const CommandStructure COMMAND_STRUCTURE = { @@ -45,11 +45,13 @@ namespace vcpkg::Commands::Hash if (args.command_arguments.size() == 1) { - do_file_hash(paths.get_cmake_exe(), args.command_arguments[0], "SHA512"); + auto hash = get_file_hash(paths.get_cmake_exe(), args.command_arguments[0], "SHA512"); + System::println(hash); } if (args.command_arguments.size() == 2) { - do_file_hash(paths.get_cmake_exe(), args.command_arguments[0], args.command_arguments[1]); + auto hash = get_file_hash(paths.get_cmake_exe(), args.command_arguments[0], args.command_arguments[1]); + System::println(hash); } Checks::exit_success(VCPKG_LINE_INFO); diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 793951ab5..649e8f1d8 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -30,8 +30,8 @@ namespace vcpkg::Dependencies 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; + std::set<std::string> to_install_features; + std::set<std::string> original_features; bool will_remove = false; bool transient_uninstalled = true; RequestType request_type = RequestType::AUTO_SELECTED; @@ -143,7 +143,7 @@ namespace vcpkg::Dependencies InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const SourceControlFile& scf, - const std::unordered_set<std::string>& features, + const std::set<std::string>& features, const RequestType& request_type) : spec(spec) , source_control_file(scf) @@ -155,7 +155,7 @@ namespace vcpkg::Dependencies InstallPlanAction::InstallPlanAction(const PackageSpec& spec, InstalledPackageView&& ipv, - const std::unordered_set<std::string>& features, + const std::set<std::string>& features, const RequestType& request_type) : spec(spec) , installed_package(std::move(ipv)) diff --git a/toolsrc/src/vcpkg/statusparagraphs.cpp b/toolsrc/src/vcpkg/statusparagraphs.cpp index b23d8b884..c642af59b 100644 --- a/toolsrc/src/vcpkg/statusparagraphs.cpp +++ b/toolsrc/src/vcpkg/statusparagraphs.cpp @@ -54,6 +54,11 @@ namespace vcpkg const Triplet& triplet, const std::string& feature) { + if (feature == "core") + { + // The core feature maps to .feature == "" + return find(name, triplet, ""); + } 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; @@ -64,6 +69,11 @@ namespace vcpkg const Triplet& triplet, const std::string& feature) const { + if (feature == "core") + { + // The core feature maps to .feature == "" + return find(name, triplet, ""); + } 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; |
