Skip to content

Commit

Permalink
Use system CMake to unpack if available during 7z bootstrap (#793)
Browse files Browse the repository at this point in the history
* Use installed CMake to unpack if available during 7z bootstrap

* Document fallbacks
  • Loading branch information
vicroms authored Nov 10, 2022
1 parent 837ecfc commit 3c8138a
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 9 deletions.
3 changes: 3 additions & 0 deletions include/vcpkg/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -51,6 +53,7 @@ namespace vcpkg
const Path& exe_path);

ExpectedL<Path> find_system_tar(const Filesystem& fs);
ExpectedL<Path> find_system_cmake(const Filesystem& fs);

std::unique_ptr<ToolCache> get_tool_cache(Filesystem& fs,
std::shared_ptr<const DownloadManager> downloader,
Expand Down
32 changes: 23 additions & 9 deletions src/vcpkg/archives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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);
}
Expand Down
37 changes: 37 additions & 0 deletions src/vcpkg/tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
Expand Down Expand Up @@ -899,6 +903,39 @@ namespace vcpkg
}
}

ExpectedL<Path> 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<Path> 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<ToolCache> get_tool_cache(Filesystem& fs,
std::shared_ptr<const DownloadManager> downloader,
Path downloads,
Expand Down

0 comments on commit 3c8138a

Please sign in to comment.