From 2b9035063234f04fb68c3b4fefe8d3da7a5175a6 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 10 Feb 2017 17:00:46 -0800 Subject: [PATCH] Separate dependency check from build_package() --- toolsrc/include/vcpkg_Commands.h | 11 ++++- toolsrc/src/commands_build.cpp | 53 +++++++++++++++---------- toolsrc/src/commands_build_external.cpp | 8 +++- toolsrc/src/commands_install.cpp | 4 +- 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/toolsrc/include/vcpkg_Commands.h b/toolsrc/include/vcpkg_Commands.h index ef300ac12..86c77a8bf 100644 --- a/toolsrc/include/vcpkg_Commands.h +++ b/toolsrc/include/vcpkg_Commands.h @@ -2,6 +2,7 @@ #include "vcpkg_cmd_arguments.h" #include "vcpkg_paths.h" +#include "StatusParagraphs.h" namespace vcpkg::Commands { @@ -11,16 +12,22 @@ namespace vcpkg::Commands namespace Build { + enum class DependencyStatus + { + ALL_DEPENDENCIES_INSTALLED, + MISSING_DEPENDENCIES + }; + enum class BuildResult { BUILD_NOT_STARTED = 0, SUCCESS, - CASCADED_DUE_TO_MISSING_DEPENDENCIES, BUILD_FAILED, POST_BUILD_CHECKS_FAILED, }; - BuildResult build_package(const SourceParagraph& source_paragraph, const package_spec& spec, const vcpkg_paths& paths, const fs::path& port_dir); + DependencyStatus check_dependencies(const SourceParagraph& source_paragraph, const package_spec& spec, const StatusParagraphs& status_db); + BuildResult build_package(const SourceParagraph& source_paragraph, const package_spec& spec, const vcpkg_paths& paths, const fs::path& port_dir, const DependencyStatus& dependency_status); void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet); } diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp index fa2468e1c..c9292aae9 100644 --- a/toolsrc/src/commands_build.cpp +++ b/toolsrc/src/commands_build.cpp @@ -24,11 +24,12 @@ namespace vcpkg::Commands::Build std::ofstream(binary_control_file) << bpgh; } - BuildResult build_package(const SourceParagraph& source_paragraph, const package_spec& spec, const vcpkg_paths& paths, const fs::path& port_dir) + BuildResult build_package(const SourceParagraph& source_paragraph, const package_spec& spec, const vcpkg_paths& paths, const fs::path& port_dir, const DependencyStatus& dependency_status) { Checks::check_exit(spec.name() == source_paragraph.name, "inconsistent arguments to build_package()"); - const triplet& target_triplet = spec.target_triplet(); + Checks::check_exit(dependency_status == DependencyStatus::ALL_DEPENDENCIES_INSTALLED, "Dependencies must be satisfied before attempting to build a package"); + const triplet& target_triplet = spec.target_triplet(); const fs::path ports_cmake_script_path = paths.ports_cmake; const Environment::vcvarsall_and_platform_toolset vcvarsall_bat = Environment::get_vcvarsall_bat(paths); const std::wstring command = Strings::wformat(LR"("%s" %s >nul 2>&1 && cmake -DCMD=BUILD -DPORT=%s -DTARGET_TRIPLET=%s -DVCPKG_PLATFORM_TOOLSET=%s "-DCURRENT_PORT_DIR=%s/." -P "%s")", @@ -76,6 +77,22 @@ namespace vcpkg::Commands::Build return BuildResult::SUCCESS; } + DependencyStatus check_dependencies(const SourceParagraph& source_paragraph, const package_spec& spec, const StatusParagraphs& status_db) + { + Checks::check_exit(spec.name() == source_paragraph.name, "inconsistent arguments to check_dependencies()"); + const triplet& target_triplet = spec.target_triplet(); + + for (auto&& dep : source_paragraph.depends) + { + if (status_db.find_installed(dep.name, target_triplet) == status_db.end()) + { + return DependencyStatus::MISSING_DEPENDENCIES; + } + } + + return DependencyStatus::ALL_DEPENDENCIES_INSTALLED; + } + void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet) { static const std::string example = Commands::Help::create_example_string("build zlib:x64-windows"); @@ -90,7 +107,7 @@ namespace vcpkg::Commands::Build const package_spec spec = Input::check_and_get_package_spec(args.command_arguments.at(0), default_target_triplet, example); Input::check_triplet(spec.target_triplet(), paths); - const std::unordered_set options = args.check_and_get_optional_command_arguments({OPTION_CHECKS_ONLY}); + const std::unordered_set options = args.check_and_get_optional_command_arguments({ OPTION_CHECKS_ONLY }); if (options.find(OPTION_CHECKS_ONLY) != options.end()) { const size_t error_count = PostBuildLint::perform_all_checks(spec, paths); @@ -106,24 +123,19 @@ namespace vcpkg::Commands::Build Checks::check_exit(!maybe_spgh.error_code(), "Could not find package named %s: %s", spec, maybe_spgh.error_code().message()); const SourceParagraph& spgh = *maybe_spgh.get(); - const std::vector first_level_deps = filter_dependencies(spgh.depends, spec.target_triplet()); - - std::vector first_level_deps_specs; - for (const std::string& dep : first_level_deps) + Environment::ensure_utilities_on_path(paths); + const DependencyStatus dependency_status = check_dependencies(spgh, spec, status_db); + if (dependency_status == DependencyStatus::MISSING_DEPENDENCIES) { - first_level_deps_specs.push_back(package_spec::from_name_and_triplet(dep, spec.target_triplet()).get_or_throw()); - } + std::vector unmet_dependencies = Dependencies::create_install_plan(paths, { spec }, status_db); + unmet_dependencies.erase( + std::remove_if(unmet_dependencies.begin(), unmet_dependencies.end(), [&spec](const package_spec_with_install_plan& p) + { + return (p.spec == spec) || (p.plan.plan_type == install_plan_type::ALREADY_INSTALLED); + }), + unmet_dependencies.end()); - std::vector unmet_dependencies = Dependencies::create_install_plan(paths, first_level_deps_specs, status_db); - unmet_dependencies.erase( - std::remove_if(unmet_dependencies.begin(), unmet_dependencies.end(), [](const package_spec_with_install_plan& p) - { - return p.plan.plan_type == install_plan_type::ALREADY_INSTALLED; - }), - unmet_dependencies.end()); - - if (!unmet_dependencies.empty()) - { + Checks::check_exit(unmet_dependencies.empty()); System::println(System::color::error, "The build command requires all dependencies to be already installed."); System::println("The following dependencies are missing:"); System::println(""); @@ -135,8 +147,7 @@ namespace vcpkg::Commands::Build exit(EXIT_FAILURE); } - Environment::ensure_utilities_on_path(paths); - const BuildResult result = build_package(spgh, spec, paths, paths.port_dir(spec)); + const BuildResult result = build_package(spgh, spec, paths, paths.port_dir(spec), dependency_status); if (result != BuildResult::SUCCESS) { exit(EXIT_FAILURE); diff --git a/toolsrc/src/commands_build_external.cpp b/toolsrc/src/commands_build_external.cpp index 8e9bf50fd..319e3c3d8 100644 --- a/toolsrc/src/commands_build_external.cpp +++ b/toolsrc/src/commands_build_external.cpp @@ -12,6 +12,8 @@ namespace vcpkg::Commands::BuildExternal static const std::string example = Commands::Help::create_example_string(R"(build_external zlib2 C:\path\to\dir\with\controlfile\)"); args.check_exact_arg_count(2, example); + StatusParagraphs status_db = database_load_check(paths); + expected maybe_current_spec = package_spec::from_string(args.command_arguments[0], default_target_triplet); if (auto spec = maybe_current_spec.get()) { @@ -21,8 +23,10 @@ namespace vcpkg::Commands::BuildExternal const expected maybe_spgh = try_load_port(port_dir); if (auto spgh = maybe_spgh.get()) { - const Build::BuildResult result = Commands::Build::build_package(*spgh, *spec, paths, port_dir); - if (result !=Build::BuildResult::SUCCESS) + const Build::DependencyStatus dependency_status = Build::check_dependencies(*spgh, *spec, status_db); + Checks::check_exit(dependency_status == Build::DependencyStatus::ALL_DEPENDENCIES_INSTALLED); + const Build::BuildResult result = Commands::Build::build_package(*spgh, *spec, paths, port_dir, dependency_status); + if (result != Build::BuildResult::SUCCESS) { exit(EXIT_FAILURE); } diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index 48da05e9c..a57d2cc6d 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -214,7 +214,9 @@ namespace vcpkg::Commands::Install } else if (action.plan.plan_type == install_plan_type::BUILD_AND_INSTALL) { - const Build::BuildResult result = Commands::Build::build_package(*action.plan.source_pgh, action.spec, paths, paths.port_dir(action.spec)); + const Build::DependencyStatus dependency_status = Build::check_dependencies(*action.plan.source_pgh, action.spec, status_db); + Checks::check_exit(dependency_status == Build::DependencyStatus::ALL_DEPENDENCIES_INSTALLED); + const Build::BuildResult result = Commands::Build::build_package(*action.plan.source_pgh, action.spec, paths, paths.port_dir(action.spec), dependency_status); if (result != Build::BuildResult::SUCCESS) { exit(EXIT_FAILURE);