From 1488563a276849bb96d3ea540415a4576b869ff5 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Thu, 27 Aug 2026 17:07:58 +0800 Subject: [PATCH] fix(platform): honor php-config library directory fix gh-7 --- src/Installer/LibPhpInstaller.php | 9 +++- src/Platform/Macos.php | 4 +- src/Platform/PlatformBase.php | 9 ++-- src/Platform/UnixPlatform.php | 79 ++++++++++++++++++++++++------- 4 files changed, 77 insertions(+), 24 deletions(-) diff --git a/src/Installer/LibPhpInstaller.php b/src/Installer/LibPhpInstaller.php index a894cba5..cbe06e76 100644 --- a/src/Installer/LibPhpInstaller.php +++ b/src/Installer/LibPhpInstaller.php @@ -2,6 +2,8 @@ namespace TypePhp\Installer; +use TypePhp\Platform\Linux; + final class LibPhpInstaller { private const string RELEASE_API = 'https://www.php.net/releases/index.php?json=1&version=%s&max=100'; @@ -51,7 +53,12 @@ final class LibPhpInstaller public function hasLibPhp(string $prefix): bool { - return is_file($prefix . '/lib/libphp.so') || is_file($prefix . '/lib/libphp.a'); + try { + (new Linux())->detectPhpLibs(rtrim($prefix, '/')); + return true; + } catch (\RuntimeException) { + return false; + } } public function installedVersion(string $prefix): ?string diff --git a/src/Platform/Macos.php b/src/Platform/Macos.php index da36b723..3b8d85e5 100644 --- a/src/Platform/Macos.php +++ b/src/Platform/Macos.php @@ -92,8 +92,8 @@ class Macos extends UnixPlatform } if ($phpDir !== null) { - $phpLibDir = $phpDir . '/lib'; - if (is_dir($phpLibDir)) { + $phpLibDir = $this->resolvePhpLibDir($phpDir); + if ($phpLibDir !== null) { $rpaths[] = $phpLibDir; } } diff --git a/src/Platform/PlatformBase.php b/src/Platform/PlatformBase.php index 48d244fe..10a1d678 100644 --- a/src/Platform/PlatformBase.php +++ b/src/Platform/PlatformBase.php @@ -117,16 +117,19 @@ abstract class PlatformBase return []; } - $ext = ltrim($this->getSharedLibraryExtension(), '.'); $warnings = []; - if (!is_file($phpDir . '/lib/libphp.' . $ext)) { + try { + $this->detectPhpLibs($phpDir); + } catch (\RuntimeException $e) { + $ext = ltrim($this->getSharedLibraryExtension(), '.'); $warnings[] = [ 'warning' => "The `libphp.{$ext}` is not found", - 'info' => 'Run tpc.php in an interactive terminal to build it automatically, or set PHP_HOME', + 'info' => $e->getMessage() . '. Run tpc.php in an interactive terminal to build it automatically, or set PHP_HOME', ]; } + $ext = ltrim($this->getSharedLibraryExtension(), '.'); if (!is_file($phpxDir . '/lib/libphpx.' . $ext)) { $warnings[] = [ 'warning' => "The `libphpx.{$ext}` is not found", diff --git a/src/Platform/UnixPlatform.php b/src/Platform/UnixPlatform.php index 76fca93d..e2f101f5 100644 --- a/src/Platform/UnixPlatform.php +++ b/src/Platform/UnixPlatform.php @@ -160,7 +160,7 @@ abstract class UnixPlatform extends PlatformBase { $phpConfigPath = $this->findPhpConfig($phpDir); if ($phpConfigPath) { - $includes = shell_exec("{$phpConfigPath} --includes 2>/dev/null"); + $includes = shell_exec(escapeshellarg($phpConfigPath) . ' --includes 2>/dev/null'); if ($includes) { preg_match_all('/-I([^\s]+)/', $includes, $matches); if (!empty($matches[1])) { @@ -205,25 +205,47 @@ abstract class UnixPlatform extends PlatformBase $whichResult = trim(shell_exec('which php-config 2>/dev/null')); if ($whichResult && is_executable($whichResult)) { - return $whichResult; + $prefix = $this->getPhpConfigValue($whichResult, '--prefix'); + $expected = realpath($phpDir) ?: rtrim($phpDir, '/'); + $actual = $prefix === null ? null : (realpath($prefix) ?: rtrim($prefix, '/')); + if ($actual === $expected) { + return $whichResult; + } } return null; } + protected function getPhpConfigValue(string $phpConfig, string $option): ?string + { + $value = shell_exec(escapeshellarg($phpConfig) . ' ' . escapeshellarg($option) . ' 2>/dev/null'); + if (!is_string($value) || trim($value) === '') { + return null; + } + return trim($value); + } + + protected function resolvePhpLibDir(string $phpDir): ?string + { + $phpConfig = $this->findPhpConfig($phpDir); + if ($phpConfig !== null) { + $libDir = $this->getPhpConfigValue($phpConfig, '--lib-dir'); + if ($libDir !== null && is_dir($libDir)) { + return rtrim($libDir, '/'); + } + } + + $libDir = rtrim($phpDir, '/') . '/lib'; + return is_dir($libDir) ? $libDir : null; + } + /** * 构建 PHP 库路径 */ public function buildPhpLibPaths(string $phpDir): array { - $paths = []; - - $libPath = $phpDir . '/lib'; - if (is_dir($libPath)) { - $paths[] = $libPath; - } - - return $paths; + $libPath = $this->resolvePhpLibDir($phpDir); + return $libPath === null ? [] : [$libPath]; } /** @@ -231,18 +253,39 @@ abstract class UnixPlatform extends PlatformBase */ public function detectPhpLibs(string $phpDir): array { - $libPath = $phpDir . '/lib'; - - if (!is_dir($libPath)) { - throw new \RuntimeException("PHP lib directory not found: {$libPath}"); + $libPath = $this->resolvePhpLibDir($phpDir); + if ($libPath === null) { + throw new \RuntimeException("PHP library directory not found for installation: {$phpDir}"); } $ext = ltrim($this->getSharedLibraryExtension(), '.'); - $embedLib = $libPath . '/libphp.' . $ext; - $staticLib = $libPath . '/libphp.a'; + $embedLib = null; + $staticLib = null; + + $phpConfig = $this->findPhpConfig($phpDir); + $configuredEmbed = $phpConfig === null ? null : $this->getPhpConfigValue($phpConfig, '--lib-embed'); + if ($configuredEmbed !== null) { + $configuredPath = str_starts_with($configuredEmbed, '/') + ? $configuredEmbed + : $libPath . '/' . $configuredEmbed; + if (is_file($configuredPath)) { + if (str_ends_with($configuredPath, '.a')) { + $staticLib = $configuredPath; + } else { + $embedLib = $configuredPath; + } + } + } + + if ($embedLib === null && $staticLib === null) { + $sharedCandidate = $libPath . '/libphp.' . $ext; + $staticCandidate = $libPath . '/libphp.a'; + $embedLib = is_file($sharedCandidate) ? $sharedCandidate : null; + $staticLib = is_file($staticCandidate) ? $staticCandidate : null; + } - $hasEmbed = file_exists($embedLib); - $hasStatic = file_exists($staticLib); + $hasEmbed = $embedLib !== null; + $hasStatic = $staticLib !== null; if (!$hasEmbed && !$hasStatic) { throw new \RuntimeException("Neither libphp.{$ext} nor libphp.a found");