From 34b4db1fb45df541b8a2c7592a57ac6a8fd0b900 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 16 Nov 2017 17:42:15 -0800 Subject: [PATCH] [vcpkg] Output autodetected CMake usage information after install. --- toolsrc/include/vcpkg/build.h | 6 ++ toolsrc/include/vcpkg/install.h | 14 ++-- toolsrc/src/vcpkg/install.cpp | 140 +++++++++++++++++++++++++++----- 3 files changed, 134 insertions(+), 26 deletions(-) diff --git a/toolsrc/include/vcpkg/build.h b/toolsrc/include/vcpkg/build.h index 824f3ccaf9..cbd34c7307 100644 --- a/toolsrc/include/vcpkg/build.h +++ b/toolsrc/include/vcpkg/build.h @@ -69,6 +69,12 @@ namespace vcpkg::Build EXCLUDED, }; + struct BuildResults + { + BuildResult result_code; + std::unique_ptr binary_control_file; + }; + static constexpr std::array BUILD_RESULT_VALUES = { BuildResult::SUCCEEDED, BuildResult::BUILD_FAILED, diff --git a/toolsrc/include/vcpkg/install.h b/toolsrc/include/vcpkg/install.h index df75423182..e436e2238e 100644 --- a/toolsrc/include/vcpkg/install.h +++ b/toolsrc/include/vcpkg/install.h @@ -30,11 +30,15 @@ namespace vcpkg::Install struct SpecSummary { - explicit SpecSummary(const PackageSpec& spec); + SpecSummary(const PackageSpec& spec, const Dependencies::AnyAction* action); + + const BinaryParagraph* get_binary_paragraph() const; PackageSpec spec; - Build::BuildResult result; + Build::BuildResults build_result; std::string timing; + + const Dependencies::AnyAction* action; }; struct InstallSummary @@ -62,9 +66,9 @@ namespace vcpkg::Install const fs::path& listfile() const; }; - Build::BuildResult perform_install_plan_action(const VcpkgPaths& paths, - const Dependencies::InstallPlanAction& action, - StatusParagraphs& status_db); + Build::BuildResults perform_install_plan_action(const VcpkgPaths& paths, + const Dependencies::InstallPlanAction& action, + StatusParagraphs& status_db); enum class InstallResult { diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 88ef5c73d4..7edcafb1fd 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -247,10 +247,11 @@ namespace vcpkg::Install } using Build::BuildResult; + using Build::BuildResults; - BuildResult perform_install_plan_action(const VcpkgPaths& paths, - const InstallPlanAction& action, - StatusParagraphs& status_db) + BuildResults perform_install_plan_action(const VcpkgPaths& paths, + const InstallPlanAction& action, + StatusParagraphs& status_db) { const InstallPlanType& plan_type = action.plan_type; const std::string display_name = action.spec.to_string(); @@ -267,7 +268,7 @@ namespace vcpkg::Install System::Color::warning, "Package %s is already installed -- not building from HEAD", display_name); else System::println(System::Color::success, "Package %s is already installed", display_name); - return BuildResult::SUCCEEDED; + return {BuildResult::SUCCEEDED, nullptr}; } if (plan_type == InstallPlanType::BUILD_AND_INSTALL) @@ -302,21 +303,21 @@ namespace vcpkg::Install if (result.code != Build::BuildResult::SUCCEEDED) { System::println(System::Color::error, Build::create_error_message(result.code, action.spec)); - return result.code; + return {result.code, nullptr}; } System::println("Building package %s... done", display_name_with_features); - const BinaryControlFile bcf = - Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); + auto bcf = std::make_unique( + Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO)); System::println("Installing package %s... ", display_name_with_features); - const auto install_result = install_package(paths, bcf, &status_db); + const auto install_result = install_package(paths, *bcf, &status_db); switch (install_result) { case InstallResult::SUCCESS: System::println(System::Color::success, "Installing package %s... done", display_name); - return BuildResult::SUCCEEDED; - case InstallResult::FILE_CONFLICTS: return BuildResult::FILE_CONFLICTS; + return {BuildResult::SUCCEEDED, std::move(bcf)}; + case InstallResult::FILE_CONFLICTS: return {BuildResult::FILE_CONFLICTS, nullptr}; default: Checks::unreachable(VCPKG_LINE_INFO); } } @@ -335,8 +336,8 @@ namespace vcpkg::Install { case InstallResult::SUCCESS: System::println(System::Color::success, "Installing package %s... done", display_name); - return BuildResult::SUCCEEDED; - case InstallResult::FILE_CONFLICTS: return BuildResult::FILE_CONFLICTS; + return {BuildResult::SUCCEEDED, nullptr}; + case InstallResult::FILE_CONFLICTS: return {BuildResult::FILE_CONFLICTS, nullptr}; default: Checks::unreachable(VCPKG_LINE_INFO); } } @@ -344,7 +345,7 @@ namespace vcpkg::Install if (plan_type == InstallPlanType::EXCLUDED) { System::println(System::Color::warning, "Package %s is excluded", display_name); - return BuildResult::EXCLUDED; + return {BuildResult::EXCLUDED, nullptr}; } Checks::unreachable(VCPKG_LINE_INFO); @@ -458,7 +459,8 @@ namespace vcpkg::Install for (const SpecSummary& result : this->results) { - System::println(" %s: %s: %s", result.spec, Build::to_string(result.result), result.timing); + System::println( + " %s: %s: %s", result.spec, Build::to_string(result.build_result.result_code), result.timing); } std::map summary; @@ -469,7 +471,7 @@ namespace vcpkg::Install for (const SpecSummary& r : this->results) { - summary[r.result]++; + summary[r.build_result.result_code]++; } System::println("\nSUMMARY"); @@ -500,11 +502,11 @@ namespace vcpkg::Install const std::string display_name = spec.to_string(); System::println("Starting package %d/%d: %s", counter, package_count, display_name); - results.push_back(SpecSummary{spec}); + results.emplace_back(spec, &action); if (const auto install_action = action.install_plan.get()) { - const BuildResult result = perform_install_plan_action(paths, *install_action, status_db); + Build::BuildResults result = perform_install_plan_action(paths, *install_action, status_db); if (clean_buildtrees == CleanBuildtrees::YES) { auto& fs = paths.get_filesystem(); @@ -520,13 +522,13 @@ namespace vcpkg::Install } } - if (result != BuildResult::SUCCEEDED && keep_going == KeepGoing::NO) + if (result.result_code != BuildResult::SUCCEEDED && keep_going == KeepGoing::NO) { System::println(Build::create_user_troubleshooting_message(install_action->spec)); Checks::exit_fail(VCPKG_LINE_INFO); } - results.back().result = result; + results.back().build_result = std::move(result); } else if (const auto remove_action = action.remove_plan.get()) { @@ -542,7 +544,7 @@ namespace vcpkg::Install System::println("Elapsed time for package %s: %s", display_name, build_timer.to_string()); } - return InstallSummary{results, timer.to_string()}; + return InstallSummary{std::move(results), timer.to_string()}; } static const std::string OPTION_DRY_RUN = "--dry-run"; @@ -576,6 +578,69 @@ namespace vcpkg::Install &get_all_port_names, }; + static void print_cmake_information(const BinaryParagraph& bpgh, const VcpkgPaths& paths) + { + static const std::regex cmake_library_regex("^add_library\\(([^\\s\\$\\)]+)\\s"); + + auto& fs = paths.get_filesystem(); + + auto files = fs.read_lines(paths.listfile_path(bpgh)); + if (auto p_lines = files.get()) + { + for (auto&& suffix : *p_lines) + { + if (Strings::case_insensitive_ascii_find(suffix, "/share/") != suffix.end()) + { + std::vector library_targets; + + // File is inside the share folder + auto path = paths.installed / suffix; + auto maybe_contents = fs.read_contents(path); + if (auto p_contents = maybe_contents.get()) + { + std::sregex_iterator next(p_contents->begin(), p_contents->end(), cmake_library_regex); + std::sregex_iterator last; + + while (next != last) + { + auto match = *next; + library_targets.push_back(match[1]); + ++next; + } + } + + if (library_targets.empty()) + { + } + else if (library_targets.size() <= 4) + { + System::println("\nThe package %s provides CMake targets:\n" + "\n" + " find_package(%s REQUIRED)\n" + " target_link_libraries(main PRIVATE %s)", + bpgh.spec, + path.parent_path().filename().u8string(), + Strings::join(" ", library_targets)); + } + else + { + auto omitted = library_targets.size() - 4; + library_targets.erase(library_targets.begin() + 4, library_targets.end()); + System::println("\nThe package %s provides CMake targets:\n" + "\n" + " find_package(%s REQUIRED)\n" + " # Note: %d targets were omitted\n" + " target_link_libraries(main PRIVATE %s)", + bpgh.spec, + path.parent_path().filename().u8string(), + omitted, + Strings::join(" ", library_targets)); + } + } + } + } + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { // input sanitization @@ -670,8 +735,41 @@ namespace vcpkg::Install summary.print(); } + auto& fs = paths.get_filesystem(); + + for (auto&& result : summary.results) + { + if (!result.action) continue; + if (auto p_install_action = result.action->install_plan.get()) + { + if (p_install_action->request_type != RequestType::USER_REQUESTED) continue; + auto bpgh = result.get_binary_paragraph(); + if (!bpgh) continue; + print_cmake_information(*bpgh, paths); + } + } + Checks::exit_success(VCPKG_LINE_INFO); } - SpecSummary::SpecSummary(const PackageSpec& spec) : spec(spec), result(BuildResult::NULLVALUE), timing("0") {} + SpecSummary::SpecSummary(const PackageSpec& spec, const Dependencies::AnyAction* action) + : spec(spec), build_result{BuildResult::NULLVALUE, nullptr}, timing("0"), action(action) + { + } + + const BinaryParagraph* SpecSummary::get_binary_paragraph() const + { + if (build_result.binary_control_file) return &build_result.binary_control_file->core_paragraph; + if (action) + if (auto p_install_plan = action->install_plan.get()) + { + if (auto p_bcf = p_install_plan->any_paragraph.binary_control_file.get()) + return &p_bcf->core_paragraph; + else if (auto p_status = p_install_plan->any_paragraph.status_paragraph.get()) + { + return &p_status->package; + } + } + return nullptr; + } }