fix(platform): honor php-config library directory

fix gh-7
master
韩天峰 1 day ago
parent c9d9f58de0
commit 1488563a27
  1. 9
      src/Installer/LibPhpInstaller.php
  2. 4
      src/Platform/Macos.php
  3. 9
      src/Platform/PlatformBase.php
  4. 79
      src/Platform/UnixPlatform.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

@ -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;
}
}

@ -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",

@ -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");

Loading…
Cancel
Save