Refactor WindowsUtil to cache Visual Studio search results and add CMake find modules

This commit is contained in:
crazywhalecc
2026-03-21 00:30:30 +08:00
parent d1ec473f21
commit 1213cb578e

View File

@@ -8,8 +8,10 @@ use StaticPHP\Util\FileSystem;
class WindowsUtil
{
private static array|false|null $vsCache = null;
/**
* Find windows program using executable name.
* Find Windows program using executable name.
*
* @param string $name command name (xxx.exe)
* @param array $paths search path (default use env path)
@@ -39,6 +41,10 @@ class WindowsUtil
*/
public static function findVisualStudio(): array|false
{
if (self::$vsCache !== null) {
return self::$vsCache;
}
// call vswhere (need VS and C++ tools installed), output is json
$vswhere_exec = PKG_ROOT_PATH . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'vswhere.exe';
$args = [
@@ -49,13 +55,13 @@ class WindowsUtil
$cmd = escapeshellarg($vswhere_exec) . ' ' . implode(' ', $args);
$result = f_exec($cmd, $out, $code);
if ($code !== 0 || !$result) {
return false;
return self::$vsCache = false;
}
$json = json_decode(implode("\n", $out), true);
if (!is_array($json) || count($json) === 0) {
return false;
return self::$vsCache = false;
}
return [
return self::$vsCache = [
'version' => $json[0]['installationVersion'],
'major_version' => explode('.', $json[0]['installationVersion'])[0],
'dir' => $json[0]['installationPath'],
@@ -89,6 +95,7 @@ class WindowsUtil
$ldflags = '/nodefaultlib:msvcrt /nodefaultlib:msvcrtd /defaultlib:libcmt';
}
$buildroot = str_replace('\\', '\\\\', BUILD_ROOT_PATH);
$source = str_replace('\\', '/', SOURCE_PATH);
$toolchain = <<<CMAKE
set(CMAKE_SYSTEM_NAME Windows)
SET(CMAKE_SYSTEM_PROCESSOR x64)
@@ -99,11 +106,50 @@ SET(CMAKE_CXX_FLAGS_DEBUG "{$cflags}")
SET(CMAKE_EXE_LINKER_FLAGS "{$ldflags}")
SET(CMAKE_FIND_ROOT_PATH "{$buildroot}")
SET(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded)
list(PREPEND CMAKE_MODULE_PATH "{$source}/cmake-find")
CMAKE;
if (!is_dir(SOURCE_PATH)) {
FileSystem::createDir(SOURCE_PATH);
}
FileSystem::writeFile(SOURCE_PATH . '\toolchain.cmake', $toolchain);
self::writeCmakeFindModules();
return realpath(SOURCE_PATH . '\toolchain.cmake');
}
/**
* Write cmake-find wrapper modules to source/cmake-find/.
* These override cmake's built-in Find*.cmake modules to inject
* Windows-specific static library dependencies (e.g. zlib into OpenSSL).
* Called both from makeCmakeToolchainFile() and from WindowsCMakeExecutor
* so the modules are always present even when the static toolchain.cmake
* file is used directly without regeneration.
*/
public static function writeCmakeFindModules(): void
{
$cmake_find_dir = SOURCE_PATH . DIRECTORY_SEPARATOR . 'cmake-find';
if (!is_dir($cmake_find_dir)) {
FileSystem::createDir($cmake_find_dir);
}
FileSystem::writeFile($cmake_find_dir . DIRECTORY_SEPARATOR . 'FindOpenSSL.cmake', <<<'CMAKE'
# Custom FindOpenSSL.cmake wrapper for static-php-cli Windows builds.
if(WIN32 AND (OpenSSL_FOUND OR OPENSSL_FOUND))
list(GET CMAKE_FIND_ROOT_PATH 0 _spc_buildroot)
# Normalize to forward slashes — backslash paths cause 'Invalid character
# escape' errors when cmake parses them inside string arguments.
file(TO_CMAKE_PATH "${_spc_buildroot}" _spc_buildroot)
set(_spc_zlib "${_spc_buildroot}/lib/zlibstatic.lib")
if(EXISTS "${_spc_zlib}")
foreach(_spc_var OPENSSL_LIBRARIES OPENSSL_CRYPTO_LIBRARIES OPENSSL_SSL_LIBRARIES)
if(DEFINED ${_spc_var} AND NOT "${_spc_zlib}" IN_LIST ${_spc_var})
list(APPEND ${_spc_var} "${_spc_zlib}")
endif()
endforeach()
endif()
unset(_spc_buildroot)
unset(_spc_zlib)
unset(_spc_var)
endif()
CMAKE);
}
}