From 3c8138a40af0a29db2037827c101d608989ca69e Mon Sep 17 00:00:00 2001 From: Victor Romero Date: Wed, 9 Nov 2022 20:32:38 -0800 Subject: [PATCH] Use system CMake to unpack if available during 7z bootstrap (#793) * Use installed CMake to unpack if available during 7z bootstrap * Document fallbacks --- include/vcpkg/tools.h | 3 +++ src/vcpkg/archives.cpp | 32 +++++++++++++++++++++++--------- src/vcpkg/tools.cpp | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/include/vcpkg/tools.h b/include/vcpkg/tools.h index 3f4f8a22b6..e6ae3cb26e 100644 --- a/include/vcpkg/tools.h +++ b/include/vcpkg/tools.h @@ -31,6 +31,8 @@ namespace vcpkg static constexpr StringLiteral ARIA2 = "aria2"; static constexpr StringLiteral NODE = "node"; static constexpr StringLiteral IFW_INSTALLER_BASE = "ifw_installerbase"; + // This duplicate of CMake should only be used as a fallback to unpack + static constexpr StringLiteral CMAKE_SYSTEM = "cmake_system"; // This duplicate of 7zip uses msiexec to unpack, which is a fallback for Windows 7. static constexpr StringLiteral SEVEN_ZIP_MSI = "7zip_msi"; static constexpr StringLiteral PYTHON3 = "python3"; @@ -51,6 +53,7 @@ namespace vcpkg const Path& exe_path); ExpectedL find_system_tar(const Filesystem& fs); + ExpectedL find_system_cmake(const Filesystem& fs); std::unique_ptr get_tool_cache(Filesystem& fs, std::shared_ptr downloader, diff --git a/src/vcpkg/archives.cpp b/src/vcpkg/archives.cpp index ff341046be..591594d1fc 100644 --- a/src/vcpkg/archives.cpp +++ b/src/vcpkg/archives.cpp @@ -217,6 +217,17 @@ namespace vcpkg fs.write_contents(to_path, contents, VCPKG_LINE_INFO); } + // We are trying to bootstrap vcpkg's copy of CMake which comes in a zipped file. + // If this is successful, we'll use the downloaded CMake for most extractions. + // We will also extract a portable 7z (using the bootstrapped CMake) to use when performance is required. + // + // We use the following methods to attempt this bootstrap, in order: + // 1) Search for a System32/tar.exe (available on Windows 10+) + // tar.exe unpacks cmake.zip -> cmake.exe unpacks 7z.7z + // 2) Search for a user installed CMake on PATH and Program Files [(x86)] + // (user) cmake.exe unpacks cmake.zip -> (vcpkg) cmake.exe unpacks 7z.7z + // 3) As a last resource, install 7zip using a MSI installer + // msiexec installs 7zip.msi -> 7zip unpacks cmake.zip -> cmake.exe unpacks 7z.7z void win32_extract_bootstrap_zip( Filesystem& fs, const ToolCache& tools, MessageSink& status_sink, const Path& archive, const Path& to_path) { @@ -229,19 +240,22 @@ namespace vcpkg if (fs.exists(tar_path, IgnoreErrors{})) { // On Windows 10, tar.exe is in the box. - - // Example: - // tar unpacks cmake unpacks 7zip unpacks git extract_tar(tar_path, archive, to_path_partial); } else { - // On Windows <10, we attempt to use msiexec to unpack 7zip. - - // Example: - // msiexec unpacks 7zip_msi unpacks cmake unpacks 7zip unpacks git - win32_extract_with_seven_zip( - tools.get_tool_path(Tools::SEVEN_ZIP_MSI, status_sink), archive, to_path_partial); + auto maybe_cmake_tool = find_system_cmake(fs); + if (maybe_cmake_tool) + { + // If the user has a CMake version installed we can use that to unpack. + extract_tar_cmake(maybe_cmake_tool.value_or_exit(VCPKG_LINE_INFO), archive, to_path_partial); + } + else + { + // On Windows <10, we attempt to use msiexec to unpack 7zip. + win32_extract_with_seven_zip( + tools.get_tool_path(Tools::SEVEN_ZIP_MSI, status_sink), archive, to_path_partial); + } } fs.rename_with_retry(to_path_partial, to_path, VCPKG_LINE_INFO); } diff --git a/src/vcpkg/tools.cpp b/src/vcpkg/tools.cpp index 63ac1b1689..9bb2f1d7d6 100644 --- a/src/vcpkg/tools.cpp +++ b/src/vcpkg/tools.cpp @@ -868,6 +868,10 @@ namespace vcpkg { return {find_system_tar(fs).value_or_exit(VCPKG_LINE_INFO), {}}; } + if (tool == Tools::CMAKE_SYSTEM) + { + return {find_system_cmake(fs).value_or_exit(VCPKG_LINE_INFO), {}}; + } GenericToolProvider provider{tool}; return get_path(provider, status_sink); }); @@ -899,6 +903,39 @@ namespace vcpkg } } + ExpectedL find_system_cmake(const Filesystem& fs) + { + auto tools = fs.find_from_PATH(Tools::CMAKE); + if (!tools.empty()) + { + return std::move(tools[0]); + } + +#if defined(_WIN32) + std::vector candidate_paths; + const auto& program_files = get_program_files_platform_bitness(); + if (const auto pf = program_files.get()) + { + auto path = *pf / "CMake" / "bin" / "cmake.exe"; + if (fs.exists(path, IgnoreErrors{})) return path; + } + + const auto& program_files_32_bit = get_program_files_32_bit(); + if (const auto pf = program_files_32_bit.get()) + { + auto path = *pf / "CMake" / "bin" / "cmake.exe"; + if (fs.exists(path, IgnoreErrors{})) return path; + } +#endif + + return msg::format(msg::msgErrorMessage) + .append(msgToolFetchFailed, msg::tool_name = Tools::CMAKE) +#if !defined(_WIN32) + .append(msgInstallWithSystemManager) +#endif + ; + } + std::unique_ptr get_tool_cache(Filesystem& fs, std::shared_ptr downloader, Path downloads,