refactor(backend): 重构编译器后端实现以支持 GCC/Clang 共享基类

- 将 Clang 和 GCC 后端重构为继承自新的 GccLikeBackend 基类
- 移除重复的编译和链接命令构建逻辑
- 添加平台特定的钩子方法用于扩展功能
- 在 FunctionContext 中添加 SSA 构建器属性
- 统一编译器和链接器命令的初始化方式
- 优化 Windows 平台兼容性处理逻辑
pull/3/head
韩天峰 2 months ago
parent d49743a0fe
commit 7c2192ff54
  1. 2
      phpunit/src/SsaAnalysisTest.php
  2. 452
      src/Php/Backend/Clang.php
  3. 359
      src/Php/Backend/Gcc.php
  4. 355
      src/Php/Backend/GccLikeBackend.php
  5. 4
      src/Php/Context/FunctionContext.php
  6. 209
      src/Php/Platform/Linux.php
  7. 217
      src/Php/Platform/Macos.php
  8. 211
      src/Php/Platform/UnixPlatform.php
  9. 1
      src/Php/Translator.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');
}

@ -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=<triple>)
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=<triple>)
if (!empty($config['target_platform'])) {
$cmd .= ' --target=' . $config['target_platform'];
}
// LTO(链接时优化)
if (!empty($config['lto'])) {
$cmd .= ' -flto';
return;
}
return $cmd;
parent::addPlatformFullLinkFlags($options, $cmd);
}
}

@ -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=<triple>)
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=<triple>)
if (!empty($config['target_platform'])) {
$cmd .= ' --target=' . $config['target_platform'];
}
// LTO(链接时优化)
if (!empty($config['lto'])) {
$cmd .= ' -flto';
}
return $cmd;
return $this->linkerCommand ?? $this->compilerCommand;
}
}

@ -0,0 +1,355 @@
<?php
namespace PhpAot\Php\Backend;
use PhpAot\Php\Platform\PlatformBase;
/**
* GCC/Clang 共享后端基类
* 包含 Unix-like 编译器(GCC、Clang)的通用命令行构建逻辑。
* 子类只需覆盖平台差异的钩子方法。
*/
abstract class GccLikeBackend extends CompilerBackend
{
protected string $compilerCommand;
protected ?string $linkerCommand;
public function __construct(PlatformBase $platform, string $compilerCommand, ?string $linkerCommand = null)
{
parent::__construct($platform);
$this->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;
}
}

@ -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 = [];

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

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

@ -0,0 +1,211 @@
<?php
namespace PhpAot\Php\Platform;
/**
* Unix-like 平台基类(Linux, macOS)
* 包含 GCC/Clang 通用标志语法的共享实现
*/
abstract class UnixPlatform extends PlatformBase
{
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 '';
}
$ext = ltrim($this->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,
];
}
}

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

Loading…
Cancel
Save