diff options
| author | Robert Schumacher <roschuma@microsoft.com> | 2017-10-12 11:22:25 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-10-12 11:22:25 -0700 |
| commit | 85e6b1b36e734c0db50464b07b77589d63c3c875 (patch) | |
| tree | 095289838517a64f06298b1a05ded47a7139d7d9 /toolsrc/src | |
| parent | d7a313c5c356e1641f18cd14ad0ac0c3901bc0bf (diff) | |
| parent | 9c3f9582fb4541a59e4282269e4f6c9c7debcc3e (diff) | |
| download | vcpkg-85e6b1b36e734c0db50464b07b77589d63c3c875.tar.gz vcpkg-85e6b1b36e734c0db50464b07b77589d63c3c875.zip | |
Merge branch 'master' into vtk-components
Diffstat (limited to 'toolsrc/src')
49 files changed, 1742 insertions, 951 deletions
diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp index 9abd388b9..1504912ab 100644 --- a/toolsrc/src/BinaryParagraph.cpp +++ b/toolsrc/src/BinaryParagraph.cpp @@ -56,7 +56,7 @@ namespace vcpkg this->default_features = parse_comma_list(parser.optional_field(Fields::DEFAULTFEATURES)); } - if (auto err = parser.error_info(this->spec.to_string())) + if (const auto err = parser.error_info(this->spec.to_string())) { System::println( System::Color::error, "Error: while parsing the Binary Paragraph for %s", this->spec.to_string()); @@ -80,23 +80,17 @@ namespace vcpkg 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->version = Strings::EMPTY; this->feature = fpgh.name; this->description = fpgh.description; - this->maintainer = ""; + this->maintainer = Strings::EMPTY; this->depends = filter_dependencies(fpgh.depends, triplet); } std::string BinaryParagraph::displayname() const { - if (this->feature == "") - { - return this->spec.name() + "[core]:" + this->spec.triplet().to_string(); - } - else - { - return this->spec.name() + "[" + this->feature + "]:" + this->spec.triplet().to_string(); - } + const auto f = this->feature.empty() ? "core" : this->feature; + return Strings::format("%s[%s]:%s", this->spec.name(), f, this->spec.triplet()); } std::string BinaryParagraph::dir() const { return this->spec.dir(); } diff --git a/toolsrc/src/MachineType.cpp b/toolsrc/src/MachineType.cpp index 2f44ce21a..af6378c88 100644 --- a/toolsrc/src/MachineType.cpp +++ b/toolsrc/src/MachineType.cpp @@ -7,7 +7,7 @@ namespace vcpkg { MachineType to_machine_type(const uint16_t value) { - MachineType t = static_cast<MachineType>(value); + const MachineType t = static_cast<MachineType>(value); switch (t) { case MachineType::UNKNOWN: diff --git a/toolsrc/src/PackageSpec.cpp b/toolsrc/src/PackageSpec.cpp index a43bc5ff5..890de8899 100644 --- a/toolsrc/src/PackageSpec.cpp +++ b/toolsrc/src/PackageSpec.cpp @@ -38,7 +38,7 @@ namespace vcpkg for (auto&& feature : spec->features) f_specs.push_back(FeatureSpec{pspec, feature}); - if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, ""}); + if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, Strings::EMPTY}); } else { @@ -56,7 +56,7 @@ namespace vcpkg std::vector<FeatureSpec> ret; for (auto&& spec : specs) { - ret.emplace_back(spec.package_spec, ""); + ret.emplace_back(spec.package_spec, Strings::EMPTY); for (auto&& feature : spec.features) ret.emplace_back(spec.package_spec, feature); } diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp index a7dee4fd3..6a6f191df 100644 --- a/toolsrc/src/Paragraphs.cpp +++ b/toolsrc/src/Paragraphs.cpp @@ -254,7 +254,7 @@ namespace vcpkg::Paragraphs for (auto&& path : fs.get_files_non_recursive(ports_dir)) { auto maybe_spgh = try_load_port(fs, path); - if (auto spgh = maybe_spgh.get()) + if (const auto spgh = maybe_spgh.get()) { ret.paragraphs.emplace_back(std::move(*spgh)); } @@ -272,8 +272,20 @@ namespace vcpkg::Paragraphs auto results = try_load_all_ports(fs, ports_dir); if (!results.errors.empty()) { - print_error_message(results.errors); - Checks::exit_fail(VCPKG_LINE_INFO); + if (GlobalState::debugging) + { + print_error_message(results.errors); + } + else + { + for (auto&& error : results.errors) + { + System::println( + System::Color::warning, "Warning: an error occurred while parsing '%s'", error->name); + } + System::println(System::Color::warning, + "Use '--debug' to get more information about the parse failures.\n"); + } } return std::move(results.paragraphs); } diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index a5d923ad2..6d9a0da73 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -10,9 +10,9 @@ #include "vcpkg_System.h" #include "vcpkg_Util.h" -using vcpkg::Build::PreBuildInfo; using vcpkg::Build::BuildInfo; using vcpkg::Build::BuildPolicy; +using vcpkg::Build::PreBuildInfo; namespace vcpkg::PostBuildLint { @@ -38,9 +38,9 @@ namespace vcpkg::PostBuildLint } }; - const std::vector<OutdatedDynamicCrt>& get_outdated_dynamic_crts() + Span<const OutdatedDynamicCrt> get_outdated_dynamic_crts(CStringView toolset) { - static const std::vector<OutdatedDynamicCrt> v_no_msvcrt = { + static const std::vector<OutdatedDynamicCrt> V_NO_MSVCRT = { {"msvcp100.dll", R"(msvcp100\.dll)"}, {"msvcp100d.dll", R"(msvcp100d\.dll)"}, {"msvcp110.dll", R"(msvcp110\.dll)"}, @@ -59,7 +59,7 @@ namespace vcpkg::PostBuildLint {"msvcrt20.dll", R"(msvcrt20\.dll)"}, {"msvcrt40.dll", R"(msvcrt40\.dll)"}}; - return v_no_msvcrt; + return V_NO_MSVCRT; } static LintStatus check_for_files_in_include_directory(const Files::Filesystem& fs, @@ -361,6 +361,7 @@ namespace vcpkg::PostBuildLint case MachineType::I386: return "x86"; case MachineType::ARM: case MachineType::ARMNT: return "arm"; + case MachineType::ARM64: return "arm64"; default: return "Machine Type Code = " + std::to_string(static_cast<uint16_t>(machine_type)); } } @@ -369,12 +370,12 @@ namespace vcpkg::PostBuildLint std::vector<FileAndArch> binaries_with_invalid_architecture) { System::println(System::Color::warning, "The following files were built for an incorrect architecture:"); - System::println(""); + System::println(); for (const FileAndArch& b : binaries_with_invalid_architecture) { System::println(" %s", b.file.generic_string()); System::println("Expected %s, but was: %s", expected_architecture, b.actual_arch); - System::println(""); + System::println(); } } @@ -389,7 +390,7 @@ namespace vcpkg::PostBuildLint file.extension() == ".dll", "The file extension was not .dll: %s", file.generic_string()); - COFFFileReader::DllInfo info = COFFFileReader::read_dll(file); + const CoffFileReader::DllInfo info = CoffFileReader::read_dll(file); const std::string actual_architecture = get_actual_architecture(info.machine_type); if (expected_architecture != actual_architecture) @@ -418,7 +419,7 @@ namespace vcpkg::PostBuildLint file.extension() == ".lib", "The file extension was not .lib: %s", file.generic_string()); - COFFFileReader::LibInfo info = COFFFileReader::read_lib(file); + CoffFileReader::LibInfo info = CoffFileReader::read_lib(file); // This is zero for folly's debug library // TODO: Why? @@ -487,7 +488,7 @@ namespace vcpkg::PostBuildLint System::println(System::Color::warning, "Release binaries were not found"); } - System::println(""); + System::println(); return LintStatus::ERROR_DETECTED; } @@ -580,7 +581,7 @@ namespace vcpkg::PostBuildLint return LintStatus::SUCCESS; } - struct BuildType_and_file + struct BuildTypeAndFile { fs::path file; BuildType build_type; @@ -594,7 +595,7 @@ namespace vcpkg::PostBuildLint bad_build_types.erase(std::remove(bad_build_types.begin(), bad_build_types.end(), expected_build_type), bad_build_types.end()); - std::vector<BuildType_and_file> libs_with_invalid_crt; + std::vector<BuildTypeAndFile> libs_with_invalid_crt; for (const fs::path& lib : libs) { @@ -621,12 +622,12 @@ namespace vcpkg::PostBuildLint System::println(System::Color::warning, "Expected %s crt linkage, but the following libs had invalid crt linkage:", expected_build_type.to_string()); - System::println(""); - for (const BuildType_and_file btf : libs_with_invalid_crt) + System::println(); + for (const BuildTypeAndFile btf : libs_with_invalid_crt) { System::println(" %s: %s", btf.file.generic_string(), btf.build_type.to_string()); } - System::println(""); + System::println(); System::println(System::Color::warning, "To inspect the lib files, use:\n dumpbin.exe /directives mylibfile.lib"); @@ -636,12 +637,12 @@ namespace vcpkg::PostBuildLint return LintStatus::SUCCESS; } - struct OutdatedDynamicCrt_and_file + struct OutdatedDynamicCrtAndFile { fs::path file; OutdatedDynamicCrt outdated_crt; - OutdatedDynamicCrt_and_file() = delete; + OutdatedDynamicCrtAndFile() = delete; }; static LintStatus check_outdated_crt_linkage_of_dlls(const std::vector<fs::path>& dlls, @@ -650,7 +651,7 @@ namespace vcpkg::PostBuildLint { if (build_info.policies.is_enabled(BuildPolicy::ALLOW_OBSOLETE_MSVCRT)) return LintStatus::SUCCESS; - std::vector<OutdatedDynamicCrt_and_file> dlls_with_outdated_crt; + std::vector<OutdatedDynamicCrtAndFile> dlls_with_outdated_crt; for (const fs::path& dll : dlls) { @@ -662,7 +663,7 @@ namespace vcpkg::PostBuildLint "Running command:\n %s\n failed", Strings::to_utf8(cmd_line)); - for (const OutdatedDynamicCrt& outdated_crt : get_outdated_dynamic_crts()) + for (const OutdatedDynamicCrt& outdated_crt : get_outdated_dynamic_crts("v141")) { if (std::regex_search(ec_data.output.cbegin(), ec_data.output.cend(), outdated_crt.regex)) { @@ -675,12 +676,12 @@ namespace vcpkg::PostBuildLint if (!dlls_with_outdated_crt.empty()) { System::println(System::Color::warning, "Detected outdated dynamic CRT in the following files:"); - System::println(""); - for (const OutdatedDynamicCrt_and_file btf : dlls_with_outdated_crt) + System::println(); + for (const OutdatedDynamicCrtAndFile btf : dlls_with_outdated_crt) { System::println(" %s: %s", btf.file.generic_string(), btf.outdated_crt.name); } - System::println(""); + System::println(); System::println(System::Color::warning, "To inspect the dll files, use:\n dumpbin.exe /dependents mydllfile.dll"); @@ -722,7 +723,7 @@ namespace vcpkg::PostBuildLint const auto& fs = paths.get_filesystem(); // for dumpbin - const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset); + const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); const fs::path package_dir = paths.package_dir(spec); size_t error_count = 0; diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index c69770ae1..0f1a38d19 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -25,7 +25,7 @@ namespace vcpkg static const std::string VERSION = "Version"; } - static span<const std::string> get_list_of_valid_fields() + static Span<const std::string> get_list_of_valid_fields() { static const std::string valid_fields[] = { Fields::SOURCE, @@ -38,7 +38,7 @@ namespace vcpkg return valid_fields; } - void print_error_message(span<const std::unique_ptr<Parse::ParseControlErrorInfo>> error_info_list) + void print_error_message(Span<const std::unique_ptr<Parse::ParseControlErrorInfo>> error_info_list) { Checks::check_exit(VCPKG_LINE_INFO, error_info_list.size() > 0); @@ -137,7 +137,7 @@ namespace vcpkg auto control_file = std::make_unique<SourceControlFile>(); auto maybe_source = parse_source_paragraph(std::move(control_paragraphs.front())); - if (auto source = maybe_source.get()) + if (const auto source = maybe_source.get()) control_file->core_paragraph = std::move(*source); else return std::move(maybe_source).error(); @@ -147,7 +147,7 @@ namespace vcpkg for (auto&& feature_pgh : control_paragraphs) { auto maybe_feature = parse_feature_paragraph(std::move(feature_pgh)); - if (auto feature = maybe_feature.get()) + if (const auto feature = maybe_feature.get()) control_file->feature_paragraphs.emplace_back(std::move(*feature)); else return std::move(maybe_feature).error(); @@ -170,24 +170,17 @@ namespace vcpkg std::string Dependency::name() const { - std::string str = this->depend.name; - if (this->depend.features.empty()) return str; + if (this->depend.features.empty()) return this->depend.name; - str += "["; - for (auto&& s : this->depend.features) - { - str += s + ","; - } - str.pop_back(); - str += "]"; - return str; + const std::string features = Strings::join(",", this->depend.features); + return Strings::format("%s[%s]", this->depend.name, features); } std::vector<Dependency> vcpkg::expand_qualified_dependencies(const std::vector<std::string>& depends) { return Util::fmap(depends, [&](const std::string& depend_string) -> Dependency { auto pos = depend_string.find(' '); - if (pos == std::string::npos) return Dependency::parse_dependency(depend_string, ""); + if (pos == std::string::npos) return Dependency::parse_dependency(depend_string, Strings::EMPTY); // expect of the form "\w+ \[\w+\]" Dependency dep; @@ -195,7 +188,7 @@ namespace vcpkg if (depend_string.c_str()[pos + 1] != '(' || depend_string[depend_string.size() - 1] != ')') { // Error, but for now just slurp the entire string. - return Dependency::parse_dependency(depend_string, ""); + return Dependency::parse_dependency(depend_string, Strings::EMPTY); } dep.qualifier = depend_string.substr(pos + 2, depend_string.size() - pos - 3); return dep; @@ -220,11 +213,7 @@ namespace vcpkg return FeatureSpec::from_strings_and_triplet(filter_dependencies(deps, t), t); } - const std::string to_string(const Dependency& dep) - { - std::string name = dep.name(); - return name; - } + std::string to_string(const Dependency& dep) { return dep.name(); } ExpectedT<Supports, std::vector<std::string>> Supports::parse(const std::vector<std::string>& strs) { @@ -263,7 +252,7 @@ namespace vcpkg bool Supports::is_supported(Architecture arch, Platform plat, Linkage crt, ToolsetVersion tools) { - auto is_in_or_empty = [](auto v, auto&& c) -> bool { return c.empty() || c.end() != Util::find(c, v); }; + const auto is_in_or_empty = [](auto v, auto&& c) -> bool { return c.empty() || c.end() != Util::find(c, v); }; if (!is_in_or_empty(arch, architectures)) return false; if (!is_in_or_empty(plat, platforms)) return false; if (!is_in_or_empty(crt, crt_linkages)) return false; diff --git a/toolsrc/src/StatusParagraph.cpp b/toolsrc/src/StatusParagraph.cpp index 5b5c3978f..f8ae293c2 100644 --- a/toolsrc/src/StatusParagraph.cpp +++ b/toolsrc/src/StatusParagraph.cpp @@ -33,8 +33,8 @@ namespace vcpkg this->package = BinaryParagraph(std::move(fields)); auto b = status_field.begin(); - auto mark = b; - auto e = status_field.end(); + const auto mark = b; + const auto e = status_field.end(); // Todo: improve error handling while (b != e && *b != ' ') diff --git a/toolsrc/src/StatusParagraphs.cpp b/toolsrc/src/StatusParagraphs.cpp index 02ee61f75..aaba95eb9 100644 --- a/toolsrc/src/StatusParagraphs.cpp +++ b/toolsrc/src/StatusParagraphs.cpp @@ -67,7 +67,7 @@ namespace vcpkg { Checks::check_exit(VCPKG_LINE_INFO, pgh != nullptr, "Inserted null paragraph"); const PackageSpec& spec = pgh->package.spec; - auto ptr = find(spec.name(), spec.triplet(), pgh->package.feature); + const auto ptr = find(spec.name(), spec.triplet(), pgh->package.feature); if (ptr == end()) { paragraphs.push_back(std::move(pgh)); diff --git a/toolsrc/src/VcpkgCmdArguments.cpp b/toolsrc/src/VcpkgCmdArguments.cpp index cf6c7b562..cb261930e 100644 --- a/toolsrc/src/VcpkgCmdArguments.cpp +++ b/toolsrc/src/VcpkgCmdArguments.cpp @@ -124,7 +124,7 @@ namespace vcpkg continue; } - auto eq_pos = arg.find('='); + const auto eq_pos = arg.find('='); if (eq_pos != std::string::npos) { args.optional_command_arguments.emplace(arg.substr(0, eq_pos), arg.substr(eq_pos + 1)); @@ -158,7 +158,7 @@ namespace vcpkg auto options_copy = this->optional_command_arguments; for (const std::string& option : valid_switches) { - auto it = options_copy.find(option); + const auto it = options_copy.find(option); if (it != options_copy.end()) { if (it->second.has_value()) @@ -177,7 +177,7 @@ namespace vcpkg for (const std::string& option : valid_settings) { - auto it = options_copy.find(option); + const auto it = options_copy.find(option); if (it != options_copy.end()) { if (!it->second.has_value()) @@ -222,17 +222,17 @@ namespace vcpkg void VcpkgCmdArguments::check_max_arg_count(const size_t expected_arg_count) const { - return check_max_arg_count(expected_arg_count, ""); + return check_max_arg_count(expected_arg_count, Strings::EMPTY); } void VcpkgCmdArguments::check_min_arg_count(const size_t expected_arg_count) const { - return check_min_arg_count(expected_arg_count, ""); + return check_min_arg_count(expected_arg_count, Strings::EMPTY); } void VcpkgCmdArguments::check_exact_arg_count(const size_t expected_arg_count) const { - return check_exact_arg_count(expected_arg_count, ""); + return check_exact_arg_count(expected_arg_count, Strings::EMPTY); } void VcpkgCmdArguments::check_max_arg_count(const size_t expected_arg_count, const std::string& example_text) const diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 17a11b1a9..dac9e40e7 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -10,27 +10,31 @@ namespace vcpkg { + static constexpr CWStringView V_120 = L"v120"; + static constexpr CWStringView V_140 = L"v140"; + static constexpr CWStringView V_141 = L"v141"; + static bool exists_and_has_equal_or_greater_version(const std::wstring& version_cmd, const std::array<int, 3>& expected_version) { - static const std::regex re(R"###((\d+)\.(\d+)\.(\d+))###"); + static const std::regex RE(R"###((\d+)\.(\d+)\.(\d+))###"); - auto rc = System::cmd_execute_and_capture_output(Strings::wformat(LR"(%s)", version_cmd)); + const auto rc = System::cmd_execute_and_capture_output(Strings::wformat(LR"(%s)", version_cmd)); if (rc.exit_code != 0) { return false; } std::match_results<std::string::const_iterator> match; - auto found = std::regex_search(rc.output, match, re); + const auto found = std::regex_search(rc.output, match, RE); if (!found) { return false; } - int d1 = atoi(match[1].str().c_str()); - int d2 = atoi(match[2].str().c_str()); - int d3 = atoi(match[3].str().c_str()); + const int d1 = atoi(match[1].str().c_str()); + const int d2 = atoi(match[2].str().c_str()); + const int d3 = atoi(match[3].str().c_str()); if (d1 > expected_version[0] || (d1 == expected_version[0] && d2 > expected_version[1]) || (d1 == expected_version[0] && d2 == expected_version[1] && d3 >= expected_version[2])) { @@ -58,46 +62,40 @@ namespace vcpkg return nullopt; } - static std::vector<fs::path> find_from_PATH(const std::wstring& name) - { - const std::wstring cmd = Strings::wformat(L"where.exe %s", name); - auto out = System::cmd_execute_and_capture_output(cmd); - if (out.exit_code != 0) - { - return {}; - } - - return Util::fmap(Strings::split(out.output, "\n"), [](auto&& s) { return fs::path(s); }); - } - static fs::path fetch_dependency(const fs::path& scripts_folder, const std::wstring& tool_name, const fs::path& expected_downloaded_path, const std::array<int, 3>& version) { + const std::string tool_name_utf8 = Strings::to_utf8(tool_name); + const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); + System::println("A suitable version of %s was not found (required v%s). Downloading portable %s v%s...", + tool_name_utf8, + version_as_string, + tool_name_utf8, + version_as_string); const fs::path script = scripts_folder / "fetchDependency.ps1"; - auto install_cmd = System::create_powershell_script_cmd(script, Strings::wformat(L"-Dependency %s", tool_name)); - System::ExitCodeAndOutput rc = System::cmd_execute_and_capture_output(install_cmd); + const auto install_cmd = + System::create_powershell_script_cmd(script, Strings::wformat(L"-Dependency %s", tool_name)); + const System::ExitCodeAndOutput rc = System::cmd_execute_and_capture_output(install_cmd); if (rc.exit_code) { - const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); - System::println(System::Color::error, "Launching powershell failed or was denied when trying to fetch %s version %s.\n" "(No sufficient installed version was found)", - Strings::to_utf8(tool_name), + tool_name_utf8, version_as_string); { auto locked_metrics = Metrics::g_metrics.lock(); locked_metrics->track_property("error", "powershell install failed"); - locked_metrics->track_property("installcmd", install_cmd); + locked_metrics->track_property("dependency", tool_name); } Checks::exit_with_code(VCPKG_LINE_INFO, rc.exit_code); } const fs::path actual_downloaded_path = Strings::trimmed(rc.output); std::error_code ec; - auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec); + const auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec); Checks::check_exit(VCPKG_LINE_INFO, eq && !ec, "Expected dependency downloaded path to be %s, but was %s", @@ -108,71 +106,99 @@ namespace vcpkg static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { - static constexpr std::array<int, 3> expected_version = {3, 9, 1}; - static const std::wstring version_check_arguments = L"--version"; + static constexpr std::array<int, 3> EXPECTED_VERSION = {3, 9, 3}; + static const std::wstring VERSION_CHECK_ARGUMENTS = L"--version"; - const fs::path downloaded_copy = downloads_folder / "cmake-3.9.1-win32-x86" / "bin" / "cmake.exe"; - const std::vector<fs::path> from_path = find_from_PATH(L"cmake"); + const fs::path downloaded_copy = downloads_folder / "cmake-3.9.3-win32-x86" / "bin" / "cmake.exe"; + const std::vector<fs::path> from_path = Files::find_from_PATH(L"cmake"); std::vector<fs::path> candidate_paths; candidate_paths.push_back(downloaded_copy); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - candidate_paths.push_back(System::get_ProgramFiles_platform_bitness() / "CMake" / "bin" / "cmake.exe"); - candidate_paths.push_back(System::get_ProgramFiles_32_bit() / "CMake" / "bin"); + candidate_paths.push_back(System::get_program_files_platform_bitness() / "CMake" / "bin" / "cmake.exe"); + candidate_paths.push_back(System::get_program_files_32_bit() / "CMake" / "bin"); const Optional<fs::path> path = - find_if_has_equal_or_greater_version(candidate_paths, version_check_arguments, expected_version); - if (auto p = path.get()) + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + if (const auto p = path.get()) { return *p; } - return fetch_dependency(scripts_folder, L"cmake", downloaded_copy, expected_version); + return fetch_dependency(scripts_folder, L"cmake", downloaded_copy, EXPECTED_VERSION); } fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { - static constexpr std::array<int, 3> expected_version = {4, 1, 0}; - static const std::wstring version_check_arguments = L""; + static constexpr std::array<int, 3> EXPECTED_VERSION = {4, 3, 0}; + static const std::wstring VERSION_CHECK_ARGUMENTS = Strings::WEMPTY; - const fs::path downloaded_copy = downloads_folder / "nuget-4.1.0" / "nuget.exe"; - const std::vector<fs::path> from_path = find_from_PATH(L"nuget"); + const fs::path downloaded_copy = downloads_folder / "nuget-4.3.0" / "nuget.exe"; + const std::vector<fs::path> from_path = Files::find_from_PATH(L"nuget"); std::vector<fs::path> candidate_paths; candidate_paths.push_back(downloaded_copy); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - auto path = find_if_has_equal_or_greater_version(candidate_paths, version_check_arguments, expected_version); - if (auto p = path.get()) + auto path = find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + if (const auto p = path.get()) { return *p; } - return fetch_dependency(scripts_folder, L"nuget", downloaded_copy, expected_version); + return fetch_dependency(scripts_folder, L"nuget", downloaded_copy, EXPECTED_VERSION); } fs::path get_git_path(const fs::path& downloads_folder, const fs::path& scripts_folder) { - static constexpr std::array<int, 3> expected_version = {2, 14, 1}; - static const std::wstring version_check_arguments = L"--version"; + static constexpr std::array<int, 3> EXPECTED_VERSION = {2, 14, 1}; + static const std::wstring VERSION_CHECK_ARGUMENTS = L"--version"; const fs::path downloaded_copy = downloads_folder / "MinGit-2.14.1-32-bit" / "cmd" / "git.exe"; - const std::vector<fs::path> from_path = find_from_PATH(L"git"); + const std::vector<fs::path> from_path = Files::find_from_PATH(L"git"); std::vector<fs::path> candidate_paths; candidate_paths.push_back(downloaded_copy); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); - candidate_paths.push_back(System::get_ProgramFiles_platform_bitness() / "git" / "cmd" / "git.exe"); - candidate_paths.push_back(System::get_ProgramFiles_32_bit() / "git" / "cmd" / "git.exe"); + candidate_paths.push_back(System::get_program_files_platform_bitness() / "git" / "cmd" / "git.exe"); + candidate_paths.push_back(System::get_program_files_32_bit() / "git" / "cmd" / "git.exe"); const Optional<fs::path> path = - find_if_has_equal_or_greater_version(candidate_paths, version_check_arguments, expected_version); - if (auto p = path.get()) + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + if (const auto p = path.get()) { return *p; } - return fetch_dependency(scripts_folder, L"git", downloaded_copy, expected_version); + return fetch_dependency(scripts_folder, L"git", downloaded_copy, EXPECTED_VERSION); + } + + static fs::path get_ifw_installerbase_path(const fs::path& downloads_folder, const fs::path& scripts_folder) + { + static constexpr std::array<int, 3> EXPECTED_VERSION = {3, 1, 81}; + static const std::wstring VERSION_CHECK_ARGUMENTS = L"--framework-version"; + + const fs::path downloaded_copy = + downloads_folder / "QtInstallerFramework-win-x86" / "bin" / "installerbase.exe"; + + std::vector<fs::path> candidate_paths; + candidate_paths.push_back(downloaded_copy); + // TODO: Uncomment later + // const std::vector<fs::path> from_path = Files::find_from_PATH(L"installerbase"); + // candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + // candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" / + // "Tools" / "QtInstallerFramework" / "3.1" / "bin" / "installerbase.exe"); + // candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" / + // "QtIFW-3.1.0" / "bin" / "installerbase.exe"); + + const Optional<fs::path> path = + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + if (const auto p = path.get()) + { + return *p; + } + + return fetch_dependency(scripts_folder, L"installerbase", downloaded_copy, EXPECTED_VERSION); } Expected<VcpkgPaths> VcpkgPaths::create(const fs::path& vcpkg_root_dir) @@ -233,7 +259,7 @@ namespace vcpkg { for (auto&& path : get_filesystem().get_files_non_recursive(this->triplets)) { - std::string triplet_file_name = path.stem().generic_u8string(); + const std::string triplet_file_name = path.stem().generic_u8string(); if (t.canonical_name() == triplet_file_name) // TODO: fuzzy compare { // t.value = triplet_file_name; // NOTE: uncomment when implementing fuzzy compare @@ -258,26 +284,51 @@ namespace vcpkg return this->nuget_exe.get_lazy([this]() { return get_nuget_path(this->downloads, this->scripts); }); } - static std::vector<std::string> get_VS2017_installation_instances(const VcpkgPaths& paths) + const fs::path& VcpkgPaths::get_ifw_installerbase_exe() const { - const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1"; - const std::wstring cmd = System::create_powershell_script_cmd(script); - System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd); - Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Could not run script to detect VS 2017 instances"); - return Strings::split(ec_data.output, "\n"); + return this->ifw_installerbase_exe.get_lazy( + [this]() { return get_ifw_installerbase_path(this->downloads, this->scripts); }); + } + + const fs::path& VcpkgPaths::get_ifw_binarycreator_exe() const + { + return this->ifw_binarycreator_exe.get_lazy( + [this]() { return get_ifw_installerbase_exe().parent_path() / "binarycreator.exe"; }); + } + + const fs::path& VcpkgPaths::get_ifw_repogen_exe() const + { + return this->ifw_repogen_exe.get_lazy( + [this]() { return get_ifw_installerbase_exe().parent_path() / "repogen.exe"; }); } - static Optional<fs::path> get_VS2015_installation_instance() + struct VisualStudioInstance { - const Optional<std::wstring> vs2015_cmntools_optional = System::get_environment_variable(L"VS140COMNTOOLS"); - if (auto v = vs2015_cmntools_optional.get()) + fs::path root_path; + std::string version; + std::string release_type; + std::string preference_weight; // Mostly unused, just for verification that order is as intended + + std::string major_version() const { return version.substr(0, 2); } + }; + + static std::vector<VisualStudioInstance> get_visual_studio_instances(const VcpkgPaths& paths) + { + const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1"; + const std::wstring cmd = System::create_powershell_script_cmd(script); + const System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd); + Checks::check_exit( + VCPKG_LINE_INFO, ec_data.exit_code == 0, "Could not run script to detect Visual Studio instances"); + + const std::vector<std::string> instances_as_strings = Strings::split(ec_data.output, "\n"); + std::vector<VisualStudioInstance> output; + for (const std::string& instance_as_string : instances_as_strings) { - const fs::path vs2015_cmntools = fs::path(*v).parent_path(); // The call to parent_path() is needed because - // the env variable has a trailing backslash - return vs2015_cmntools.parent_path().parent_path(); + const std::vector<std::string> split = Strings::split(instance_as_string, "::"); + output.push_back({split.at(3), split.at(2), split.at(1), split.at(0)}); } - return nullopt; + return output; } static std::vector<Toolset> find_toolset_instances(const VcpkgPaths& paths) @@ -286,99 +337,122 @@ namespace vcpkg const auto& fs = paths.get_filesystem(); - const std::vector<std::string> vs2017_installation_instances = get_VS2017_installation_instances(paths); // Note: this will contain a mix of vcvarsall.bat locations and dumpbin.exe locations. std::vector<fs::path> paths_examined; std::vector<Toolset> found_toolsets; - // VS2015 - const Optional<fs::path> vs_2015_installation_instance = get_VS2015_installation_instance(); - if (auto v = vs_2015_installation_instance.get()) - { - const fs::path vs2015_vcvarsall_bat = *v / "VC" / "vcvarsall.bat"; + const std::vector<VisualStudioInstance> vs_instances = get_visual_studio_instances(paths); + const bool v140_is_available = Util::find_if(vs_instances, [&](const VisualStudioInstance& vs_instance) { + return vs_instance.major_version() == "14"; + }) != vs_instances.cend(); - paths_examined.push_back(vs2015_vcvarsall_bat); - if (fs.exists(vs2015_vcvarsall_bat)) + for (const VisualStudioInstance& vs_instance : vs_instances) + { + const std::string major_version = vs_instance.major_version(); + if (major_version == "15") { - const fs::path vs2015_dumpbin_exe = *v / "VC" / "bin" / "dumpbin.exe"; - paths_examined.push_back(vs2015_dumpbin_exe); + const fs::path vc_dir = vs_instance.root_path / "VC"; - const fs::path vs2015_bin_dir = vs2015_vcvarsall_bat.parent_path() / "bin"; + // Skip any instances that do not have vcvarsall. + const fs::path vcvarsall_dir = vc_dir / "Auxiliary" / "Build"; + const fs::path vcvarsall_bat = vcvarsall_dir / "vcvarsall.bat"; + paths_examined.push_back(vcvarsall_bat); + if (!fs.exists(vcvarsall_bat)) continue; + + // Get all supported architectures std::vector<ToolsetArchOption> supported_architectures; - if (fs.exists(vs2015_bin_dir / "vcvars32.bat")) + if (fs.exists(vcvarsall_dir / "vcvars32.bat")) supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); - if (fs.exists(vs2015_bin_dir / "amd64\\vcvars64.bat")) - supported_architectures.push_back({L"x64", CPU::X64, CPU::X64}); - if (fs.exists(vs2015_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat")) + if (fs.exists(vcvarsall_dir / "vcvars64.bat")) + supported_architectures.push_back({L"amd64", CPU::X64, CPU::X64}); + if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat")) supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); - if (fs.exists(vs2015_bin_dir / "x86_arm\\vcvarsx86_arm.bat")) + if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat")) supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); - if (fs.exists(vs2015_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat")) + if (fs.exists(vcvarsall_dir / "vcvarsx86_arm64.bat")) + supported_architectures.push_back({L"x86_arm64", CPU::X86, CPU::ARM64}); + if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat")) supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); - if (fs.exists(vs2015_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat")) + if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat")) supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); - - if (fs.exists(vs2015_dumpbin_exe)) + if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm64.bat")) + supported_architectures.push_back({L"amd64_arm64", CPU::X64, CPU::ARM64}); + + // Locate the "best" MSVC toolchain version + const fs::path msvc_path = vc_dir / "Tools" / "MSVC"; + std::vector<fs::path> msvc_subdirectories = fs.get_files_non_recursive(msvc_path); + Util::unstable_keep_if(msvc_subdirectories, + [&fs](const fs::path& path) { return fs.is_directory(path); }); + + // Sort them so that latest comes first + std::sort( + msvc_subdirectories.begin(), + msvc_subdirectories.end(), + [](const fs::path& left, const fs::path& right) { return left.filename() > right.filename(); }); + + for (const fs::path& subdir : msvc_subdirectories) { - found_toolsets.push_back( - {vs2015_dumpbin_exe, vs2015_vcvarsall_bat, L"v140", supported_architectures}); + const fs::path dumpbin_path = subdir / "bin" / "HostX86" / "x86" / "dumpbin.exe"; + paths_examined.push_back(dumpbin_path); + if (fs.exists(dumpbin_path)) + { + found_toolsets.push_back(Toolset{ + vs_instance.root_path, dumpbin_path, vcvarsall_bat, {}, V_141, supported_architectures}); + + if (v140_is_available) + { + found_toolsets.push_back(Toolset{vs_instance.root_path, + dumpbin_path, + vcvarsall_bat, + {L"-vcvars_ver=14.0"}, + V_140, + supported_architectures}); + } + + break; + } } + + continue; } - } - // VS2017 - Optional<Toolset> vs2017_toolset; - for (const fs::path& instance : vs2017_installation_instances) - { - const fs::path vc_dir = instance / "VC"; - - // Skip any instances that do not have vcvarsall. - const fs::path vcvarsall_dir = vc_dir / "Auxiliary" / "Build"; - const fs::path vcvarsall_bat = vcvarsall_dir / "vcvarsall.bat"; - paths_examined.push_back(vcvarsall_bat); - if (!fs.exists(vcvarsall_bat)) continue; - - // Get all supported architectures - std::vector<ToolsetArchOption> supported_architectures; - if (fs.exists(vcvarsall_dir / "vcvars32.bat")) - supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); - if (fs.exists(vcvarsall_dir / "vcvars64.bat")) - supported_architectures.push_back({L"amd64", CPU::X64, CPU::X64}); - if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat")) - supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); - if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat")) - supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); - if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat")) - supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); - if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat")) - supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); - - // Locate the "best" MSVC toolchain version - const fs::path msvc_path = vc_dir / "Tools" / "MSVC"; - std::vector<fs::path> msvc_subdirectories = fs.get_files_non_recursive(msvc_path); - Util::unstable_keep_if(msvc_subdirectories, [&fs](const fs::path& path) { return fs.is_directory(path); }); - - // Sort them so that latest comes first - std::sort(msvc_subdirectories.begin(), - msvc_subdirectories.end(), - [](const fs::path& left, const fs::path& right) { return left.filename() > right.filename(); }); - - for (const fs::path& subdir : msvc_subdirectories) + if (major_version == "14") { - const fs::path dumpbin_path = subdir / "bin" / "HostX86" / "x86" / "dumpbin.exe"; - paths_examined.push_back(dumpbin_path); - if (fs.exists(dumpbin_path)) + const fs::path vcvarsall_bat = vs_instance.root_path / "VC" / "vcvarsall.bat"; + + paths_examined.push_back(vcvarsall_bat); + if (fs.exists(vcvarsall_bat)) { - vs2017_toolset = Toolset{dumpbin_path, vcvarsall_bat, L"v141", supported_architectures}; - break; + const fs::path vs2015_dumpbin_exe = vs_instance.root_path / "VC" / "bin" / "dumpbin.exe"; + paths_examined.push_back(vs2015_dumpbin_exe); + + const fs::path vs2015_bin_dir = vcvarsall_bat.parent_path() / "bin"; + std::vector<ToolsetArchOption> supported_architectures; + if (fs.exists(vs2015_bin_dir / "vcvars32.bat")) + supported_architectures.push_back({L"x86", CPU::X86, CPU::X86}); + if (fs.exists(vs2015_bin_dir / "amd64\\vcvars64.bat")) + supported_architectures.push_back({L"x64", CPU::X64, CPU::X64}); + if (fs.exists(vs2015_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat")) + supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64}); + if (fs.exists(vs2015_bin_dir / "x86_arm\\vcvarsx86_arm.bat")) + supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM}); + if (fs.exists(vs2015_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat")) + supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86}); + if (fs.exists(vs2015_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat")) + supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM}); + + if (fs.exists(vs2015_dumpbin_exe)) + { + found_toolsets.push_back({vs_instance.root_path, + vs2015_dumpbin_exe, + vcvarsall_bat, + {}, + V_140, + supported_architectures}); + } } } - if (auto value = vs2017_toolset.get()) - { - found_toolsets.push_back(*value); - break; - } } if (found_toolsets.empty()) @@ -395,24 +469,54 @@ namespace vcpkg return found_toolsets; } - const Toolset& VcpkgPaths::get_toolset(const std::string& toolset_version) const + const Toolset& VcpkgPaths::get_toolset(const Optional<std::string>& toolset_version, + const Optional<fs::path>& visual_studio_path) const { // Invariant: toolsets are non-empty and sorted with newest at back() - const auto& vs_toolsets = this->toolsets.get_lazy([this]() { return find_toolset_instances(*this); }); + const std::vector<Toolset>& vs_toolsets = + this->toolsets.get_lazy([this]() { return find_toolset_instances(*this); }); + + std::vector<const Toolset*> candidates = Util::element_pointers(vs_toolsets); + const auto tsv = toolset_version.get(); + const auto vsp = visual_studio_path.get(); - if (toolset_version.empty()) + if (tsv && vsp) { - return vs_toolsets.back(); + const std::wstring w_toolset_version = Strings::to_utf16(*tsv); + const fs::path vs_root_path = *vsp; + Util::stable_keep_if(candidates, [&](const Toolset* t) { + return w_toolset_version == t->version && vs_root_path == t->visual_studio_root_path; + }); + Checks::check_exit(VCPKG_LINE_INFO, + !candidates.empty(), + "Could not find Visual Studio instace at %s with %s toolset.", + vs_root_path.generic_string(), + *tsv); + + Checks::check_exit(VCPKG_LINE_INFO, candidates.size() == 1); + return *candidates.back(); } - else + + if (tsv) { - const auto toolset = Util::find_if(vs_toolsets, [&](const Toolset& toolset) { - return toolset_version == Strings::to_utf8(toolset.version); - }); + const std::wstring w_toolset_version = Strings::to_utf16(*tsv); + Util::stable_keep_if(candidates, [&](const Toolset* t) { return w_toolset_version == t->version; }); Checks::check_exit( - VCPKG_LINE_INFO, toolset != vs_toolsets.end(), "Could not find toolset '%s'", toolset_version); - return *toolset; + VCPKG_LINE_INFO, !candidates.empty(), "Could not find Visual Studio instace with %s toolset.", *tsv); + } + + if (vsp) + { + const fs::path vs_root_path = *vsp; + Util::stable_keep_if(candidates, + [&](const Toolset* t) { return vs_root_path == t->visual_studio_root_path; }); + Checks::check_exit(VCPKG_LINE_INFO, + !candidates.empty(), + "Could not find Visual Studio instace at %s.", + vs_root_path.generic_string()); } + + return *candidates.front(); } Files::Filesystem& VcpkgPaths::get_filesystem() const { return Files::get_real_filesystem(); } diff --git a/toolsrc/src/coff_file_reader.cpp b/toolsrc/src/coff_file_reader.cpp index 6c38c452b..bb3a6cefd 100644 --- a/toolsrc/src/coff_file_reader.cpp +++ b/toolsrc/src/coff_file_reader.cpp @@ -5,7 +5,7 @@ using namespace std; -namespace vcpkg::COFFFileReader +namespace vcpkg::CoffFileReader { template<class T> static T reinterpret_bytes(const char* data) @@ -24,7 +24,7 @@ namespace vcpkg::COFFFileReader template<class T> static T peek_value_from_stream(fstream& fs) { - fpos_t original_pos = fs.tellg().seekpos(); + const fpos_t original_pos = fs.tellg().seekpos(); T data; fs.read(reinterpret_cast<char*>(&data), sizeof data); fs.seekg(original_pos); @@ -236,7 +236,7 @@ namespace vcpkg::COFFFileReader read_and_verify_PE_signature(fs); CoffFileHeader header = CoffFileHeader::read(fs); - MachineType machine = header.machine_type(); + const MachineType machine = header.machine_type(); return {machine}; } @@ -282,7 +282,7 @@ namespace vcpkg::COFFFileReader marker.advance_by(ArchiveMemberHeader::HEADER_SIZE + second_linker_member_header.member_size()); marker.seek_to_marker(fs); - bool hasLongnameMemberHeader = peek_value_from_stream<uint16_t>(fs) == 0x2F2F; + const bool hasLongnameMemberHeader = peek_value_from_stream<uint16_t>(fs) == 0x2F2F; if (hasLongnameMemberHeader) { const ArchiveMemberHeader longnames_member_header = ArchiveMemberHeader::read(fs); diff --git a/toolsrc/src/commands_autocomplete.cpp b/toolsrc/src/commands_autocomplete.cpp new file mode 100644 index 000000000..3963f904b --- /dev/null +++ b/toolsrc/src/commands_autocomplete.cpp @@ -0,0 +1,79 @@ +#include "pch.h" + +#include "Paragraphs.h" +#include "SortedVector.h" +#include "vcpkg_Commands.h" +#include "vcpkg_Maps.h" +#include "vcpkg_System.h" +#include "vcpkglib.h" + +namespace vcpkg::Commands::Autocomplete +{ + std::vector<std::string> autocomplete_install( + const std::vector<std::unique_ptr<SourceControlFile>>& source_paragraphs, const std::string& start_with) + { + std::vector<std::string> results; + const auto& istartswith = Strings::case_insensitive_ascii_starts_with; + + for (const auto& source_control_file : source_paragraphs) + { + auto&& sp = *source_control_file->core_paragraph; + + if (istartswith(sp.name, start_with)) + { + results.push_back(sp.name); + } + } + return results; + } + + std::vector<std::string> autocomplete_remove(std::vector<StatusParagraph*> installed_packages, + const std::string& start_with) + { + std::vector<std::string> results; + const auto& istartswith = Strings::case_insensitive_ascii_starts_with; + + for (const auto& installed_package : installed_packages) + { + auto sp = installed_package->package.displayname(); + + if (istartswith(sp, start_with)) + { + results.push_back(sp); + } + } + return results; + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { + static const std::string EXAMPLE = + Strings::format("The argument should be a command line to autocomplete.\n%s", + Commands::Help::create_example_string("autocomplete install z")); + + args.check_min_arg_count(1, EXAMPLE); + args.check_max_arg_count(2, EXAMPLE); + args.check_and_get_optional_command_arguments({}); + + const std::string requested_command = args.command_arguments.at(0); + const std::string start_with = + args.command_arguments.size() > 1 ? args.command_arguments.at(1) : Strings::EMPTY; + std::vector<std::string> results; + if (requested_command == "install") + { + auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); + auto& source_paragraphs = sources_and_errors.paragraphs; + + results = autocomplete_install(source_paragraphs, start_with); + } + else if (requested_command == "remove") + { + const StatusParagraphs status_db = database_load_check(paths); + std::vector<StatusParagraph*> installed_packages = get_installed_ports(status_db); + results = autocomplete_remove(installed_packages, start_with); + } + + System::println(Strings::join(" ", results)); + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/commands_available_commands.cpp b/toolsrc/src/commands_available_commands.cpp index 87cc43dca..d3280e6d7 100644 --- a/toolsrc/src/commands_available_commands.cpp +++ b/toolsrc/src/commands_available_commands.cpp @@ -34,7 +34,7 @@ namespace vcpkg::Commands {"import", &Import::perform_and_exit}, {"cache", &Cache::perform_and_exit}, {"portsdiff", &PortsDiff::perform_and_exit}, - }; + {"autocomplete", &Autocomplete::perform_and_exit}}; return t; } diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp index 4da9cede2..a69958058 100644 --- a/toolsrc/src/commands_build.cpp +++ b/toolsrc/src/commands_build.cpp @@ -29,8 +29,8 @@ namespace vcpkg::Commands::BuildCommand const PackageSpec& spec = full_spec.package_spec; if (options.find(OPTION_CHECKS_ONLY) != options.end()) { - auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, spec.triplet()); - auto build_info = Build::read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); + const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, spec.triplet()); + const auto build_info = Build::read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); Checks::check_exit(VCPKG_LINE_INFO, error_count == 0); Checks::exit_success(VCPKG_LINE_INFO); @@ -45,7 +45,7 @@ namespace vcpkg::Commands::BuildCommand Checks::exit_fail(VCPKG_LINE_INFO); } - for (std::string str : full_spec.features) + for (const std::string& str : full_spec.features) { System::println("%s \n", str); } @@ -56,8 +56,8 @@ namespace vcpkg::Commands::BuildCommand scf->core_paragraph->name, spec.name()); - StatusParagraphs status_db = database_load_check(paths); - Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; + const StatusParagraphs status_db = database_load_check(paths); + const Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; const Build::BuildPackageConfig build_config{ *scf->core_paragraph, spec.triplet(), paths.port_dir(spec), build_package_options}; @@ -68,12 +68,12 @@ namespace vcpkg::Commands::BuildCommand System::println(System::Color::error, "The build command requires all dependencies to be already installed."); System::println("The following dependencies are missing:"); - System::println(""); + System::println(); for (const auto& p : result.unmet_dependencies) { System::println(" %s", p); } - System::println(""); + System::println(); Checks::exit_fail(VCPKG_LINE_INFO); } @@ -89,11 +89,11 @@ namespace vcpkg::Commands::BuildCommand void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { - static const std::string example = Commands::Help::create_example_string("build zlib:x64-windows"); - args.check_exact_arg_count( - 1, example); // Build only takes a single package and all dependencies must already be installed - std::string command_argument = args.command_arguments.at(0); - const FullPackageSpec spec = Input::check_and_get_full_package_spec(command_argument, default_triplet, example); + static const std::string EXAMPLE = Commands::Help::create_example_string("build zlib:x64-windows"); + // Build only takes a single package and all dependencies must already be installed + args.check_exact_arg_count(1, EXAMPLE); + const std::string command_argument = args.command_arguments.at(0); + const FullPackageSpec spec = Input::check_and_get_full_package_spec(command_argument, default_triplet, EXAMPLE); Input::check_triplet(spec.package_spec.triplet(), paths); const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({OPTION_CHECKS_ONLY}); diff --git a/toolsrc/src/commands_build_external.cpp b/toolsrc/src/commands_build_external.cpp index ff70e9cf2..7e85f2250 100644 --- a/toolsrc/src/commands_build_external.cpp +++ b/toolsrc/src/commands_build_external.cpp @@ -2,17 +2,16 @@ #include "vcpkg_Commands.h" #include "vcpkg_Input.h" -#include "vcpkg_System.h" namespace vcpkg::Commands::BuildExternal { void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { - static const std::string example = + 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); + args.check_exact_arg_count(2, EXAMPLE); const FullPackageSpec spec = - Input::check_and_get_full_package_spec(args.command_arguments.at(0), default_triplet, example); + Input::check_and_get_full_package_spec(args.command_arguments.at(0), default_triplet, EXAMPLE); Input::check_triplet(spec.package_spec.triplet(), paths); const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({}); diff --git a/toolsrc/src/commands_cache.cpp b/toolsrc/src/commands_cache.cpp index 75de78461..5b65b197f 100644 --- a/toolsrc/src/commands_cache.cpp +++ b/toolsrc/src/commands_cache.cpp @@ -15,7 +15,7 @@ namespace vcpkg::Commands::Cache { const Expected<std::unordered_map<std::string, std::string>> pghs = Paragraphs::get_single_paragraph(paths.get_filesystem(), path / "CONTROL"); - if (auto p = pghs.get()) + if (const auto p = pghs.get()) { const BinaryParagraph binary_paragraph = BinaryParagraph(*p); output.push_back(binary_paragraph); @@ -27,10 +27,10 @@ namespace vcpkg::Commands::Cache void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = Strings::format( + static const std::string EXAMPLE = Strings::format( "The argument should be a substring to search for, or no argument to display all cached libraries.\n%s", Commands::Help::create_example_string("cache png")); - args.check_max_arg_count(1, example); + args.check_max_arg_count(1, EXAMPLE); args.check_and_get_optional_command_arguments({}); const std::vector<BinaryParagraph> binary_paragraphs = read_all_binary_paragraphs(paths); diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp index f781adf69..75ff65556 100644 --- a/toolsrc/src/commands_ci.cpp +++ b/toolsrc/src/commands_ci.cpp @@ -13,9 +13,9 @@ namespace vcpkg::Commands::CI { + using Build::BuildResult; using Dependencies::InstallPlanAction; using Dependencies::InstallPlanType; - using Build::BuildResult; static std::vector<PackageSpec> load_all_package_specs(Files::Filesystem& fs, const fs::path& ports_directory, @@ -30,8 +30,8 @@ namespace vcpkg::Commands::CI void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { - static const std::string example = Commands::Help::create_example_string("ci x64-windows"); - args.check_max_arg_count(1, example); + static const std::string EXAMPLE = Commands::Help::create_example_string("ci x64-windows"); + args.check_max_arg_count(1, EXAMPLE); const Triplet triplet = args.command_arguments.size() == 1 ? Triplet::from_canonical_name(args.command_arguments.at(0)) : default_triplet; @@ -41,57 +41,19 @@ namespace vcpkg::Commands::CI StatusParagraphs status_db = database_load_check(paths); const auto& paths_port_file = Dependencies::PathsPortFile(paths); - const std::vector<InstallPlanAction> install_plan = + 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"); - std::vector<BuildResult> results; - std::vector<std::string> timing; - const ElapsedTime timer = ElapsedTime::create_started(); - size_t counter = 0; - const size_t package_count = install_plan.size(); const Build::BuildPackageOptions install_plan_options = {Build::UseHeadVersion::NO, Build::AllowDownloads::YES}; - for (const InstallPlanAction& action : install_plan) - { - const ElapsedTime build_timer = ElapsedTime::create_started(); - counter++; - const std::string display_name = action.spec.to_string(); - System::println("Starting package %d/%d: %s", counter, package_count, display_name); - - timing.push_back("0"); - results.push_back(BuildResult::NULLVALUE); - - const BuildResult result = - Install::perform_install_plan_action(paths, action, install_plan_options, status_db); - timing.back() = build_timer.to_string(); - results.back() = result; - System::println("Elapsed time for package %s: %s", action.spec, build_timer.to_string()); - } - - System::println("Total time taken: %s", timer.to_string()); - - for (size_t i = 0; i < results.size(); i++) - { - System::println("%s: %s: %s", install_plan[i].spec, Build::to_string(results[i]), timing[i]); - } - - std::map<BuildResult, int> summary; - for (const BuildResult& v : Build::BuildResult_values) - { - summary[v] = 0; - } - - for (const BuildResult& r : results) - { - summary[r]++; - } + const std::vector<Dependencies::AnyAction> action_plan = + Util::fmap(install_plan, [](InstallPlanAction& install_action) { + return Dependencies::AnyAction(std::move(install_action)); + }); - System::println("\n\nSUMMARY"); - for (const std::pair<const BuildResult, int>& entry : summary) - { - System::println(" %s: %d", Build::to_string(entry.first), entry.second); - } + Install::perform_and_exit( + action_plan, install_plan_options, Install::KeepGoing::YES, Install::PrintSummary::YES, paths, status_db); Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/commands_contact.cpp b/toolsrc/src/commands_contact.cpp index 7f4161802..8374350ee 100644 --- a/toolsrc/src/commands_contact.cpp +++ b/toolsrc/src/commands_contact.cpp @@ -7,8 +7,8 @@ namespace vcpkg::Commands::Contact { const std::string& email() { - static const std::string s_email = R"(vcpkg@microsoft.com)"; - return s_email; + static const std::string S_EMAIL = R"(vcpkg@microsoft.com)"; + return S_EMAIL; } void perform_and_exit(const VcpkgCmdArguments& args) diff --git a/toolsrc/src/commands_create.cpp b/toolsrc/src/commands_create.cpp index 7f85b776a..6898f7399 100644 --- a/toolsrc/src/commands_create.cpp +++ b/toolsrc/src/commands_create.cpp @@ -2,7 +2,6 @@ #include "vcpkg_Commands.h" #include "vcpkg_Files.h" -#include "vcpkg_Input.h" #include "vcpkg_System.h" #include "vcpkglib.h" @@ -10,10 +9,10 @@ namespace vcpkg::Commands::Create { void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = Commands::Help::create_example_string( + static const std::string EXAMPLE = Commands::Help::create_example_string( R"###(create zlib2 http://zlib.net/zlib1211.zip "zlib1211-2.zip")###"); - args.check_max_arg_count(3, example); - args.check_min_arg_count(2, example); + args.check_max_arg_count(3, EXAMPLE); + args.check_min_arg_count(2, EXAMPLE); args.check_and_get_optional_command_arguments({}); const std::string port_name = args.command_arguments.at(0); const std::string url = args.command_arguments.at(1); diff --git a/toolsrc/src/commands_depends.cpp b/toolsrc/src/commands_depends.cpp index 49e1c6c01..17cd9c881 100644 --- a/toolsrc/src/commands_depends.cpp +++ b/toolsrc/src/commands_depends.cpp @@ -10,8 +10,8 @@ namespace vcpkg::Commands::DependInfo { void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = Commands::Help::create_example_string(R"###(depend-info [pat])###"); - args.check_max_arg_count(1, example); + static const std::string EXAMPLE = Commands::Help::create_example_string(R"###(depend-info [pat])###"); + args.check_max_arg_count(1, EXAMPLE); args.check_and_get_optional_command_arguments({}); std::vector<std::unique_ptr<SourceControlFile>> source_control_files = @@ -46,7 +46,7 @@ namespace vcpkg::Commands::DependInfo for (auto&& source_control_file : source_control_files) { const SourceParagraph& source_paragraph = *source_control_file->core_paragraph; - auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name(); }); + const auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name(); }); System::println("%s: %s", source_paragraph.name, s); } diff --git a/toolsrc/src/commands_edit.cpp b/toolsrc/src/commands_edit.cpp index 72005a461..823c87534 100644 --- a/toolsrc/src/commands_edit.cpp +++ b/toolsrc/src/commands_edit.cpp @@ -6,14 +6,40 @@ namespace vcpkg::Commands::Edit { + static std::vector<fs::path> find_from_registry() + { + static const std::array<const wchar_t*, 3> REGKEYS = { + LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)", + LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1287CAD5-7C8D-410D-88B9-0D1EE4A83FF2}_is1)", + LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)", + }; + + std::vector<fs::path> output; + for (auto&& keypath : REGKEYS) + { + const Optional<std::wstring> code_installpath = + System::get_registry_string(HKEY_LOCAL_MACHINE, keypath, L"InstallLocation"); + if (const auto c = code_installpath.get()) + { + const fs::path install_path = fs::path(*c); + output.push_back(install_path / "Code - Insiders.exe"); + output.push_back(install_path / "Code.exe"); + } + } + return output; + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { static const std::string OPTION_BUILDTREES = "--buildtrees"; + static const fs::path VS_CODE_INSIDERS = fs::path{"Microsoft VS Code Insiders"} / "Code - Insiders.exe"; + static const fs::path VS_CODE = fs::path{"Microsoft VS Code"} / "Code.exe"; + auto& fs = paths.get_filesystem(); - static const std::string example = Commands::Help::create_example_string("edit zlib"); - args.check_exact_arg_count(1, example); + static const std::string EXAMPLE = Commands::Help::create_example_string("edit zlib"); + args.check_exact_arg_count(1, EXAMPLE); const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({OPTION_BUILDTREES}); const std::string port_name = args.command_arguments.at(0); @@ -21,82 +47,40 @@ namespace vcpkg::Commands::Edit const fs::path portpath = paths.ports / port_name; Checks::check_exit(VCPKG_LINE_INFO, fs.is_directory(portpath), R"(Could not find port named "%s")", port_name); - // Find the user's selected editor - std::wstring env_EDITOR; - - if (env_EDITOR.empty()) - { - const Optional<std::wstring> env_EDITOR_optional = System::get_environment_variable(L"EDITOR"); - if (auto e = env_EDITOR_optional.get()) - { - env_EDITOR = *e; - } - } - - if (env_EDITOR.empty()) - { - const fs::path CODE_EXE_PATH = System::get_ProgramFiles_platform_bitness() / "Microsoft VS Code/Code.exe"; - if (fs.exists(CODE_EXE_PATH)) - { - env_EDITOR = CODE_EXE_PATH; - } - } - - if (env_EDITOR.empty()) - { - const fs::path CODE_EXE_PATH = System::get_ProgramFiles_32_bit() / "Microsoft VS Code/Code.exe"; - if (fs.exists(CODE_EXE_PATH)) - { - env_EDITOR = CODE_EXE_PATH; - } - } + std::vector<fs::path> candidate_paths; + const std::vector<fs::path> from_path = Files::find_from_PATH(L"EDITOR"); + candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + candidate_paths.push_back(System::get_program_files_platform_bitness() / VS_CODE_INSIDERS); + candidate_paths.push_back(System::get_program_files_32_bit() / VS_CODE_INSIDERS); + candidate_paths.push_back(System::get_program_files_platform_bitness() / VS_CODE); + candidate_paths.push_back(System::get_program_files_32_bit() / VS_CODE); - if (env_EDITOR.empty()) - { - static const std::array<const wchar_t*, 4> regkeys = { - LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)", - LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)", - LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)", - LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)", - }; - for (auto&& keypath : regkeys) - { - const Optional<std::wstring> code_installpath = - System::get_registry_string(HKEY_LOCAL_MACHINE, keypath, L"InstallLocation"); - if (auto c = code_installpath.get()) - { - auto p = fs::path(*c) / "Code.exe"; - if (fs.exists(p)) - { - env_EDITOR = p.native(); - break; - } - auto p_insiders = fs::path(*c) / "Code - Insiders.exe"; - if (fs.exists(p_insiders)) - { - env_EDITOR = p_insiders.native(); - break; - } - } - } - } + const std::vector<fs::path> from_registry = find_from_registry(); + candidate_paths.insert(candidate_paths.end(), from_registry.cbegin(), from_registry.cend()); - if (env_EDITOR.empty()) + auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { return fs.exists(p); }); + if (it == candidate_paths.cend()) { - Checks::exit_with_message( - VCPKG_LINE_INFO, "Visual Studio Code was not found and the environment variable EDITOR is not set"); + System::println(System::Color::error, + "Error: Visual Studio Code was not found and the environment variable EDITOR is not set."); + System::println("The following paths were examined:"); + Files::print_paths(candidate_paths); + System::println("You can also set the environmental variable EDITOR to your editor of choice."); + Checks::exit_fail(VCPKG_LINE_INFO); } + const fs::path env_editor = *it; if (options.find(OPTION_BUILDTREES) != options.cend()) { const auto buildtrees_current_dir = paths.buildtrees / port_name; - std::wstring cmdLine = Strings::wformat(LR"("%s" "%s" -n)", env_EDITOR, buildtrees_current_dir.native()); - Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmdLine)); + const std::wstring cmd_line = + Strings::wformat(LR"("%s" "%s" -n)", env_editor, buildtrees_current_dir.native()); + Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line)); } - std::wstring cmdLine = Strings::wformat( - LR"("%s" "%s" "%s" -n)", env_EDITOR, portpath.native(), (portpath / "portfile.cmake").native()); - Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmdLine)); + const std::wstring cmd_line = Strings::wformat( + LR"("%s" "%s" "%s" -n)", env_editor, portpath.native(), (portpath / "portfile.cmake").native()); + Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line)); } } diff --git a/toolsrc/src/commands_env.cpp b/toolsrc/src/commands_env.cpp index dd7172b89..6dad3e882 100644 --- a/toolsrc/src/commands_env.cpp +++ b/toolsrc/src/commands_env.cpp @@ -8,12 +8,13 @@ namespace vcpkg::Commands::Env { void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { - static const std::string example = Commands::Help::create_example_string(R"(env --Triplet x64-windows)"); - args.check_exact_arg_count(0, example); + static const std::string EXAMPLE = Commands::Help::create_example_string(R"(env --Triplet x64-windows)"); + args.check_exact_arg_count(0, EXAMPLE); args.check_and_get_optional_command_arguments({}); - auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet); - System::cmd_execute_clean(Build::make_build_env_cmd(pre_build_info, paths.get_toolset(pre_build_info.platform_toolset)) + L" && cmd"); + const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet); + const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); + System::cmd_execute_clean(Build::make_build_env_cmd(pre_build_info, toolset) + L" && cmd"); Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/commands_export.cpp b/toolsrc/src/commands_export.cpp index cbcb219b6..20838f5a5 100644 --- a/toolsrc/src/commands_export.cpp +++ b/toolsrc/src/commands_export.cpp @@ -2,6 +2,7 @@ #include "Paragraphs.h" #include "vcpkg_Commands.h" +#include "vcpkg_Commands_Export_IFW.h" #include "vcpkg_Dependencies.h" #include "vcpkg_Input.h" #include "vcpkg_System.h" @@ -21,7 +22,7 @@ namespace vcpkg::Commands::Export const std::string& nuget_id, const std::string& nupkg_version) { - static constexpr auto content_template = R"( + static constexpr auto CONTENT_TEMPLATE = R"( <package> <metadata> <id>@NUGET_ID@</id> @@ -40,7 +41,7 @@ namespace vcpkg::Commands::Export </package> )"; - std::string nuspec_file_content = std::regex_replace(content_template, std::regex("@NUGET_ID@"), nuget_id); + std::string nuspec_file_content = std::regex_replace(CONTENT_TEMPLATE, std::regex("@NUGET_ID@"), nuget_id); nuspec_file_content = std::regex_replace(nuspec_file_content, std::regex("@VERSION@"), nupkg_version); nuspec_file_content = std::regex_replace(nuspec_file_content, std::regex("@RAW_EXPORTED_DIR@"), raw_exported_dir); @@ -62,12 +63,12 @@ namespace vcpkg::Commands::Export static void print_plan(const std::map<ExportPlanType, std::vector<const ExportPlanAction*>>& group_by_plan_type) { - static constexpr std::array<ExportPlanType, 2> order = {ExportPlanType::ALREADY_BUILT, + static constexpr std::array<ExportPlanType, 2> ORDER = {ExportPlanType::ALREADY_BUILT, ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT}; - for (const ExportPlanType plan_type : order) + for (const ExportPlanType plan_type : ORDER) { - auto it = group_by_plan_type.find(plan_type); + const auto it = group_by_plan_type.find(plan_type); if (it == group_by_plan_type.cend()) { continue; @@ -151,7 +152,7 @@ namespace vcpkg::Commands::Export enum class BackingEnum { ZIP = 1, - _7ZIP, + SEVEN_ZIP, }; constexpr ArchiveFormat() = delete; @@ -174,7 +175,7 @@ namespace vcpkg::Commands::Export namespace ArchiveFormatC { constexpr const ArchiveFormat ZIP(ArchiveFormat::BackingEnum::ZIP, L"zip", L"zip"); - constexpr const ArchiveFormat _7ZIP(ArchiveFormat::BackingEnum::_7ZIP, L"7z", L"7zip"); + constexpr const ArchiveFormat SEVEN_ZIP(ArchiveFormat::BackingEnum::SEVEN_ZIP, L"7z", L"7zip"); } static fs::path do_archive_export(const VcpkgPaths& paths, @@ -205,110 +206,173 @@ namespace vcpkg::Commands::Export static Optional<std::string> maybe_lookup(std::unordered_map<std::string, std::string> const& m, std::string const& key) { - auto it = m.find(key); - if (it != m.end()) - return it->second; - else - return nullopt; + const auto it = m.find(key); + if (it != m.end()) return it->second; + return nullopt; } - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + void export_integration_files(const fs::path& raw_exported_dir_path, const VcpkgPaths& paths) { + const std::vector<fs::path> integration_files_relative_to_root = { + {".vcpkg-root"}, + {fs::path{"scripts"} / "buildsystems" / "msbuild" / "applocal.ps1"}, + {fs::path{"scripts"} / "buildsystems" / "msbuild" / "vcpkg.targets"}, + {fs::path{"scripts"} / "buildsystems" / "vcpkg.cmake"}, + {fs::path{"scripts"} / "cmake" / "vcpkg_get_windows_sdk.cmake"}, + {fs::path{"scripts"} / "getWindowsSDK.ps1"}, + {fs::path{"scripts"} / "getProgramFilesPlatformBitness.ps1"}, + {fs::path{"scripts"} / "getProgramFiles32bit.ps1"}, + }; + + for (const fs::path& file : integration_files_relative_to_root) + { + const fs::path source = paths.root / file; + fs::path destination = raw_exported_dir_path / file; + Files::Filesystem& fs = paths.get_filesystem(); + std::error_code ec; + fs.create_directories(destination.parent_path(), ec); + Checks::check_exit(VCPKG_LINE_INFO, !ec); + fs.copy_file(source, destination, fs::copy_options::overwrite_existing, ec); + Checks::check_exit(VCPKG_LINE_INFO, !ec); + } + } + + struct ExportArguments + { + bool dry_run; + bool raw; + bool nuget; + bool ifw; + bool zip; + bool seven_zip; + + Optional<std::string> maybe_nuget_id; + Optional<std::string> maybe_nuget_version; + + IFW::Options ifw_options; + std::vector<PackageSpec> specs; + }; + + static ExportArguments handle_export_command_arguments(const VcpkgCmdArguments& args, + const Triplet& default_triplet) + { + ExportArguments ret; + static const std::string OPTION_DRY_RUN = "--dry-run"; static const std::string OPTION_RAW = "--raw"; static const std::string OPTION_NUGET = "--nuget"; + static const std::string OPTION_IFW = "--ifw"; static const std::string OPTION_ZIP = "--zip"; - static const std::string OPTION_7ZIP = "--7zip"; + static const std::string OPTION_SEVEN_ZIP = "--7zip"; static const std::string OPTION_NUGET_ID = "--nuget-id"; static const std::string OPTION_NUGET_VERSION = "--nuget-version"; + static const std::string OPTION_IFW_REPOSITORY_URL = "--ifw-repository-url"; + static const std::string OPTION_IFW_PACKAGES_DIR_PATH = "--ifw-packages-directory-path"; + static const std::string OPTION_IFW_REPOSITORY_DIR_PATH = "--ifw-repository-directory-path"; + static const std::string OPTION_IFW_CONFIG_FILE_PATH = "--ifw-configuration-file-path"; + static const std::string OPTION_IFW_INSTALLER_FILE_PATH = "--ifw-installer-file-path"; // input sanitization - static const std::string example = + static const std::string EXAMPLE = Commands::Help::create_example_string("export zlib zlib:x64-windows boost --nuget"); - args.check_min_arg_count(1, example); + args.check_min_arg_count(1, EXAMPLE); - const std::vector<PackageSpec> specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_package_spec(arg, default_triplet, example); + ret.specs = Util::fmap(args.command_arguments, [&](auto&& arg) { + return Input::check_and_get_package_spec(arg, default_triplet, EXAMPLE); }); - for (auto&& spec : specs) - Input::check_triplet(spec.triplet(), paths); const auto options = args.check_and_get_optional_command_arguments( { OPTION_DRY_RUN, OPTION_RAW, OPTION_NUGET, + OPTION_IFW, OPTION_ZIP, - OPTION_7ZIP, + OPTION_SEVEN_ZIP, }, { OPTION_NUGET_ID, OPTION_NUGET_VERSION, + OPTION_IFW_REPOSITORY_URL, + OPTION_IFW_PACKAGES_DIR_PATH, + OPTION_IFW_REPOSITORY_DIR_PATH, + OPTION_IFW_CONFIG_FILE_PATH, + OPTION_IFW_INSTALLER_FILE_PATH, }); - const bool dryRun = options.switches.find(OPTION_DRY_RUN) != options.switches.cend(); - const bool raw = options.switches.find(OPTION_RAW) != options.switches.cend(); - const bool nuget = options.switches.find(OPTION_NUGET) != options.switches.cend(); - const bool zip = options.switches.find(OPTION_ZIP) != options.switches.cend(); - const bool _7zip = options.switches.find(OPTION_7ZIP) != options.switches.cend(); - - if (!raw && !nuget && !zip && !_7zip && !dryRun) + ret.dry_run = options.switches.find(OPTION_DRY_RUN) != options.switches.cend(); + ret.raw = options.switches.find(OPTION_RAW) != options.switches.cend(); + ret.nuget = options.switches.find(OPTION_NUGET) != options.switches.cend(); + ret.ifw = options.switches.find(OPTION_IFW) != options.switches.cend(); + ret.zip = options.switches.find(OPTION_ZIP) != options.switches.cend(); + ret.seven_zip = options.switches.find(OPTION_SEVEN_ZIP) != options.switches.cend(); + + if (!ret.raw && !ret.nuget && !ret.ifw && !ret.zip && !ret.seven_zip && !ret.dry_run) { - System::println(System::Color::error, "Must provide at least one export type: --raw --nuget --zip --7zip"); - System::print(example); + System::println(System::Color::error, + "Must provide at least one export type: --raw --nuget --ifw --zip --7zip"); + System::print(EXAMPLE); Checks::exit_fail(VCPKG_LINE_INFO); } - auto maybe_nuget_id = maybe_lookup(options.settings, OPTION_NUGET_ID); - auto maybe_nuget_version = maybe_lookup(options.settings, OPTION_NUGET_VERSION); - - Checks::check_exit(VCPKG_LINE_INFO, !maybe_nuget_id || nuget, "--nuget-id is only valid with --nuget"); - Checks::check_exit( - VCPKG_LINE_INFO, !maybe_nuget_version || nuget, "--nuget-version is only valid with --nuget"); - - // create the plan - StatusParagraphs status_db = database_load_check(paths); - std::vector<ExportPlanAction> export_plan = Dependencies::create_export_plan(paths, specs, status_db); - Checks::check_exit(VCPKG_LINE_INFO, !export_plan.empty(), "Export plan cannot be empty"); - - std::map<ExportPlanType, std::vector<const ExportPlanAction*>> group_by_plan_type; - Util::group_by(export_plan, &group_by_plan_type, [](const ExportPlanAction& p) { return p.plan_type; }); - print_plan(group_by_plan_type); - - const bool has_non_user_requested_packages = - Util::find_if(export_plan, [](const ExportPlanAction& package) -> bool { - return package.request_type != RequestType::USER_REQUESTED; - }) != export_plan.cend(); - - if (has_non_user_requested_packages) - { - System::println(System::Color::warning, - "Additional packages (*) need to be exported to complete this operation."); - } - - auto it = group_by_plan_type.find(ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT); - if (it != group_by_plan_type.cend() && !it->second.empty()) - { - System::println(System::Color::error, "There are packages that have not been built."); - - // No need to show all of them, just the user-requested ones. Dependency resolution will handle the rest. - std::vector<const ExportPlanAction*> unbuilt = it->second; - Util::erase_remove_if( - unbuilt, [](const ExportPlanAction* a) { return a->request_type != RequestType::USER_REQUESTED; }); - - auto s = Strings::join(" ", unbuilt, [](const ExportPlanAction* a) { return a->spec.to_string(); }); - System::println("To build them, run:\n" - " vcpkg install %s", - s); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - if (dryRun) + struct OptionPair { - Checks::exit_success(VCPKG_LINE_INFO); - } + const std::string& name; + Optional<std::string>& out_opt; + }; + const auto options_implies = + [&](const std::string& main_opt_name, bool main_opt, Span<const OptionPair> implying_opts) { + if (main_opt) + { + for (auto&& opt : implying_opts) + opt.out_opt = maybe_lookup(options.settings, opt.name); + } + else + { + for (auto&& opt : implying_opts) + Checks::check_exit(VCPKG_LINE_INFO, + !maybe_lookup(options.settings, opt.name), + "%s is only valid with %s", + opt.name, + main_opt_name); + } + }; + + options_implies(OPTION_NUGET, + ret.nuget, + { + {OPTION_NUGET_ID, ret.maybe_nuget_id}, + {OPTION_NUGET_VERSION, ret.maybe_nuget_version}, + }); + + options_implies(OPTION_IFW, + ret.ifw, + { + {OPTION_IFW_REPOSITORY_URL, ret.ifw_options.maybe_repository_url}, + {OPTION_IFW_PACKAGES_DIR_PATH, ret.ifw_options.maybe_packages_dir_path}, + {OPTION_IFW_REPOSITORY_DIR_PATH, ret.ifw_options.maybe_repository_dir_path}, + {OPTION_IFW_CONFIG_FILE_PATH, ret.ifw_options.maybe_config_file_path}, + {OPTION_IFW_INSTALLER_FILE_PATH, ret.ifw_options.maybe_installer_file_path}, + }); + return ret; + } - const std::string export_id = create_export_id(); + static void print_next_step_info(const fs::path& prefix) + { + const fs::path cmake_toolchain = prefix / "scripts" / "buildsystems" / "vcpkg.cmake"; + const CMakeVariable cmake_variable = CMakeVariable(L"CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string()); + System::println("\n" + "To use the exported libraries in CMake projects use:" + "\n" + " %s" + "\n", + Strings::to_utf8(cmake_variable.s)); + }; + static void handle_raw_based_export(Span<const ExportPlanAction> export_plan, + const ExportArguments& opts, + const std::string& export_id, + const VcpkgPaths& paths) + { Files::Filesystem& fs = paths.get_filesystem(); const fs::path export_to_path = paths.root; const fs::path raw_exported_dir_path = export_to_path / export_id; @@ -329,6 +393,7 @@ namespace vcpkg::Commands::Export const BinaryParagraph& binary_paragraph = action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + const InstallDir dirs = InstallDir::from_destination_root( raw_exported_dir_path / "installed", action.spec.triplet().to_string(), @@ -339,52 +404,21 @@ namespace vcpkg::Commands::Export } // Copy files needed for integration - const std::vector<fs::path> integration_files_relative_to_root = { - {".vcpkg-root"}, - {fs::path{"scripts"} / "buildsystems" / "msbuild" / "applocal.ps1"}, - {fs::path{"scripts"} / "buildsystems" / "msbuild" / "vcpkg.targets"}, - {fs::path{"scripts"} / "buildsystems" / "vcpkg.cmake"}, - {fs::path{"scripts"} / "cmake" / "vcpkg_get_windows_sdk.cmake"}, - {fs::path{"scripts"} / "getWindowsSDK.ps1"}, - {fs::path{"scripts"} / "getProgramFilesPlatformBitness.ps1"}, - {fs::path{"scripts"} / "getProgramFiles32bit.ps1"}, - }; - - for (const fs::path& file : integration_files_relative_to_root) - { - const fs::path source = paths.root / file; - const fs::path destination = raw_exported_dir_path / file; - fs.create_directories(destination.parent_path(), ec); - Checks::check_exit(VCPKG_LINE_INFO, !ec); - fs.copy_file(source, destination, fs::copy_options::overwrite_existing, ec); - Checks::check_exit(VCPKG_LINE_INFO, !ec); - } + export_integration_files(raw_exported_dir_path, paths); - auto print_next_step_info = [](const fs::path& prefix) { - const fs::path cmake_toolchain = prefix / "scripts" / "buildsystems" / "vcpkg.cmake"; - const CMakeVariable cmake_variable = - CMakeVariable(L"CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string()); - System::println("\n" - "To use the exported libraries in CMake projects use:" - "\n" - " %s" - "\n", - Strings::to_utf8(cmake_variable.s)); - }; - - if (raw) + if (opts.raw) { System::println( System::Color::success, R"(Files exported at: "%s")", raw_exported_dir_path.generic_string()); print_next_step_info(export_to_path); } - if (nuget) + if (opts.nuget) { System::println("Creating nuget package... "); - const std::string nuget_id = maybe_nuget_id.value_or(raw_exported_dir_path.filename().string()); - const std::string nuget_version = maybe_nuget_version.value_or("1.0.0"); + const std::string nuget_id = opts.maybe_nuget_id.value_or(raw_exported_dir_path.filename().string()); + const std::string nuget_version = opts.maybe_nuget_version.value_or("1.0.0"); const fs::path output_path = do_nuget_export(paths, nuget_id, nuget_version, raw_exported_dir_path, export_to_path); System::println(System::Color::success, "Creating nuget package... done"); @@ -399,7 +433,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console output_path.parent_path().u8string()); } - if (zip) + if (opts.zip) { System::println("Creating zip archive... "); const fs::path output_path = @@ -409,20 +443,83 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console print_next_step_info("[...]"); } - if (_7zip) + if (opts.seven_zip) { System::println("Creating 7zip archive... "); const fs::path output_path = - do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::_7ZIP); + do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::SEVEN_ZIP); System::println(System::Color::success, "Creating 7zip archive... done"); System::println(System::Color::success, "7zip archive exported at: %s", output_path.generic_string()); print_next_step_info("[...]"); } - if (!raw) + if (!opts.raw) { fs.remove_all(raw_exported_dir_path, ec); } + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + { + const auto opts = handle_export_command_arguments(args, default_triplet); + for (auto&& spec : opts.specs) + Input::check_triplet(spec.triplet(), paths); + + // create the plan + const StatusParagraphs status_db = database_load_check(paths); + std::vector<ExportPlanAction> export_plan = Dependencies::create_export_plan(paths, opts.specs, status_db); + Checks::check_exit(VCPKG_LINE_INFO, !export_plan.empty(), "Export plan cannot be empty"); + + std::map<ExportPlanType, std::vector<const ExportPlanAction*>> group_by_plan_type; + Util::group_by(export_plan, &group_by_plan_type, [](const ExportPlanAction& p) { return p.plan_type; }); + print_plan(group_by_plan_type); + + const bool has_non_user_requested_packages = + Util::find_if(export_plan, [](const ExportPlanAction& package) -> bool { + return package.request_type != RequestType::USER_REQUESTED; + }) != export_plan.cend(); + + if (has_non_user_requested_packages) + { + System::println(System::Color::warning, + "Additional packages (*) need to be exported to complete this operation."); + } + + const auto it = group_by_plan_type.find(ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT); + if (it != group_by_plan_type.cend() && !it->second.empty()) + { + System::println(System::Color::error, "There are packages that have not been built."); + + // No need to show all of them, just the user-requested ones. Dependency resolution will handle the rest. + std::vector<const ExportPlanAction*> unbuilt = it->second; + Util::erase_remove_if( + unbuilt, [](const ExportPlanAction* a) { return a->request_type != RequestType::USER_REQUESTED; }); + + const auto s = Strings::join(" ", unbuilt, [](const ExportPlanAction* a) { return a->spec.to_string(); }); + System::println("To build them, run:\n" + " vcpkg install %s", + s); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + if (opts.dry_run) + { + Checks::exit_success(VCPKG_LINE_INFO); + } + + std::string export_id = create_export_id(); + + if (opts.raw || opts.nuget || opts.zip || opts.seven_zip) + { + handle_raw_based_export(export_plan, opts, export_id, paths); + } + + if (opts.ifw) + { + IFW::do_export(export_plan, export_id, opts.ifw_options, paths); + + print_next_step_info("@RootDir@/src/vcpkg"); + } Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/commands_export_ifw.cpp b/toolsrc/src/commands_export_ifw.cpp new file mode 100644 index 000000000..191dbb763 --- /dev/null +++ b/toolsrc/src/commands_export_ifw.cpp @@ -0,0 +1,481 @@ +#include "pch.h" + +#include "vcpkg_Commands.h" +#include "vcpkg_Commands_Export.h" +#include "vcpkg_Commands_Export_IFW.h" + +namespace vcpkg::Commands::Export::IFW +{ + using Dependencies::ExportPlanAction; + using Dependencies::ExportPlanType; + using Install::InstallDir; + + static std::string create_release_date() + { + const tm date_time = System::get_current_date_time(); + + // Format is: YYYY-mm-dd + // 10 characters + 1 null terminating character will be written for a total of 11 chars + char mbstr[11]; + const size_t bytes_written = std::strftime(mbstr, sizeof(mbstr), "%Y-%m-%d", &date_time); + Checks::check_exit(VCPKG_LINE_INFO, + bytes_written == 10, + "Expected 10 bytes to be written, but %u were written", + bytes_written); + const std::string date_time_as_string(mbstr); + return date_time_as_string; + } + + fs::path get_packages_dir_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + return ifw_options.maybe_packages_dir_path.has_value() + ? fs::path(ifw_options.maybe_packages_dir_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-packages"); + } + + fs::path get_repository_dir_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + return ifw_options.maybe_repository_dir_path.has_value() + ? fs::path(ifw_options.maybe_repository_dir_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-repository"); + } + + fs::path get_config_file_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + return ifw_options.maybe_config_file_path.has_value() + ? fs::path(ifw_options.maybe_config_file_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-configuration.xml"); + } + + fs::path get_installer_file_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + return ifw_options.maybe_installer_file_path.has_value() + ? fs::path(ifw_options.maybe_installer_file_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-installer.exe"); + } + + fs::path export_real_package(const fs::path& ifw_packages_dir_path, + const ExportPlanAction& action, + Files::Filesystem& fs) + { + std::error_code ec; + + const BinaryParagraph& binary_paragraph = + action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + + // Prepare meta dir + const fs::path package_xml_file_path = + ifw_packages_dir_path / + Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) / "meta" / + "package.xml"; + const fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + + auto deps = Strings::join( + ",", binary_paragraph.depends, [](const std::string& dep) { return "packages." + dep + ":"; }); + + if (!deps.empty()) deps = "\n <Dependencies>" + deps + "</Dependencies>"; + + fs.write_contents(package_xml_file_path, + Strings::format( + R"###(<?xml version="1.0"?> +<Package> + <DisplayName>%s</DisplayName> + <Version>%s</Version> + <ReleaseDate>%s</ReleaseDate> + <AutoDependOn>packages.%s:,triplets.%s:</AutoDependOn>%s + <Virtual>true</Virtual> +</Package> +)###", + action.spec.to_string(), + binary_paragraph.version, + create_release_date(), + action.spec.name(), + action.spec.triplet().canonical_name(), + deps)); + + // Return dir path for export package data + return ifw_packages_dir_path / + Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) / "data" / + "installed"; + } + + void export_unique_packages(const fs::path& raw_exported_dir_path, + std::map<std::string, const ExportPlanAction*> unique_packages, + Files::Filesystem& fs) + { + std::error_code ec; + + // packages + + fs::path package_xml_file_path = raw_exported_dir_path / "packages" / "meta" / "package.xml"; + fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + fs.write_contents(package_xml_file_path, + Strings::format( + R"###(<?xml version="1.0"?> +<Package> + <DisplayName>Packages</DisplayName> + <Version>1.0.0</Version> + <ReleaseDate>%s</ReleaseDate> +</Package> +)###", + create_release_date())); + + for (auto package = unique_packages.begin(); package != unique_packages.end(); ++package) + { + const ExportPlanAction& action = *(package->second); + const BinaryParagraph& binary_paragraph = + action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + + package_xml_file_path = + raw_exported_dir_path / Strings::format("packages.%s", package->first) / "meta" / "package.xml"; + package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + + fs.write_contents(package_xml_file_path, + Strings::format( + R"###(<?xml version="1.0"?> +<Package> + <DisplayName>%s</DisplayName> + <Description>%s</Description> + <Version>%s</Version> + <ReleaseDate>%s</ReleaseDate> +</Package> +)###", + action.spec.name(), + binary_paragraph.description, + binary_paragraph.version, + create_release_date())); + } + } + + void export_unique_triplets(const fs::path& raw_exported_dir_path, + std::set<std::string> unique_triplets, + Files::Filesystem& fs) + { + std::error_code ec; + + // triplets + + fs::path package_xml_file_path = raw_exported_dir_path / "triplets" / "meta" / "package.xml"; + fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + fs.write_contents(package_xml_file_path, + Strings::format( + R"###(<?xml version="1.0"?> +<Package> + <DisplayName>Triplets</DisplayName> + <Version>1.0.0</Version> + <ReleaseDate>%s</ReleaseDate> +</Package> +)###", + create_release_date())); + + for (const std::string& triplet : unique_triplets) + { + package_xml_file_path = + raw_exported_dir_path / Strings::format("triplets.%s", triplet) / "meta" / "package.xml"; + package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + fs.write_contents(package_xml_file_path, + Strings::format( + R"###(<?xml version="1.0"?> +<Package> + <DisplayName>%s</DisplayName> + <Version>1.0.0</Version> + <ReleaseDate>%s</ReleaseDate> +</Package> +)###", + triplet, + create_release_date())); + } + } + + void export_integration(const fs::path& raw_exported_dir_path, Files::Filesystem& fs) + { + std::error_code ec; + + // integration + fs::path package_xml_file_path = raw_exported_dir_path / "integration" / "meta" / "package.xml"; + fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + + fs.write_contents(package_xml_file_path, + Strings::format( + R"###(<?xml version="1.0"?> +<Package> + <DisplayName>Integration</DisplayName> + <Version>1.0.0</Version> + <ReleaseDate>%s</ReleaseDate> +</Package> +)###", + create_release_date())); + } + + void export_config(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + std::error_code ec; + Files::Filesystem& fs = paths.get_filesystem(); + + const fs::path config_xml_file_path = get_config_file_path(export_id, ifw_options, paths); + + fs::path config_xml_dir_path = config_xml_file_path.parent_path(); + fs.create_directories(config_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for configuration file %s", + config_xml_file_path.generic_string()); + + std::string formatted_repo_url; + std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or(""); + if (!ifw_repo_url.empty()) + { + formatted_repo_url = Strings::format(R"###( + <RemoteRepositories> + <Repository> + <Url>%s</Url> + </Repository> + </RemoteRepositories>)###", + ifw_repo_url); + } + + fs.write_contents(config_xml_file_path, + Strings::format( + R"###(<?xml version="1.0"?> +<Installer> + <Name>vcpkg</Name> + <Version>1.0.0</Version> + <StartMenuDir>vcpkg</StartMenuDir> + <TargetDir>@RootDir@/src/vcpkg</TargetDir>%s +</Installer> +)###", + formatted_repo_url)); + } + + void export_maintenance_tool(const fs::path& ifw_packages_dir_path, const VcpkgPaths& paths) + { + System::println("Exporting maintenance tool... "); + + std::error_code ec; + Files::Filesystem& fs = paths.get_filesystem(); + + const fs::path& installerbase_exe = paths.get_ifw_installerbase_exe(); + fs::path tempmaintenancetool = ifw_packages_dir_path / "maintenance" / "data" / "tempmaintenancetool.exe"; + fs.create_directories(tempmaintenancetool.parent_path(), ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + tempmaintenancetool.generic_string()); + fs.copy_file(installerbase_exe, tempmaintenancetool, fs::copy_options::overwrite_existing, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not write package file %s", tempmaintenancetool.generic_string()); + + fs::path package_xml_file_path = ifw_packages_dir_path / "maintenance" / "meta" / "package.xml"; + fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + fs.write_contents(package_xml_file_path, + Strings::format( + R"###(<?xml version="1.0"?> +<Package> + <DisplayName>Maintenance Tool</DisplayName> + <Description>Maintenance Tool</Description> + <Version>1.0.0</Version> + <ReleaseDate>%s</ReleaseDate> + <Script>maintenance.qs</Script> + <Essential>true</Essential> + <Virtual>true</Virtual> + <ForcedInstallation>true</ForcedInstallation> +</Package> +)###", + create_release_date())); + const fs::path script_source = paths.root / "scripts" / "ifw" / "maintenance.qs"; + const fs::path script_destination = ifw_packages_dir_path / "maintenance" / "meta" / "maintenance.qs"; + fs.copy_file(script_source, script_destination, fs::copy_options::overwrite_existing, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not write package file %s", script_destination.generic_string()); + + System::println("Exporting maintenance tool... done"); + } + + void do_repository(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + const fs::path& repogen_exe = paths.get_ifw_repogen_exe(); + const fs::path packages_dir = get_packages_dir_path(export_id, ifw_options, paths); + const fs::path repository_dir = get_repository_dir_path(export_id, ifw_options, paths); + + System::println("Generating repository %s...", repository_dir.generic_string()); + + std::error_code ec; + Files::Filesystem& fs = paths.get_filesystem(); + + fs.remove_all(repository_dir, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not remove outdated repository directory %s", repository_dir.generic_string()); + + const std::wstring cmd_line = Strings::wformat(LR"("%s" --packages "%s" "%s" > nul)", + repogen_exe.native(), + packages_dir.native(), + repository_dir.native()); + + const int exit_code = System::cmd_execute_clean(cmd_line); + Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: IFW repository generating failed"); + + System::println(System::Color::success, "Generating repository %s... done.", repository_dir.generic_string()); + } + + void do_installer(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + const fs::path& binarycreator_exe = paths.get_ifw_binarycreator_exe(); + const fs::path config_file = get_config_file_path(export_id, ifw_options, paths); + const fs::path packages_dir = get_packages_dir_path(export_id, ifw_options, paths); + const fs::path repository_dir = get_repository_dir_path(export_id, ifw_options, paths); + const fs::path installer_file = get_installer_file_path(export_id, ifw_options, paths); + + System::println("Generating installer %s...", installer_file.generic_string()); + + std::wstring cmd_line; + + std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or(""); + if (!ifw_repo_url.empty()) + { + cmd_line = Strings::wformat(LR"("%s" --online-only --config "%s" --repository "%s" "%s" > nul)", + binarycreator_exe.native(), + config_file.native(), + repository_dir.native(), + installer_file.native()); + } + else + { + cmd_line = Strings::wformat(LR"("%s" --config "%s" --packages "%s" "%s" > nul)", + binarycreator_exe.native(), + config_file.native(), + packages_dir.native(), + installer_file.native()); + } + + const int exit_code = System::cmd_execute_clean(cmd_line); + Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: IFW installer generating failed"); + + System::println(System::Color::success, "Generating installer %s... done.", installer_file.generic_string()); + } + + void do_export(const std::vector<ExportPlanAction>& export_plan, + const std::string& export_id, + const Options& ifw_options, + const VcpkgPaths& paths) + { + std::error_code ec; + Files::Filesystem& fs = paths.get_filesystem(); + + // Prepare packages directory + const fs::path ifw_packages_dir_path = get_packages_dir_path(export_id, ifw_options, paths); + + fs.remove_all(ifw_packages_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not remove outdated packages directory %s", + ifw_packages_dir_path.generic_string()); + + fs.create_directory(ifw_packages_dir_path, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not create packages directory %s", ifw_packages_dir_path.generic_string()); + + // Export maintenance tool + export_maintenance_tool(ifw_packages_dir_path, paths); + + System::println("Exporting packages %s... ", ifw_packages_dir_path.generic_string()); + + // execute the plan + std::map<std::string, const ExportPlanAction*> unique_packages; + std::set<std::string> unique_triplets; + for (const ExportPlanAction& action : export_plan) + { + if (action.plan_type != ExportPlanType::ALREADY_BUILT) + { + Checks::unreachable(VCPKG_LINE_INFO); + } + + const std::string display_name = action.spec.to_string(); + System::println("Exporting package %s... ", display_name); + + const BinaryParagraph& binary_paragraph = + action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + + unique_packages[action.spec.name()] = &action; + unique_triplets.insert(action.spec.triplet().canonical_name()); + + // Export real package and return data dir for installation + fs::path ifw_package_dir_path = export_real_package(ifw_packages_dir_path, action, fs); + + // Copy package data + const InstallDir dirs = InstallDir::from_destination_root(ifw_package_dir_path, + action.spec.triplet().to_string(), + ifw_package_dir_path / "vcpkg" / "info" / + (binary_paragraph.fullstem() + ".list")); + + Install::install_files_and_write_listfile(paths.get_filesystem(), paths.package_dir(action.spec), dirs); + System::println("Exporting package %s... done", display_name); + } + + System::println("Exporting packages %s... done", ifw_packages_dir_path.generic_string()); + + const fs::path config_file = get_config_file_path(export_id, ifw_options, paths); + + System::println("Generating configuration %s...", config_file.generic_string()); + + // Unique packages + export_unique_packages(ifw_packages_dir_path, unique_packages, fs); + + // Unique triplets + export_unique_triplets(ifw_packages_dir_path, unique_triplets, fs); + + // Copy files needed for integration + export_integration_files(ifw_packages_dir_path / "integration" / "data", paths); + // Integration + export_integration(ifw_packages_dir_path, fs); + + // Configuration + export_config(export_id, ifw_options, paths); + + System::println("Generating configuration %s... done.", config_file.generic_string()); + + // Do repository (optional) + std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or(""); + if (!ifw_repo_url.empty()) + { + do_repository(export_id, ifw_options, paths); + } + + // Do installer + do_installer(export_id, ifw_options, paths); + } +} diff --git a/toolsrc/src/commands_hash.cpp b/toolsrc/src/commands_hash.cpp index 0da2b031f..b3211b9f8 100644 --- a/toolsrc/src/commands_hash.cpp +++ b/toolsrc/src/commands_hash.cpp @@ -6,22 +6,22 @@ namespace vcpkg::Commands::Hash { - static void do_file_hash(fs::path const& path, std::wstring const& hashType) + static void do_file_hash(fs::path const& path, std::wstring const& hash_type) { - auto cmd_line = Strings::wformat(LR"(CertUtil.exe -hashfile "%s" %s)", path.c_str(), hashType); - auto ec_data = System::cmd_execute_and_capture_output(cmd_line); + const auto cmd_line = Strings::wformat(LR"(CertUtil.exe -hashfile "%s" %s)", path.c_str(), hash_type); + const auto ec_data = System::cmd_execute_and_capture_output(cmd_line); Checks::check_exit( VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", Strings::to_utf8(cmd_line)); std::string const& output = ec_data.output; - auto start = output.find_first_of("\r\n"); + const auto start = output.find_first_of("\r\n"); Checks::check_exit(VCPKG_LINE_INFO, start != std::string::npos, "Unexpected output format from command: %s", Strings::to_utf8(cmd_line)); - auto end = output.find_first_of("\r\n", start + 1); + const auto end = output.find_first_of("\r\n", start + 1); Checks::check_exit(VCPKG_LINE_INFO, end != std::string::npos, "Unexpected output format from command: %s", @@ -34,11 +34,11 @@ namespace vcpkg::Commands::Hash void perform_and_exit(const VcpkgCmdArguments& args) { - static const std::string example = + static const std::string EXAMPLE = Strings::format("The argument should be a file path\n%s", Commands::Help::create_example_string("hash boost_1_62_0.tar.bz2")); - args.check_min_arg_count(1, example); - args.check_max_arg_count(2, example); + args.check_min_arg_count(1, EXAMPLE); + args.check_max_arg_count(2, EXAMPLE); args.check_and_get_optional_command_arguments({}); if (args.command_arguments.size() == 1) diff --git a/toolsrc/src/commands_import.cpp b/toolsrc/src/commands_import.cpp index 5db1885b2..412a03d7f 100644 --- a/toolsrc/src/commands_import.cpp +++ b/toolsrc/src/commands_import.cpp @@ -28,7 +28,7 @@ namespace vcpkg::Commands::Import for (auto&& file : files) { if (fs.is_directory(file)) continue; - auto ext = file.extension(); + const auto ext = file.extension(); if (ext == ".dll") binaries.dlls.push_back(std::move(file)); else if (ext == ".lib") @@ -46,7 +46,7 @@ namespace vcpkg::Commands::Import for (auto const& src_path : files) { - fs::path dest_path = destination_folder / src_path.filename(); + const fs::path dest_path = destination_folder / src_path.filename(); fs.copy(src_path, dest_path, fs::copy_options::overwrite_existing); } } @@ -59,10 +59,10 @@ namespace vcpkg::Commands::Import check_is_directory(VCPKG_LINE_INFO, fs, include_directory); check_is_directory(VCPKG_LINE_INFO, fs, project_directory); check_is_directory(VCPKG_LINE_INFO, fs, destination_path); - Binaries debug_binaries = find_binaries_in_dir(fs, project_directory / "Debug"); - Binaries release_binaries = find_binaries_in_dir(fs, project_directory / "Release"); + const Binaries debug_binaries = find_binaries_in_dir(fs, project_directory / "Debug"); + const Binaries release_binaries = find_binaries_in_dir(fs, project_directory / "Release"); - fs::path destination_include_directory = destination_path / "include"; + const fs::path destination_include_directory = destination_path / "include"; fs.copy(include_directory, destination_include_directory, fs::copy_options::recursive | fs::copy_options::overwrite_existing); @@ -82,20 +82,20 @@ namespace vcpkg::Commands::Import const BinaryParagraph& control_file_data) { auto& fs = paths.get_filesystem(); - fs::path library_destination_path = paths.package_dir(control_file_data.spec); + const fs::path library_destination_path = paths.package_dir(control_file_data.spec); std::error_code ec; fs.create_directory(library_destination_path, ec); place_library_files_in(paths.get_filesystem(), include_directory, project_directory, library_destination_path); - fs::path control_file_path = library_destination_path / "CONTROL"; + const fs::path control_file_path = library_destination_path / "CONTROL"; fs.write_contents(control_file_path, Strings::serialize(control_file_data)); } void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = Commands::Help::create_example_string( + static const std::string EXAMPLE = Commands::Help::create_example_string( R"(import C:\path\to\CONTROLfile C:\path\to\includedir C:\path\to\projectdir)"); - args.check_exact_arg_count(3, example); + args.check_exact_arg_count(3, EXAMPLE); args.check_and_get_optional_command_arguments({}); const fs::path control_file_path(args.command_arguments[0]); diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index a2e95eb48..4411dd3ae 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -59,7 +59,7 @@ namespace vcpkg::Commands::Install auto files = fs.get_files_recursive(source_dir); for (auto&& file : files) { - auto status = fs.status(file, ec); + const auto status = fs.status(file, ec); if (ec) { System::println(System::Color::error, "failed: %s: %s", file.u8string(), ec.message()); @@ -199,7 +199,7 @@ namespace vcpkg::Commands::Install bcf.core_paragraph.spec); System::print("\n "); System::println(Strings::join("\n ", intersection)); - System::println(""); + System::println(); return InstallResult::FILE_CONFLICTS; } @@ -309,7 +309,7 @@ namespace vcpkg::Commands::Install const BinaryControlFile bcf = Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO); System::println("Installing package %s... ", display_name_with_features); - 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: @@ -328,7 +328,7 @@ namespace vcpkg::Commands::Install System::Color::warning, "Package %s is already built -- not building from HEAD", display_name); } System::println("Installing package %s... ", display_name); - auto install_result = install_package( + const auto install_result = install_package( paths, action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO), &status_db); switch (install_result) { @@ -442,20 +442,101 @@ namespace vcpkg::Commands::Install } } + void perform_and_exit(const std::vector<AnyAction>& action_plan, + const Build::BuildPackageOptions& install_plan_options, + const KeepGoing keep_going, + const PrintSummary print_summary, + const VcpkgPaths& paths, + StatusParagraphs& status_db) + { + std::vector<BuildResult> results; + std::vector<std::string> timing; + const ElapsedTime timer = ElapsedTime::create_started(); + size_t counter = 0; + const size_t package_count = action_plan.size(); + + for (const auto& action : action_plan) + { + const ElapsedTime build_timer = ElapsedTime::create_started(); + counter++; + + const std::string display_name = action.spec().to_string(); + System::println("Starting package %d/%d: %s", counter, package_count, display_name); + + timing.push_back("0"); + results.push_back(BuildResult::NULLVALUE); + + if (const auto install_action = action.install_plan.get()) + { + const BuildResult result = + perform_install_plan_action(paths, *install_action, install_plan_options, status_db); + if (result != 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; + } + else if (const auto remove_action = action.remove_plan.get()) + { + Checks::check_exit(VCPKG_LINE_INFO, GlobalState::feature_packages); + Remove::perform_remove_plan_action(paths, *remove_action, Remove::Purge::YES, status_db); + } + else + { + Checks::unreachable(VCPKG_LINE_INFO); + } + + timing.back() = build_timer.to_string(); + System::println("Elapsed time for package %s: %s", display_name, build_timer.to_string()); + } + + System::println("Total time taken: %s", timer.to_string()); + + if (print_summary == PrintSummary::YES) + { + for (size_t i = 0; i < results.size(); i++) + { + System::println("%s: %s: %s", action_plan[i].spec(), Build::to_string(results[i]), timing[i]); + } + + std::map<BuildResult, int> summary; + for (const BuildResult& v : Build::BUILD_RESULT_VALUES) + { + summary[v] = 0; + } + + for (const BuildResult& r : results) + { + summary[r]++; + } + + System::println("\n\nSUMMARY"); + for (const std::pair<const BuildResult, int>& entry : summary) + { + System::println(" %s: %d", Build::to_string(entry.first), entry.second); + } + } + + Checks::exit_success(VCPKG_LINE_INFO); + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { static const std::string OPTION_DRY_RUN = "--dry-run"; static const std::string OPTION_USE_HEAD_VERSION = "--head"; static const std::string OPTION_NO_DOWNLOADS = "--no-downloads"; static const std::string OPTION_RECURSE = "--recurse"; + static const std::string OPTION_KEEP_GOING = "--keep-going"; // input sanitization - static const std::string example = + static const std::string EXAMPLE = Commands::Help::create_example_string("install zlib zlib:x64-windows curl boost"); - args.check_min_arg_count(1, example); + args.check_min_arg_count(1, EXAMPLE); const std::vector<FullPackageSpec> specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_full_package_spec(arg, default_triplet, example); + return Input::check_and_get_full_package_spec(arg, default_triplet, EXAMPLE); }); for (auto&& spec : specs) @@ -469,11 +550,13 @@ namespace vcpkg::Commands::Install } const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments( - {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS, OPTION_RECURSE}); - const bool dryRun = options.find(OPTION_DRY_RUN) != options.cend(); + {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS, OPTION_RECURSE, OPTION_KEEP_GOING}); + const bool dry_run = options.find(OPTION_DRY_RUN) != options.cend(); const bool use_head_version = options.find(OPTION_USE_HEAD_VERSION) != options.cend(); const bool no_downloads = options.find(OPTION_NO_DOWNLOADS) != options.cend(); const bool is_recursive = options.find(OPTION_RECURSE) != options.cend(); + const KeepGoing keep_going = to_keep_going(options.find(OPTION_KEEP_GOING) != options.cend()); + const PrintSummary print_summary = to_print_summary(keep_going == KeepGoing::YES); // create the plan StatusParagraphs status_db = database_load_check(paths); @@ -486,8 +569,8 @@ namespace vcpkg::Commands::Install if (GlobalState::feature_packages) { std::unordered_map<std::string, SourceControlFile> scf_map; - auto all_ports = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); - for (auto&& port : all_ports.paragraphs) + auto all_ports = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); + for (auto&& port : all_ports) { scf_map[port->core_paragraph->name] = std::move(*port); } @@ -519,78 +602,12 @@ namespace vcpkg::Commands::Install print_plan(action_plan, is_recursive); - if (dryRun) + if (dry_run) { Checks::exit_success(VCPKG_LINE_INFO); } - // execute the plan - if (GlobalState::feature_packages) - { - for (const auto& action : action_plan) - { - if (auto install_action = action.install_plan.get()) - { - const BuildResult result = - perform_install_plan_action(paths, *install_action, install_plan_options, status_db); - if (result != BuildResult::SUCCEEDED) - { - System::println(Build::create_user_troubleshooting_message(install_action->spec)); - Checks::exit_fail(VCPKG_LINE_INFO); - } - } - else if (auto remove_action = action.remove_plan.get()) - { - static const std::string OPTION_PURGE = "--purge"; - static const std::string OPTION_NO_PURGE = "--no-purge"; - - const bool alsoRemoveFolderFromPackages = options.find(OPTION_NO_PURGE) == options.end(); - if (options.find(OPTION_PURGE) != options.end() && !alsoRemoveFolderFromPackages) - { - // User specified --purge and --no-purge - System::println(System::Color::error, "Error: cannot specify both --no-purge and --purge."); - System::print(example); - Checks::exit_fail(VCPKG_LINE_INFO); - } - const std::string display_name = remove_action->spec.to_string(); - switch (remove_action->plan_type) - { - case RemovePlanType::NOT_INSTALLED: - System::println(System::Color::success, "Package %s is not installed", display_name); - break; - case RemovePlanType::REMOVE: - System::println("Removing package %s... ", display_name); - Commands::Remove::remove_package(paths, remove_action->spec, &status_db); - System::println(System::Color::success, "Removing package %s... done", display_name); - break; - case RemovePlanType::UNKNOWN: - default: Checks::unreachable(VCPKG_LINE_INFO); - } - - if (alsoRemoveFolderFromPackages) - { - System::println("Purging package %s... ", display_name); - Files::Filesystem& fs = paths.get_filesystem(); - std::error_code ec; - fs.remove_all(paths.packages / remove_action->spec.dir(), ec); - System::println(System::Color::success, "Purging package %s... done", display_name); - } - } - } - } - else - { - for (const auto& action : action_plan) - { - const auto& iaction = action.install_plan.value_or_exit(VCPKG_LINE_INFO); - const BuildResult result = perform_install_plan_action(paths, iaction, install_plan_options, status_db); - if (result != BuildResult::SUCCEEDED) - { - System::println(Build::create_user_troubleshooting_message(iaction.spec)); - Checks::exit_fail(VCPKG_LINE_INFO); - } - } - } + perform_and_exit(action_plan, install_plan_options, keep_going, print_summary, paths, status_db); Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/commands_integrate.cpp b/toolsrc/src/commands_integrate.cpp index c5942f9fc..fd2f11294 100644 --- a/toolsrc/src/commands_integrate.cpp +++ b/toolsrc/src/commands_integrate.cpp @@ -8,11 +8,11 @@ namespace vcpkg::Commands::Integrate { - static const std::array<fs::path, 2> old_system_target_files = { - System::get_ProgramFiles_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets", - System::get_ProgramFiles_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets"}; - static const fs::path system_wide_targets_file = - System::get_ProgramFiles_32_bit() / "MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props"; + static const std::array<fs::path, 2> OLD_SYSTEM_TARGET_FILES = { + System::get_program_files_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets", + System::get_program_files_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets"}; + static const fs::path SYSTEM_WIDE_TARGETS_FILE = + System::get_program_files_32_bit() / "MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props"; static std::string create_appdata_targets_shortcut(const std::string& target_path) noexcept { @@ -82,7 +82,7 @@ namespace vcpkg::Commands::Integrate const std::string& nuget_id, const std::string& nupkg_version) { - static constexpr auto content_template = R"( + static constexpr auto CONTENT_TEMPLATE = R"( <package> <metadata> <id>@NUGET_ID@</id> @@ -99,7 +99,7 @@ namespace vcpkg::Commands::Integrate </package> )"; - std::string content = std::regex_replace(content_template, std::regex("@NUGET_ID@"), nuget_id); + std::string content = std::regex_replace(CONTENT_TEMPLATE, std::regex("@NUGET_ID@"), nuget_id); content = std::regex_replace(content, std::regex("@VCPKG_DIR@"), vcpkg_root_dir.string()); content = std::regex_replace(content, std::regex("@VERSION@"), nupkg_version); return content; @@ -113,36 +113,37 @@ namespace vcpkg::Commands::Integrate static ElevationPromptChoice elevated_cmd_execute(const std::string& param) { - SHELLEXECUTEINFO shExInfo = {0}; - shExInfo.cbSize = sizeof(shExInfo); - shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS; - shExInfo.hwnd = nullptr; - shExInfo.lpVerb = "runas"; - shExInfo.lpFile = "cmd"; // Application to start - - shExInfo.lpParameters = param.c_str(); // Additional parameters - shExInfo.lpDirectory = nullptr; - shExInfo.nShow = SW_HIDE; - shExInfo.hInstApp = nullptr; - - if (!ShellExecuteExA(&shExInfo)) + SHELLEXECUTEINFOW sh_ex_info = {0}; + sh_ex_info.cbSize = sizeof(sh_ex_info); + sh_ex_info.fMask = SEE_MASK_NOCLOSEPROCESS; + sh_ex_info.hwnd = nullptr; + sh_ex_info.lpVerb = L"runas"; + sh_ex_info.lpFile = L"cmd"; // Application to start + + auto wparam = Strings::to_utf16(param); + sh_ex_info.lpParameters = wparam.c_str(); // Additional parameters + sh_ex_info.lpDirectory = nullptr; + sh_ex_info.nShow = SW_HIDE; + sh_ex_info.hInstApp = nullptr; + + if (!ShellExecuteExW(&sh_ex_info)) { return ElevationPromptChoice::NO; } - if (shExInfo.hProcess == nullptr) + if (sh_ex_info.hProcess == nullptr) { return ElevationPromptChoice::NO; } - WaitForSingleObject(shExInfo.hProcess, INFINITE); - CloseHandle(shExInfo.hProcess); + WaitForSingleObject(sh_ex_info.hProcess, INFINITE); + CloseHandle(sh_ex_info.hProcess); return ElevationPromptChoice::YES; } static fs::path get_appdata_targets_path() { - static const fs::path local_app_data = + static const fs::path LOCAL_APP_DATA = fs::path(System::get_environment_variable(L"LOCALAPPDATA").value_or_exit(VCPKG_LINE_INFO)); - return local_app_data / "vcpkg" / "vcpkg.user.targets"; + return LOCAL_APP_DATA / "vcpkg" / "vcpkg.user.targets"; } static void integrate_install(const VcpkgPaths& paths) @@ -150,13 +151,13 @@ namespace vcpkg::Commands::Integrate auto& fs = paths.get_filesystem(); // TODO: This block of code should eventually be removed - for (auto&& old_system_wide_targets_file : old_system_target_files) + for (auto&& old_system_wide_targets_file : OLD_SYSTEM_TARGET_FILES) { if (fs.exists(old_system_wide_targets_file)) { const std::string param = Strings::format(R"(/c DEL "%s" /Q > nul)", old_system_wide_targets_file.string()); - ElevationPromptChoice user_choice = elevated_cmd_execute(param); + const ElevationPromptChoice user_choice = elevated_cmd_execute(param); switch (user_choice) { case ElevationPromptChoice::YES: break; @@ -174,15 +175,15 @@ namespace vcpkg::Commands::Integrate fs.create_directory(tmp_dir, ec); bool should_install_system = true; - const Expected<std::string> system_wide_file_contents = fs.read_contents(system_wide_targets_file); - if (auto contents_data = system_wide_file_contents.get()) + const Expected<std::string> system_wide_file_contents = fs.read_contents(SYSTEM_WIDE_TARGETS_FILE); + static const std::regex RE(R"###(<!-- version (\d+) -->)###"); + if (const auto contents_data = system_wide_file_contents.get()) { - std::regex re(R"###(<!-- version (\d+) -->)###"); std::match_results<std::string::const_iterator> match; - auto found = std::regex_search(*contents_data, match, re); + const auto found = std::regex_search(*contents_data, match, RE); if (found) { - int ver = atoi(match[1].str().c_str()); + const int ver = atoi(match[1].str().c_str()); if (ver >= 1) should_install_system = false; } } @@ -193,10 +194,10 @@ namespace vcpkg::Commands::Integrate fs.write_contents(sys_src_path, create_system_targets_shortcut()); const std::string param = Strings::format(R"(/c mkdir "%s" & copy "%s" "%s" /Y > nul)", - system_wide_targets_file.parent_path().string(), + SYSTEM_WIDE_TARGETS_FILE.parent_path().string(), sys_src_path.string(), - system_wide_targets_file.string()); - ElevationPromptChoice user_choice = elevated_cmd_execute(param); + SYSTEM_WIDE_TARGETS_FILE.string()); + const ElevationPromptChoice user_choice = elevated_cmd_execute(param); switch (user_choice) { case ElevationPromptChoice::YES: break; @@ -207,9 +208,9 @@ namespace vcpkg::Commands::Integrate } Checks::check_exit(VCPKG_LINE_INFO, - fs.exists(system_wide_targets_file), + fs.exists(SYSTEM_WIDE_TARGETS_FILE), "Error: failed to copy targets file to %s", - system_wide_targets_file.string()); + SYSTEM_WIDE_TARGETS_FILE.string()); } const fs::path appdata_src_path = tmp_dir / "vcpkg.user.targets"; @@ -217,7 +218,7 @@ namespace vcpkg::Commands::Integrate create_appdata_targets_shortcut(paths.buildsystems_msbuild_targets.string())); auto appdata_dst_path = get_appdata_targets_path(); - auto rc = fs.copy_file(appdata_src_path, appdata_dst_path, fs::copy_options::overwrite_existing, ec); + const auto rc = fs.copy_file(appdata_src_path, appdata_dst_path, fs::copy_options::overwrite_existing, ec); if (!rc || ec) { @@ -245,7 +246,7 @@ namespace vcpkg::Commands::Integrate const fs::path path = get_appdata_targets_path(); std::error_code ec; - bool was_deleted = fs.remove(path, ec); + const bool was_deleted = fs.remove(path, ec); Checks::check_exit(VCPKG_LINE_INFO, !ec, "Error: Unable to remove user-wide integration: %d", ec.message()); @@ -317,10 +318,10 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = Strings::format("Commands:\n" + static const std::string EXAMPLE = Strings::format("Commands:\n" "%s", INTEGRATE_COMMAND_HELPSTRING); - args.check_exact_arg_count(1, example); + args.check_exact_arg_count(1, EXAMPLE); args.check_and_get_optional_command_arguments({}); if (args.command_arguments[0] == "install") diff --git a/toolsrc/src/commands_list.cpp b/toolsrc/src/commands_list.cpp index 3cfa7e184..640885860 100644 --- a/toolsrc/src/commands_list.cpp +++ b/toolsrc/src/commands_list.cpp @@ -8,9 +8,9 @@ namespace vcpkg::Commands::List { static const std::string OPTION_FULLDESC = "--x-full-desc"; // TODO: This should find a better home, eventually - static void do_print(const StatusParagraph& pgh, bool FullDesc) + static void do_print(const StatusParagraph& pgh, bool full_desc) { - if (FullDesc) + if (full_desc) { System::println("%-30s %-16s %s", pgh.package.displayname(), pgh.package.version, pgh.package.description); } @@ -25,10 +25,10 @@ namespace vcpkg::Commands::List void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = Strings::format( + static const std::string EXAMPLE = Strings::format( "The argument should be a substring to search for, or no argument to display all installed libraries.\n%s", Commands::Help::create_example_string("list png")); - args.check_max_arg_count(1, example); + args.check_max_arg_count(1, EXAMPLE); const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({OPTION_FULLDESC}); diff --git a/toolsrc/src/commands_owns.cpp b/toolsrc/src/commands_owns.cpp index 757292e96..718a0277f 100644 --- a/toolsrc/src/commands_owns.cpp +++ b/toolsrc/src/commands_owns.cpp @@ -25,9 +25,9 @@ namespace vcpkg::Commands::Owns void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = Strings::format("The argument should be a pattern to search for. %s", + static const std::string EXAMPLE = Strings::format("The argument should be a pattern to search for. %s", Commands::Help::create_example_string("owns zlib.dll")); - args.check_exact_arg_count(1, example); + args.check_exact_arg_count(1, EXAMPLE); args.check_and_get_optional_command_arguments({}); StatusParagraphs status_db = database_load_check(paths); diff --git a/toolsrc/src/commands_portsdiff.cpp b/toolsrc/src/commands_portsdiff.cpp index 83d62896f..2334b2270 100644 --- a/toolsrc/src/commands_portsdiff.cpp +++ b/toolsrc/src/commands_portsdiff.cpp @@ -2,7 +2,6 @@ #include "Paragraphs.h" #include "SortedVector.h" -#include "SourceParagraph.h" #include "vcpkg_Commands.h" #include "vcpkg_Maps.h" #include "vcpkg_System.h" @@ -69,7 +68,7 @@ namespace vcpkg::Commands::PortsDiff for (const std::string& name : ports_to_print) { const VersionT& version = names_and_versions.at(name); - System::println("%-20s %-16s", name, version); + System::println(" - %-14s %-16s", name, version); } } @@ -117,11 +116,11 @@ namespace vcpkg::Commands::PortsDiff void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = + static const std::string EXAMPLE = Strings::format("The argument should be a branch/tag/hash to checkout.\n%s", Commands::Help::create_example_string("portsdiff mybranchname")); - args.check_min_arg_count(1, example); - args.check_max_arg_count(2, example); + args.check_min_arg_count(1, EXAMPLE); + args.check_max_arg_count(2, EXAMPLE); args.check_and_get_optional_command_arguments({}); const fs::path& git_exe = paths.get_git_exe(); @@ -139,8 +138,8 @@ namespace vcpkg::Commands::PortsDiff read_ports_from_commit(paths, git_commit_id_for_previous_snapshot); // Already sorted, so set_difference can work on std::vector too - std::vector<std::string> current_ports = Maps::extract_keys(current_names_and_versions); - std::vector<std::string> previous_ports = Maps::extract_keys(previous_names_and_versions); + const std::vector<std::string> current_ports = Maps::extract_keys(current_names_and_versions); + const std::vector<std::string> previous_ports = Maps::extract_keys(previous_names_and_versions); const SetElementPresence<std::string> setp = SetElementPresence<std::string>::create(current_ports, previous_ports); @@ -148,14 +147,14 @@ namespace vcpkg::Commands::PortsDiff const std::vector<std::string>& added_ports = setp.only_left; if (!added_ports.empty()) { - System::println("\nThe following %d ports were added:\n", added_ports.size()); + System::println("\nThe following %d ports were added:", added_ports.size()); do_print_name_and_version(added_ports, current_names_and_versions); } const std::vector<std::string>& removed_ports = setp.only_right; if (!removed_ports.empty()) { - System::println("\nThe following %d ports were removed:\n", removed_ports.size()); + System::println("\nThe following %d ports were removed:", removed_ports.size()); do_print_name_and_version(removed_ports, previous_names_and_versions); } @@ -165,10 +164,10 @@ namespace vcpkg::Commands::PortsDiff if (!updated_ports.empty()) { - System::println("\nThe following %d ports were updated:\n", updated_ports.size()); + System::println("\nThe following %d ports were updated:", updated_ports.size()); for (const UpdatedPort& p : updated_ports) { - System::println("%-20s %-16s", p.port, p.version_diff.to_string()); + System::println(" - %-14s %-16s", p.port, p.version_diff.to_string()); } } diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp index db5357514..a9f1b2564 100644 --- a/toolsrc/src/commands_remove.cpp +++ b/toolsrc/src/commands_remove.cpp @@ -18,7 +18,7 @@ namespace vcpkg::Commands::Remove { auto& fs = paths.get_filesystem(); auto spghs = status_db->find_all(spec.name(), spec.triplet()); - auto core_pkg = **status_db->find(spec.name(), spec.triplet(), ""); + const auto core_pkg = **status_db->find(spec.name(), spec.triplet(), Strings::EMPTY); for (auto&& spgh : spghs) { @@ -31,7 +31,7 @@ namespace vcpkg::Commands::Remove auto maybe_lines = fs.read_lines(paths.listfile_path(core_pkg.package)); - if (auto lines = maybe_lines.get()) + if (const auto lines = maybe_lines.get()) { std::vector<fs::path> dirs_touched; for (auto&& suffix : *lines) @@ -42,7 +42,7 @@ namespace vcpkg::Commands::Remove auto target = paths.installed / suffix; - auto status = fs.status(target, ec); + const auto status = fs.status(target, ec); if (ec) { System::println(System::Color::error, "failed: %s", ec.message()); @@ -72,7 +72,7 @@ namespace vcpkg::Commands::Remove } auto b = dirs_touched.rbegin(); - auto e = dirs_touched.rend(); + const auto e = dirs_touched.rend(); for (; b != e; ++b) { if (fs.is_empty(*b)) @@ -100,11 +100,11 @@ namespace vcpkg::Commands::Remove static void print_plan(const std::map<RemovePlanType, std::vector<const RemovePlanAction*>>& group_by_plan_type) { - static constexpr std::array<RemovePlanType, 2> order = {RemovePlanType::NOT_INSTALLED, RemovePlanType::REMOVE}; + static constexpr std::array<RemovePlanType, 2> ORDER = {RemovePlanType::NOT_INSTALLED, RemovePlanType::REMOVE}; - for (const RemovePlanType plan_type : order) + for (const RemovePlanType plan_type : ORDER) { - auto it = group_by_plan_type.find(plan_type); + const auto it = group_by_plan_type.find(plan_type); if (it == group_by_plan_type.cend()) { continue; @@ -129,6 +129,37 @@ namespace vcpkg::Commands::Remove } } + void perform_remove_plan_action(const VcpkgPaths& paths, + const RemovePlanAction& action, + const Purge purge, + StatusParagraphs& status_db) + { + const std::string display_name = action.spec.to_string(); + + switch (action.plan_type) + { + case RemovePlanType::NOT_INSTALLED: + System::println(System::Color::success, "Package %s is not installed", display_name); + break; + case RemovePlanType::REMOVE: + System::println("Removing package %s... ", display_name); + remove_package(paths, action.spec, &status_db); + System::println(System::Color::success, "Removing package %s... done", display_name); + break; + case RemovePlanType::UNKNOWN: + default: Checks::unreachable(VCPKG_LINE_INFO); + } + + if (purge == Purge::YES) + { + System::println("Purging package %s... ", display_name); + Files::Filesystem& fs = paths.get_filesystem(); + std::error_code ec; + fs.remove_all(paths.packages / action.spec.dir(), ec); + System::println(System::Color::success, "Purging package %s... done", display_name); + } + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { static const std::string OPTION_PURGE = "--purge"; @@ -136,7 +167,7 @@ namespace vcpkg::Commands::Remove static const std::string OPTION_RECURSE = "--recurse"; static const std::string OPTION_DRY_RUN = "--dry-run"; static const std::string OPTION_OUTDATED = "--outdated"; - static const std::string example = + static const std::string EXAMPLE = Commands::Help::create_example_string("remove zlib zlib:x64-windows curl boost"); const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments( {OPTION_PURGE, OPTION_NO_PURGE, OPTION_RECURSE, OPTION_DRY_RUN, OPTION_OUTDATED}); @@ -145,7 +176,7 @@ namespace vcpkg::Commands::Remove std::vector<PackageSpec> specs; if (options.find(OPTION_OUTDATED) != options.cend()) { - args.check_exact_arg_count(0, example); + args.check_exact_arg_count(0, EXAMPLE); specs = Util::fmap(Update::find_outdated_packages(paths, status_db), [](auto&& outdated) { return outdated.spec; }); @@ -157,25 +188,26 @@ namespace vcpkg::Commands::Remove } else { - args.check_min_arg_count(1, example); + args.check_min_arg_count(1, EXAMPLE); specs = Util::fmap(args.command_arguments, [&](auto&& arg) { - return Input::check_and_get_package_spec(arg, default_triplet, example); + return Input::check_and_get_package_spec(arg, default_triplet, EXAMPLE); }); for (auto&& spec : specs) Input::check_triplet(spec.triplet(), paths); } - const bool alsoRemoveFolderFromPackages = options.find(OPTION_NO_PURGE) == options.end(); - if (options.find(OPTION_PURGE) != options.end() && !alsoRemoveFolderFromPackages) + const bool no_purge_was_passed = options.find(OPTION_NO_PURGE) != options.end(); + const bool purge_was_passed = options.find(OPTION_PURGE) != options.end(); + if (purge_was_passed && no_purge_was_passed) { - // User specified --purge and --no-purge System::println(System::Color::error, "Error: cannot specify both --no-purge and --purge."); - System::print(example); + System::print(EXAMPLE); Checks::exit_fail(VCPKG_LINE_INFO); } - const bool isRecursive = options.find(OPTION_RECURSE) != options.cend(); - const bool dryRun = options.find(OPTION_DRY_RUN) != options.cend(); + const Purge purge = to_purge(purge_was_passed || !no_purge_was_passed); + const bool is_recursive = options.find(OPTION_RECURSE) != options.cend(); + const bool dry_run = options.find(OPTION_DRY_RUN) != options.cend(); const std::vector<RemovePlanAction> remove_plan = Dependencies::create_remove_plan(specs, status_db); Checks::check_exit(VCPKG_LINE_INFO, !remove_plan.empty(), "Remove plan cannot be empty"); @@ -194,7 +226,7 @@ namespace vcpkg::Commands::Remove System::println(System::Color::warning, "Additional packages (*) need to be removed to complete this operation."); - if (!isRecursive) + if (!is_recursive) { System::println(System::Color::warning, "If you are sure you want to remove them, run the command with the --recurse option"); @@ -202,37 +234,14 @@ namespace vcpkg::Commands::Remove } } - if (dryRun) + if (dry_run) { Checks::exit_success(VCPKG_LINE_INFO); } for (const RemovePlanAction& action : remove_plan) { - const std::string display_name = action.spec.to_string(); - - switch (action.plan_type) - { - case RemovePlanType::NOT_INSTALLED: - System::println(System::Color::success, "Package %s is not installed", display_name); - break; - case RemovePlanType::REMOVE: - System::println("Removing package %s... ", display_name); - remove_package(paths, action.spec, &status_db); - System::println(System::Color::success, "Removing package %s... done", display_name); - break; - case RemovePlanType::UNKNOWN: - default: Checks::unreachable(VCPKG_LINE_INFO); - } - - if (alsoRemoveFolderFromPackages) - { - System::println("Purging package %s... ", display_name); - Files::Filesystem& fs = paths.get_filesystem(); - std::error_code ec; - fs.remove_all(paths.packages / action.spec.dir(), ec); - System::println(System::Color::success, "Purging package %s... done", display_name); - } + perform_remove_plan_action(paths, action, purge, status_db); } Checks::exit_success(VCPKG_LINE_INFO); diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index 529d52a8b..d35a546c4 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -80,34 +80,15 @@ namespace vcpkg::Commands::Search void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - static const std::string example = Strings::format( + static const std::string EXAMPLE = Strings::format( "The argument should be a substring to search for, or no argument to display all libraries.\n%s", Commands::Help::create_example_string("search png")); - args.check_max_arg_count(1, example); + args.check_max_arg_count(1, EXAMPLE); const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({OPTION_GRAPH, OPTION_FULLDESC}); - auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); + auto source_paragraphs = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); - if (!sources_and_errors.errors.empty()) - { - if (GlobalState::debugging) - { - print_error_message(sources_and_errors.errors); - } - else - { - for (auto&& error : sources_and_errors.errors) - { - System::println( - System::Color::warning, "Warning: an error occurred while parsing '%s'", error->name); - } - System::println(System::Color::warning, - "Use '--debug' to get more information about the parse failures.\n"); - } - } - - auto& source_paragraphs = sources_and_errors.paragraphs; if (options.find(OPTION_GRAPH) != options.cend()) { const std::string graph_as_string = create_graph_as_string(source_paragraphs); diff --git a/toolsrc/src/commands_update.cpp b/toolsrc/src/commands_update.cpp index 35f24af12..71ea4b063 100644 --- a/toolsrc/src/commands_update.cpp +++ b/toolsrc/src/commands_update.cpp @@ -2,7 +2,6 @@ #include "Paragraphs.h" #include "vcpkg_Commands.h" -#include "vcpkg_Files.h" #include "vcpkg_System.h" #include "vcpkglib.h" @@ -22,7 +21,7 @@ namespace vcpkg::Commands::Update std::vector<OutdatedPackage> output; for (const StatusParagraph* pgh : installed_packages) { - auto it = src_names_to_versions.find(pgh->package.spec.name()); + const auto it = src_names_to_versions.find(pgh->package.spec.name()); if (it == src_names_to_versions.end()) { // Package was not installed from portfile @@ -69,31 +68,6 @@ namespace vcpkg::Commands::Update install_line); } - auto version_file = paths.get_filesystem().read_contents(paths.root / "toolsrc" / "VERSION.txt"); - if (auto version_contents = version_file.get()) - { - int maj1, min1, rev1; - auto num1 = sscanf_s(version_contents->c_str(), "\"%d.%d.%d\"", &maj1, &min1, &rev1); - - int maj2, min2, rev2; - auto num2 = sscanf_s(Version::version().c_str(), "%d.%d.%d-", &maj2, &min2, &rev2); - - if (num1 == 3 && num2 == 3) - { - if (maj1 != maj2 || min1 != min2 || rev1 != rev2) - { - System::println("Different source is available for vcpkg (%d.%d.%d -> %d.%d.%d). Use " - ".\\bootstrap-vcpkg.bat to update.", - maj2, - min2, - rev2, - maj1, - min1, - rev1); - } - } - } - Checks::exit_success(VCPKG_LINE_INFO); } } diff --git a/toolsrc/src/commands_version.cpp b/toolsrc/src/commands_version.cpp index cd21f2561..5744ea9ef 100644 --- a/toolsrc/src/commands_version.cpp +++ b/toolsrc/src/commands_version.cpp @@ -13,15 +13,44 @@ namespace vcpkg::Commands::Version { const std::string& version() { - static const std::string s_version = + static const std::string S_VERSION = #include "../VERSION.txt" +std::string(VCPKG_VERSION_AS_STRING) #ifndef NDEBUG + std::string("-debug") #endif - + std::string(Metrics::get_compiled_metrics_enabled() ? "" : "-external"); - return s_version; + + std::string(Metrics::get_compiled_metrics_enabled() ? Strings::EMPTY : "-external"); + return S_VERSION; + } + + void warn_if_vcpkg_version_mismatch(const VcpkgPaths& paths) + { + auto version_file = paths.get_filesystem().read_contents(paths.root / "toolsrc" / "VERSION.txt"); + if (const auto version_contents = version_file.get()) + { + int maj1, min1, rev1; + const auto num1 = sscanf_s(version_contents->c_str(), "\"%d.%d.%d\"", &maj1, &min1, &rev1); + + int maj2, min2, rev2; + const auto num2 = sscanf_s(Version::version().c_str(), "%d.%d.%d-", &maj2, &min2, &rev2); + + if (num1 == 3 && num2 == 3) + { + if (maj1 != maj2 || min1 != min2 || rev1 != rev2) + { + System::println(System::Color::warning, + "Warning: Different source is available for vcpkg (%d.%d.%d -> %d.%d.%d). Use " + ".\\bootstrap-vcpkg.bat to update.", + maj2, + min2, + rev2, + maj1, + min1, + rev1); + } + } + } } void perform_and_exit(const VcpkgCmdArguments& args) diff --git a/toolsrc/src/metrics.cpp b/toolsrc/src/metrics.cpp index 6263c0fcb..8a0050bfc 100644 --- a/toolsrc/src/metrics.cpp +++ b/toolsrc/src/metrics.cpp @@ -20,12 +20,12 @@ namespace vcpkg::Metrics _ftime_s(&timebuffer); time_t now = timebuffer.time; - int milli = timebuffer.millitm; + const int milli = timebuffer.millitm; - errno_t err = gmtime_s(&newtime, &now); + const errno_t err = gmtime_s(&newtime, &now); if (err) { - return ""; + return Strings::EMPTY; } strftime(&date[0], date.size(), "%Y-%m-%dT%H:%M:%S", &newtime); @@ -34,7 +34,7 @@ namespace vcpkg::Metrics static std::string generate_random_UUID() { - int partSizes[] = {8, 4, 4, 4, 12}; + int part_sizes[] = {8, 4, 4, 4, 12}; char uuid[37]; memset(uuid, 0, sizeof(uuid)); int num; @@ -50,7 +50,7 @@ namespace vcpkg::Metrics // Generating UUID format version 4 // http://en.wikipedia.org/wiki/Universally_unique_identifier - for (int i = 0; i < partSizes[part]; i++, index++) + for (int i = 0; i < part_sizes[part]; i++, index++) { if (part == 2 && i == 0) { @@ -81,8 +81,8 @@ namespace vcpkg::Metrics static const std::string& get_session_id() { - static const std::string id = generate_random_UUID(); - return id; + static const std::string ID = generate_random_UUID(); + return ID; } static std::string to_json_string(const std::string& str) @@ -101,11 +101,11 @@ namespace vcpkg::Metrics else if (ch < 0x20 || ch >= 0x80) { // Note: this treats incoming Strings as Latin-1 - static constexpr const char hex[16] = { + static constexpr const char HEX[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; encoded.append("\\u00"); - encoded.push_back(hex[ch / 16]); - encoded.push_back(hex[ch % 16]); + encoded.push_back(HEX[ch / 16]); + encoded.push_back(HEX[ch % 16]); } else { @@ -120,21 +120,21 @@ namespace vcpkg::Metrics { std::wstring path; path.resize(MAX_PATH); - auto n = GetSystemDirectoryW(&path[0], static_cast<UINT>(path.size())); + const auto n = GetSystemDirectoryW(&path[0], static_cast<UINT>(path.size())); path.resize(n); path += L"\\kernel32.dll"; - auto versz = GetFileVersionInfoSizeW(path.c_str(), nullptr); - if (versz == 0) return ""; + const auto versz = GetFileVersionInfoSizeW(path.c_str(), nullptr); + if (versz == 0) return Strings::EMPTY; std::vector<char> verbuf; verbuf.resize(versz); - if (!GetFileVersionInfoW(path.c_str(), 0, static_cast<DWORD>(verbuf.size()), &verbuf[0])) return ""; + if (!GetFileVersionInfoW(path.c_str(), 0, static_cast<DWORD>(verbuf.size()), &verbuf[0])) return Strings::EMPTY; void* rootblock; UINT rootblocksize; - if (!VerQueryValueW(&verbuf[0], L"\\", &rootblock, &rootblocksize)) return ""; + if (!VerQueryValueW(&verbuf[0], L"\\", &rootblock, &rootblocksize)) return Strings::EMPTY; auto rootblock_ffi = static_cast<VS_FIXEDFILEINFO*>(rootblock); @@ -152,7 +152,7 @@ namespace vcpkg::Metrics std::string properties; std::string measurements; - void TrackProperty(const std::string& name, const std::string& value) + void track_property(const std::string& name, const std::string& value) { if (properties.size() != 0) properties.push_back(','); properties.append(to_json_string(name)); @@ -160,7 +160,7 @@ namespace vcpkg::Metrics properties.append(to_json_string(value)); } - void TrackMetric(const std::string& name, double value) + void track_metric(const std::string& name, double value) { if (measurements.size() != 0) measurements.push_back(','); measurements.append(to_json_string(name)); @@ -241,7 +241,7 @@ namespace vcpkg::Metrics void Metrics::set_print_metrics(bool should_print_metrics) { g_should_print_metrics = should_print_metrics; } - void Metrics::track_metric(const std::string& name, double value) { g_metricmessage.TrackMetric(name, value); } + void Metrics::track_metric(const std::string& name, double value) { g_metricmessage.track_metric(name, value); } void Metrics::track_property(const std::string& name, const std::wstring& value) { @@ -251,85 +251,85 @@ namespace vcpkg::Metrics std::transform( value.begin(), value.end(), converted_value.begin(), [](wchar_t ch) { return static_cast<char>(ch); }); - g_metricmessage.TrackProperty(name, converted_value); + g_metricmessage.track_property(name, converted_value); } void Metrics::track_property(const std::string& name, const std::string& value) { - g_metricmessage.TrackProperty(name, value); + g_metricmessage.track_property(name, value); } void Metrics::upload(const std::string& payload) { - HINTERNET hSession = nullptr, hConnect = nullptr, hRequest = nullptr; - BOOL bResults = FALSE; + HINTERNET connect = nullptr, request = nullptr; + BOOL results = FALSE; - hSession = WinHttpOpen( + const HINTERNET session = WinHttpOpen( L"vcpkg/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); - if (hSession) - hConnect = WinHttpConnect(hSession, L"dc.services.visualstudio.com", INTERNET_DEFAULT_HTTPS_PORT, 0); - - if (hConnect) - hRequest = WinHttpOpenRequest(hConnect, - L"POST", - L"/v2/track", - nullptr, - WINHTTP_NO_REFERER, - WINHTTP_DEFAULT_ACCEPT_TYPES, - WINHTTP_FLAG_SECURE); - - if (hRequest) + if (session) connect = WinHttpConnect(session, L"dc.services.visualstudio.com", INTERNET_DEFAULT_HTTPS_PORT, 0); + + if (connect) + request = WinHttpOpenRequest(connect, + L"POST", + L"/v2/track", + nullptr, + WINHTTP_NO_REFERER, + WINHTTP_DEFAULT_ACCEPT_TYPES, + WINHTTP_FLAG_SECURE); + + if (request) { if (MAXDWORD <= payload.size()) abort(); std::wstring hdrs = L"Content-Type: application/json\r\n"; - bResults = WinHttpSendRequest(hRequest, - hdrs.c_str(), - static_cast<DWORD>(hdrs.size()), - (void*)&payload[0], - static_cast<DWORD>(payload.size()), - static_cast<DWORD>(payload.size()), - 0); + std::string& p = const_cast<std::string&>(payload); + results = WinHttpSendRequest(request, + hdrs.c_str(), + static_cast<DWORD>(hdrs.size()), + static_cast<void*>(&p[0]), + static_cast<DWORD>(payload.size()), + static_cast<DWORD>(payload.size()), + 0); } - if (bResults) + if (results) { - bResults = WinHttpReceiveResponse(hRequest, nullptr); + results = WinHttpReceiveResponse(request, nullptr); } DWORD http_code = 0, junk = sizeof(DWORD); - if (bResults) + if (results) { - bResults = WinHttpQueryHeaders(hRequest, - WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, - nullptr, - &http_code, - &junk, - WINHTTP_NO_HEADER_INDEX); + results = WinHttpQueryHeaders(request, + WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, + nullptr, + &http_code, + &junk, + WINHTTP_NO_HEADER_INDEX); } - std::vector<char> responseBuffer; - if (bResults) + std::vector<char> response_buffer; + if (results) { - DWORD availableData = 0, readData = 0, totalData = 0; - while ((bResults = WinHttpQueryDataAvailable(hRequest, &availableData)) == TRUE && availableData > 0) + DWORD available_data = 0, read_data = 0, total_data = 0; + while ((results = WinHttpQueryDataAvailable(request, &available_data)) == TRUE && available_data > 0) { - responseBuffer.resize(responseBuffer.size() + availableData); + response_buffer.resize(response_buffer.size() + available_data); - bResults = WinHttpReadData(hRequest, &responseBuffer.data()[totalData], availableData, &readData); + results = WinHttpReadData(request, &response_buffer.data()[total_data], available_data, &read_data); - if (!bResults) + if (!results) { break; } - totalData += readData; + total_data += read_data; - responseBuffer.resize(totalData); + response_buffer.resize(total_data); } } - if (!bResults) + if (!results) { #ifndef NDEBUG __debugbreak(); @@ -338,22 +338,22 @@ namespace vcpkg::Metrics #endif } - if (hRequest) WinHttpCloseHandle(hRequest); - if (hConnect) WinHttpCloseHandle(hConnect); - if (hSession) WinHttpCloseHandle(hSession); + if (request) WinHttpCloseHandle(request); + if (connect) WinHttpCloseHandle(connect); + if (session) WinHttpCloseHandle(session); } static fs::path get_bindir() { wchar_t buf[_MAX_PATH]; - int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); + const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); if (bytes == 0) std::abort(); return fs::path(buf, buf + bytes); } void Metrics::flush() { - std::string payload = g_metricmessage.format_event_data_template(); + const std::string payload = g_metricmessage.format_event_data_template(); if (g_should_print_metrics) std::cerr << payload << "\n"; if (!g_should_send_metrics) return; @@ -377,7 +377,7 @@ namespace vcpkg::Metrics path = vcpkgdir / "scripts" / "vcpkgmetricsuploader.exe"; if (fs.exists(path)) return path; - return L""; + return Strings::WEMPTY; }(); std::error_code ec; @@ -388,8 +388,8 @@ namespace vcpkg::Metrics const fs::path vcpkg_metrics_txt_path = temp_folder_path / ("vcpkg" + generate_random_UUID() + ".txt"); fs.write_contents(vcpkg_metrics_txt_path, payload); - const std::wstring cmdLine = + const std::wstring cmd_line = Strings::wformat(L"start %s %s", temp_folder_path_exe.native(), vcpkg_metrics_txt_path.native()); - System::cmd_execute_clean(cmdLine); + System::cmd_execute_clean(cmd_line); } } diff --git a/toolsrc/src/tests_package_spec.cpp b/toolsrc/src/tests_package_spec.cpp index fa201b372..a6b9d5b13 100644 --- a/toolsrc/src/tests_package_spec.cpp +++ b/toolsrc/src/tests_package_spec.cpp @@ -43,7 +43,7 @@ namespace UnitTest1 std::array<const char*, 6> features = {"", "0", "1", "", "2", "3"}; std::array<PackageSpec*, 6> specs = {&a_spec, &a_spec, &a_spec, &b_spec, &b_spec, &b_spec}; - for (int i = 0; i < features.size(); ++i) + for (size_t i = 0; i < features.size(); ++i) { Assert::AreEqual(features[i], fspecs[i].feature().c_str()); Assert::AreEqual(*specs[i], fspecs[i].spec()); diff --git a/toolsrc/src/triplet.cpp b/toolsrc/src/triplet.cpp index 451deb040..3b56da02a 100644 --- a/toolsrc/src/triplet.cpp +++ b/toolsrc/src/triplet.cpp @@ -15,7 +15,7 @@ namespace vcpkg bool operator==(const TripletInstance& o) const { return o.value == value; } }; - const TripletInstance Triplet::default_instance({}); + const TripletInstance Triplet::DEFAULT_INSTANCE({}); } template<> @@ -41,10 +41,10 @@ namespace vcpkg Triplet Triplet::from_canonical_name(const std::string& triplet_as_string) { std::string s(Strings::ascii_to_lowercase(triplet_as_string)); - auto it = std::find(s.cbegin(), s.cend(), '-'); + const auto it = std::find(s.cbegin(), s.cend(), '-'); Checks::check_exit(VCPKG_LINE_INFO, it != s.cend(), "Invalid triplet: %s", triplet_as_string); - auto p = g_triplet_instances.emplace(std::move(s)); + const auto p = g_triplet_instances.emplace(std::move(s)); return &*p.first; } diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index f37d079a6..706c641fb 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -11,7 +11,10 @@ #include "vcpkg_Strings.h" #include "vcpkg_System.h" #include "vcpkglib.h" +#pragma warning(push) +#pragma warning(disable : 4768) #include <Shlobj.h> +#pragma warning(pop) #include <cassert> #include <fstream> #include <memory> @@ -34,7 +37,7 @@ static void inner(const VcpkgCmdArguments& args) Checks::exit_fail(VCPKG_LINE_INFO); } - if (auto command_function = Commands::find(args.command, Commands::get_available_commands_type_c())) + if (const auto command_function = Commands::find(args.command, Commands::get_available_commands_type_c())) { return command_function(args); } @@ -47,7 +50,7 @@ static void inner(const VcpkgCmdArguments& args) else { const Optional<std::wstring> vcpkg_root_dir_env = System::get_environment_variable(L"VCPKG_ROOT"); - if (auto v = vcpkg_root_dir_env.get()) + if (const auto v = vcpkg_root_dir_env.get()) { vcpkg_root_dir = fs::stdfs::absolute(*v); } @@ -67,10 +70,11 @@ static void inner(const VcpkgCmdArguments& args) vcpkg_root_dir.string(), expected_paths.error().message()); const VcpkgPaths paths = expected_paths.value_or_exit(VCPKG_LINE_INFO); - int exit_code = _wchdir(paths.root.c_str()); + const int exit_code = _wchdir(paths.root.c_str()); Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working dir failed"); + Commands::Version::warn_if_vcpkg_version_mismatch(paths); - if (auto command_function = Commands::find(args.command, Commands::get_available_commands_type_b())) + if (const auto command_function = Commands::find(args.command, Commands::get_available_commands_type_b())) { return command_function(args, paths); } @@ -84,7 +88,7 @@ static void inner(const VcpkgCmdArguments& args) { const Optional<std::wstring> vcpkg_default_triplet_env = System::get_environment_variable(L"VCPKG_DEFAULT_TRIPLET"); - if (auto v = vcpkg_default_triplet_env.get()) + if (const auto v = vcpkg_default_triplet_env.get()) { default_triplet = Triplet::from_canonical_name(Strings::to_utf8(*v)); } @@ -96,7 +100,7 @@ static void inner(const VcpkgCmdArguments& args) Input::check_triplet(default_triplet, paths); - if (auto command_function = Commands::find(args.command, Commands::get_available_commands_type_a())) + if (const auto command_function = Commands::find(args.command, Commands::get_available_commands_type_a())) { return command_function(args, paths, default_triplet); } @@ -104,7 +108,7 @@ static void inner(const VcpkgCmdArguments& args) return invalid_command(args.command); } -static void loadConfig() +static void load_config() { fs::path localappdata; { @@ -118,7 +122,7 @@ static void loadConfig() try { auto maybe_pghs = Paragraphs::get_paragraphs(Files::get_real_filesystem(), localappdata / "vcpkg" / "config"); - if (auto p_pghs = maybe_pghs.get()) + if (const auto p_pghs = maybe_pghs.get()) { const auto& pghs = *p_pghs; @@ -207,14 +211,14 @@ int wmain(const int argc, const wchar_t* const* const argv) locked_metrics->track_property("version", Commands::Version::version()); locked_metrics->track_property("cmdline", trimmed_command_line); } - loadConfig(); + load_config(); Metrics::g_metrics.lock()->track_property("sqmuser", Metrics::get_SQM_user()); const VcpkgCmdArguments args = VcpkgCmdArguments::create_from_command_line(argc, argv); - if (auto p = args.printmetrics.get()) Metrics::g_metrics.lock()->set_print_metrics(*p); - if (auto p = args.sendmetrics.get()) Metrics::g_metrics.lock()->set_send_metrics(*p); - if (auto p = args.debug.get()) GlobalState::debugging = *p; + if (const auto p = args.printmetrics.get()) Metrics::g_metrics.lock()->set_print_metrics(*p); + if (const auto p = args.sendmetrics.get()) Metrics::g_metrics.lock()->set_send_metrics(*p); + if (const auto p = args.debug.get()) GlobalState::debugging = *p; Checks::register_console_ctrl_handler(); diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index 0ae63d4e3..9be20629d 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -30,8 +30,8 @@ namespace vcpkg::Build CWStringView to_vcvarsall_target(const std::string& cmake_system_name) { - if (cmake_system_name == "") return L""; - if (cmake_system_name == "Windows") return L""; + if (cmake_system_name == Strings::EMPTY) return Strings::WEMPTY; + if (cmake_system_name == "Windows") return Strings::WEMPTY; if (cmake_system_name == "WindowsStore") return L"store"; Checks::exit_with_message(VCPKG_LINE_INFO, "Unsupported vcvarsall target %s", cmake_system_name); @@ -61,13 +61,18 @@ namespace vcpkg::Build const wchar_t* tonull = L" >nul"; if (GlobalState::debugging) { - tonull = L""; + tonull = Strings::WEMPTY; } - auto arch = to_vcvarsall_toolchain(pre_build_info.target_architecture, toolset); - auto target = to_vcvarsall_target(pre_build_info.cmake_system_name); + const auto arch = to_vcvarsall_toolchain(pre_build_info.target_architecture, toolset); + const auto target = to_vcvarsall_target(pre_build_info.cmake_system_name); - return Strings::wformat(LR"("%s" %s %s %s 2>&1)", toolset.vcvarsall.native(), arch, target, tonull); + return Strings::wformat(LR"("%s" %s %s %s %s 2>&1)", + toolset.vcvarsall.native(), + Strings::join(L" ", toolset.vcvarsall_options), + arch, + target, + tonull); } static void create_binary_feature_control_file(const SourceParagraph& source_paragraph, @@ -85,7 +90,7 @@ namespace vcpkg::Build BinaryControlFile& bcf) { BinaryParagraph bpgh(source_paragraph, triplet); - if (auto p_ver = build_info.version.get()) + if (const auto p_ver = build_info.version.get()) { bpgh.version = *p_ver; } @@ -132,8 +137,8 @@ namespace vcpkg::Build const fs::path& git_exe_path = paths.get_git_exe(); const fs::path ports_cmake_script_path = paths.ports_cmake; - auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); - const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset); + const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); + const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path); const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); std::string features; @@ -160,7 +165,7 @@ namespace vcpkg::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_PLATFORM_TOOLSET", toolset.version.c_str()}, {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}, @@ -171,8 +176,8 @@ namespace vcpkg::Build const ElapsedTime timer = ElapsedTime::create_started(); - int return_code = System::cmd_execute_clean(command); - auto buildtimeus = timer.microseconds(); + const int return_code = System::cmd_execute_clean(command); + const auto buildtimeus = timer.microseconds(); const auto spec_string = spec.to_string(); { @@ -186,7 +191,7 @@ namespace vcpkg::Build } } - auto build_info = read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); + const BuildInfo build_info = read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec)); const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); BinaryControlFile bcf; @@ -269,7 +274,7 @@ namespace vcpkg::Build parser.required_field(BuildInfoRequiredField::CRT_LINKAGE, crt_linkage_as_string); auto crtlinkage = to_linkage_type(crt_linkage_as_string); - if (auto p = crtlinkage.get()) + if (const auto p = crtlinkage.get()) build_info.crt_linkage = *p; else Checks::exit_with_message(VCPKG_LINE_INFO, "Invalid crt linkage type: [%s]", crt_linkage_as_string); @@ -279,7 +284,7 @@ namespace vcpkg::Build std::string library_linkage_as_string; parser.required_field(BuildInfoRequiredField::LIBRARY_LINKAGE, library_linkage_as_string); auto liblinkage = to_linkage_type(library_linkage_as_string); - if (auto p = liblinkage.get()) + if (const auto p = liblinkage.get()) build_info.library_linkage = *p; else Checks::exit_with_message( @@ -289,12 +294,11 @@ namespace vcpkg::Build if (!version.empty()) build_info.version = std::move(version); std::map<BuildPolicy, bool> policies; - for (auto policy : g_all_policies) + for (auto policy : G_ALL_POLICIES) { const auto setting = parser.optional_field(to_string(policy)); - if (setting.empty()) - continue; - else if (setting == "enabled") + if (setting.empty()) continue; + if (setting == "enabled") policies.emplace(policy, true); else if (setting == "disabled") policies.emplace(policy, false); @@ -303,7 +307,7 @@ namespace vcpkg::Build VCPKG_LINE_INFO, "Unknown setting for policy '%s': %s", to_string(policy), setting); } - if (auto err = parser.error_info("PostBuildInformation")) + if (const auto err = parser.error_info("PostBuildInformation")) { print_error_message(err); Checks::exit_fail(VCPKG_LINE_INFO); @@ -337,14 +341,14 @@ namespace vcpkg::Build }); const std::wstring command = Strings::wformat(LR"(%s)", cmd_launch_cmake); - auto ec_data = System::cmd_execute_and_capture_output(command); + const auto ec_data = System::cmd_execute_and_capture_output(command); Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0); const std::vector<std::string> lines = Strings::split(ec_data.output, "\n"); PreBuildInfo pre_build_info; - auto e = lines.cend(); + const auto e = lines.cend(); auto cur = std::find(lines.cbegin(), e, FLAG_GUID); if (cur != e) ++cur; @@ -360,7 +364,7 @@ namespace vcpkg::Build const bool variable_with_no_value = s.size() == 1; const std::string variable_name = s.at(0); - const std::string variable_value = variable_with_no_value ? "" : s.at(1); + const std::string variable_value = variable_with_no_value ? Strings::EMPTY : s.at(1); if (variable_name == "VCPKG_TARGET_ARCHITECTURE") { @@ -382,7 +386,15 @@ namespace vcpkg::Build if (variable_name == "VCPKG_PLATFORM_TOOLSET") { - pre_build_info.platform_toolset = variable_value; + pre_build_info.platform_toolset = + variable_value.empty() ? nullopt : Optional<std::string>{variable_value}; + continue; + } + + if (variable_name == "VCPKG_VISUAL_STUDIO_PATH") + { + pre_build_info.visual_studio_path = + variable_value.empty() ? nullopt : Optional<fs::path>{variable_value}; continue; } diff --git a/toolsrc/src/vcpkg_Checks.cpp b/toolsrc/src/vcpkg_Checks.cpp index 2ad2d06ab..e7c9046a4 100644 --- a/toolsrc/src/vcpkg_Checks.cpp +++ b/toolsrc/src/vcpkg_Checks.cpp @@ -10,7 +10,7 @@ namespace vcpkg::Checks { [[noreturn]] static void cleanup_and_exit(const int exit_code) { - auto elapsed_us = GlobalState::timer.lock()->microseconds(); + const auto elapsed_us = GlobalState::timer.lock()->microseconds(); auto metrics = Metrics::g_metrics.lock(); metrics->track_metric("elapsed_us", elapsed_us); @@ -20,20 +20,25 @@ namespace vcpkg::Checks SetConsoleCP(GlobalState::g_init_console_cp); SetConsoleOutputCP(GlobalState::g_init_console_output_cp); - ::exit(exit_code); + fflush(nullptr); + + ::TerminateProcess(::GetCurrentProcess(), exit_code); } - static BOOL CtrlHandler(DWORD fdwCtrlType) + static BOOL ctrl_handler(DWORD fdw_ctrl_type) { { auto locked_metrics = Metrics::g_metrics.lock(); - locked_metrics->track_property("CtrlHandler", std::to_string(fdwCtrlType)); + locked_metrics->track_property("CtrlHandler", std::to_string(fdw_ctrl_type)); locked_metrics->track_property("error", "CtrlHandler was fired."); } cleanup_and_exit(EXIT_FAILURE); } - void register_console_ctrl_handler() { SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); } + void register_console_ctrl_handler() + { + SetConsoleCtrlHandler(reinterpret_cast<PHANDLER_ROUTINE>(ctrl_handler), TRUE); + } [[noreturn]] void unreachable(const LineInfo& line_info) { @@ -52,9 +57,9 @@ namespace vcpkg::Checks cleanup_and_exit(exit_code); } - [[noreturn]] void exit_with_message(const LineInfo& line_info, const CStringView errorMessage) + [[noreturn]] void exit_with_message(const LineInfo& line_info, const CStringView error_message) { - System::println(System::Color::error, errorMessage); + System::println(System::Color::error, error_message); exit_fail(line_info); } @@ -62,15 +67,15 @@ namespace vcpkg::Checks { if (!expression) { - exit_with_message(line_info, ""); + exit_with_message(line_info, Strings::EMPTY); } } - void check_exit(const LineInfo& line_info, bool expression, const CStringView errorMessage) + void check_exit(const LineInfo& line_info, bool expression, const CStringView error_message) { if (!expression) { - exit_with_message(line_info, errorMessage); + exit_with_message(line_info, error_message); } } } diff --git a/toolsrc/src/vcpkg_Chrono.cpp b/toolsrc/src/vcpkg_Chrono.cpp index d70f4a054..d96f30987 100644 --- a/toolsrc/src/vcpkg_Chrono.cpp +++ b/toolsrc/src/vcpkg_Chrono.cpp @@ -7,43 +7,43 @@ namespace vcpkg { static std::string format_time_userfriendly(const std::chrono::nanoseconds& nanos) { + using std::chrono::duration_cast; using std::chrono::hours; - using std::chrono::minutes; - using std::chrono::seconds; - using std::chrono::milliseconds; using std::chrono::microseconds; + using std::chrono::milliseconds; + using std::chrono::minutes; using std::chrono::nanoseconds; - using std::chrono::duration_cast; + using std::chrono::seconds; const double nanos_as_double = static_cast<double>(nanos.count()); if (duration_cast<hours>(nanos) > hours()) { - auto t = nanos_as_double / duration_cast<nanoseconds>(hours(1)).count(); + const auto t = nanos_as_double / duration_cast<nanoseconds>(hours(1)).count(); return Strings::format("%.4g h", t); } if (duration_cast<minutes>(nanos) > minutes()) { - auto t = nanos_as_double / duration_cast<nanoseconds>(minutes(1)).count(); + const auto t = nanos_as_double / duration_cast<nanoseconds>(minutes(1)).count(); return Strings::format("%.4g min", t); } if (duration_cast<seconds>(nanos) > seconds()) { - auto t = nanos_as_double / duration_cast<nanoseconds>(seconds(1)).count(); + const auto t = nanos_as_double / duration_cast<nanoseconds>(seconds(1)).count(); return Strings::format("%.4g s", t); } if (duration_cast<milliseconds>(nanos) > milliseconds()) { - auto t = nanos_as_double / duration_cast<nanoseconds>(milliseconds(1)).count(); + const auto t = nanos_as_double / duration_cast<nanoseconds>(milliseconds(1)).count(); return Strings::format("%.4g ms", t); } if (duration_cast<microseconds>(nanos) > microseconds()) { - auto t = nanos_as_double / duration_cast<nanoseconds>(microseconds(1)).count(); + const auto t = nanos_as_double / duration_cast<nanoseconds>(microseconds(1)).count(); return Strings::format("%.4g us", t); } diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 4525fa02a..8dd60a2eb 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -7,6 +7,7 @@ #include "vcpkg_Dependencies.h" #include "vcpkg_Files.h" #include "vcpkg_Graphs.h" +#include "vcpkg_Strings.h" #include "vcpkg_Util.h" #include "vcpkglib.h" @@ -36,7 +37,7 @@ namespace vcpkg::Dependencies { Cluster* ptr; - Cluster* operator->() { return ptr; } + Cluster* operator->() const { return ptr; } }; bool operator==(const ClusterPtr& l, const ClusterPtr& r) { return l.ptr == r.ptr; } @@ -86,7 +87,7 @@ namespace vcpkg::Dependencies } private: - void cluster_from_scf(const SourceControlFile& scf, Cluster& out_cluster) + void cluster_from_scf(const SourceControlFile& scf, Cluster& out_cluster) const { FeatureNodeEdges core_dependencies; core_dependencies.build_edges = @@ -166,7 +167,7 @@ namespace vcpkg::Dependencies InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const AnyParagraph& any_paragraph, const RequestType& request_type) - : spec(spec), request_type(request_type), plan_type(InstallPlanType::UNKNOWN), any_paragraph(any_paragraph) + : spec(spec), any_paragraph(any_paragraph), plan_type(InstallPlanType::UNKNOWN), request_type(request_type) { if (auto p = any_paragraph.status_paragraph.get()) { @@ -193,17 +194,9 @@ namespace vcpkg::Dependencies { return this->spec.to_string(); } - else - { - std::string features; - for (auto&& feature : this->feature_list) - { - features += feature + ","; - } - features.pop_back(); - return this->spec.name() + "[" + features + "]:" + this->spec.triplet().to_string(); - } + const std::string features = Strings::join(",", this->feature_list); + return Strings::format("%s[%s]:%s", this->spec.name(), features, this->spec.triplet()); } bool InstallPlanAction::compare_by_name(const InstallPlanAction* left, const InstallPlanAction* right) @@ -220,6 +213,21 @@ namespace vcpkg::Dependencies { } + const PackageSpec& AnyAction::spec() const + { + if (const auto p = install_plan.get()) + { + return p->spec; + } + + if (const auto p = remove_plan.get()) + { + return p->spec; + } + + Checks::exit_with_message(VCPKG_LINE_INFO, "Null action"); + } + bool ExportPlanAction::compare_by_name(const ExportPlanAction* left, const ExportPlanAction* right) { return left->spec.name() < right->spec.name(); @@ -450,7 +458,7 @@ namespace vcpkg::Dependencies MarkPlusResult mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan) { - if (feature == "") + if (feature.empty()) { // Indicates that core was not specified in the reference return mark_plus("core", cluster, graph, graph_plan); @@ -558,7 +566,7 @@ namespace vcpkg::Dependencies auto& status_paragraph_feature = status_paragraph->package.feature; // In this case, empty string indicates the "core" paragraph for a package. - if (status_paragraph_feature == "") + if (status_paragraph_feature.empty()) { cluster.original_features.insert("core"); } @@ -580,7 +588,7 @@ namespace vcpkg::Dependencies auto& dep_cluster = graph.get(dependency.spec()); auto depends_name = dependency.feature(); - if (depends_name == "") depends_name = "core"; + if (depends_name.empty()) depends_name = "core"; auto& target_node = dep_cluster.edges[depends_name]; target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature}); diff --git a/toolsrc/src/vcpkg_Files.cpp b/toolsrc/src/vcpkg_Files.cpp index 29da7e684..ad1fcebc6 100644 --- a/toolsrc/src/vcpkg_Files.cpp +++ b/toolsrc/src/vcpkg_Files.cpp @@ -2,6 +2,7 @@ #include "vcpkg_Files.h" #include "vcpkg_System.h" +#include "vcpkg_Util.h" #include <thread> namespace vcpkg::Files @@ -186,11 +187,23 @@ namespace vcpkg::Files void print_paths(const std::vector<fs::path>& paths) { - System::println(""); + System::println(); for (const fs::path& p : paths) { System::println(" %s", p.generic_string()); } - System::println(""); + System::println(); + } + + std::vector<fs::path> find_from_PATH(const std::wstring& name) + { + const std::wstring cmd = Strings::wformat(L"where.exe %s", name); + auto out = System::cmd_execute_and_capture_output(cmd); + if (out.exit_code != 0) + { + return {}; + } + + return Util::fmap(Strings::split(out.output, "\n"), [](auto&& s) { return fs::path(s); }); } } diff --git a/toolsrc/src/vcpkg_Input.cpp b/toolsrc/src/vcpkg_Input.cpp index 153e6a942..f1cac9632 100644 --- a/toolsrc/src/vcpkg_Input.cpp +++ b/toolsrc/src/vcpkg_Input.cpp @@ -13,7 +13,7 @@ namespace vcpkg::Input { const std::string as_lowercase = Strings::ascii_to_lowercase(package_spec_as_string); auto expected_spec = FullPackageSpec::from_string(as_lowercase, default_triplet); - if (auto spec = expected_spec.get()) + if (const auto spec = expected_spec.get()) { return PackageSpec{spec->package_spec}; } @@ -41,7 +41,7 @@ namespace vcpkg::Input { 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()) + if (const auto spec = expected_spec.get()) { return *spec; } diff --git a/toolsrc/src/vcpkg_Parse.cpp b/toolsrc/src/vcpkg_Parse.cpp index 118cde900..e671a1a05 100644 --- a/toolsrc/src/vcpkg_Parse.cpp +++ b/toolsrc/src/vcpkg_Parse.cpp @@ -23,14 +23,14 @@ namespace vcpkg::Parse void ParagraphParser::required_field(const std::string& fieldname, std::string& out) { auto maybe_field = remove_field(&fields, fieldname); - if (auto field = maybe_field.get()) + if (const auto field = maybe_field.get()) out = std::move(*field); else missing_fields.push_back(fieldname); } - std::string ParagraphParser::optional_field(const std::string& fieldname) + std::string ParagraphParser::optional_field(const std::string& fieldname) const { - return remove_field(&fields, fieldname).value_or(""); + return remove_field(&fields, fieldname).value_or(Strings::EMPTY); } std::unique_ptr<ParseControlErrorInfo> ParagraphParser::error_info(const std::string& name) const { diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index 0c1c1f9f9..bbe6b29cd 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -73,14 +73,20 @@ namespace vcpkg::Strings { std::wstring to_utf16(const CStringView s) { - std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> conversion; - return conversion.from_bytes(s); + const int size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, nullptr, 0); + std::wstring output; + output.resize(size - 1); + MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, output.data(), size - 1); + return output; } std::string to_utf8(const CWStringView w) { - std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> conversion; - return conversion.to_bytes(w); + const int size = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, nullptr, 0, nullptr, nullptr); + std::string output; + output.resize(size - 1); + WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, output.data(), size - 1, nullptr, nullptr); + return output; } std::string::const_iterator case_insensitive_ascii_find(const std::string& s, const std::string& pattern) @@ -100,7 +106,7 @@ namespace vcpkg::Strings int case_insensitive_ascii_compare(const CStringView left, const CStringView right) { - return _stricmp(left, right); + return _stricmp(left.c_str(), right.c_str()); } std::string ascii_to_lowercase(const std::string& input) @@ -110,6 +116,11 @@ namespace vcpkg::Strings return output; } + bool case_insensitive_ascii_starts_with(const std::string& s, const std::string& pattern) + { + return _strnicmp(s.c_str(), pattern.c_str(), pattern.size()) == 0; + } + void trim(std::string* s) { s->erase(std::find_if_not(s->rbegin(), s->rend(), details::isspace).base(), s->end()); @@ -130,18 +141,26 @@ namespace vcpkg::Strings trim(&s); } - Util::erase_remove_if(*strings, [](const std::string& s) { return s == ""; }); + Util::erase_remove_if(*strings, [](const std::string& s) { return s.empty(); }); } std::vector<std::string> split(const std::string& s, const std::string& delimiter) { std::vector<std::string> output; + if (delimiter.empty()) + { + output.push_back(s); + return output; + } + + const size_t delimiter_length = delimiter.length(); size_t i = 0; for (size_t pos = s.find(delimiter); pos != std::string::npos; pos = s.find(delimiter, pos)) { output.push_back(s.substr(i, pos - i)); - i = ++pos; + pos += delimiter_length; + i = pos; } // Add the rest of the string after the last delimiter, unless there is nothing after it diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index 481f2431e..5293638e3 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -19,7 +19,7 @@ namespace vcpkg::System fs::path get_exe_path_of_current_process() { wchar_t buf[_MAX_PATH]; - int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); + const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); if (bytes == 0) std::abort(); return fs::path(buf, buf + bytes); } @@ -37,9 +37,9 @@ namespace vcpkg::System CPUArchitecture get_host_processor() { auto w6432 = get_environment_variable(L"PROCESSOR_ARCHITEW6432"); - if (auto p = w6432.get()) return to_cpu_architecture(Strings::to_utf8(*p)).value_or_exit(VCPKG_LINE_INFO); + if (const auto p = w6432.get()) return to_cpu_architecture(Strings::to_utf8(*p)).value_or_exit(VCPKG_LINE_INFO); - auto procarch = get_environment_variable(L"PROCESSOR_ARCHITECTURE").value_or_exit(VCPKG_LINE_INFO); + const auto procarch = get_environment_variable(L"PROCESSOR_ARCHITECTURE").value_or_exit(VCPKG_LINE_INFO); return to_cpu_architecture(Strings::to_utf8(procarch)).value_or_exit(VCPKG_LINE_INFO); } @@ -48,8 +48,8 @@ namespace vcpkg::System std::vector<CPUArchitecture> supported_architectures; supported_architectures.push_back(get_host_processor()); - //AMD64 machines support to run x86 applications - if(supported_architectures.back()==CPUArchitecture::X64) + // AMD64 machines support to run x86 applications + if (supported_architectures.back() == CPUArchitecture::X64) { supported_architectures.push_back(CPUArchitecture::X86); } @@ -59,10 +59,10 @@ namespace vcpkg::System int cmd_execute_clean(const CWStringView cmd_line) { - static const std::wstring system_root = get_environment_variable(L"SystemRoot").value_or_exit(VCPKG_LINE_INFO); - static const std::wstring system_32 = system_root + LR"(\system32)"; - static const std::wstring new_PATH = Strings::wformat( - LR"(Path=%s;%s;%s\Wbem;%s\WindowsPowerShell\v1.0\)", system_32, system_root, system_32, system_32); + static const std::wstring SYSTEM_ROOT = get_environment_variable(L"SystemRoot").value_or_exit(VCPKG_LINE_INFO); + static const std::wstring SYSTEM_32 = SYSTEM_ROOT + LR"(\system32)"; + static const std::wstring NEW_PATH = Strings::wformat( + LR"(Path=%s;%s;%s\Wbem;%s\WindowsPowerShell\v1.0\)", SYSTEM_32, SYSTEM_ROOT, SYSTEM_32, SYSTEM_32); std::vector<std::wstring> env_wstrings = { L"ALLUSERSPROFILE", @@ -106,6 +106,8 @@ namespace vcpkg::System L"HTTPS_PROXY", // Enables find_package(CUDA) in CMake L"CUDA_PATH", + // Environmental variable generated automatically by CUDA after installation + L"NVCUDASAMPLES_ROOT", }; // Flush stdout before launching external process @@ -116,7 +118,7 @@ namespace vcpkg::System for (auto&& env_wstring : env_wstrings) { const Optional<std::wstring> value = System::get_environment_variable(env_wstring); - auto v = value.get(); + const auto v = value.get(); if (!v || v->empty()) continue; env_cstr.append(env_wstring); @@ -125,7 +127,7 @@ namespace vcpkg::System env_cstr.push_back(L'\0'); } - env_cstr.append(new_PATH); + env_cstr.append(NEW_PATH); env_cstr.push_back(L'\0'); STARTUPINFOW startup_info; @@ -153,7 +155,7 @@ namespace vcpkg::System CloseHandle(process_info.hThread); - DWORD result = WaitForSingleObject(process_info.hProcess, INFINITE); + const DWORD result = WaitForSingleObject(process_info.hProcess, INFINITE); Checks::check_exit(VCPKG_LINE_INFO, result != WAIT_FAILED, "WaitForSingleObject failed"); DWORD exit_code = 0; @@ -171,11 +173,22 @@ namespace vcpkg::System // Basically we are wrapping it in quotes const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line); Debug::println("_wsystem(%s)", Strings::to_utf8(actual_cmd_line)); - int exit_code = _wsystem(actual_cmd_line.c_str()); + const int exit_code = _wsystem(actual_cmd_line.c_str()); Debug::println("_wsystem() returned %d", exit_code); return exit_code; } + // On Win7, output from powershell calls contain a byte order mark, so we strip it out if it is present + static void remove_byte_order_marks(std::wstring* s) + { + const wchar_t* a = s->c_str(); + // This is the UTF-8 byte-order mark + while (s->size() >= 3 && a[0] == 0xEF && a[1] == 0xBB && a[2] == 0xBF) + { + s->erase(0, 3); + } + } + ExitCodeAndOutput cmd_execute_and_capture_output(const CWStringView cmd_line) { // Flush stdout before launching external process @@ -184,24 +197,26 @@ namespace vcpkg::System const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s 2>&1")###", cmd_line); Debug::println("_wpopen(%s)", Strings::to_utf8(actual_cmd_line)); - std::string output; - char buf[1024]; - auto pipe = _wpopen(actual_cmd_line.c_str(), L"r"); + std::wstring output; + wchar_t buf[1024]; + const auto pipe = _wpopen(actual_cmd_line.c_str(), L"r"); if (pipe == nullptr) { - return {1, output}; + return {1, Strings::to_utf8(output)}; } - while (fgets(buf, 1024, pipe)) + while (fgetws(buf, 1024, pipe)) { output.append(buf); } if (!feof(pipe)) { - return {1, output}; + return {1, Strings::to_utf8(output)}; } - auto ec = _pclose(pipe); - Debug::println("_wpopen() returned %d", ec); - return {ec, output}; + + const auto ec = _pclose(pipe); + Debug::println("_pclose() returned %d", ec); + remove_byte_order_marks(&output); + return {ec, Strings::to_utf8(output)}; } std::wstring create_powershell_script_cmd(const fs::path& script_path, const CWStringView args) @@ -211,7 +226,9 @@ namespace vcpkg::System LR"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.native(), args); } - void print(const CStringView message) { fputs(message, stdout); } + void println() { println(Strings::EMPTY); } + + void print(const CStringView message) { fputs(message.c_str(), stdout); } void println(const CStringView message) { @@ -221,15 +238,15 @@ namespace vcpkg::System void print(const Color c, const CStringView message) { - HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + const HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE); - CONSOLE_SCREEN_BUFFER_INFO consoleScreenBufferInfo{}; - GetConsoleScreenBufferInfo(hConsole, &consoleScreenBufferInfo); - auto original_color = consoleScreenBufferInfo.wAttributes; + CONSOLE_SCREEN_BUFFER_INFO console_screen_buffer_info{}; + GetConsoleScreenBufferInfo(console_handle, &console_screen_buffer_info); + const auto original_color = console_screen_buffer_info.wAttributes; - SetConsoleTextAttribute(hConsole, static_cast<WORD>(c) | (original_color & 0xF0)); + SetConsoleTextAttribute(console_handle, static_cast<WORD>(c) | (original_color & 0xF0)); print(message); - SetConsoleTextAttribute(hConsole, original_color); + SetConsoleTextAttribute(console_handle, original_color); } void println(const Color c, const CStringView message) @@ -240,13 +257,13 @@ namespace vcpkg::System Optional<std::wstring> get_environment_variable(const CWStringView varname) noexcept { - auto sz = GetEnvironmentVariableW(varname, nullptr, 0); + const auto sz = GetEnvironmentVariableW(varname.c_str(), nullptr, 0); if (sz == 0) return nullopt; std::wstring ret(sz, L'\0'); Checks::check_exit(VCPKG_LINE_INFO, MAXDWORD >= ret.size()); - auto sz2 = GetEnvironmentVariableW(varname, ret.data(), static_cast<DWORD>(ret.size())); + const auto sz2 = GetEnvironmentVariableW(varname.c_str(), ret.data(), static_cast<DWORD>(ret.size())); Checks::check_exit(VCPKG_LINE_INFO, sz2 + 1 == sz); ret.pop_back(); return ret; @@ -257,59 +274,60 @@ namespace vcpkg::System return hkey_type == REG_SZ || hkey_type == REG_MULTI_SZ || hkey_type == REG_EXPAND_SZ; } - Optional<std::wstring> get_registry_string(HKEY base, const CWStringView subKey, const CWStringView valuename) + Optional<std::wstring> get_registry_string(HKEY base, const CWStringView sub_key, const CWStringView valuename) { HKEY k = nullptr; - LSTATUS ec = RegOpenKeyExW(base, subKey, NULL, KEY_READ, &k); + const LSTATUS ec = RegOpenKeyExW(base, sub_key.c_str(), NULL, KEY_READ, &k); if (ec != ERROR_SUCCESS) return nullopt; - DWORD dwBufferSize = 0; - DWORD dwType = 0; - auto rc = RegQueryValueExW(k, valuename, nullptr, &dwType, nullptr, &dwBufferSize); - if (rc != ERROR_SUCCESS || !is_string_keytype(dwType) || dwBufferSize == 0 || - dwBufferSize % sizeof(wchar_t) != 0) + DWORD dw_buffer_size = 0; + DWORD dw_type = 0; + auto rc = RegQueryValueExW(k, valuename.c_str(), nullptr, &dw_type, nullptr, &dw_buffer_size); + if (rc != ERROR_SUCCESS || !is_string_keytype(dw_type) || dw_buffer_size == 0 || + dw_buffer_size % sizeof(wchar_t) != 0) return nullopt; std::wstring ret; - ret.resize(dwBufferSize / sizeof(wchar_t)); + ret.resize(dw_buffer_size / sizeof(wchar_t)); - rc = RegQueryValueExW(k, valuename, nullptr, &dwType, reinterpret_cast<LPBYTE>(ret.data()), &dwBufferSize); - if (rc != ERROR_SUCCESS || !is_string_keytype(dwType) || dwBufferSize != sizeof(wchar_t) * ret.size()) + rc = RegQueryValueExW( + k, valuename.c_str(), nullptr, &dw_type, reinterpret_cast<LPBYTE>(ret.data()), &dw_buffer_size); + if (rc != ERROR_SUCCESS || !is_string_keytype(dw_type) || dw_buffer_size != sizeof(wchar_t) * ret.size()) return nullopt; ret.pop_back(); // remove extra trailing null byte return ret; } - static const fs::path& get_ProgramFiles() + static const fs::path& get_program_files() { - static const fs::path p = System::get_environment_variable(L"PROGRAMFILES").value_or_exit(VCPKG_LINE_INFO); - return p; + static const fs::path PATH = System::get_environment_variable(L"PROGRAMFILES").value_or_exit(VCPKG_LINE_INFO); + return PATH; } - const fs::path& get_ProgramFiles_32_bit() + const fs::path& get_program_files_32_bit() { - static const fs::path p = []() -> fs::path { + static const fs::path PATH = []() -> fs::path { auto value = System::get_environment_variable(L"ProgramFiles(x86)"); if (auto v = value.get()) { return std::move(*v); } - return get_ProgramFiles(); + return get_program_files(); }(); - return p; + return PATH; } - const fs::path& get_ProgramFiles_platform_bitness() + const fs::path& get_program_files_platform_bitness() { - static const fs::path p = []() -> fs::path { + static const fs::path PATH = []() -> fs::path { auto value = System::get_environment_variable(L"ProgramW6432"); if (auto v = value.get()) { return std::move(*v); } - return get_ProgramFiles(); + return get_program_files(); }(); - return p; + return PATH; } } diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp index 96e9f05e1..5cdafdbc8 100644 --- a/toolsrc/src/vcpkglib.cpp +++ b/toolsrc/src/vcpkglib.cpp @@ -39,7 +39,7 @@ namespace vcpkg { auto& fs = paths.get_filesystem(); - auto updates_dir = paths.vcpkg_dir_updates; + const auto updates_dir = paths.vcpkg_dir_updates; std::error_code ec; fs.create_directory(paths.installed, ec); @@ -90,9 +90,9 @@ namespace vcpkg static int update_id = 0; auto& fs = paths.get_filesystem(); - auto my_update_id = update_id++; - auto tmp_update_filename = paths.vcpkg_dir_updates / "incomplete"; - auto update_filename = paths.vcpkg_dir_updates / std::to_string(my_update_id); + const auto my_update_id = update_id++; + const auto tmp_update_filename = paths.vcpkg_dir_updates / "incomplete"; + const auto update_filename = paths.vcpkg_dir_updates / std::to_string(my_update_id); fs.write_contents(tmp_update_filename, Strings::serialize(p)); fs.rename(tmp_update_filename, update_filename); @@ -189,7 +189,7 @@ namespace vcpkg for (const std::unique_ptr<StatusParagraph>& pgh : status_db) { - if (pgh->state != InstallState::INSTALLED || pgh->package.feature != "") + if (pgh->state != InstallState::INSTALLED || !pgh->package.feature.empty()) { continue; } @@ -233,7 +233,7 @@ namespace vcpkg const fs::path& cmake_script, const std::vector<CMakeVariable>& pass_variables) { - std::wstring cmd_cmake_pass_variables = Strings::join(L" ", pass_variables, [](auto&& v) { return v.s; }); + const std::wstring cmd_cmake_pass_variables = Strings::join(L" ", pass_variables, [](auto&& v) { return v.s; }); return Strings::wformat( LR"("%s" %s -P "%s")", cmake_exe.native(), cmd_cmake_pass_variables, cmake_script.generic_wstring()); } |
