From 95827cfb736758d6fcffaba120b30b8b12f12cde Mon Sep 17 00:00:00 2001 From: rango Date: Thu, 7 May 2026 21:21:43 +0800 Subject: [PATCH] =?UTF-8?q?feat(backend):=20=E6=B7=BB=E5=8A=A0=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E5=99=A8=E5=92=8C=E5=B9=B3=E5=8F=B0=E6=8A=BD=E8=B1=A1?= =?UTF-8?q?=E5=B1=82=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现 CompilerBackend 抽象基类定义编译器接口 - 添加 Clang、GCC、MSVC 编译器后端具体实现 - 创建 PlatformBase 抽象基类定义平台接口 - 添加 Windows、Linux、macOS 平台具体实现 - 实现 CompilerFactory 工厂类自动创建编译器 - 实现 PlatformFactory 工厂类自动检测平台 - 提供跨平台路径处理和命令行参数生成 - 添加完整的使用示例和架构说明文档 --- src/Php/Backend/Clang.php | 200 +++++++++++++++++++++++++++ src/Php/Backend/CompilerBackend.php | 109 +++++++++++++++ src/Php/Backend/CompilerFactory.php | 68 +++++++++ src/Php/Backend/Gcc.php | 143 +++++++++++++++++++ src/Php/Backend/Msvc.php | 156 +++++++++++++++++++++ src/Php/Backend/README.md | 193 ++++++++++++++++++++++++++ src/Php/Backend/example_usage.php | 78 +++++++++++ src/Php/Platform/Linux.php | 121 ++++++++++++++++ src/Php/Platform/Macos.php | 129 +++++++++++++++++ src/Php/Platform/PlatformBase.php | 71 ++++++++++ src/Php/Platform/PlatformFactory.php | 58 ++++++++ src/Php/Platform/Windows.php | 145 +++++++++++++++++++ 12 files changed, 1471 insertions(+) create mode 100644 src/Php/Backend/Clang.php create mode 100644 src/Php/Backend/CompilerBackend.php create mode 100644 src/Php/Backend/CompilerFactory.php create mode 100644 src/Php/Backend/Gcc.php create mode 100644 src/Php/Backend/Msvc.php create mode 100644 src/Php/Backend/README.md create mode 100644 src/Php/Backend/example_usage.php create mode 100644 src/Php/Platform/Linux.php create mode 100644 src/Php/Platform/Macos.php create mode 100644 src/Php/Platform/PlatformBase.php create mode 100644 src/Php/Platform/PlatformFactory.php create mode 100644 src/Php/Platform/Windows.php diff --git a/src/Php/Backend/Clang.php b/src/Php/Backend/Clang.php new file mode 100644 index 00000000..7d9e7aaa --- /dev/null +++ b/src/Php/Backend/Clang.php @@ -0,0 +1,200 @@ +platform instanceof \PhpAot\Php\Platform\Windows) { + return 'link'; + } + return 'clang++'; + } + + 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 + { + $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); + + // 优化级别 + $optimizeLevel = $options['optimize'] ?? 2; + + // 调试模式 + if (!empty($options['debug'])) { + $cmd .= ' -O0 -g'; + } else { + $cmd .= ' -O' . $optimizeLevel; + } + + // 警告级别 + $cmd .= ' -Wall'; + + // C++ 标准 + $cppStd = $options['cpp_std'] ?? 'c++17'; + $cmd .= ' -std=' . $cppStd; + + // Sanitizer 支持 + if (!empty($options['sanitize'])) { + $cmd .= ' -fsanitize=' . $options['sanitize']; + } + + // PIC(位置无关代码) + if (!empty($options['pic'])) { + $cmd .= ' -fPIC'; + } + + return $cmd; + } + + 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); + + // 调试信息 + if (!empty($options['debug'])) { + $cmd .= ' /DEBUG'; + } + + // Windows 子系统 + if (!empty($options['no_console'])) { + $cmd .= ' ' . $this->platform->getSubsystemOptions(true); + } + + // CRT 配置 + $cmd .= ' ' . $this->platform->getCrtConfig(); + } else { + // Unix/Linux/macOS 使用 GCC 风格语法 + $cmd .= ' -o ' . escapeshellarg($outputFile); + + // 共享库 + if (!empty($options['shared'])) { + $cmd .= ' ' . $this->platform->getSharedLinkFlag(); + + // macOS 需要 install_name + if ($this->platform instanceof \PhpAot\Php\Platform\Macos && !empty($options['install_name'])) { + $cmd .= ' ' . $this->platform->getCurrentInstallNameOption($options['install_name']); + } + } + + // RPATH(运行时库搜索路径) + if (!empty($options['rpath'])) { + $cmd .= ' ' . $this->platform->getRpathOptions($options['rpath']); + } + + // Sanitizer 链接选项 + if (!empty($options['sanitize'])) { + $cmd .= ' -fsanitize=' . $options['sanitize']; + } + } + + return $cmd; + } +} diff --git a/src/Php/Backend/CompilerBackend.php b/src/Php/Backend/CompilerBackend.php new file mode 100644 index 00000000..6b55e633 --- /dev/null +++ b/src/Php/Backend/CompilerBackend.php @@ -0,0 +1,109 @@ +platform = $platform; + } + + /** + * 获取编译器名称 + */ + abstract public function getName(): string; + + /** + * 获取编译器命令 + */ + abstract public function getCompilerCommand(): string; + + /** + * 获取链接器命令 + */ + abstract public function getLinkerCommand(): string; + + /** + * 编译单个文件 + */ + abstract public function compileFile( + string $sourceFile, + string $outputFile, + array $includePaths = [], + array $defines = [], + array $flags = [] + ): string; + + /** + * 链接目标文件 + */ + abstract public function linkObjects( + array $objectFiles, + string $outputFile, + array $libraryPaths = [], + array $libraries = [], + array $flags = [] + ): string; + + /** + * 构建完整的编译命令 + */ + abstract public function buildCompileCommand( + string $sourceFile, + string $outputFile, + array $options = [] + ): string; + + /** + * 构建完整的链接命令 + */ + abstract public function buildLinkCommand( + array $objectFiles, + string $outputFile, + array $options = [] + ): string; + + /** + * 获取平台实例 + */ + public function getPlatform(): PlatformBase + { + return $this->platform; + } + + /** + * 格式化包含路径 + */ + protected function formatIncludePaths(array $includePaths): string + { + return $this->platform->getIncludeFlags($includePaths); + } + + /** + * 格式化库路径 + */ + protected function formatLibraryPaths(array $libraryPaths): string + { + return $this->platform->getLibraryPathFlags($libraryPaths); + } + + /** + * 格式化库文件 + */ + protected function formatLibraries(array $libraries): string + { + return $this->platform->getLibraryFlags($libraries); + } +} diff --git a/src/Php/Backend/CompilerFactory.php b/src/Php/Backend/CompilerFactory.php new file mode 100644 index 00000000..8b520bf8 --- /dev/null +++ b/src/Php/Backend/CompilerFactory.php @@ -0,0 +1,68 @@ +getName()); + } + } + + /** + * 创建指定类型的编译器后端 + */ + public static function createByName(string $compilerName, PlatformBase $platform): CompilerBackend + { + return match (strtolower($compilerName)) { + 'msvc', 'cl' => new Msvc($platform), + 'gcc', 'g++' => new Gcc($platform), + 'clang', 'clang++' => new Clang($platform), + default => throw new \RuntimeException("Unsupported compiler: {$compilerName}"), + }; + } + + /** + * 自动检测并创建编译器和平台 + */ + public static function autoDetect(string $compilerName = ''): array + { + // 创建平台 + $platform = \PhpAot\Php\Platform\PlatformFactory::create(); + + // 创建编译器 + if (!empty($compilerName)) { + $compiler = self::createByName($compilerName, $platform); + } else { + $compiler = self::create($platform); + } + + return [ + 'platform' => $platform, + 'compiler' => $compiler, + ]; + } +} diff --git a/src/Php/Backend/Gcc.php b/src/Php/Backend/Gcc.php new file mode 100644 index 00000000..cdb443e2 --- /dev/null +++ b/src/Php/Backend/Gcc.php @@ -0,0 +1,143 @@ +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); + + // 优化级别 + $optimizeLevel = $options['optimize'] ?? 2; + $cmd .= ' -O' . $optimizeLevel; + + // 调试信息 + if (!empty($options['debug'])) { + $cmd .= ' -g'; + } + + // 警告级别 + $cmd .= ' -Wall'; + + // C++ 标准 + $cppStd = $options['cpp_std'] ?? 'c++17'; + $cmd .= ' -std=' . $cppStd; + + // PIC(位置无关代码) + if (!empty($options['pic'])) { + $cmd .= ' -fPIC'; + } + + 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['shared'])) { + $cmd .= ' ' . $this->platform->getSharedLinkFlag(); + + // macOS 需要 install_name + if ($this->platform instanceof \PhpAot\Php\Platform\Macos && !empty($options['install_name'])) { + $cmd .= ' ' . $this->platform->getCurrentInstallNameOption($options['install_name']); + } + } + + // RPATH(运行时库搜索路径) + if (!empty($options['rpath'])) { + $cmd .= ' ' . $this->platform->getRpathOptions($options['rpath']); + } + + return $cmd; + } +} diff --git a/src/Php/Backend/Msvc.php b/src/Php/Backend/Msvc.php new file mode 100644 index 00000000..43e627ca --- /dev/null +++ b/src/Php/Backend/Msvc.php @@ -0,0 +1,156 @@ +getCompilerCommand(); + $cmd .= ' /c ' . escapeshellarg($sourceFile); + $cmd .= ' /Fo' . 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 .= ' /OUT:' . 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 .= ' /Fo' . escapeshellarg($outputFile); + + // 平台宏定义 + $cmd .= ' /DZEND_WIN32 /DPHP_WIN32 /DZEND_DEBUG=0'; + + // ZTS 支持 + if ($this->platform instanceof Windows && $this->platform->isZts()) { + $cmd .= ' /DZTS'; + } + + // 优化级别 + $optimizeLevel = $options['optimize'] ?? 2; + $cmd .= ' /O' . ($optimizeLevel >= 2 ? '2' : ($optimizeLevel === 0 ? 'd' : '1')); + + // 警告级别 + $cmd .= ' /W3'; + + // C++ 标准 + $cppStd = $options['cpp_std'] ?? 'c++17'; + $cmd .= ' /std:' . $cppStd; + + // 异常处理 + $cmd .= ' /EHsc'; + + // CRT + $cmd .= ' /MD'; + + // nologo + $cmd .= ' /nologo'; + + return $cmd; + } + + public function buildLinkCommand(array $objectFiles, string $outputFile, array $options = []): string + { + $cmd = $this->getLinkerCommand(); + $cmd .= ' ' . implode(' ', array_map('escapeshellarg', $objectFiles)); + $cmd .= ' /OUT:' . escapeshellarg($outputFile); + + // 调试信息 + if (!empty($options['debug'])) { + $cmd .= ' /DEBUG'; + } + + // Windows 子系统 + if (!empty($options['no_console'])) { + $cmd .= ' ' . $this->platform->getSubsystemOptions(true); + } + + // CRT 配置 + $cmd .= ' ' . $this->platform->getCrtConfig(); + + // nologo + $cmd .= ' /nologo'; + + return $cmd; + } +} diff --git a/src/Php/Backend/README.md b/src/Php/Backend/README.md new file mode 100644 index 00000000..1d2a0876 --- /dev/null +++ b/src/Php/Backend/README.md @@ -0,0 +1,193 @@ +# 编译器和平台抽象层 + +## 目录结构 + +``` +src/Php/ +├── Backend/ # 编译器后端抽象 +│ ├── CompilerBackend.php # 编译器抽象基类 +│ ├── CompilerFactory.php # 编译器工厂(自动检测) +│ ├── Msvc.php # MSVC 编译器实现 ✅ +│ ├── Gcc.php # GCC 编译器实现 ✅ +│ ├── Clang.php # Clang 编译器实现 ✅ +│ ├── example_usage.php # 使用示例 +│ └── README.md # 本文档 +└── Platform/ # 平台抽象 + ├── PlatformBase.php # 平台抽象基类 + ├── PlatformFactory.php # 平台工厂(自动检测) + ├── Windows.php # Windows 平台实现 ✅ + ├── Linux.php # Linux 平台实现 ✅ + └── Macos.php # macOS 平台实现 ✅ +``` + +## 设计理念 + +### 1. 平台抽象 (Platform) + +**职责:** +- 处理不同操作系统的差异 +- 提供统一的路径、文件扩展名、命令行参数格式 +- 封装平台特定的配置和选项 + +**核心方法:** +- `getIncludeFlags()` - 获取包含路径参数 +- `getLibraryPathFlags()` - 获取库路径参数 +- `getLibraryFlags()` - 获取库文件参数 +- `getObjectExtension()` - 获取对象文件扩展名 +- `getExecutableExtension()` - 获取可执行文件扩展名 + +### 2. 编译器后端 (Backend) + +**职责:** +- 处理不同编译器的差异 +- 生成编译和链接命令 +- 封装编译器特定的选项和标志 + +**核心方法:** +- `compileFile()` - 编译单个文件 +- `linkObjects()` - 链接目标文件 +- `buildCompileCommand()` - 构建完整编译命令 +- `buildLinkCommand()` - 构建完整链接命令 + +## 使用示例 + +### 基本用法 + +```php +use PhpAot\Php\Platform\Windows; +use PhpAot\Php\Backend\Msvc; + +// 创建平台实例 +$platform = new Windows( + phpLibs: ['php8embed.lib', 'php8ts.lib'], + isZts: true +); + +// 创建编译器后端 +$compiler = new Msvc($platform); + +// 构建编译命令 +$compileCmd = $compiler->buildCompileCommand( + 'source.cpp', + 'source.obj', + [ + 'optimize' => 2, + 'cpp_std' => 'c++17', + ] +); + +// 构建链接命令 +$linkCmd = $compiler->buildLinkCommand( + ['source.obj'], + 'output.exe', + [ + 'debug' => true, + 'no_console' => false, + ] +); +``` + +### 跨平台支持 + +```php +use PhpAot\Php\Platform\Linux; +use PhpAot\Php\Platform\Macos; +use PhpAot\Php\Backend\Gcc; + +// 自动检测当前平台 +if ((new Windows())->isCurrent()) { + $platform = new Windows(); + $compiler = new Msvc($platform); +} elseif ((new Linux())->isCurrent()) { + $platform = new Linux(); + $compiler = new Gcc($platform); +} elseif ((new Macos())->isCurrent()) { + $platform = new Macos(); + $compiler = new Gcc($platform); // macOS 通常也用 GCC/Clang +} +``` + +## 优势 + +### 1. 关注点分离 +- **Platform**: 只关心操作系统差异 +- **Backend**: 只关心编译器差异 +- 两者独立,可以任意组合 + +### 2. 易于扩展 +- 添加新平台:继承 `PlatformBase` +- 添加新编译器:继承 `CompilerBackend` +- 无需修改现有代码 + +### 3. 易于测试 +- 每个类职责单一 +- 可以独立单元测试 +- 便于 Mock 和 stub + +### 4. 代码复用 +- 平台相关逻辑集中管理 +- 编译器相关逻辑集中管理 +- 避免重复代码 + +## 迁移计划 + +### 阶段 1:创建抽象层(✅ 已完成) +- ✅ 创建 Platform 抽象和实现 + - ✅ PlatformBase.php + - ✅ Windows.php + - ✅ Linux.php + - ✅ Macos.php + - ✅ PlatformFactory.php +- ✅ 创建 Backend 抽象和实现 + - ✅ CompilerBackend.php + - ✅ Msvc.php + - ✅ Gcc.php + - ✅ Clang.php + - ✅ CompilerFactory.php +- ✅ 创建使用示例和文档 + - ✅ example_usage.php + - ✅ README.md + +### 阶段 2:重构 CompilerBase +- 将平台相关代码迁移到 Platform 类 +- 将编译器相关代码迁移到 Backend 类 +- CompilerBase 作为协调者使用这些类 + +### 阶段 3:清理和优化 +- 删除冗余代码 +- 更新文档 +- 完善测试 + +## 下一步工作 + +### ✅ 已完成 +1. **完成 Backend 实现** + - ✅ 创建 `Gcc.php` + - ✅ 创建 `Clang.php` + - ✅ 创建 `CompilerFactory.php`(自动检测) + +2. **完成 Platform 实现** + - ✅ 创建所有平台实现 + - ✅ 创建 `PlatformFactory.php`(自动检测) + +3. **文档和示例** + - ✅ 创建详细 README + - ✅ 创建使用示例 + +### 🔄 进行中 +4. **重构 CompilerBase** + - ⏳ 使用新的 Platform 和 Backend 类 + - ⏳ 保持向后兼容 + - ⏳ 逐步迁移现有代码 + +### 📋 待办 +5. **添加单元测试** + - ⏳ 测试所有 Platform 实现 + - ⏳ 测试所有 Backend 实现 + - ⏳ 测试工厂类 + - ⏳ 测试集成场景 + +6. **文档完善** + - ⏳ 添加更多使用示例 + - ⏳ 编写迁移指南 + - ⏳ 更新 API 文档 diff --git a/src/Php/Backend/example_usage.php b/src/Php/Backend/example_usage.php new file mode 100644 index 00000000..5ea2be56 --- /dev/null +++ b/src/Php/Backend/example_usage.php @@ -0,0 +1,78 @@ +getName()}\n"; +echo " 编译器: {$compiler->getName()}\n"; +echo " 对象文件扩展名: {$platform->getObjectExtension()}\n"; +echo " 可执行文件扩展名: {$platform->getExecutableExtension()}\n"; +echo "\n"; + +// 示例 2:构建编译命令 +echo "2. 构建编译命令:\n"; +$compileCmd = $compiler->buildCompileCommand( + 'test.cpp', + 'test' . $platform->getObjectExtension(), + [ + 'optimize' => 2, + 'debug' => false, + 'cpp_std' => 'c++17', + ] +); +echo " {$compileCmd}\n"; +echo "\n"; + +// 示例 3:构建链接命令 +echo "3. 构建链接命令:\n"; +$linkCmd = $compiler->buildLinkCommand( + ['test' . $platform->getObjectExtension()], + 'output' . $platform->getExecutableExtension(), + [ + 'debug' => true, + 'no_console' => false, + ] +); +echo " {$linkCmd}\n"; +echo "\n"; + +// 示例 4:手动指定平台和编译器 +echo "4. 手动指定平台和编译器:\n"; +use PhpAot\Php\Platform\Windows; +use PhpAot\Php\Backend\Msvc; + +$windowsPlatform = new Windows( + phpLibs: ['php8embed.lib', 'php8ts.lib'], + isZts: true +); +$msvcCompiler = new Msvc($windowsPlatform); + +echo " 平台: {$windowsPlatform->getName()}\n"; +echo " 编译器: {$msvcCompiler->getName()}\n"; +echo " ZTS: " . ($windowsPlatform->isZts() ? 'Yes' : 'No') . "\n"; +echo "\n"; + +// 示例 5:跨平台路径处理 +echo "5. 跨平台路径处理:\n"; +$path = $platform->joinPath('src', 'Php', 'Backend'); +echo " 组合路径: {$path}\n"; +echo " 路径分隔符: '{$platform->getPathSeparator()}'\n"; +echo "\n"; + +echo "=== 示例完成 ===\n"; diff --git a/src/Php/Platform/Linux.php b/src/Php/Platform/Linux.php new file mode 100644 index 00000000..d154876f --- /dev/null +++ b/src/Php/Platform/Linux.php @@ -0,0 +1,121 @@ +getPathSeparator(), $path); + } + + /** + * 组合路径 + */ + public function joinPath(string ...$parts): string + { + return implode($this->getPathSeparator(), $parts); + } +} diff --git a/src/Php/Platform/PlatformFactory.php b/src/Php/Platform/PlatformFactory.php new file mode 100644 index 00000000..e8d6c579 --- /dev/null +++ b/src/Php/Platform/PlatformFactory.php @@ -0,0 +1,58 @@ +isCurrent()) { + return new Windows(); + } elseif ((new Linux())->isCurrent()) { + return new Linux(); + } elseif ((new Macos())->isCurrent()) { + return new Macos(); + } else { + throw new \RuntimeException("Unsupported platform: " . PHP_OS); + } + } + + /** + * 获取当前平台名称 + */ + public static function getCurrentPlatformName(): string + { + return self::create()->getName(); + } + + /** + * 判断是否为 Windows 平台 + */ + public static function isWindows(): bool + { + return (new Windows())->isCurrent(); + } + + /** + * 判断是否为 Linux 平台 + */ + public static function isLinux(): bool + { + return (new Linux())->isCurrent(); + } + + /** + * 判断是否为 macOS 平台 + */ + public static function isMacos(): bool + { + return (new Macos())->isCurrent(); + } +} diff --git a/src/Php/Platform/Windows.php b/src/Php/Platform/Windows.php new file mode 100644 index 00000000..3c47dbb6 --- /dev/null +++ b/src/Php/Platform/Windows.php @@ -0,0 +1,145 @@ +phpLibs = $phpLibs; + $this->isZts = $isZts; + } + + public function getName(): string + { + return 'Windows'; + } + + public function isCurrent(): bool + { + return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'; + } + + public function getIncludeFlags(array $includePaths): string + { + if (empty($includePaths)) { + return ''; + } + + $flags = []; + foreach ($includePaths as $path) { + $flags[] = '/I "' . $path . '"'; + } + + return implode(' ', $flags); + } + + public function getLibraryPathFlags(array $libraryPaths): string + { + if (empty($libraryPaths)) { + return ''; + } + + $flags = []; + foreach ($libraryPaths as $path) { + $flags[] = '/LIBPATH:"' . $path . '"'; + } + + return implode(' ', $flags); + } + + public function getLibraryFlags(array $libraries): string + { + if (empty($libraries)) { + return ''; + } + + $flags = []; + foreach ($libraries as $lib) { + $flags[] = '"' . $lib . '"'; + } + + return implode(' ', $flags); + } + + public function getObjectExtension(): string + { + return '.obj'; + } + + public function getExecutableExtension(): string + { + return '.exe'; + } + + public function getSharedLibraryExtension(): string + { + return '.dll'; + } + + public function getPathSeparator(): string + { + return '\\'; + } + + /** + * 获取 PHP 库文件列表 + */ + public function getPhpLibs(): array + { + return $this->phpLibs; + } + + /** + * 判断是否为 ZTS 模式 + */ + public function isZts(): bool + { + return $this->isZts; + } + + /** + * 获取 Windows 子系统选项 + */ + public function getSubsystemOptions(bool $noConsole): string + { + if (!$noConsole) { + return ''; + } + + return '/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup'; + } + + /** + * 获取 CRT 库配置 + */ + public function getCrtConfig(): string + { + return '/NODEFAULTLIB:LIBCMT'; + } + + /** + * 获取调试选项 + */ + public function getDebugOptions(bool $debugInfo): string + { + if (!$debugInfo) { + return ''; + } + + return '/DEBUG'; + } +}