/dev/null'); if (!empty($phpDir)) { return trim($phpDir); } $phpExe = trim(shell_exec('which php 2>/dev/null')); if ($phpExe && file_exists($phpExe)) { $phpDir = dirname(dirname($phpExe)); if (is_dir($phpDir)) { return $phpDir; } } throw new \RuntimeException('The `php-config` is not found. Please install PHP development package or set PHP_HOME environment variable'); } public function getIntegerLiteralSuffix(): string { return 'L'; } /** * 获取 RPATH 选项 */ public function getRpathOptions(array $paths): string { if (empty($paths)) { return ''; } $rpaths = []; foreach ($paths as $path) { $rpaths[] = '-Wl,-rpath,' . escapeshellarg($path); } return implode(' ', $rpaths); } /** * 获取 PIC 选项 */ public function getPicFlag(): string { return '-fPIC'; } /** * 获取共享库链接选项 */ public function getSharedLinkFlag(): string { return '-shared'; } /** * 构建 PHP 包含路径(使用 php-config 动态获取) */ public function buildPhpIncludePaths(string $phpDir): array { // 优先使用 php-config 获取包含路径 $phpConfigPath = $this->findPhpConfig($phpDir); if ($phpConfigPath) { $includes = shell_exec("{$phpConfigPath} --includes 2>/dev/null"); if ($includes) { // 解析 -I/path 格式的路径 preg_match_all('/-I([^\s]+)/', $includes, $matches); if (!empty($matches[1])) { // 过滤不存在的路径并返回 return array_filter($matches[1], 'is_dir'); } } } // 回退到硬编码路径(兼容旧版本) $paths = [ $phpDir . '/include/php', $phpDir . '/include/php/main', $phpDir . '/include/php/TSRM', $phpDir . '/include/php/Zend', $phpDir . '/include/php/ext', ]; // 过滤不存在的路径 return array_filter($paths, 'is_dir'); } /** * 查找 php-config 可执行文件 */ private function findPhpConfig(string $phpDir): ?string { // 优先使用 PHP_DIR 指定的路径 $candidate = $phpDir . '/bin/php-config'; if (is_executable($candidate)) { return $candidate; } // 回退到 PATH 中查找(通过 which 命令) $whichResult = trim(shell_exec('which php-config 2>/dev/null')); if ($whichResult && is_executable($whichResult)) { return $whichResult; } return null; } /** * 构建 PHP 库路径 */ public function buildPhpLibPaths(string $phpDir): array { $paths = []; $libPath = $phpDir . '/lib'; if (is_dir($libPath)) { $paths[] = $libPath; } return $paths; } /** * 检测 PHP 库文件 */ public function detectPhpLibs(string $phpDir): array { $libPath = $phpDir . '/lib'; if (!is_dir($libPath)) { throw new \RuntimeException("PHP lib directory not found: {$libPath}"); } $embedLib = $libPath . '/libphp.so'; $staticLib = $libPath . '/libphp.a'; $hasEmbed = file_exists($embedLib); $hasStatic = file_exists($staticLib); if (!$hasEmbed && !$hasStatic) { throw new \RuntimeException('Neither libphp.so nor libphp.a found'); } return [ 'embed' => $hasEmbed ? $embedLib : null, 'static' => $hasStatic ? $staticLib : null, 'is_shared' => $hasEmbed, ]; } }