From 7c2192ff5407d50fbd9b2b742d3be1a1f6f52b3d Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Wed, 24 Jun 2026 11:21:09 +0800 Subject: [PATCH] =?UTF-8?q?refactor(backend):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=BC=96=E8=AF=91=E5=99=A8=E5=90=8E=E7=AB=AF=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E4=BB=A5=E6=94=AF=E6=8C=81=20GCC/Clang=20=E5=85=B1=E4=BA=AB?= =?UTF-8?q?=E5=9F=BA=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 Clang 和 GCC 后端重构为继承自新的 GccLikeBackend 基类 - 移除重复的编译和链接命令构建逻辑 - 添加平台特定的钩子方法用于扩展功能 - 在 FunctionContext 中添加 SSA 构建器属性 - 统一编译器和链接器命令的初始化方式 - 优化 Windows 平台兼容性处理逻辑 --- phpunit/src/SsaAnalysisTest.php | 2 +- src/Php/Backend/Clang.php | 452 +++------------------------- src/Php/Backend/Gcc.php | 359 +--------------------- src/Php/Backend/GccLikeBackend.php | 355 ++++++++++++++++++++++ src/Php/Context/FunctionContext.php | 4 + src/Php/Platform/Linux.php | 209 +------------ src/Php/Platform/Macos.php | 217 +------------ src/Php/Platform/UnixPlatform.php | 211 +++++++++++++ src/Php/Translator.php | 1 + 9 files changed, 615 insertions(+), 1195 deletions(-) create mode 100644 src/Php/Backend/GccLikeBackend.php create mode 100644 src/Php/Platform/UnixPlatform.php diff --git a/phpunit/src/SsaAnalysisTest.php b/phpunit/src/SsaAnalysisTest.php index f10f710d..1765c3de 100644 --- a/phpunit/src/SsaAnalysisTest.php +++ b/phpunit/src/SsaAnalysisTest.php @@ -108,7 +108,7 @@ class SsaAnalysisTest extends TestCase $builder->build(); $this->setContextProperty('ssaBuilder', $builder); - $this->invoke('optimizeLoopVars'); + $this->invoke('optimizeLoopVars', $builder); return $this->getContextProperty('localVars'); } diff --git a/src/Php/Backend/Clang.php b/src/Php/Backend/Clang.php index 23ed1f2b..dbd8c0c3 100644 --- a/src/Php/Backend/Clang.php +++ b/src/Php/Backend/Clang.php @@ -3,20 +3,17 @@ namespace PhpAot\Php\Backend; use PhpAot\Php\Platform\PlatformBase; +use PhpAot\Php\Platform\Windows; +use PhpAot\Php\Platform\Macos; /** * Clang 编译器后端实现 */ -class Clang extends CompilerBackend +class Clang extends GccLikeBackend { - private string $compilerCommand; - private ?string $linkerCommand; - public function __construct(PlatformBase $platform, string $compilerCommand = 'clang++', ?string $linkerCommand = null) { - parent::__construct($platform); - $this->compilerCommand = $compilerCommand; - $this->linkerCommand = $linkerCommand; + parent::__construct($platform, $compilerCommand, $linkerCommand); } public function getName(): string @@ -24,19 +21,13 @@ class Clang extends CompilerBackend return 'Clang'; } - public function getCompilerCommand(): string - { - return $this->compilerCommand; - } - public function getLinkerCommand(): string { if ($this->linkerCommand !== null) { return $this->linkerCommand; } - // Windows 下使用 MSVC 链接器,其他平台使用 clang++ - if ($this->platform instanceof \PhpAot\Php\Platform\Windows) { + if ($this->platform instanceof Windows) { return 'link'; } return $this->compilerCommand; @@ -71,445 +62,72 @@ class Clang extends CompilerBackend return 'link'; } - public function compileFile( - string $sourceFile, - string $outputFile, - array $includePaths = [], - array $defines = [], - array $flags = [] - ): string { - $cmd = $this->getCompilerCommand(); - - // Windows 下需要 MSVC 兼容模式 - if ($this->platform instanceof \PhpAot\Php\Platform\Windows) { - $cmd .= ' -fms-compatibility'; - $cmd .= ' -fms-compatibility-version=19.40'; - $cmd .= ' -fdelayed-template-parsing'; - $cmd .= ' -fms-extensions'; - } - - $cmd .= ' -c ' . escapeshellarg($sourceFile); - $cmd .= ' -o ' . escapeshellarg($outputFile); - - // 添加包含路径 - if (!empty($includePaths)) { - $cmd .= ' ' . $this->formatIncludePaths($includePaths); - } - - // 添加宏定义 - foreach ($defines as $define) { - $cmd .= ' -D' . $define; - } - - // 添加额外标志 - if (!empty($flags)) { - $cmd .= ' ' . implode(' ', $flags); - } - - return $cmd; - } - - public function linkObjects( - array $objectFiles, - string $outputFile, - array $libraryPaths = [], - array $libraries = [], - array $flags = [] - ): string { - $cmd = $this->getLinkerCommand(); - - // 添加目标文件 - $cmd .= ' ' . implode(' ', array_map('escapeshellarg', $objectFiles)); - - // 输出文件 - if ($this->platform instanceof \PhpAot\Php\Platform\Windows) { - $cmd .= ' /OUT:' . escapeshellarg($outputFile); - } else { - $cmd .= ' -o ' . escapeshellarg($outputFile); - } - - // 添加库路径 - if (!empty($libraryPaths)) { - $cmd .= ' ' . $this->formatLibraryPaths($libraryPaths); - } - - // 添加库文件 - if (!empty($libraries)) { - $cmd .= ' ' . $this->formatLibraries($libraries); - } - - // 添加额外标志 - if (!empty($flags)) { - $cmd .= ' ' . implode(' ', $flags); - } - - return $cmd; - } + // ──── 钩子方法覆盖 ──── - public function buildCompileCommand(string $sourceFile, string $outputFile, array $options = []): string + protected function getCompilerPrefixFlags(): string { - $cmd = $this->getCompilerCommand(); - - // Windows 下需要 MSVC 兼容模式 - if ($this->platform instanceof \PhpAot\Php\Platform\Windows) { - $cmd .= ' -fms-compatibility'; - $cmd .= ' -fms-compatibility-version=19.40'; - $cmd .= ' -fdelayed-template-parsing'; - $cmd .= ' -fms-extensions'; - } - - $cmd .= ' -c'; - $cmd .= ' ' . escapeshellarg($sourceFile); - $cmd .= ' -o ' . escapeshellarg($outputFile); - - if (!empty($options['include_paths'])) { - $cmd .= ' ' . $this->formatIncludePaths($options['include_paths']); + if ($this->platform instanceof Windows) { + return ' -fms-compatibility' + . ' -fms-compatibility-version=19.40' + . ' -fdelayed-template-parsing' + . ' -fms-extensions'; } - - $cmd .= $this->buildCompileOptions($options); - - return $cmd; + return ''; } - /** - * 构建 C 文件的编译命令(不包含 C++ 特定选项) - */ - public function buildCCompileCommand(string $sourceFile, string $outputFile, array $options = []): string + protected function getLinkerOutputFlag(): string { - $cmd = $this->getCompilerCommand(); - - // Windows 下需要 MSVC 兼容模式 - if ($this->platform instanceof \PhpAot\Php\Platform\Windows) { - $cmd .= ' -fms-compatibility'; - $cmd .= ' -fms-compatibility-version=19.40'; - $cmd .= ' -fdelayed-template-parsing'; - $cmd .= ' -fms-extensions'; - } - - $cmd .= ' -c'; - $cmd .= ' -x c'; - $cmd .= ' ' . escapeshellarg($sourceFile); - $cmd .= ' -o ' . escapeshellarg($outputFile); - - if (!empty($options['include_paths'])) { - $cmd .= ' ' . $this->formatIncludePaths($options['include_paths']); - } - - // 优化级别(C 文件通常使用较低的优化) - $optimizeLevel = $options['optimize'] ?? 0; - - // 调试模式 - if (!empty($options['debug'])) { - $cmd .= ' -O0 -g'; - } else { - $cmd .= ' -O' . $optimizeLevel; - } - - // 警告级别 - $cmd .= ' -Wall'; - - // 注意:C 文件不使用 -std=c++17 等 C++ 特定选项 - - return $cmd; + return $this->platform instanceof Windows ? '/OUT:' : '-o'; } - /** - * 构建原生源文件的编译命令(汇编/Objective-C 等) - * - * @param string $language 语言标识(assembler, objective-c, objective-c++) - */ - public function buildNativeCompileCommand(string $sourceFile, string $outputFile, array $options = [], string $language = ''): string + protected function formatSanitizerFlag(string $sanitizer): string { - $cmd = $this->getCompilerCommand(); - - // Windows 下需要 MSVC 兼容模式 - if ($this->platform instanceof \PhpAot\Php\Platform\Windows) { - $cmd .= ' -fms-compatibility'; - $cmd .= ' -fms-compatibility-version=19.40'; - $cmd .= ' -fdelayed-template-parsing'; - $cmd .= ' -fms-extensions'; - } - - $cmd .= ' -c'; - if ($language !== '') { - $cmd .= ' -x ' . $language; - } - $cmd .= ' ' . escapeshellarg($sourceFile); - $cmd .= ' -o ' . escapeshellarg($outputFile); - - if (!empty($options['include_paths'])) { - $cmd .= ' ' . $this->formatIncludePaths($options['include_paths']); - } - - $cmd .= $this->buildCompileOptions($options); - - return $cmd; + return '-fsanitize=' . $sanitizer; } - public function buildLinkCommand(array $objectFiles, string $outputFile, array $options = []): string - { - $cmd = $this->getLinkerCommand(); - $cmd .= ' ' . implode(' ', array_map('escapeshellarg', $objectFiles)); - - // Windows 使用 MSVC 链接器语法 - if ($this->platform instanceof \PhpAot\Php\Platform\Windows) { - $cmd .= ' /OUT:' . escapeshellarg($outputFile); - - } else { - $cmd .= ' -o ' . escapeshellarg($outputFile); - } - - if (!empty($options['library_paths'])) { - $cmd .= ' ' . $this->formatLibraryPaths($options['library_paths']); - } - - if (!empty($options['ldflags'])) { - $cmd .= ' ' . $options['ldflags']; - } - - $cmd .= $this->buildLinkOptions($options); - - if (!empty($options['libraries'])) { - $cmd .= ' ' . $this->formatLibraries($options['libraries']); - } - - return $cmd; - } - - /** - * 构建完整的编译选项 - */ - public function buildFullCompileOptions(array $options = []): string + protected function addPICFlag(array $config, string &$cmd): void { - $cmd = ''; - - // Windows MSVC 兼容模式 - if ($this->platform instanceof \PhpAot\Php\Platform\Windows) { - $cmd .= ' -fms-compatibility'; - $cmd .= ' -fms-compatibility-version=19.40'; - $cmd .= ' -fdelayed-template-parsing'; - $cmd .= ' -fms-extensions'; - } - - // 优化级别 - if (!empty($options['debug'])) { - $cmd .= ' -O0 -g'; - } else { - $optimizeLevel = $options['optimize'] ?? 2; - $cmd .= ' -O' . $optimizeLevel; - } - - // 警告 - $cmd .= ' -Wall'; - - // C++ 标准 - if (!empty($options['cpp_std'])) { - $cmd .= ' -std=' . $options['cpp_std']; - } - - // 目标 CPU 指令集 - if (!empty($options['march'])) { - $cmd .= ' -march=' . $options['march']; + if ($this->platform instanceof Windows) { + return; } - - // Sanitizer - if (!empty($options['sanitize'])) { - $cmd .= ' -fsanitize=' . $options['sanitize']; - } - - // PIC - if (!empty($options['pic'])) { + if ((!empty($config['build_mode']) && $config['build_mode'] === 'ext') || !empty($config['pic'])) { $cmd .= ' -fPIC'; } - - return $cmd; } - /** - * 构建完整的链接选项 - */ - public function buildFullLinkOptions(array $options = []): string + protected function addPlatformLinkFlags(array $config, string &$cmd): void { - $cmd = ''; - - // Windows 特定选项 - if ($this->platform instanceof \PhpAot\Php\Platform\Windows) { - // 调试 - if (!empty($options['debug'])) { + if ($this->platform instanceof Windows) { + if (!empty($config['debug'])) { $cmd .= ' /DEBUG'; } - - // Windows 子系统 - if (!empty($options['no_console'])) { + if (!empty($config['no_console'])) { $cmd .= ' ' . $this->platform->getSubsystemOptions(true); } - - // CRT $cmd .= ' ' . $this->platform->getCrtConfig(); - } else { - // Unix/Linux/macOS - // 共享库 - if (!empty($options['shared'])) { - $cmd .= ' ' . $this->platform->getSharedLinkFlag(); - } - - // RPATH - if (!empty($options['rpath'])) { - $cmd .= ' ' . $this->platform->getRpathOptions($options['rpath']); - } - } - - // Sanitizer - if (!empty($options['sanitize'])) { - $cmd .= ' -fsanitize=' . $options['sanitize']; - } - - return $cmd; - } - /** - * 构建编译选项(实现抽象方法) - */ - public function buildCompileOptions(array $config = []): string - { - $cmd = ''; - - // Windows MSVC 兼容模式 - if ($this->platform instanceof \PhpAot\Php\Platform\Windows) { - $cmd .= ' -fms-compatibility'; - $cmd .= ' -fms-compatibility-version=19.40'; - $cmd .= ' -fdelayed-template-parsing'; - $cmd .= ' -fms-extensions'; - } - - // Sanitizer - if (!empty($config['sanitize'])) { - $cmd .= ' -fsanitize=' . $config['sanitize']; - } - - // 优化和调试 - if (!empty($config['debug'])) { - $cmd .= ' -O0 -g'; - } else { - $optimizeLevel = $config['optimize'] ?? 2; - $cmd .= ' -O' . $optimizeLevel; - } - - // 警告 - $cmd .= ' -Wall'; - - // C++ 标准 - if (!empty($config['cpp_std'])) { - $cmd .= ' -std=' . $config['cpp_std']; - } - - // 目标 CPU 指令集 - if (!empty($config['march'])) { - $cmd .= ' -march=' . $config['march']; - } - - // 交叉编译目标平台 (--target=) - if (!empty($config['target_platform'])) { - $cmd .= ' --target=' . $config['target_platform']; - } - - // PIC (Position Independent Code) - if ((!empty($config['build_mode']) && $config['build_mode'] === 'ext') || !empty($config['pic'])) { - if ($this->platform instanceof \PhpAot\Php\Platform\Windows) { - // Windows Clang 不需要特殊处理 - } else { - $cmd .= ' -fPIC'; - } - } - - // 性能分析宏 - if (!empty($config['enable_profiler'])) { - $cmd .= ' -DPPROF_ON=1'; - if (!empty($config['prof_output'])) { - $cmd .= ' -DPROF_OUTPUT_FILE=\'"' . $config['prof_output'] . '"\''; - } - } - - // 用户自定义编译标志 - if (!empty($config['cxxflags'])) { - $cmd .= ' ' . $config['cxxflags']; - } - - // 用户自定义预处理器宏 - if (!empty($config['user_defines'])) { - foreach ($config['user_defines'] as $define) { - $cmd .= ' -D' . $define; + if (!empty($config['build_mode']) && $config['build_mode'] === 'ext') { + $cmd .= ' /DLL'; } + return; } - // LTO(链接时优化) - if (!empty($config['lto'])) { - $cmd .= ' -flto'; - } - - return $cmd; + parent::addPlatformLinkFlags($config, $cmd); } - /** - * 构建链接选项(实现抽象方法) - */ - public function buildLinkOptions(array $config = []): string + protected function addPlatformFullLinkFlags(array $options, string &$cmd): void { - $cmd = ''; - - // Windows 特定选项 - if ($this->platform instanceof \PhpAot\Php\Platform\Windows) { - // 调试 - if (!empty($config['debug'])) { + if ($this->platform instanceof Windows) { + if (!empty($options['debug'])) { $cmd .= ' /DEBUG'; } - - // Windows 子系统 - if (!empty($config['no_console'])) { + if (!empty($options['no_console'])) { $cmd .= ' ' . $this->platform->getSubsystemOptions(true); } - - // CRT $cmd .= ' ' . $this->platform->getCrtConfig(); - - // 扩展模块选项 - if (!empty($config['build_mode']) && $config['build_mode'] === 'ext') { - $cmd .= ' /DLL'; - } - } else { - // Unix/Linux/macOS - // 扩展模块选项 - if ((!empty($config['build_mode']) && $config['build_mode'] === 'ext') || !empty($config['shared'])) { - $cmd .= ' ' . $this->platform->getSharedLinkFlag(); - - if ($this->platform instanceof \PhpAot\Php\Platform\Macos && !empty($config['install_name'])) { - $cmd .= ' ' . $this->platform->getCurrentInstallNameOption($config['install_name']); - } - } - - // RPATH - if (!empty($config['rpath'])) { - foreach ($config['rpath'] as $path) { - $cmd .= ' -Wl,-rpath,' . escapeshellarg($path); - } - } - } - - // Sanitizer - if (!empty($config['sanitize'])) { - $cmd .= ' -fsanitize=' . $config['sanitize']; - } - - // 交叉编译目标平台 (--target=) - if (!empty($config['target_platform'])) { - $cmd .= ' --target=' . $config['target_platform']; - } - - // LTO(链接时优化) - if (!empty($config['lto'])) { - $cmd .= ' -flto'; + return; } - return $cmd; + parent::addPlatformFullLinkFlags($options, $cmd); } } diff --git a/src/Php/Backend/Gcc.php b/src/Php/Backend/Gcc.php index bfb5a6f9..c884bee7 100644 --- a/src/Php/Backend/Gcc.php +++ b/src/Php/Backend/Gcc.php @@ -7,16 +7,11 @@ use PhpAot\Php\Platform\PlatformBase; /** * GCC 编译器后端实现 */ -class Gcc extends CompilerBackend +class Gcc extends GccLikeBackend { - private string $compilerCommand; - private string $linkerCommand; - public function __construct(PlatformBase $platform, string $compilerCommand = 'g++', ?string $linkerCommand = null) { - parent::__construct($platform); - $this->compilerCommand = $compilerCommand; - $this->linkerCommand = $linkerCommand ?? $compilerCommand; + parent::__construct($platform, $compilerCommand, $linkerCommand); } public function getName(): string @@ -24,356 +19,8 @@ class Gcc extends CompilerBackend return 'GCC'; } - public function getCompilerCommand(): string - { - return $this->compilerCommand; - } - public function getLinkerCommand(): string { - return $this->linkerCommand; - } - - public function compileFile( - string $sourceFile, - string $outputFile, - array $includePaths = [], - array $defines = [], - array $flags = [] - ): string { - $cmd = $this->getCompilerCommand(); - $cmd .= ' -c ' . escapeshellarg($sourceFile); - $cmd .= ' -o ' . escapeshellarg($outputFile); - - // 添加包含路径 - if (!empty($includePaths)) { - $cmd .= ' ' . $this->formatIncludePaths($includePaths); - } - - // 添加宏定义 - foreach ($defines as $define) { - $cmd .= ' -D' . $define; - } - - // 添加额外标志 - if (!empty($flags)) { - $cmd .= ' ' . implode(' ', $flags); - } - - return $cmd; - } - - public function linkObjects( - array $objectFiles, - string $outputFile, - array $libraryPaths = [], - array $libraries = [], - array $flags = [] - ): string { - $cmd = $this->getLinkerCommand(); - - // 添加目标文件 - $cmd .= ' ' . implode(' ', array_map('escapeshellarg', $objectFiles)); - - // 输出文件 - $cmd .= ' -o ' . escapeshellarg($outputFile); - - // 添加库路径 - if (!empty($libraryPaths)) { - $cmd .= ' ' . $this->formatLibraryPaths($libraryPaths); - } - - // 添加库文件 - if (!empty($libraries)) { - $cmd .= ' ' . $this->formatLibraries($libraries); - } - - // 添加额外标志 - if (!empty($flags)) { - $cmd .= ' ' . implode(' ', $flags); - } - - return $cmd; - } - - public function buildCompileCommand(string $sourceFile, string $outputFile, array $options = []): string - { - $cmd = $this->getCompilerCommand(); - $cmd .= ' -c'; - $cmd .= ' ' . escapeshellarg($sourceFile); - $cmd .= ' -o ' . escapeshellarg($outputFile); - - if (!empty($options['include_paths'])) { - $cmd .= ' ' . $this->formatIncludePaths($options['include_paths']); - } - - $cmd .= $this->buildCompileOptions($options); - - return $cmd; - } - - /** - * 构建 C 文件的编译命令(不包含 C++ 特定选项) - */ - public function buildCCompileCommand(string $sourceFile, string $outputFile, array $options = []): string - { - $cmd = $this->getCompilerCommand(); - $cmd .= ' -c'; - $cmd .= ' -x c'; - $cmd .= ' ' . escapeshellarg($sourceFile); - $cmd .= ' -o ' . escapeshellarg($outputFile); - - if (!empty($options['include_paths'])) { - $cmd .= ' ' . $this->formatIncludePaths($options['include_paths']); - } - - // 优化级别(C 文件通常使用较低的优化) - $optimizeLevel = $options['optimize'] ?? 0; - $cmd .= ' -O' . $optimizeLevel; - - // 调试信息 - if (!empty($options['debug'])) { - $cmd .= ' -g'; - } - - // 警告级别 - $cmd .= ' -Wall'; - - // 注意:C 文件不使用 -std=c++17 等 C++ 特定选项 - - return $cmd; - } - - /** - * 构建原生源文件的编译命令(汇编/Objective-C 等) - * - * @param string $language 语言标识(assembler, objective-c, objective-c++) - */ - public function buildNativeCompileCommand(string $sourceFile, string $outputFile, array $options = [], string $language = ''): string - { - $cmd = $this->getCompilerCommand(); - $cmd .= ' -c'; - if ($language !== '') { - $cmd .= ' -x ' . $language; - } - $cmd .= ' ' . escapeshellarg($sourceFile); - $cmd .= ' -o ' . escapeshellarg($outputFile); - - if (!empty($options['include_paths'])) { - $cmd .= ' ' . $this->formatIncludePaths($options['include_paths']); - } - - $cmd .= $this->buildCompileOptions($options); - - return $cmd; - } - - public function buildLinkCommand(array $objectFiles, string $outputFile, array $options = []): string - { - $cmd = $this->getLinkerCommand(); - $cmd .= ' ' . implode(' ', array_map('escapeshellarg', $objectFiles)); - $cmd .= ' -o ' . escapeshellarg($outputFile); - - if (!empty($options['library_paths'])) { - $cmd .= ' ' . $this->formatLibraryPaths($options['library_paths']); - } - - if (!empty($options['ldflags'])) { - $cmd .= ' ' . $options['ldflags']; - } - - $cmd .= $this->buildLinkOptions($options); - - if (!empty($options['libraries'])) { - $cmd .= ' ' . $this->formatLibraries($options['libraries']); - } - - return $cmd; - } - - /** - * 构建完整的编译选项 - */ - public function buildFullCompileOptions(array $options = []): string - { - $cmd = ''; - - // 优化级别 - if (!empty($options['debug'])) { - $cmd .= ' -O0 -g'; - } else { - $optimizeLevel = $options['optimize'] ?? 2; - $cmd .= ' -O' . $optimizeLevel; - } - - // 警告 - $cmd .= ' -Wall'; - - // C++ 标准 - if (!empty($options['cpp_std'])) { - $cmd .= ' -std=' . $options['cpp_std']; - } - - // 目标 CPU 指令集 - if (!empty($options['march'])) { - $cmd .= ' -march=' . $options['march']; - } - - // Sanitizer - if (!empty($options['sanitize'])) { - $cmd .= ' -fsanitize=' . $options['sanitize']; - } - - // PIC - if (!empty($options['pic'])) { - $cmd .= ' -fPIC'; - } - - return $cmd; - } - - /** - * 构建完整的链接选项 - */ - public function buildFullLinkOptions(array $options = []): string - { - $cmd = ''; - - // 共享库 - if (!empty($options['shared'])) { - $cmd .= ' ' . $this->platform->getSharedLinkFlag(); - } - - // RPATH - if (!empty($options['rpath'])) { - $cmd .= ' ' . $this->platform->getRpathOptions($options['rpath']); - } - - // Sanitizer - if (!empty($options['sanitize'])) { - $cmd .= ' -fsanitize=' . $options['sanitize']; - } - - return $cmd; - } - - /** - * 构建编译选项(实现抽象方法) - */ - public function buildCompileOptions(array $config = []): string - { - $cmd = ''; - - // Sanitizer - if (!empty($config['sanitize'])) { - if ($config['sanitize'] === 'address' || $config['sanitize'] === 'addr') { - $cmd .= ' -fsanitize=address'; - } elseif ($config['sanitize'] === 'undefined' || $config['sanitize'] === 'undef') { - $cmd .= ' -fsanitize=undefined'; - } - } - - // 优化和调试 - if (!empty($config['debug'])) { - $cmd .= ' -O0 -g'; - } else { - $optimizeLevel = $config['optimize'] ?? 2; - $cmd .= ' -O' . $optimizeLevel; - } - - // 警告 - $cmd .= ' -Wall'; - - // C++ 标准 - if (!empty($config['cpp_std'])) { - $cmd .= ' -std=' . $config['cpp_std']; - } - - // 目标 CPU 指令集 - if (!empty($config['march'])) { - $cmd .= ' -march=' . $config['march']; - } - - // 交叉编译目标平台 (--target=) - if (!empty($config['target_platform'])) { - $cmd .= ' --target=' . $config['target_platform']; - } - - // PIC (Position Independent Code) - if ((!empty($config['build_mode']) && $config['build_mode'] === 'ext') || !empty($config['pic'])) { - $cmd .= ' -fPIC'; - } - - // 性能分析宏 - if (!empty($config['enable_profiler'])) { - $cmd .= ' -DPPROF_ON=1'; - if (!empty($config['prof_output'])) { - $cmd .= ' -DPROF_OUTPUT_FILE=\'"' . $config['prof_output'] . '"\''; - } - } - - // 用户自定义编译标志 - if (!empty($config['cxxflags'])) { - $cmd .= ' ' . $config['cxxflags']; - } - - // 用户自定义预处理器宏 - if (!empty($config['user_defines'])) { - foreach ($config['user_defines'] as $define) { - $cmd .= ' -D' . $define; - } - } - - // LTO(链接时优化) - if (!empty($config['lto'])) { - $cmd .= ' -flto'; - } - - return $cmd; - } - - /** - * 构建链接选项(实现抽象方法) - */ - public function buildLinkOptions(array $config = []): string - { - $cmd = ''; - - // 扩展模块选项 - if ((!empty($config['build_mode']) && $config['build_mode'] === 'ext') || !empty($config['shared'])) { - $cmd .= ' ' . $this->platform->getSharedLinkFlag(); - - if ($this->platform instanceof \PhpAot\Php\Platform\Macos && !empty($config['install_name'])) { - $cmd .= ' ' . $this->platform->getCurrentInstallNameOption($config['install_name']); - } - } - - // RPATH - if (!empty($config['rpath'])) { - foreach ($config['rpath'] as $path) { - $cmd .= ' -Wl,-rpath,' . escapeshellarg($path); - } - } - - // Sanitizer - if (!empty($config['sanitize'])) { - if ($config['sanitize'] === 'address' || $config['sanitize'] === 'addr') { - $cmd .= ' -fsanitize=address'; - } elseif ($config['sanitize'] === 'undefined' || $config['sanitize'] === 'undef') { - $cmd .= ' -fsanitize=undefined'; - } - } - - // 交叉编译目标平台 (--target=) - if (!empty($config['target_platform'])) { - $cmd .= ' --target=' . $config['target_platform']; - } - - // LTO(链接时优化) - if (!empty($config['lto'])) { - $cmd .= ' -flto'; - } - - return $cmd; + return $this->linkerCommand ?? $this->compilerCommand; } } diff --git a/src/Php/Backend/GccLikeBackend.php b/src/Php/Backend/GccLikeBackend.php new file mode 100644 index 00000000..5e0b2da0 --- /dev/null +++ b/src/Php/Backend/GccLikeBackend.php @@ -0,0 +1,355 @@ +compilerCommand = $compilerCommand; + $this->linkerCommand = $linkerCommand; + } + + public function getCompilerCommand(): string + { + return $this->compilerCommand; + } + + // ──── 钩子方法(子类覆盖点) ──── + + /** 编译器特定的前缀标志(如 MSVC 兼容模式) */ + protected function getCompilerPrefixFlags(): string + { + return ''; + } + + /** 链接器输出标志(-o vs /OUT:) */ + protected function getLinkerOutputFlag(): string + { + return '-o'; + } + + /** 格式化 sanitizer 标志 */ + protected function formatSanitizerFlag(string $sanitizer): string + { + return match ($sanitizer) { + 'address', 'addr' => '-fsanitize=address', + 'undefined', 'undef' => '-fsanitize=undefined', + default => '-fsanitize=' . $sanitizer, + }; + } + + /** 添加 PIC 标志 */ + protected function addPICFlag(array $config, string &$cmd): void + { + if ((!empty($config['build_mode']) && $config['build_mode'] === 'ext') || !empty($config['pic'])) { + $cmd .= ' -fPIC'; + } + } + + /** 添加平台特定的链接选项 */ + protected function addPlatformLinkFlags(array $config, string &$cmd): void + { + if ((!empty($config['build_mode']) && $config['build_mode'] === 'ext') || !empty($config['shared'])) { + $cmd .= ' ' . $this->platform->getSharedLinkFlag(); + + if ($this->platform instanceof \PhpAot\Php\Platform\Macos && !empty($config['install_name'])) { + $cmd .= ' ' . $this->platform->getCurrentInstallNameOption($config['install_name']); + } + } + + if (!empty($config['rpath'])) { + foreach ($config['rpath'] as $path) { + $cmd .= ' -Wl,-rpath,' . escapeshellarg($path); + } + } + } + + /** 添加平台特定的完整链接选项 */ + protected function addPlatformFullLinkFlags(array $options, string &$cmd): void + { + if (!empty($options['shared'])) { + $cmd .= ' ' . $this->platform->getSharedLinkFlag(); + } + + if (!empty($options['rpath'])) { + $cmd .= ' ' . $this->platform->getRpathOptions($options['rpath']); + } + } + + // ──── 抽象方法实现 ──── + + public function compileFile( + string $sourceFile, + string $outputFile, + array $includePaths = [], + array $defines = [], + array $flags = [] + ): string { + $cmd = $this->getCompilerCommand(); + $cmd .= $this->getCompilerPrefixFlags(); + $cmd .= ' -c ' . escapeshellarg($sourceFile); + $cmd .= ' -o ' . escapeshellarg($outputFile); + + if (!empty($includePaths)) { + $cmd .= ' ' . $this->formatIncludePaths($includePaths); + } + + foreach ($defines as $define) { + $cmd .= ' -D' . $define; + } + + if (!empty($flags)) { + $cmd .= ' ' . implode(' ', $flags); + } + + return $cmd; + } + + public function linkObjects( + array $objectFiles, + string $outputFile, + array $libraryPaths = [], + array $libraries = [], + array $flags = [] + ): string { + $cmd = $this->getLinkerCommand(); + $cmd .= ' ' . implode(' ', array_map('escapeshellarg', $objectFiles)); + $cmd .= ' ' . $this->getLinkerOutputFlag() . ' ' . escapeshellarg($outputFile); + + if (!empty($libraryPaths)) { + $cmd .= ' ' . $this->formatLibraryPaths($libraryPaths); + } + + if (!empty($libraries)) { + $cmd .= ' ' . $this->formatLibraries($libraries); + } + + if (!empty($flags)) { + $cmd .= ' ' . implode(' ', $flags); + } + + return $cmd; + } + + public function buildCompileCommand(string $sourceFile, string $outputFile, array $options = []): string + { + $cmd = $this->getCompilerCommand(); + $cmd .= $this->getCompilerPrefixFlags(); + $cmd .= ' -c'; + $cmd .= ' ' . escapeshellarg($sourceFile); + $cmd .= ' -o ' . escapeshellarg($outputFile); + + if (!empty($options['include_paths'])) { + $cmd .= ' ' . $this->formatIncludePaths($options['include_paths']); + } + + $cmd .= $this->buildCompileOptions($options); + + return $cmd; + } + + public function buildCCompileCommand(string $sourceFile, string $outputFile, array $options = []): string + { + $cmd = $this->getCompilerCommand(); + $cmd .= $this->getCompilerPrefixFlags(); + $cmd .= ' -c'; + $cmd .= ' -x c'; + $cmd .= ' ' . escapeshellarg($sourceFile); + $cmd .= ' -o ' . escapeshellarg($outputFile); + + if (!empty($options['include_paths'])) { + $cmd .= ' ' . $this->formatIncludePaths($options['include_paths']); + } + + $optimizeLevel = $options['optimize'] ?? 0; + if (!empty($options['debug'])) { + $cmd .= ' -O0 -g'; + } else { + $cmd .= ' -O' . $optimizeLevel; + } + + $cmd .= ' -Wall'; + + return $cmd; + } + + public function buildNativeCompileCommand(string $sourceFile, string $outputFile, array $options = [], string $language = ''): string + { + $cmd = $this->getCompilerCommand(); + $cmd .= $this->getCompilerPrefixFlags(); + $cmd .= ' -c'; + if ($language !== '') { + $cmd .= ' -x ' . $language; + } + $cmd .= ' ' . escapeshellarg($sourceFile); + $cmd .= ' -o ' . escapeshellarg($outputFile); + + if (!empty($options['include_paths'])) { + $cmd .= ' ' . $this->formatIncludePaths($options['include_paths']); + } + + $cmd .= $this->buildCompileOptions($options); + + return $cmd; + } + + public function buildLinkCommand(array $objectFiles, string $outputFile, array $options = []): string + { + $cmd = $this->getLinkerCommand(); + $cmd .= ' ' . implode(' ', array_map('escapeshellarg', $objectFiles)); + $cmd .= ' ' . $this->getLinkerOutputFlag() . ' ' . escapeshellarg($outputFile); + + if (!empty($options['library_paths'])) { + $cmd .= ' ' . $this->formatLibraryPaths($options['library_paths']); + } + + if (!empty($options['ldflags'])) { + $cmd .= ' ' . $options['ldflags']; + } + + $cmd .= $this->buildLinkOptions($options); + + if (!empty($options['libraries'])) { + $cmd .= ' ' . $this->formatLibraries($options['libraries']); + } + + return $cmd; + } + + public function buildCompileOptions(array $config = []): string + { + $cmd = ''; + + $cmd .= $this->getCompilerPrefixFlags(); + + if (!empty($config['sanitize'])) { + $cmd .= ' ' . $this->formatSanitizerFlag($config['sanitize']); + } + + if (!empty($config['debug'])) { + $cmd .= ' -O0 -g'; + } else { + $optimizeLevel = $config['optimize'] ?? 2; + $cmd .= ' -O' . $optimizeLevel; + } + + $cmd .= ' -Wall'; + + if (!empty($config['cpp_std'])) { + $cmd .= ' -std=' . $config['cpp_std']; + } + + if (!empty($config['march'])) { + $cmd .= ' -march=' . $config['march']; + } + + if (!empty($config['target_platform'])) { + $cmd .= ' --target=' . $config['target_platform']; + } + + $this->addPICFlag($config, $cmd); + + if (!empty($config['enable_profiler'])) { + $cmd .= ' -DPPROF_ON=1'; + if (!empty($config['prof_output'])) { + $cmd .= ' -DPROF_OUTPUT_FILE=\'"' . $config['prof_output'] . '"\''; + } + } + + if (!empty($config['cxxflags'])) { + $cmd .= ' ' . $config['cxxflags']; + } + + if (!empty($config['user_defines'])) { + foreach ($config['user_defines'] as $define) { + $cmd .= ' -D' . $define; + } + } + + if (!empty($config['lto'])) { + $cmd .= ' -flto'; + } + + return $cmd; + } + + public function buildLinkOptions(array $config = []): string + { + $cmd = ''; + + $this->addPlatformLinkFlags($config, $cmd); + + if (!empty($config['sanitize'])) { + $cmd .= ' ' . $this->formatSanitizerFlag($config['sanitize']); + } + + if (!empty($config['target_platform'])) { + $cmd .= ' --target=' . $config['target_platform']; + } + + if (!empty($config['lto'])) { + $cmd .= ' -flto'; + } + + return $cmd; + } + + public function buildFullCompileOptions(array $options = []): string + { + $cmd = ''; + + $cmd .= $this->getCompilerPrefixFlags(); + + if (!empty($options['debug'])) { + $cmd .= ' -O0 -g'; + } else { + $optimizeLevel = $options['optimize'] ?? 2; + $cmd .= ' -O' . $optimizeLevel; + } + + $cmd .= ' -Wall'; + + if (!empty($options['cpp_std'])) { + $cmd .= ' -std=' . $options['cpp_std']; + } + + if (!empty($options['march'])) { + $cmd .= ' -march=' . $options['march']; + } + + if (!empty($options['sanitize'])) { + $cmd .= ' ' . $this->formatSanitizerFlag($options['sanitize']); + } + + if (!empty($options['pic'])) { + $cmd .= ' -fPIC'; + } + + return $cmd; + } + + public function buildFullLinkOptions(array $options = []): string + { + $cmd = ''; + + $this->addPlatformFullLinkFlags($options, $cmd); + + if (!empty($options['sanitize'])) { + $cmd .= ' -fsanitize=' . $options['sanitize']; + } + + return $cmd; + } +} diff --git a/src/Php/Context/FunctionContext.php b/src/Php/Context/FunctionContext.php index e2b5a119..33eb40c2 100644 --- a/src/Php/Context/FunctionContext.php +++ b/src/Php/Context/FunctionContext.php @@ -10,6 +10,9 @@ namespace PhpAot\Php\Context; class FunctionContext { + /** SSA builder for the current function. Built once per function, discarded with the context. */ + public ?\PhpAot\Php\Analysis\SsaBuilder $ssaBuilder = null; + /** Map of SSA-stable object variable name => class name (SsaPropOptimizer). */ public array $stableObjects = []; @@ -76,6 +79,7 @@ class FunctionContext $this->stdArrays = []; $this->stdContainers = []; $this->objectProps = []; + $this->ssaBuilder = null; $this->stableObjects = []; $this->hoistedProps = []; $this->unsafeObjectProps = []; diff --git a/src/Php/Platform/Linux.php b/src/Php/Platform/Linux.php index c01d5b28..35175a70 100644 --- a/src/Php/Platform/Linux.php +++ b/src/Php/Platform/Linux.php @@ -5,7 +5,7 @@ namespace PhpAot\Php\Platform; /** * Linux 平台实现 */ -class Linux extends PlatformBase +class Linux extends UnixPlatform { public function getName(): string { @@ -17,133 +17,21 @@ class Linux extends PlatformBase return PHP_OS === 'Linux'; } - public function getIncludeFlags(array $includePaths): string - { - if (empty($includePaths)) { - return ''; - } - - $flags = []; - foreach ($includePaths as $path) { - $flags[] = '-I' . escapeshellarg($path); - } - - return implode(' ', $flags); - } - - public function getLibraryPathFlags(array $libraryPaths): string - { - if (empty($libraryPaths)) { - return ''; - } - - $flags = []; - foreach ($libraryPaths as $path) { - $flags[] = '-L' . escapeshellarg($path); - } - - return implode(' ', $flags); - } - - public function getLibraryFlags(array $libraries): string - { - if (empty($libraries)) { - return ''; - } - - $flags = []; - foreach ($libraries as $lib) { - // 移除 lib 前缀和 .a/.so 后缀 - $libName = basename($lib); - if (str_starts_with($libName, 'lib')) { - $libName = substr($libName, 3); - } - $libName = preg_replace('/\.(a|so)$/', '', $libName); - - $flags[] = '-l' . $libName; - } - - return implode(' ', $flags); - } - - public function getObjectExtension(): string - { - return '.o'; - } - - public function getExecutableExtension(): string - { - return ''; - } - public function getSharedLibraryExtension(): string { return '.so'; } - public function getPathSeparator(): string - { - return '/'; - } - public function getDefaultCompiler(): string { return 'g++'; } - public function getPhpDir(): string - { - $phpDir = getenv('PHP_HOME'); - if ($phpDir && is_dir($phpDir)) { - return rtrim($phpDir, '\/'); - } - - $phpDir = shell_exec('php-config --prefix 2>/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'; - } - /** * 获取共享库链接选项 */ @@ -151,99 +39,4 @@ class Linux extends PlatformBase { 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, - ]; - } } diff --git a/src/Php/Platform/Macos.php b/src/Php/Platform/Macos.php index ecc5aa04..15dbe326 100644 --- a/src/Php/Platform/Macos.php +++ b/src/Php/Platform/Macos.php @@ -5,7 +5,7 @@ namespace PhpAot\Php\Platform; /** * macOS 平台实现 */ -class Macos extends PlatformBase +class Macos extends UnixPlatform { public function getName(): string { @@ -17,128 +17,16 @@ class Macos extends PlatformBase return strtoupper(substr(PHP_OS, 0, 6)) === 'DARWIN'; } - public function getIncludeFlags(array $includePaths): string - { - if (empty($includePaths)) { - return ''; - } - - $flags = []; - foreach ($includePaths as $path) { - $flags[] = '-I' . escapeshellarg($path); - } - - return implode(' ', $flags); - } - - public function getLibraryPathFlags(array $libraryPaths): string - { - if (empty($libraryPaths)) { - return ''; - } - - $flags = []; - foreach ($libraryPaths as $path) { - $flags[] = '-L' . escapeshellarg($path); - } - - return implode(' ', $flags); - } - - public function getLibraryFlags(array $libraries): string - { - if (empty($libraries)) { - return ''; - } - - $flags = []; - foreach ($libraries as $lib) { - // 移除 lib 前缀和 .a/.dylib 后缀 - $libName = basename($lib); - if (str_starts_with($libName, 'lib')) { - $libName = substr($libName, 3); - } - $libName = preg_replace('/\.(a|dylib)$/', '', $libName); - - $flags[] = '-l' . $libName; - } - - return implode(' ', $flags); - } - - public function getObjectExtension(): string - { - return '.o'; - } - - public function getExecutableExtension(): string - { - return ''; - } - public function getSharedLibraryExtension(): string { return '.dylib'; } - public function getPathSeparator(): string - { - return '/'; - } - public function getDefaultCompiler(): string { return 'clang++'; } - public function getPhpDir(): string - { - $phpDir = getenv('PHP_HOME'); - if ($phpDir && is_dir($phpDir)) { - return rtrim($phpDir, '\/'); - } - - $phpDir = shell_exec('php-config --prefix 2>/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'); - } - - /** - * 获取 RPATH 选项(macOS 需要绝对路径) - */ - 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'; - } - /** * 获取共享库链接选项 */ @@ -155,124 +43,27 @@ class Macos extends PlatformBase return '-install_name ' . escapeshellarg($path); } - /** - * 构建 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.dylib'; - $staticLib = $libPath . '/libphp.a'; - - $hasEmbed = file_exists($embedLib); - $hasStatic = file_exists($staticLib); - - if (!$hasEmbed && !$hasStatic) { - throw new \RuntimeException('Neither libphp.dylib nor libphp.a found'); - } - - return [ - 'embed' => $hasEmbed ? $embedLib : null, - 'static' => $hasStatic ? $staticLib : null, - 'is_shared' => $hasEmbed, - ]; - } - /** * 获取默认的 RPATH 路径列表(macOS 需要) */ public function getDefaultRpaths(?string $phpxDir = null, ?string $phpDir = null): array { $rpaths = []; - - // 添加 phpx 库路径 + if ($phpxDir !== null) { $phpxLibDir = $phpxDir . '/lib'; if (is_dir($phpxLibDir)) { $rpaths[] = $phpxLibDir; } } - - // 添加 PHP 库路径 + if ($phpDir !== null) { $phpLibDir = $phpDir . '/lib'; if (is_dir($phpLibDir)) { $rpaths[] = $phpLibDir; } } - + return $rpaths; } } diff --git a/src/Php/Platform/UnixPlatform.php b/src/Php/Platform/UnixPlatform.php new file mode 100644 index 00000000..225c14df --- /dev/null +++ b/src/Php/Platform/UnixPlatform.php @@ -0,0 +1,211 @@ +getSharedLibraryExtension(), '.'); + $flags = []; + foreach ($libraries as $lib) { + $libName = basename($lib); + if (str_starts_with($libName, 'lib')) { + $libName = substr($libName, 3); + } + $libName = preg_replace('/\.(a|' . $ext . ')$/', '', $libName); + + $flags[] = '-l' . $libName; + } + + return implode(' ', $flags); + } + + public function getObjectExtension(): string + { + return '.o'; + } + + public function getExecutableExtension(): string + { + return ''; + } + + public function getPathSeparator(): string + { + return '/'; + } + + public function getPhpDir(): string + { + $phpDir = getenv('PHP_HOME'); + if ($phpDir && is_dir($phpDir)) { + return rtrim($phpDir, '\/'); + } + + $phpDir = shell_exec('php-config --prefix 2>/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'); + } + + /** + * 获取 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'; + } + + /** + * 构建 PHP 包含路径(使用 php-config 动态获取) + */ + public function buildPhpIncludePaths(string $phpDir): array + { + $phpConfigPath = $this->findPhpConfig($phpDir); + if ($phpConfigPath) { + $includes = shell_exec("{$phpConfigPath} --includes 2>/dev/null"); + if ($includes) { + 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 可执行文件 + */ + protected function findPhpConfig(string $phpDir): ?string + { + $candidate = $phpDir . '/bin/php-config'; + if (is_executable($candidate)) { + return $candidate; + } + + $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}"); + } + + $ext = ltrim($this->getSharedLibraryExtension(), '.'); + $embedLib = $libPath . '/libphp.' . $ext; + $staticLib = $libPath . '/libphp.a'; + + $hasEmbed = file_exists($embedLib); + $hasStatic = file_exists($staticLib); + + if (!$hasEmbed && !$hasStatic) { + throw new \RuntimeException("Neither libphp.{$ext} nor libphp.a found"); + } + + return [ + 'embed' => $hasEmbed ? $embedLib : null, + 'static' => $hasStatic ? $staticLib : null, + 'is_shared' => $hasEmbed, + ]; + } +} diff --git a/src/Php/Translator.php b/src/Php/Translator.php index 94441541..d1ebef75 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -2799,6 +2799,7 @@ CODE; /** SSA/e-SSA analysis for the current function. Built once per function, discarded with the context. */ $ssaBuilder = new SsaBuilder($v->stmts, $this->functionDef->argInfoList); $ssaBuilder->build(); + $this->context->ssaBuilder = $ssaBuilder; // Narrow local variable types based on SSA analysis $this->optimizeVarTypes($ssaBuilder); // Narrow range-proven loop counters independent of native_types