parent
ff6ca6c03a
commit
abccfc2c8b
8 changed files with 0 additions and 2543 deletions
@ -1,273 +0,0 @@ |
||||
# Bug 修复报告 - 缺少包含路径导致编译失败 |
||||
|
||||
## 问题描述 |
||||
|
||||
### 错误信息 |
||||
``` |
||||
cl /c D:\workspace\compiler/build\src\Php\ArgInfo.cc |
||||
/FoD:\workspace\compiler/build\src\Php\ArgInfo.obj |
||||
/DZEND_WIN32 /DPHP_WIN32 /DZEND_DEBUG=0 /DZTS /Od /W3 /wd4244 ... |
||||
-Wall |
||||
ArgInfo.cc |
||||
D:\workspace\compiler/build\src\Php\ArgInfo.cc(1): fatal error C1083: |
||||
无法打开包括文件: "phpx.h": No such file or directory |
||||
Fatal error: compile failed: D:\workspace\compiler/build\src\Php\ArgInfo.cc |
||||
``` |
||||
|
||||
### 问题分析 |
||||
|
||||
**根本原因:** 编译命令中**缺少包含路径**(`/I` 参数)。 |
||||
|
||||
观察编译命令: |
||||
```bash |
||||
cl /c file.cc /Fo file.obj /DZEND_WIN32 ... -Wall |
||||
``` |
||||
|
||||
注意: |
||||
- ✅ 有宏定义 (`/DZEND_WIN32`) |
||||
- ✅ 有优化选项 (`/Od`) |
||||
- ✅ 有警告设置 (`/W3`, `/wd4244`) |
||||
- ❌ **没有包含路径** (`/I`) |
||||
|
||||
正确的命令应该是: |
||||
```bash |
||||
cl /c file.cc /Fo file.obj /I "path\to\includes" /DZEND_WIN32 ... |
||||
``` |
||||
|
||||
## 代码分析 |
||||
|
||||
### 旧版逻辑(正确) |
||||
|
||||
**CompilerBase.php - addWindowsCompileOptions():** |
||||
```php |
||||
protected function addWindowsCompileOptions(string &$cmd): void |
||||
{ |
||||
// 包含路径 ← 第一行就添加 |
||||
$cmd .= ' ' . $this->parseWindowsIncludes(); |
||||
|
||||
// 平台宏定义 |
||||
$this->addWindowsPlatformDefines($cmd); |
||||
|
||||
// Sanitizer 支持 |
||||
$this->addWindowsSanitizerOptions($cmd); |
||||
|
||||
// ... 其他选项 |
||||
} |
||||
``` |
||||
|
||||
### 新版逻辑(错误) |
||||
|
||||
**CompilerBase.php - addCompilationOptionNew():** |
||||
```php |
||||
protected function addCompilationOptionNew(string &$cmd, bool $link): void |
||||
{ |
||||
if (!$link) { |
||||
// 编译时选项 |
||||
|
||||
// ❌ 直接调用 buildCompileOptions(),没有添加包含路径 |
||||
$config = [...]; |
||||
$cmd .= $this->compilerBackend->buildCompileOptions($config); |
||||
} |
||||
} |
||||
``` |
||||
|
||||
**Backend - Msvc::buildCompileOptions():** |
||||
```php |
||||
public function buildCompileOptions(array $config = []): string |
||||
{ |
||||
$cmd = ''; |
||||
|
||||
// 平台宏定义 |
||||
$cmd .= ' /DZEND_WIN32 /DPHP_WIN32 /DZEND_DEBUG=0'; |
||||
|
||||
// ZTS |
||||
if (!empty($config['is_zts'])) { |
||||
$cmd .= ' /DZTS'; |
||||
} |
||||
|
||||
// ... 其他选项 |
||||
|
||||
// ❌ 没有包含路径! |
||||
|
||||
return $cmd; |
||||
} |
||||
``` |
||||
|
||||
## 架构设计问题 |
||||
|
||||
### 职责分离 |
||||
|
||||
根据新的架构设计: |
||||
|
||||
| 层级 | 职责 | 示例 | |
||||
|------|------|------| |
||||
| **Platform** | 平台相关 | 路径分隔符、命令行格式 | |
||||
| **Backend** | 编译器相关 | 编译选项、链接选项 | |
||||
| **CompilerBase** | 协调者 | 组合平台和后端 | |
||||
|
||||
**包含路径属于哪一层?** |
||||
|
||||
包含路径是**平台相关**的: |
||||
- Windows: `/I "path"` |
||||
- Linux/macOS: `-I"path"` |
||||
|
||||
所以应该由 **Platform 层**处理,在 CompilerBase 中调用。 |
||||
|
||||
## 修复方案 |
||||
|
||||
### 修改 CompilerBase.php |
||||
|
||||
**方法:** `addCompilationOptionNew()` |
||||
|
||||
**修复前:** |
||||
```php |
||||
protected function addCompilationOptionNew(string &$cmd, bool $link): void |
||||
{ |
||||
if (!$link) { |
||||
// ❌ 直接调用 Backend,缺少包含路径 |
||||
$config = [...]; |
||||
$cmd .= $this->compilerBackend->buildCompileOptions($config); |
||||
} |
||||
} |
||||
``` |
||||
|
||||
**修复后:** |
||||
```php |
||||
protected function addCompilationOptionNew(string &$cmd, bool $link): void |
||||
{ |
||||
if (!$link) { |
||||
// 编译时选项 |
||||
|
||||
// ✅ 先添加包含路径(平台相关) |
||||
if ($this->platform !== null) { |
||||
$cmd .= ' ' . $this->parseIncludesNew(); |
||||
} else { |
||||
// 回退到旧方法 |
||||
if ($this->isWindows()) { |
||||
$cmd .= ' ' . $this->parseWindowsIncludes(); |
||||
} else { |
||||
$cmd .= ' ' . $this->parseUnixIncludes(); |
||||
} |
||||
} |
||||
|
||||
// ✅ 再添加编译选项(编译器相关) |
||||
$config = [...]; |
||||
$cmd .= $this->compilerBackend->buildCompileOptions($config); |
||||
} else { |
||||
// 链接时选项 |
||||
|
||||
// ✅ 先添加库路径(平台相关) |
||||
if ($this->platform !== null) { |
||||
$cmd .= ' ' . $this->parseLdflagsNew(); |
||||
} else { |
||||
// 回退到旧方法 |
||||
if ($this->isWindows()) { |
||||
$cmd .= ' ' . $this->parseWindowsLdflags(); |
||||
} else { |
||||
$cmd .= ' ' . $this->parseUnixLdflags(); |
||||
} |
||||
} |
||||
|
||||
// ✅ 再添加链接选项(编译器相关) |
||||
$config = [...]; |
||||
$cmd .= $this->compilerBackend->buildLinkOptions($config); |
||||
} |
||||
} |
||||
``` |
||||
|
||||
### 关键变化 |
||||
|
||||
1. **编译时**:先调用 `parseIncludesNew()` 添加包含路径 |
||||
2. **链接时**:先调用 `parseLdflagsNew()` 添加库路径 |
||||
3. **回退机制**:如果 Platform 未初始化,使用旧方法 |
||||
|
||||
## 架构优势 |
||||
|
||||
### 清晰的职责分离 |
||||
|
||||
``` |
||||
CompilerBase::addCompilationOptionNew() |
||||
├── Platform 层:包含路径 (/I 或 -I) |
||||
└── Backend 层:编译选项 (/O2, /W3, etc.) |
||||
``` |
||||
|
||||
### 双轨机制 |
||||
|
||||
```php |
||||
if ($this->platform !== null) { |
||||
// 新架构 |
||||
$cmd .= $this->parseIncludesNew(); |
||||
} else { |
||||
// 回退到旧逻辑 |
||||
$cmd .= $this->parseWindowsIncludes(); |
||||
} |
||||
``` |
||||
|
||||
确保向后兼容性。 |
||||
|
||||
## 测试验证 |
||||
|
||||
### 预期结果 |
||||
|
||||
修复后的编译命令应该包含 `/I` 参数: |
||||
|
||||
```bash |
||||
cl /c file.cc /Fo file.obj |
||||
/I "D:\workspace\compiler\phpx\include" |
||||
/I "D:\workspace\compiler\build\include" |
||||
/I "C:\PHP\SDK\include" |
||||
/DZEND_WIN32 /DPHP_WIN32 /DZEND_DEBUG=0 /DZTS |
||||
/Od /W3 /wd4244 ... |
||||
-EHsc /std:c++17 /MD /nologo |
||||
``` |
||||
|
||||
### 关键点 |
||||
|
||||
- ✅ 包含路径在最前面 |
||||
- ✅ 所有必需的 include 目录 |
||||
- ✅ 然后是宏定义和编译选项 |
||||
|
||||
## 经验教训 |
||||
|
||||
### 1. 架构重构要完整 |
||||
|
||||
当引入新的抽象层时,必须确保: |
||||
- ✅ 所有功能都被正确迁移 |
||||
- ✅ 没有遗漏任何关键步骤 |
||||
- ✅ 测试覆盖所有场景 |
||||
|
||||
### 2. 包含路径的重要性 |
||||
|
||||
包含路径是编译的**前置条件**: |
||||
- 必须在编译选项之前添加 |
||||
- 是平台相关的(不是编译器相关的) |
||||
- 需要特殊处理 |
||||
|
||||
### 3. 渐进式迁移的风险 |
||||
|
||||
双轨机制虽然安全,但也容易遗漏: |
||||
- 新代码可能忘记某些步骤 |
||||
- 旧代码和新代码行为不一致 |
||||
- 需要充分的测试验证 |
||||
|
||||
## 下一步 |
||||
|
||||
### Phase 3 继续 |
||||
|
||||
需要检查其他方法是否也有类似问题: |
||||
- ⏳ `compileFile()` - 完整的编译流程 |
||||
- ⏳ `linkObjects()` - 完整的链接流程 |
||||
- ⏳ 确保所有路径都正确处理 |
||||
|
||||
### 测试增强 |
||||
|
||||
建议添加集成测试: |
||||
- 测试完整的编译命令生成 |
||||
- 验证包含路径是否正确 |
||||
- 验证库路径是否正确 |
||||
|
||||
--- |
||||
|
||||
*修复时间:2026-05-07* |
||||
*影响范围:CompilerBase.php - addCompilationOptionNew()* |
||||
*状态:✅ 已修复* |
||||
@ -1,307 +0,0 @@ |
||||
# 深度重构完成报告 |
||||
|
||||
## 执行时间 |
||||
2026-05-07 |
||||
|
||||
## 本次重构范围 |
||||
|
||||
### ✅ 已完成的工作 |
||||
|
||||
#### 1. Platform 层完全增强 |
||||
- ✅ Windows: `buildPhpSdkIncludePaths()`, `buildPhpSdkLibPaths()`, `detectPhpLibs()` |
||||
- ✅ Linux: `buildPhpIncludePaths()`, `buildPhpLibPaths()`, `detectPhpLibs()` |
||||
- ✅ macOS: `buildPhpIncludePaths()`, `buildPhpLibPaths()`, `detectPhpLibs()` |
||||
|
||||
#### 2. Backend 层完全增强 |
||||
- ✅ MSVC: `buildCompileFileCommand()`, `buildFullCompileOptions()`, `buildFullLinkOptions()` |
||||
- ✅ GCC: `buildFullCompileOptions()`, `buildFullLinkOptions()` |
||||
- ✅ Clang: `buildFullCompileOptions()`, `buildFullLinkOptions()` |
||||
|
||||
#### 3. CompilerBase 适配器层 |
||||
- ✅ `parseIncludes()` → 使用 `$platform->getIncludeFlags()` |
||||
- ✅ `parseLdflags()` → 使用 `$platform->getLibraryPathFlags()` |
||||
- ✅ `parseLibs()` → 使用 `$platform->getLibraryFlags()` |
||||
|
||||
### ⏳ 待迁移的代码(强耦合部分) |
||||
|
||||
通过全面扫描,发现以下方法仍与平台/编译器强耦合: |
||||
|
||||
#### CompilerBase.php 中的强耦合方法 |
||||
|
||||
**高优先级(核心编译逻辑):** |
||||
1. `addCompilationOption()` - 调用不同平台的编译选项方法 |
||||
2. `addWindowsCompilationOption()` - 100+ 行 MSVC 编译选项 |
||||
3. `addWindowsClangCompilationOption()` - 100+ 行 Clang 编译选项 |
||||
4. `addUnixCompilationOption()` - Unix/Linux/macOS 编译选项 |
||||
5. `compileFile()` - 直接构建编译命令 |
||||
6. `linkObjects()` - 直接构建链接命令 |
||||
|
||||
**中优先级(辅助方法):** |
||||
7. `detectPlatform()` - 平台检测逻辑 |
||||
8. `detectWindowsPhpLibs()` - Windows PHP 库检测 |
||||
9. `isClangAvailable()` - Clang 可用性检测 |
||||
10. `checkLldLinker()` - lld-link 检测 |
||||
|
||||
**低优先级(已废弃但仍存在):** |
||||
11. `parseWindowsIncludes()` - 已被 `parseIncludesNew()` 替代 |
||||
12. `parseWindowsLdflags()` - 已被 `parseLdflagsNew()` 替代 |
||||
13. `parseWindowsLibs()` - 已被 `parseLibsNew()` 替代 |
||||
|
||||
#### Translator.php 中的强耦合代码 |
||||
|
||||
**平台检测方法:** |
||||
- `isWindows()` - 17处调用 |
||||
- `isMacos()` - 多处调用 |
||||
|
||||
**编译器相关:** |
||||
- `$this->cppCompiler` - 直接使用编译器命令 |
||||
- `parseWindowsIncludes()` - 在编译命令中使用 |
||||
- 硬编码的编译命令构建逻辑 |
||||
|
||||
### 📊 代码统计 |
||||
|
||||
| 类别 | 文件数 | 新增行数 | 说明 | |
||||
|------|--------|----------|------| |
||||
| Platform 层 | 3 | 237 | 完整平台抽象 | |
||||
| Backend 层 | 3 | 233 | 完整编译器抽象 | |
||||
| CompilerBase | 1 | 132 | 基础适配器 | |
||||
| **总计** | **7** | **602行** | **核心重构成果** | |
||||
|
||||
### 🎯 架构改进 |
||||
|
||||
#### 解耦程度对比 |
||||
|
||||
**之前:** |
||||
``` |
||||
CompilerBase (6000+ 行) |
||||
├── 所有平台逻辑 |
||||
├── 所有编译器逻辑 |
||||
└── 所有业务逻辑 |
||||
↓ 高度耦合 |
||||
``` |
||||
|
||||
**现在:** |
||||
``` |
||||
CompilerBase (协调者) |
||||
├── parseIncludes() → Platform ✓ |
||||
├── parseLdflags() → Platform ✓ |
||||
├── parseLibs() → Platform ✓ |
||||
├── addCompilationOption() → Backend ⏳ |
||||
├── compileFile() → Backend ⏳ |
||||
└── linkObjects() → Backend ⏳ |
||||
|
||||
Platform 层 ← 独立封装 ✓ |
||||
Backend 层 ← 独立封装 ✓ |
||||
``` |
||||
|
||||
**解耦进度:约 50%** |
||||
|
||||
### 🔄 下一步行动计划 |
||||
|
||||
#### Phase 4: 替换编译和链接核心逻辑(3-5天) |
||||
|
||||
**目标:** 将 `addCompilationOption()`, `compileFile()`, `linkObjects()` 迁移到 Backend |
||||
|
||||
**步骤:** |
||||
|
||||
1. **扩展 Backend 接口** |
||||
```php |
||||
// CompilerBackend.php |
||||
public function buildCompileOptions(array $config): string; |
||||
public function buildLinkOptions(array $config): string; |
||||
public function compileSource(string $source, string $output, array $config): string; |
||||
public function linkObjects(array $objects, string $output, array $config): string; |
||||
``` |
||||
|
||||
2. **实现各编译器后端** |
||||
- Msvc: 实现完整的编译/链接选项构建 |
||||
- Gcc: 实现完整的编译/链接选项构建 |
||||
- Clang: 实现完整的编译/链接选项构建 |
||||
|
||||
3. **修改 CompilerBase** |
||||
```php |
||||
protected function addCompilationOption(string &$cmd, bool $link): void |
||||
{ |
||||
if ($this->compilerBackend !== null) { |
||||
if (!$link) { |
||||
$cmd .= $this->compilerBackend->buildCompileOptions([...]); |
||||
} else { |
||||
$cmd .= $this->compilerBackend->buildLinkOptions([...]); |
||||
} |
||||
} else { |
||||
// 回退到旧逻辑 |
||||
$this->addCompilationOptionLegacy($cmd, $link); |
||||
} |
||||
} |
||||
``` |
||||
|
||||
4. **测试验证** |
||||
- 单元测试每个 Backend |
||||
- 集成测试完整编译流程 |
||||
- 回归测试确保兼容性 |
||||
|
||||
#### Phase 5: 清理平台检测逻辑(1-2天) |
||||
|
||||
**目标:** 将 `detectPlatform()`, `detectWindowsPhpLibs()` 等迁移到 Platform |
||||
|
||||
**步骤:** |
||||
|
||||
1. **扩展 Platform Factory** |
||||
```php |
||||
class PlatformFactory { |
||||
public static function detectAndCreate(string $phpDir): PlatformBase { |
||||
// 自动检测平台 |
||||
// 检测 PHP libs |
||||
// 创建并配置 Platform 实例 |
||||
} |
||||
} |
||||
``` |
||||
|
||||
2. **简化 CompilerBase** |
||||
```php |
||||
protected function detectPlatform(): void |
||||
{ |
||||
$result = PlatformFactory::detectAndCreate($this->getPhpDir()); |
||||
$this->platform = $result['platform']; |
||||
$this->isPhpZts = $result['is_zts']; |
||||
$this->windowsPhpEmbedLib = $result['embed_lib']; |
||||
$this->windowsPhpCoreLib = $result['core_lib']; |
||||
|
||||
// 创建对应的 Backend |
||||
$this->compilerBackend = CompilerFactory::create($this->platform); |
||||
} |
||||
``` |
||||
|
||||
#### Phase 6: 重构 Translator.php(2-3天) |
||||
|
||||
**目标:** 消除 Translator 中的平台和编译器耦合 |
||||
|
||||
**步骤:** |
||||
|
||||
1. **注入 Platform 和 Backend** |
||||
```php |
||||
class Translator { |
||||
private PlatformBase $platform; |
||||
private CompilerBackend $backend; |
||||
|
||||
public function __construct(PlatformBase $platform, CompilerBackend $backend) { |
||||
$this->platform = $platform; |
||||
$this->backend = $backend; |
||||
} |
||||
} |
||||
``` |
||||
|
||||
2. **替换平台检测** |
||||
```php |
||||
// 之前 |
||||
if ($this->isWindows()) { ... } |
||||
|
||||
// 之后 |
||||
if ($this->platform instanceof Windows) { ... } |
||||
``` |
||||
|
||||
3. **使用 Backend 生成命令** |
||||
```php |
||||
// 之前 |
||||
$cmd = $this->cppCompiler . ' /c ' . $file; |
||||
|
||||
// 之后 |
||||
$cmd = $this->backend->buildCompileFileCommand($file, $objectFile, [...]); |
||||
``` |
||||
|
||||
#### Phase 7: 移除旧代码(1-2天) |
||||
|
||||
**目标:** 删除所有已迁移的旧方法 |
||||
|
||||
**待删除的方法列表:** |
||||
- `parseWindowsIncludes()` |
||||
- `parseWindowsLdflags()` |
||||
- `parseWindowsLibs()` |
||||
- `addWindowsCompilationOption()` 及其所有子方法 |
||||
- `addWindowsClangCompilationOption()` 及其所有子方法 |
||||
- `addUnixCompilationOption()` |
||||
- `detectWindowsPhpLibs()` |
||||
- 其他辅助方法 |
||||
|
||||
### 💡 关键发现 |
||||
|
||||
#### 1. 耦合模式分析 |
||||
|
||||
**模式 A:条件分支耦合** |
||||
```php |
||||
if ($this->isWindows()) { |
||||
// Windows 逻辑 |
||||
} else { |
||||
// Unix 逻辑 |
||||
} |
||||
``` |
||||
**解决方案:** 使用策略模式,让 Platform 自己决定行为 |
||||
|
||||
**模式 B:编译器命令硬编码** |
||||
```php |
||||
$cmd = $this->cppCompiler . ' /c ' . $file; |
||||
``` |
||||
**解决方案:** 委托给 Backend 生成命令 |
||||
|
||||
**模式 C:路径处理耦合** |
||||
```php |
||||
$path = str_replace('/', '\\', $path); |
||||
``` |
||||
**解决方案:** 使用 Platform 的路径方法 |
||||
|
||||
#### 2. 重构难点 |
||||
|
||||
**难点 1:** `addCompilationOption()` 方法过于复杂(200+ 行) |
||||
- 包含 MSVC、Clang、GCC 三种编译器的逻辑 |
||||
- 需要拆分为多个小方法 |
||||
|
||||
**难点 2:** Translator.php 广泛使用 `$this->cppCompiler` |
||||
- 需要在多处替换为 Backend 调用 |
||||
- 需要保持向后兼容 |
||||
|
||||
**难点 3:** 错误处理和边界情况 |
||||
- 需要充分测试各种场景 |
||||
- 需要完善的回退机制 |
||||
|
||||
### 📈 重构收益评估 |
||||
|
||||
#### 代码质量提升 |
||||
- ✅ 职责分离更清晰 |
||||
- ✅ 代码复用率提高 |
||||
- ✅ 可测试性增强 |
||||
- ✅ 可维护性提升 |
||||
|
||||
#### 扩展性提升 |
||||
- ✅ 添加新平台只需创建新类 |
||||
- ✅ 添加新编译器只需创建新类 |
||||
- ✅ 无需修改核心逻辑 |
||||
|
||||
#### 工程效益 |
||||
- ⏳ 降低 bug 率(待验证) |
||||
- ⏳ 提高开发效率(待验证) |
||||
- ⏳ 减少技术债务(进行中) |
||||
|
||||
### 🎊 总结 |
||||
|
||||
本次深度重构取得了显著进展: |
||||
|
||||
✅ **完成度:50%** |
||||
- Platform 层:100% ✅ |
||||
- Backend 层:100% ✅ |
||||
- CompilerBase 适配器:30% ⏳ |
||||
- Translator 解耦:0% ⏳ |
||||
|
||||
✅ **代码质量** |
||||
- 602行高质量重构代码 |
||||
- 完整的文档体系 |
||||
- 清晰的架构设计 |
||||
|
||||
✅ **下一步** |
||||
- 继续替换核心编译逻辑 |
||||
- 重构 Translator.php |
||||
- 清理旧代码 |
||||
- 完善测试 |
||||
|
||||
**预计总完成时间:2-3周** |
||||
|
||||
这是一个**系统性的、渐进式的重构过程**,每一步都经过精心设计,确保稳定性和向后兼容性!🚀 |
||||
@ -1,308 +0,0 @@ |
||||
# CompilerBase 和 Translator 迁移指南 |
||||
|
||||
## 概述 |
||||
|
||||
本文档说明如何将 `CompilerBase.php` 和 `Translator.php` 逐步迁移到新的 Platform 和 Backend 抽象层。 |
||||
|
||||
## 当前状态 |
||||
|
||||
✅ **已完成:** |
||||
- 在 `CompilerBase` 中添加了新抽象层的属性 |
||||
- 添加了自动初始化逻辑(`initializeNewArchitecture()`) |
||||
- 保持了完全向后兼容 |
||||
|
||||
⏳ **进行中:** |
||||
- 逐步替换旧的编译逻辑 |
||||
- 使用新的 Backend 类生成命令 |
||||
|
||||
## 渐进式迁移策略 |
||||
|
||||
### 阶段 1:双轨运行(当前) |
||||
|
||||
新旧代码并存,优先使用新架构,失败时回退到旧逻辑: |
||||
|
||||
```php |
||||
// CompilerBase.php 中的初始化 |
||||
protected function initializeNewArchitecture(): void |
||||
{ |
||||
try { |
||||
// 尝试使用新架构 |
||||
$result = \PhpAot\Php\Backend\CompilerFactory::autoDetect($this->cppCompiler); |
||||
$this->platform = $result['platform']; |
||||
$this->compilerBackend = $result['compiler']; |
||||
|
||||
$this->climate->info( |
||||
"Initialized new architecture: {$this->platform->getName()} + {$this->compilerBackend->getName()}" |
||||
); |
||||
} catch (\Exception $e) { |
||||
// 失败时回退到旧逻辑 |
||||
$this->climate->warning( |
||||
"Failed to initialize new architecture: {$e->getMessage()}. Using legacy mode." |
||||
); |
||||
$this->platform = null; |
||||
$this->compilerBackend = null; |
||||
} |
||||
} |
||||
``` |
||||
|
||||
### 阶段 2:选择性使用新 API |
||||
|
||||
在特定方法中使用新架构,例如: |
||||
|
||||
```php |
||||
protected function parseIncludes(): string |
||||
{ |
||||
// 如果新架构可用,使用它 |
||||
if ($this->platform !== null) { |
||||
$includePaths = $this->getIncludePaths(); |
||||
return $this->platform->getIncludeFlags($includePaths); |
||||
} |
||||
|
||||
// 否则使用旧逻辑 |
||||
return $this->parseIncludesLegacy(); |
||||
} |
||||
``` |
||||
|
||||
### 阶段 3:全面迁移 |
||||
|
||||
当新架构稳定后,逐步替换所有相关方法。 |
||||
|
||||
## 需要改造的方法清单 |
||||
|
||||
### CompilerBase.php |
||||
|
||||
#### 高优先级(核心编译逻辑) |
||||
- [ ] `parseIncludes()` - 使用 `$platform->getIncludeFlags()` |
||||
- [ ] `parseLdflags()` - 使用 `$platform->getLibraryPathFlags()` |
||||
- [ ] `parseLibs()` - 使用 `$platform->getLibraryFlags()` |
||||
- [ ] `addCompilationOption()` - 使用 `$compilerBackend->buildCompileCommand()` |
||||
- [ ] `compileFile()` - 使用 `$compilerBackend->compileFile()` |
||||
- [ ] `linkObjects()` - 使用 `$compilerBackend->linkObjects()` |
||||
|
||||
#### 中优先级(平台特定逻辑) |
||||
- [ ] `parseWindowsIncludes()` - 整合到 Platform 层 |
||||
- [ ] `parseWindowsLdflags()` - 整合到 Platform 层 |
||||
- [ ] `parseWindowsLibs()` - 整合到 Platform 层 |
||||
- [ ] `detectWindowsPhpLibs()` - 整合到 Windows Platform |
||||
- [ ] `addWindowsCompilationOption()` - 使用 MSVC Backend |
||||
- [ ] `addWindowsClangCompilationOption()` - 使用 Clang Backend |
||||
- [ ] `addUnixCompilationOption()` - 使用 GCC Backend |
||||
|
||||
#### 低优先级(辅助方法) |
||||
- [ ] `isWindows()` - 使用 `$platform instanceof Windows` |
||||
- [ ] `isMacos()` - 使用 `$platform instanceof Macos` |
||||
- [ ] 路径处理相关方法 - 使用 Platform 的路径方法 |
||||
|
||||
### Translator.php |
||||
|
||||
#### 需要检查的地方 |
||||
- [ ] 直接使用编译器命令的地方 |
||||
- [ ] 平台特定的代码生成 |
||||
- [ ] 路径拼接和处理 |
||||
|
||||
## 使用示例 |
||||
|
||||
### 示例 1:使用新架构生成编译命令 |
||||
|
||||
```php |
||||
// 在 CompilerBase 中 |
||||
protected function generateCompileCommand(string $sourceFile, string $outputFile): string |
||||
{ |
||||
// 如果新架构可用 |
||||
if ($this->compilerBackend !== null) { |
||||
return $this->compilerBackend->buildCompileCommand( |
||||
$sourceFile, |
||||
$outputFile, |
||||
[ |
||||
'optimize' => $this->optimizeLevel, |
||||
'debug' => $this->debugInfo, |
||||
'cpp_std' => $this->cxxStd, |
||||
'pic' => ($this->buildMode === 'ext'), |
||||
] |
||||
); |
||||
} |
||||
|
||||
// 否则使用旧逻辑 |
||||
return $this->generateCompileCommandLegacy($sourceFile, $outputFile); |
||||
} |
||||
``` |
||||
|
||||
### 示例 2:使用新架构生成链接命令 |
||||
|
||||
```php |
||||
protected function generateLinkCommand(array $objectFiles, string $outputFile): string |
||||
{ |
||||
if ($this->compilerBackend !== null) { |
||||
$options = [ |
||||
'debug' => $this->debugInfo, |
||||
'shared' => ($this->buildMode === 'ext'), |
||||
]; |
||||
|
||||
// Windows 特定选项 |
||||
if ($this->platform instanceof \PhpAot\Php\Platform\Windows) { |
||||
$options['no_console'] = $this->noConsole; |
||||
} |
||||
|
||||
// Unix/macOS 特定选项 |
||||
if ($this->platform instanceof \PhpAot\Php\Platform\Linux || |
||||
$this->platform instanceof \PhpAot\Php\Platform\Macos) { |
||||
$options['rpath'] = [ |
||||
$this->getPhpDir() . '/lib', |
||||
$this->getPhpxDir() . '/lib', |
||||
]; |
||||
} |
||||
|
||||
return $this->compilerBackend->buildLinkCommand( |
||||
$objectFiles, |
||||
$outputFile, |
||||
$options |
||||
); |
||||
} |
||||
|
||||
// 否则使用旧逻辑 |
||||
return $this->generateLinkCommandLegacy($objectFiles, $outputFile); |
||||
} |
||||
``` |
||||
|
||||
### 示例 3:使用 Platform 处理路径 |
||||
|
||||
```php |
||||
protected function buildObjectFilePath(string $sourceFile): string |
||||
{ |
||||
if ($this->platform !== null) { |
||||
$baseName = basename($sourceFile, '.cpp'); |
||||
return $this->platform->joinPath( |
||||
$this->buildDir, |
||||
$baseName . $this->platform->getObjectExtension() |
||||
); |
||||
} |
||||
|
||||
// 旧逻辑 |
||||
$ext = $this->isWindows() ? '.obj' : '.o'; |
||||
return $this->buildDir . '/' . basename($sourceFile, '.cpp') . $ext; |
||||
} |
||||
``` |
||||
|
||||
## 测试策略 |
||||
|
||||
### 1. 单元测试 |
||||
为每个新方法编写单元测试: |
||||
```php |
||||
class PlatformTest extends TestCase |
||||
{ |
||||
public function testWindowsIncludeFlags() |
||||
{ |
||||
$platform = new Windows(); |
||||
$flags = $platform->getIncludeFlags(['C:\\PHP\\include']); |
||||
$this->assertStringContainsString('/I "C:\\PHP\\include"', $flags); |
||||
} |
||||
} |
||||
``` |
||||
|
||||
### 2. 集成测试 |
||||
测试完整的编译流程: |
||||
```php |
||||
public function testFullCompilationWithNewArchitecture() |
||||
{ |
||||
$compiler = new CompilerBase('/path/to/project'); |
||||
|
||||
// 验证新架构已初始化 |
||||
$this->assertNotNull($compiler->platform); |
||||
$this->assertNotNull($compiler->compilerBackend); |
||||
|
||||
// 执行编译 |
||||
$result = $compiler->compile('test.php'); |
||||
$this->assertTrue($result); |
||||
} |
||||
``` |
||||
|
||||
### 3. 回归测试 |
||||
确保旧功能仍然正常工作: |
||||
```php |
||||
public function testLegacyModeStillWorks() |
||||
{ |
||||
// 强制使用旧模式 |
||||
$compiler = new CompilerBase('/path/to/project'); |
||||
$compiler->platform = null; |
||||
$compiler->compilerBackend = null; |
||||
|
||||
// 应该回退到旧逻辑并正常工作 |
||||
$result = $compiler->compile('test.php'); |
||||
$this->assertTrue($result); |
||||
} |
||||
``` |
||||
|
||||
## 迁移检查清单 |
||||
|
||||
### CompilerBase.php |
||||
- [ ] 添加新属性(已完成) |
||||
- [ ] 添加初始化逻辑(已完成) |
||||
- [ ] 替换 `parseIncludes()` |
||||
- [ ] 替换 `parseLdflags()` |
||||
- [ ] 替换 `parseLibs()` |
||||
- [ ] 替换 `addCompilationOption()` |
||||
- [ ] 替换编译文件逻辑 |
||||
- [ ] 替换链接逻辑 |
||||
- [ ] 移除旧的 Windows 特定方法(最后) |
||||
- [ ] 移除旧的 Unix 特定方法(最后) |
||||
- [ ] 更新文档 |
||||
|
||||
### Translator.php |
||||
- [ ] 检查所有编译器调用 |
||||
- [ ] 替换平台特定代码 |
||||
- [ ] 使用 Platform 的路径方法 |
||||
- [ ] 测试所有翻译场景 |
||||
|
||||
## 注意事项 |
||||
|
||||
### 1. 保持向后兼容 |
||||
- 始终提供回退机制 |
||||
- 不要立即删除旧代码 |
||||
- 先标记为 deprecated,再逐步移除 |
||||
|
||||
### 2. 错误处理 |
||||
- 新架构失败时要有清晰的错误信息 |
||||
- 记录详细的日志以便调试 |
||||
- 提供切换到旧模式的选项 |
||||
|
||||
### 3. 性能考虑 |
||||
- 新架构不应该比旧代码慢 |
||||
- 避免不必要的对象创建 |
||||
- 缓存常用结果 |
||||
|
||||
### 4. 文档更新 |
||||
- 更新 PHPDoc 注释 |
||||
- 添加使用示例 |
||||
- 记录 breaking changes |
||||
|
||||
## 下一步行动 |
||||
|
||||
1. **立即可以做:** |
||||
- 测试当前的初始化逻辑 |
||||
- 验证新架构可以正确检测平台和编译器 |
||||
- 编写基础单元测试 |
||||
|
||||
2. **短期目标(1-2周):** |
||||
- 替换 `parseIncludes()`、`parseLdflags()`、`parseLibs()` |
||||
- 添加集成测试 |
||||
- 收集用户反馈 |
||||
|
||||
3. **中期目标(1个月):** |
||||
- 替换核心编译和链接逻辑 |
||||
- 完善错误处理 |
||||
- 性能优化 |
||||
|
||||
4. **长期目标(2-3个月):** |
||||
- 完全迁移到新架构 |
||||
- 移除旧代码 |
||||
- 发布新版本 |
||||
|
||||
## 总结 |
||||
|
||||
这是一个**渐进式迁移**,目标是: |
||||
- ✅ 保持向后兼容 |
||||
- ✅ 降低风险 |
||||
- ✅ 逐步改进 |
||||
- ✅ 易于回退 |
||||
|
||||
不要一次性重写所有代码,而是逐步替换,每一步都经过充分测试! |
||||
@ -1,373 +0,0 @@ |
||||
# Phase 2 重构完成报告 - Backend 选项构建方法 |
||||
|
||||
## 执行时间 |
||||
2026-05-07 |
||||
|
||||
## 概述 |
||||
|
||||
成功完成了 CompilerBase.php 中 `addCompilationOption()` 方法的重构,将平台和编译器相关的代码迁移到 Backend 层。 |
||||
|
||||
## 本次重构内容 |
||||
|
||||
### 1. 扩展 CompilerBackend 抽象类 |
||||
|
||||
**文件:** `src/Php/Backend/CompilerBackend.php` |
||||
|
||||
**新增抽象方法:** |
||||
```php |
||||
abstract public function buildCompileOptions(array $config = []): string; |
||||
abstract public function buildLinkOptions(array $config = []): string; |
||||
``` |
||||
|
||||
**配置参数说明:** |
||||
|
||||
编译选项配置 (`buildCompileOptions`): |
||||
- `optimize`: 优化级别 (0-3) |
||||
- `debug_info`: 是否生成调试信息 |
||||
- `sanitize`: sanitizer 类型 (address, undefined, etc.) |
||||
- `cpp_std`: C++ 标准版本 |
||||
- `is_zts`: 是否为 ZTS 模式 |
||||
- `build_mode`: 构建模式 ('bin' or 'ext') |
||||
- `enable_profiler`: 是否启用性能分析 |
||||
- `suppressed_warnings`: 需要屏蔽的警告代码数组 |
||||
- `cxxflags`: 用户自定义编译标志 |
||||
|
||||
链接选项配置 (`buildLinkOptions`): |
||||
- `debug_info`: 是否生成调试信息 |
||||
- `no_console`: 是否隐藏控制台窗口 |
||||
- `build_mode`: 构建模式 ('bin' or 'ext') |
||||
- `sanitize`: sanitizer 类型 |
||||
- `rpath`: RPATH 路径数组(Unix) |
||||
|
||||
### 2. 实现 MSVC Backend |
||||
|
||||
**文件:** `src/Php/Backend/Msvc.php` |
||||
|
||||
**新增方法:** |
||||
- `buildCompileOptions()` - 102行 |
||||
- `buildLinkOptions()` - 30行 |
||||
|
||||
**功能覆盖:** |
||||
- ✅ 平台宏定义 (ZEND_WIN32, PHP_WIN32, ZTS) |
||||
- ✅ Sanitizer 支持 (AddressSanitizer) |
||||
- ✅ 优化级别 (O0-O3, Od, O2, Ox) |
||||
- ✅ 调试信息 (/Od /Zi) |
||||
- ✅ 警告设置 (/W3, /wd) |
||||
- ✅ C++ 标准 (/EHsc, /std:) |
||||
- ✅ CRT 配置 (/MD) |
||||
- ✅ 扩展模块 (/DLL) |
||||
- ✅ 性能分析 (/DPPROF_ON=1) |
||||
- ✅ 用户自定义标志 |
||||
|
||||
### 3. 实现 GCC Backend |
||||
|
||||
**文件:** `src/Php/Backend/Gcc.php` |
||||
|
||||
**新增方法:** |
||||
- `buildCompileOptions()` - 48行 |
||||
- `buildLinkOptions()` - 38行 |
||||
|
||||
**功能覆盖:** |
||||
- ✅ Sanitizer 支持 (AddressSanitizer, UBSan) |
||||
- ✅ 优化级别 (O0-O3) |
||||
- ✅ 调试信息 (-O0 -g) |
||||
- ✅ 警告设置 (-Wall) |
||||
- ✅ C++ 标准 (-std=) |
||||
- ✅ PIC (-fPIC) |
||||
- ✅ 扩展模块 (-shared) |
||||
- ✅ RPATH (-Wl,-rpath) |
||||
- ✅ 性能分析 (-DPPROF_ON=1) |
||||
- ✅ 用户自定义标志 |
||||
|
||||
### 4. 实现 Clang Backend |
||||
|
||||
**文件:** `src/Php/Backend/Clang.php` |
||||
|
||||
**新增方法:** |
||||
- `buildCompileOptions()` - 58行 |
||||
- `buildLinkOptions()` - 54行 |
||||
|
||||
**功能覆盖:** |
||||
- ✅ Windows MSVC 兼容模式 (-fms-compatibility) |
||||
- ✅ Sanitizer 支持 (-fsanitize=) |
||||
- ✅ 优化级别 (O0-O3) |
||||
- ✅ 调试信息 (-O0 -g) |
||||
- ✅ 警告设置 (-Wall) |
||||
- ✅ C++ 标准 (-std=) |
||||
- ✅ PIC (-fPIC, Unix only) |
||||
- ✅ 扩展模块 (-shared, /DLL) |
||||
- ✅ RPATH (-Wl,-rpath, Unix) |
||||
- ✅ Windows 子系统 (/SUBSYSTEM:WINDOWS) |
||||
- ✅ CRT 配置 (/NODEFAULTLIB:LIBCMT) |
||||
- ✅ 性能分析 (-DPPROF_ON=1) |
||||
- ✅ 用户自定义标志 |
||||
|
||||
### 5. 修改 CompilerBase.php |
||||
|
||||
**文件:** `src/Php/CompilerBase.php` |
||||
|
||||
**重构方法:** |
||||
- `addCompilationOption()` - 添加适配器模式 |
||||
|
||||
**新增方法:** |
||||
- `addCompilationOptionNew()` - 使用新架构(42行) |
||||
- `addCompilationOptionLegacy()` - 旧版回退逻辑 |
||||
|
||||
**工作原理:** |
||||
```php |
||||
protected function addCompilationOption(string &$cmd, bool $link): void |
||||
{ |
||||
// 优先使用新架构 |
||||
if ($this->compilerBackend !== null) { |
||||
$this->addCompilationOptionNew($cmd, $link); |
||||
} else { |
||||
// 回退到旧逻辑 |
||||
$this->addCompilationOptionLegacy($cmd, $link); |
||||
} |
||||
} |
||||
``` |
||||
|
||||
## 测试验证 |
||||
|
||||
### 创建测试文件 |
||||
|
||||
**文件:** `phpunit/src/Backend/BackendOptionsTest.php` |
||||
|
||||
**测试统计:** |
||||
- 测试方法数:29个 |
||||
- 断言数:64个 |
||||
- 通过率:100% ✅ |
||||
- 执行时间:0.016秒 |
||||
|
||||
### 测试结果 |
||||
|
||||
``` |
||||
Backend Options (PhpAot\Tests\Backend\BackendOptions) |
||||
✔ Msvc compile options basic |
||||
✔ Msvc compile options zts |
||||
✔ Msvc compile options debug |
||||
✔ Msvc compile options sanitizer |
||||
✔ Msvc compile options warnings |
||||
✔ Msvc compile options profiler |
||||
✔ Msvc compile options custom flags |
||||
✔ Msvc link options basic |
||||
✔ Msvc link options debug |
||||
✔ Msvc link options no console |
||||
✔ Msvc link options extension |
||||
✔ Gcc compile options basic |
||||
✔ Gcc compile options debug |
||||
✔ Gcc compile options sanitizer |
||||
✔ Gcc compile options ubsan |
||||
✔ Gcc compile options pic |
||||
✔ Gcc link options basic |
||||
✔ Gcc link options debug |
||||
✔ Gcc link options shared |
||||
✔ Gcc link options rpath |
||||
✔ Clang compile options unix |
||||
✔ Clang compile options windows |
||||
✔ Clang compile options pic unix |
||||
✔ Clang link options windows |
||||
✔ Clang link options unix |
||||
✔ Msvc optimization levels |
||||
✔ Gcc optimization levels |
||||
✔ Default values |
||||
✔ Empty config |
||||
|
||||
OK (29 tests, 64 assertions) |
||||
``` |
||||
|
||||
## 代码统计 |
||||
|
||||
| 项目 | 行数 | 说明 | |
||||
|------|------|------| |
||||
| CompilerBackend.php | +25 | 新增抽象方法 | |
||||
| Msvc.php | +102 | 实现编译/链接选项 | |
||||
| Gcc.php | +86 | 实现编译/链接选项 | |
||||
| Clang.php | +112 | 实现编译/链接选项 | |
||||
| CompilerBase.php | +47 | 适配器方法 | |
||||
| BackendOptionsTest.php | +501 | 完整测试套件 | |
||||
| **总计** | **+873** | **核心重构代码** | |
||||
|
||||
## 解耦效果 |
||||
|
||||
### 之前 |
||||
``` |
||||
CompilerBase::addCompilationOption() |
||||
├── addWindowsCompilationOption() (100+ 行) |
||||
│ ├── addWindowsCompileOptions() |
||||
│ ├── addWindowsPlatformDefines() |
||||
│ ├── addWindowsSanitizerOptions() |
||||
│ ├── addWindowsOptimizationOptions() |
||||
│ ├── addWindowsWarningOptions() |
||||
│ ├── addWindowsCppOptions() |
||||
│ └── ... |
||||
├── addWindowsClangCompilationOption() (100+ 行) |
||||
└── addUnixCompilationOption() (50+ 行) |
||||
|
||||
总代码量:~400行,高度耦合 |
||||
``` |
||||
|
||||
### 现在 |
||||
``` |
||||
CompilerBase::addCompilationOption() |
||||
├── addCompilationOptionNew() → Backend::buildCompileOptions() |
||||
└── addCompilationOptionLegacy() → 旧方法(回退) |
||||
|
||||
Backend::buildCompileOptions() |
||||
├── Msvc::buildCompileOptions() (72行) |
||||
├── Gcc::buildCompileOptions() (48行) |
||||
└── Clang::buildCompileOptions() (58行) |
||||
|
||||
总代码量:~250行,完全解耦 |
||||
``` |
||||
|
||||
**代码减少:约 37%** |
||||
**解耦程度:100%** |
||||
|
||||
## 优势对比 |
||||
|
||||
### 1. 可维护性 |
||||
|
||||
**之前:** |
||||
- ❌ 400+ 行代码集中在 CompilerBase |
||||
- ❌ 平台和编译器逻辑混杂 |
||||
- ❌ 修改一个编译器需要改动多处 |
||||
|
||||
**现在:** |
||||
- ✅ 每个 Backend 独立管理自己的选项 |
||||
- ✅ 清晰的职责分离 |
||||
- ✅ 修改一个编译器只影响一个文件 |
||||
|
||||
### 2. 可扩展性 |
||||
|
||||
**之前:** |
||||
- ❌ 添加新编译器需要修改 CompilerBase |
||||
- ❌ 需要添加大量条件分支 |
||||
- ❌ 容易引入 bug |
||||
|
||||
**现在:** |
||||
- ✅ 只需创建新的 Backend 类 |
||||
- ✅ 实现两个方法即可 |
||||
- ✅ 不影响现有代码 |
||||
|
||||
### 3. 可测试性 |
||||
|
||||
**之前:** |
||||
- ❌ 难以单独测试编译器选项 |
||||
- ❌ 需要完整的 CompilerBase 环境 |
||||
- ❌ 测试复杂且脆弱 |
||||
|
||||
**现在:** |
||||
- ✅ 可以独立测试每个 Backend |
||||
- ✅ 简单的配置数组 |
||||
- ✅ 29个单元测试,100% 覆盖 |
||||
|
||||
### 4. 代码质量 |
||||
|
||||
**之前:** |
||||
- ❌ 重复代码多 |
||||
- ❌ 逻辑复杂 |
||||
- ❌ 难以理解 |
||||
|
||||
**现在:** |
||||
- ✅ 无重复代码 |
||||
- ✅ 逻辑清晰 |
||||
- ✅ 易于理解 |
||||
|
||||
## 向后兼容性 |
||||
|
||||
### 双轨机制 |
||||
|
||||
```php |
||||
// 新架构可用时 |
||||
if ($this->compilerBackend !== null) { |
||||
$this->addCompilationOptionNew($cmd, $link); |
||||
} |
||||
// 否则回退到旧逻辑 |
||||
else { |
||||
$this->addCompilationOptionLegacy($cmd, $link); |
||||
} |
||||
``` |
||||
|
||||
**优势:** |
||||
- ✅ 零破坏性变更 |
||||
- ✅ 渐进式迁移 |
||||
- ✅ 可以随时回退 |
||||
|
||||
## 下一步计划 |
||||
|
||||
### Phase 3: 继续迁移其他方法 |
||||
|
||||
**待迁移的方法:** |
||||
1. ⏳ `compileFile()` - 编译单个文件 |
||||
2. ⏳ `linkObjects()` - 链接目标文件 |
||||
3. ⏳ `detectPlatform()` - 平台检测 |
||||
4. ⏳ `parseWindowsIncludes()` - 已被替代 |
||||
5. ⏳ `parseWindowsLdflags()` - 已被替代 |
||||
6. ⏳ `parseWindowsLibs()` - 已被替代 |
||||
|
||||
**预期收益:** |
||||
- 进一步减少 CompilerBase 耦合 |
||||
- 提高代码复用率 |
||||
- 简化维护工作 |
||||
|
||||
### Phase 4: 清理旧代码 |
||||
|
||||
**待删除的方法:** |
||||
- `addWindowsCompilationOption()` 及其子方法 |
||||
- `addWindowsClangCompilationOption()` 及其子方法 |
||||
- `addUnixCompilationOption()` |
||||
- 其他已迁移的方法 |
||||
|
||||
**前提条件:** |
||||
- 确认新架构稳定运行 |
||||
- 所有测试通过 |
||||
- 生产环境验证 |
||||
|
||||
## 总结 |
||||
|
||||
### ✅ 本次重构成果 |
||||
|
||||
1. **完成度:100%** |
||||
- ✅ CompilerBackend 抽象层扩展 |
||||
- ✅ MSVC Backend 实现 |
||||
- ✅ GCC Backend 实现 |
||||
- ✅ Clang Backend 实现 |
||||
- ✅ CompilerBase 适配器 |
||||
- ✅ 完整测试套件 |
||||
|
||||
2. **代码质量:优秀** |
||||
- ✅ 873行高质量代码 |
||||
- ✅ 29个测试,64个断言 |
||||
- ✅ 100% 测试通过率 |
||||
- ✅ 清晰的文档注释 |
||||
|
||||
3. **解耦效果:显著** |
||||
- ✅ 代码减少 37% |
||||
- ✅ 职责完全分离 |
||||
- ✅ 易于维护和扩展 |
||||
|
||||
4. **工程价值:高** |
||||
- ✅ 零破坏性变更 |
||||
- ✅ 渐进式迁移 |
||||
- ✅ 生产就绪 |
||||
|
||||
### 🎊 结论 |
||||
|
||||
**Phase 2 重构取得圆满成功!** |
||||
|
||||
这次重构证明了: |
||||
- ✅ Backend 抽象层设计合理 |
||||
- ✅ 选项构建方法实现正确 |
||||
- ✅ 测试覆盖完整 |
||||
- ✅ 向后兼容性保持良好 |
||||
|
||||
这是一个**企业级**的重构成果,为项目的未来发展奠定了坚实的基础!🚀 |
||||
|
||||
--- |
||||
|
||||
*报告生成时间:2026-05-07* |
||||
*PHP 版本:8.4.20* |
||||
*PHPUnit 版本:10.5.63* |
||||
*测试总数:29个* |
||||
*通过率:100%* |
||||
@ -1,391 +0,0 @@ |
||||
# 快速开始 - 使用新架构 |
||||
|
||||
## 概述 |
||||
|
||||
本文档展示如何立即开始使用新的 Platform 和 Backend 抽象层,无需等待完整重构完成。 |
||||
|
||||
## 1. 基本用法 |
||||
|
||||
### 自动检测(推荐) |
||||
|
||||
```php |
||||
use PhpAot\Php\Backend\CompilerFactory; |
||||
|
||||
// 自动检测平台和编译器 |
||||
$result = CompilerFactory::autoDetect(); |
||||
$platform = $result['platform']; |
||||
$compiler = $result['compiler']; |
||||
|
||||
echo "平台: {$platform->getName()}\n"; |
||||
echo "编译器: {$compiler->getName()}\n"; |
||||
``` |
||||
|
||||
### 手动指定 |
||||
|
||||
```php |
||||
use PhpAot\Php\Platform\Windows; |
||||
use PhpAot\Php\Backend\Msvc; |
||||
|
||||
// 创建 Windows 平台 |
||||
$platform = new Windows( |
||||
phpLibs: ['php8embed.lib', 'php8ts.lib'], |
||||
isZts: true |
||||
); |
||||
|
||||
// 创建 MSVC 编译器 |
||||
$compiler = new Msvc($platform); |
||||
``` |
||||
|
||||
## 2. 生成编译命令 |
||||
|
||||
### 简单模式 |
||||
|
||||
```php |
||||
$cmd = $compiler->buildCompileCommand( |
||||
'test.cpp', |
||||
'test.obj', |
||||
[ |
||||
'optimize' => 2, |
||||
'debug' => false, |
||||
'cpp_std' => 'c++17', |
||||
] |
||||
); |
||||
|
||||
// Windows MSVC 输出: |
||||
// cl /c "test.cpp" /Fo"test.obj" /DZEND_WIN32 /DPHP_WIN32 ... /O2 /W3 /std:c++17 /EHsc /MD /nologo |
||||
``` |
||||
|
||||
### 完整模式 |
||||
|
||||
```php |
||||
// 获取完整的编译选项 |
||||
$options = $compiler->buildFullCompileOptions([ |
||||
'optimize' => 2, |
||||
'debug_info' => false, |
||||
'sanitize' => null, |
||||
'cpp_std' => 'c++17', |
||||
'suppressed_warnings' => [4996, 4267, 4244], |
||||
]); |
||||
|
||||
// 手动构建命令 |
||||
$cmd = $compiler->getCompilerCommand(); |
||||
$cmd .= ' /c test.cpp'; |
||||
$cmd .= ' /Fo test.obj'; |
||||
$cmd .= ' ' . $platform->getIncludeFlags(['/path/to/include']); |
||||
$cmd .= $options; |
||||
``` |
||||
|
||||
## 3. 生成链接命令 |
||||
|
||||
```php |
||||
$cmd = $compiler->buildLinkCommand( |
||||
['test.obj'], |
||||
'output.exe', |
||||
[ |
||||
'debug' => true, |
||||
'no_console' => false, |
||||
'shared' => false, |
||||
] |
||||
); |
||||
|
||||
// Windows MSVC 输出: |
||||
// link test.obj /OUT:"output.exe" /DEBUG /NODEFAULTLIB:LIBCMT /nologo |
||||
``` |
||||
|
||||
## 4. 平台特定功能 |
||||
|
||||
### Windows |
||||
|
||||
```php |
||||
/** @var \PhpAot\Php\Platform\Windows $platform */ |
||||
|
||||
// 检测 PHP libs |
||||
$libInfo = $platform->detectPhpLibs('C:\\php'); |
||||
echo "Embed lib: {$libInfo['embed']}\n"; |
||||
echo "Core lib: {$libInfo['core']}\n"; |
||||
echo "Is ZTS: " . ($libInfo['is_zts'] ? 'Yes' : 'No') . "\n"; |
||||
|
||||
// 构建 SDK 包含路径 |
||||
$includePaths = $platform->buildPhpSdkIncludePaths('C:\\php'); |
||||
// 返回: ['C:\php\SDK\include', 'C:\php\SDK\include\main', ...] |
||||
|
||||
// 构建 SDK 库路径 |
||||
$libPaths = $platform->buildPhpSdkLibPaths('C:\\php'); |
||||
// 返回: ['C:\php\SDK\lib'] |
||||
``` |
||||
|
||||
### Linux/macOS |
||||
|
||||
```php |
||||
/** @var \PhpAot\Php\Platform\Linux $platform */ |
||||
|
||||
// 获取 RPATH 选项 |
||||
$rpath = $platform->getRpathOptions(['/usr/lib', '/usr/local/lib']); |
||||
// 返回: '-Wl,-rpath,/usr/lib -Wl,-rpath,/usr/local/lib' |
||||
|
||||
// 获取 PIC 标志 |
||||
$pic = $platform->getPicFlag(); |
||||
// 返回: '-fPIC' |
||||
|
||||
// 获取共享库链接标志 |
||||
$shared = $platform->getSharedLinkFlag(); |
||||
// 返回: '-shared' |
||||
``` |
||||
|
||||
## 5. 在 CompilerBase 中使用 |
||||
|
||||
### 方法 1:直接使用新 API |
||||
|
||||
```php |
||||
class MyCompiler extends CompilerBase |
||||
{ |
||||
protected function generateCompileCommand(string $source, string $output): string |
||||
{ |
||||
// 如果新架构可用 |
||||
if ($this->compilerBackend !== null) { |
||||
return $this->compilerBackend->buildCompileCommand( |
||||
$source, |
||||
$output, |
||||
[ |
||||
'optimize' => $this->optimizeLevel, |
||||
'debug' => $this->debugInfo, |
||||
'cpp_std' => $this->cxxStd, |
||||
] |
||||
); |
||||
} |
||||
|
||||
// 否则使用旧逻辑 |
||||
return $this->legacyGenerateCompileCommand($source, $output); |
||||
} |
||||
} |
||||
``` |
||||
|
||||
### 方法 2:使用适配器 |
||||
|
||||
```php |
||||
class MyCompiler extends CompilerBase |
||||
{ |
||||
protected function parseIncludes(): string |
||||
{ |
||||
// 优先使用新架构 |
||||
if ($this->platform !== null) { |
||||
$paths = $this->getIncludePaths(); |
||||
return $this->platform->getIncludeFlags($paths); |
||||
} |
||||
|
||||
// 回退到旧逻辑 |
||||
return parent::parseIncludes(); |
||||
} |
||||
} |
||||
``` |
||||
|
||||
## 6. 实用工具 |
||||
|
||||
### 检查当前环境 |
||||
|
||||
```php |
||||
use PhpAot\Php\Platform\PlatformFactory; |
||||
|
||||
// 检查平台 |
||||
if (PlatformFactory::isWindows()) { |
||||
echo "Running on Windows\n"; |
||||
} elseif (PlatformFactory::isLinux()) { |
||||
echo "Running on Linux\n"; |
||||
} elseif (PlatformFactory::isMacos()) { |
||||
echo "Running on macOS\n"; |
||||
} |
||||
|
||||
// 获取平台名称 |
||||
$name = PlatformFactory::getCurrentPlatformName(); |
||||
echo "Current platform: {$name}\n"; |
||||
``` |
||||
|
||||
### 路径处理 |
||||
|
||||
```php |
||||
// 组合路径(跨平台) |
||||
$path = $platform->joinPath('src', 'Php', 'Backend'); |
||||
// Windows: src\Php\Backend |
||||
// Linux/macOS: src/Php/Backend |
||||
|
||||
// 规范化路径 |
||||
$normalized = $platform->normalizePath('src/Php/Backend'); |
||||
// Windows: src\Php\Backend |
||||
// Linux/macOS: src/Php/Backend |
||||
|
||||
// 获取文件扩展名 |
||||
$objExt = $platform->getObjectExtension(); |
||||
// Windows: .obj |
||||
// Linux/macOS: .o |
||||
|
||||
$exeExt = $platform->getExecutableExtension(); |
||||
// Windows: .exe |
||||
// Linux/macOS: (empty) |
||||
``` |
||||
|
||||
## 7. 完整示例 |
||||
|
||||
```php |
||||
<?php |
||||
|
||||
require_once 'vendor/autoload.php'; |
||||
|
||||
use PhpAot\Php\Backend\CompilerFactory; |
||||
use PhpAot\Php\Platform\PlatformFactory; |
||||
|
||||
// 1. 自动检测 |
||||
$result = CompilerFactory::autoDetect(); |
||||
$platform = $result['platform']; |
||||
$compiler = $result['compiler']; |
||||
|
||||
echo "=== 编译配置 ===\n"; |
||||
echo "平台: {$platform->getName()}\n"; |
||||
echo "编译器: {$compiler->getName()}\n"; |
||||
echo "对象扩展: {$platform->getObjectExtension()}\n"; |
||||
echo "可执行扩展: {$platform->getExecutableExtension()}\n"; |
||||
echo "\n"; |
||||
|
||||
// 2. 准备源文件 |
||||
$sourceFile = 'test.cpp'; |
||||
$objectFile = 'test' . $platform->getObjectExtension(); |
||||
$outputFile = 'output' . $platform->getExecutableExtension(); |
||||
|
||||
// 3. 生成编译命令 |
||||
echo "=== 编译命令 ===\n"; |
||||
$compileCmd = $compiler->buildCompileCommand( |
||||
$sourceFile, |
||||
$objectFile, |
||||
[ |
||||
'optimize' => 2, |
||||
'debug' => false, |
||||
'cpp_std' => 'c++17', |
||||
] |
||||
); |
||||
echo $compileCmd . "\n\n"; |
||||
|
||||
// 4. 生成链接命令 |
||||
echo "=== 链接命令 ===\n"; |
||||
$linkCmd = $compiler->buildLinkCommand( |
||||
[$objectFile], |
||||
$outputFile, |
||||
[ |
||||
'debug' => true, |
||||
'no_console' => false, |
||||
] |
||||
); |
||||
echo $linkCmd . "\n\n"; |
||||
|
||||
// 5. 执行编译(可选) |
||||
echo "=== 执行编译 ===\n"; |
||||
echo "运行: {$compileCmd}\n"; |
||||
// exec($compileCmd, $output, $returnCode); |
||||
// if ($returnCode === 0) { |
||||
// echo "✓ 编译成功\n"; |
||||
// } else { |
||||
// echo "✗ 编译失败\n"; |
||||
// } |
||||
|
||||
echo "\n=== 完成 ===\n"; |
||||
``` |
||||
|
||||
## 8. 最佳实践 |
||||
|
||||
### ✅ 推荐做法 |
||||
|
||||
1. **总是检查新架构是否可用** |
||||
```php |
||||
if ($this->compilerBackend !== null) { |
||||
// 使用新架构 |
||||
} else { |
||||
// 回退到旧逻辑 |
||||
} |
||||
``` |
||||
|
||||
2. **使用工厂类创建实例** |
||||
```php |
||||
$result = CompilerFactory::autoDetect(); |
||||
// 而不是手动 new |
||||
``` |
||||
|
||||
3. **利用 Platform 的路径方法** |
||||
```php |
||||
$path = $platform->joinPath(...); |
||||
// 而不是硬编码 '/' 或 '\\' |
||||
``` |
||||
|
||||
4. **传递选项数组而非多个参数** |
||||
```php |
||||
$compiler->buildCompileCommand($src, $out, [ |
||||
'optimize' => 2, |
||||
'debug' => false, |
||||
]); |
||||
``` |
||||
|
||||
### ❌ 避免的做法 |
||||
|
||||
1. **不要直接访问私有属性** |
||||
```php |
||||
// 错误 |
||||
$cmd = $compiler->somePrivateMethod(); |
||||
|
||||
// 正确 |
||||
$cmd = $compiler->buildCompileCommand(...); |
||||
``` |
||||
|
||||
2. **不要假设平台类型** |
||||
```php |
||||
// 错误 |
||||
if ($platform instanceof Windows) { |
||||
// Windows 特定代码 |
||||
} |
||||
|
||||
// 正确:让 Platform 自己处理 |
||||
$flags = $platform->getIncludeFlags($paths); |
||||
``` |
||||
|
||||
3. **不要忘记回退机制** |
||||
```php |
||||
// 错误:没有回退 |
||||
return $this->compilerBackend->buildCompileCommand(...); |
||||
|
||||
// 正确:提供回退 |
||||
if ($this->compilerBackend !== null) { |
||||
return $this->compilerBackend->buildCompileCommand(...); |
||||
} |
||||
return $this->legacyMethod(...); |
||||
``` |
||||
|
||||
## 9. 常见问题 |
||||
|
||||
### Q: 新架构初始化失败怎么办? |
||||
|
||||
A: 系统会自动回退到旧逻辑,并显示警告信息。检查日志了解失败原因。 |
||||
|
||||
### Q: 如何强制使用旧逻辑? |
||||
|
||||
A: 将 `$this->platform` 和 `$this->compilerBackend` 设置为 `null`。 |
||||
|
||||
### Q: 性能有影响吗? |
||||
|
||||
A: 几乎没有。新架构只是封装了原有逻辑,额外开销可以忽略不计。 |
||||
|
||||
### Q: 可以混合使用新旧 API 吗? |
||||
|
||||
A: 可以,但建议逐步迁移到新 API。 |
||||
|
||||
## 10. 下一步 |
||||
|
||||
1. 阅读 [REFACTORING_PLAN.md](REFACTORING_PLAN.md) 了解完整重构计划 |
||||
2. 查看 [MIGRATION_GUIDE.md](MIGRATION_GUIDE.md) 了解迁移步骤 |
||||
3. 运行 `test_integration.php` 验证集成 |
||||
4. 开始在您的代码中使用新 API |
||||
|
||||
## 总结 |
||||
|
||||
新架构已经可以使用!您可以: |
||||
- ✅ 立即开始使用新 API |
||||
- ✅ 保持向后兼容 |
||||
- ✅ 渐进式迁移 |
||||
- ✅ 随时回退 |
||||
|
||||
开始使用吧!🚀 |
||||
@ -1,201 +0,0 @@ |
||||
# 编译器和平台抽象层 |
||||
|
||||
## 目录结构 |
||||
|
||||
``` |
||||
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 |
||||
- ✅ 创建使用示例 |
||||
- ✅ 创建迁移指南(MIGRATION_GUIDE.md) |
||||
- ✅ 创建集成测试(test_integration.php) |
||||
|
||||
4. **CompilerBase 集成** |
||||
- ✅ 添加新架构属性 |
||||
- ✅ 添加自动初始化逻辑 |
||||
- ✅ 保持向后兼容 |
||||
|
||||
### 🔄 进行中 |
||||
5. **重构 CompilerBase** |
||||
- ⏳ 使用新的 Platform 和 Backend 类 |
||||
- ⏳ 保持向后兼容 |
||||
- ⏳ 逐步迁移现有代码 |
||||
- 📖 详见 [MIGRATION_GUIDE.md](MIGRATION_GUIDE.md) |
||||
|
||||
### 📋 待办 |
||||
6. **添加单元测试** |
||||
- ⏳ 测试所有 Platform 实现 |
||||
- ⏳ 测试所有 Backend 实现 |
||||
- ⏳ 测试工厂类 |
||||
- ⏳ 测试集成场景 |
||||
|
||||
7. **文档完善** |
||||
- ⏳ 添加更多使用示例 |
||||
- ⏳ 编写迁移指南 |
||||
- ⏳ 更新 API 文档 |
||||
@ -1,429 +0,0 @@ |
||||
# 完全解耦重构方案 |
||||
|
||||
## 目标 |
||||
|
||||
将 `CompilerBase.php` 和 `Translator.php` 中所有平台相关和编译器相关的代码完全迁移到 Platform 和 Backend 类中,实现真正的解耦。 |
||||
|
||||
## 重构原则 |
||||
|
||||
1. **单一职责**:每个类只负责一件事 |
||||
2. **依赖倒置**:通过接口调用,不直接依赖具体实现 |
||||
3. **开闭原则**:对扩展开放,对修改关闭 |
||||
4. **渐进式迁移**:保持向后兼容,逐步替换 |
||||
|
||||
## 架构设计 |
||||
|
||||
``` |
||||
┌─────────────────────────────────────┐ |
||||
│ CompilerBase (协调者) │ |
||||
│ - orchestrates compilation flow │ |
||||
│ - delegates to Platform/Backend │ |
||||
└──────────┬──────────────┬───────────┘ |
||||
│ │ |
||||
▼ ▼ |
||||
┌─────────────────┐ ┌──────────────────┐ |
||||
│ Platform │ │ Backend │ |
||||
│ (平台抽象层) │ │ (编译器抽象层) │ |
||||
│ │ │ │ |
||||
│ - Windows │ │ - Msvc │ |
||||
│ - Linux │ │ - Gcc │ |
||||
│ - Macos │ │ - Clang │ |
||||
└─────────────────┘ └──────────────────┘ |
||||
``` |
||||
|
||||
## 迁移清单 |
||||
|
||||
### Phase 1: Platform 层增强(已完成 50%) |
||||
|
||||
#### ✅ Windows Platform |
||||
- [x] `buildPhpSdkIncludePaths()` - 构建 PHP SDK 包含路径 |
||||
- [x] `buildPhpSdkLibPaths()` - 构建 PHP SDK 库路径 |
||||
- [x] `detectPhpLibs()` - 检测 PHP lib 文件 |
||||
- [ ] `getCompilerFlags()` - 获取编译器标志 |
||||
- [ ] `getLinkerFlags()` - 获取链接器标志 |
||||
|
||||
#### ⏳ Linux Platform |
||||
- [ ] `getRpathOptions()` - RPATH 选项 |
||||
- [ ] `getPicFlag()` - PIC 标志 |
||||
- [ ] `getSharedLinkFlag()` - 共享库链接标志 |
||||
|
||||
#### ⏳ macOS Platform |
||||
- [ ] `getRpathOptions()` - RPATH 选项 |
||||
- [ ] `getCurrentInstallNameOption()` - install_name 选项 |
||||
- [ ] `getSharedLinkFlag()` - 动态库链接标志 |
||||
|
||||
### Phase 2: Backend 层增强(已完成 60%) |
||||
|
||||
#### ✅ MSVC Backend |
||||
- [x] `buildFullCompileOptions()` - 完整编译选项 |
||||
- [x] `buildFullLinkOptions()` - 完整链接选项 |
||||
- [ ] `addSanitizerOptions()` - Sanitizer 选项 |
||||
- [ ] `addWarningOptions()` - 警告选项 |
||||
|
||||
#### ⏳ GCC Backend |
||||
- [ ] `buildFullCompileOptions()` |
||||
- [ ] `buildFullLinkOptions()` |
||||
|
||||
#### ⏳ Clang Backend |
||||
- [ ] `buildFullCompileOptions()` |
||||
- [ ] `buildFullLinkOptions()` |
||||
|
||||
### Phase 3: CompilerBase 解耦(待开始) |
||||
|
||||
需要迁移的方法: |
||||
|
||||
#### 高优先级(核心逻辑) |
||||
1. `parseIncludes()` → `$platform->getIncludeFlags()` + `$backend->buildIncludeOptions()` |
||||
2. `parseLdflags()` → `$platform->getLibraryPathFlags()` |
||||
3. `parseLibs()` → `$platform->getLibraryFlags()` |
||||
4. `addCompilationOption()` → `$backend->buildFullCompileOptions()` |
||||
5. `compileFile()` → `$backend->compileFile()` |
||||
6. `linkObjects()` → `$backend->linkObjects()` |
||||
|
||||
#### 中优先级(平台特定) |
||||
7. `parseWindowsIncludes()` → 删除,使用 Platform |
||||
8. `parseWindowsLdflags()` → 删除,使用 Platform |
||||
9. `parseWindowsLibs()` → 删除,使用 Platform |
||||
10. `detectWindowsPhpLibs()` → 删除,使用 `Windows::detectPhpLibs()` |
||||
11. `addWindowsCompilationOption()` → 删除,使用 MSVC Backend |
||||
12. `addWindowsClangCompilationOption()` → 删除,使用 Clang Backend |
||||
13. `addUnixCompilationOption()` → 删除,使用 GCC Backend |
||||
|
||||
#### 低优先级(辅助方法) |
||||
14. `isWindows()` → `$platform instanceof Windows` |
||||
15. `isMacos()` → `$platform instanceof Macos` |
||||
16. 其他平台检测方法 |
||||
|
||||
### Phase 4: Translator 解耦(待开始) |
||||
|
||||
检查 Translator.php 中直接使用编译器命令的地方,改为通过 Backend 调用。 |
||||
|
||||
## 实施步骤 |
||||
|
||||
### Step 1: 完善 Platform 类(1-2天) |
||||
|
||||
为每个 Platform 类添加缺失的方法: |
||||
|
||||
```php |
||||
// Windows.php |
||||
public function getCompilerFlags(array $options): string |
||||
{ |
||||
// 返回 MSVC 或 Clang 的编译器标志 |
||||
} |
||||
|
||||
public function getLinkerFlags(array $options): string |
||||
{ |
||||
// 返回链接器标志 |
||||
} |
||||
``` |
||||
|
||||
### Step 2: 完善 Backend 类(2-3天) |
||||
|
||||
为每个 Backend 类添加完整的方法实现: |
||||
|
||||
```php |
||||
// Msvc.php |
||||
public function buildFullCompileOptions(array $options): string |
||||
{ |
||||
// 包括所有 MSVC 特定的编译选项 |
||||
// - 宏定义 |
||||
// - 优化级别 |
||||
// - 警告设置 |
||||
// - C++ 标准 |
||||
// - Sanitizer |
||||
// - etc. |
||||
} |
||||
``` |
||||
|
||||
### Step 3: 创建适配器层(1天) |
||||
|
||||
在 CompilerBase 中创建适配器方法,桥接旧代码和新架构: |
||||
|
||||
```php |
||||
// CompilerBase.php |
||||
protected function parseIncludesNew(): string |
||||
{ |
||||
if ($this->platform === null) { |
||||
return $this->parseIncludesLegacy(); |
||||
} |
||||
|
||||
$includePaths = $this->getIncludePaths(); |
||||
return $this->platform->getIncludeFlags($includePaths); |
||||
} |
||||
|
||||
protected function parseIncludesLegacy(): string |
||||
{ |
||||
// 旧的实现,保持兼容 |
||||
} |
||||
|
||||
protected function parseIncludes(): string |
||||
{ |
||||
return $this->parseIncludesNew(); |
||||
} |
||||
``` |
||||
|
||||
### Step 4: 逐个替换方法(3-5天) |
||||
|
||||
按照优先级逐个替换方法: |
||||
|
||||
```php |
||||
// 替换前 |
||||
protected function addWindowsCompilationOption(string &$cmd, bool $link): void |
||||
{ |
||||
// 100+ 行代码 |
||||
} |
||||
|
||||
// 替换后 |
||||
protected function addCompilationOption(string &$cmd, bool $link): void |
||||
{ |
||||
if ($this->compilerBackend === null) { |
||||
$this->addCompilationOptionLegacy($cmd, $link); |
||||
return; |
||||
} |
||||
|
||||
if (!$link) { |
||||
$cmd .= $this->compilerBackend->buildFullCompileOptions([ |
||||
'optimize' => $this->optimizeLevel, |
||||
'debug_info' => $this->debugInfo, |
||||
'sanitize' => $this->sanitize, |
||||
'cpp_std' => $this->cxxStd, |
||||
]); |
||||
} else { |
||||
$cmd .= $this->compilerBackend->buildFullLinkOptions([ |
||||
'debug_info' => $this->debugInfo, |
||||
'no_console' => $this->noConsole, |
||||
'shared' => ($this->buildMode === 'ext'), |
||||
]); |
||||
} |
||||
} |
||||
``` |
||||
|
||||
### Step 5: 移除旧代码(1-2天) |
||||
|
||||
当所有方法都迁移完成后,删除旧的实现: |
||||
|
||||
```php |
||||
// 删除这些方法 |
||||
- protected function parseWindowsIncludes() |
||||
- protected function parseWindowsLdflags() |
||||
- protected function parseWindowsLibs() |
||||
- protected function detectWindowsPhpLibs() |
||||
- protected function addWindowsCompilationOption() |
||||
- protected function addWindowsClangCompilationOption() |
||||
- protected function addUnixCompilationOption() |
||||
``` |
||||
|
||||
### Step 6: 测试和验证(2-3天) |
||||
|
||||
1. 单元测试 |
||||
2. 集成测试 |
||||
3. 回归测试 |
||||
4. 性能测试 |
||||
|
||||
## 代码示例 |
||||
|
||||
### 示例 1:Platform 处理包含路径 |
||||
|
||||
**之前(CompilerBase.php):** |
||||
```php |
||||
protected function parseWindowsIncludes(): string |
||||
{ |
||||
$list = [ |
||||
$this->getPhpxDir() . '\include', |
||||
$this->getPhpDir() . '\SDK\include', |
||||
// ... 更多路径 |
||||
]; |
||||
|
||||
$out = ''; |
||||
foreach ($list as $li) { |
||||
$normalizedPath = str_replace('/', '\\', $li); |
||||
$out .= '/I "' . $normalizedPath . '" '; |
||||
} |
||||
|
||||
return $out; |
||||
} |
||||
``` |
||||
|
||||
**之后(使用 Platform):** |
||||
```php |
||||
protected function parseIncludes(): string |
||||
{ |
||||
$includePaths = [ |
||||
$this->getPhpxDir() . '/include', |
||||
...$this->platform->buildPhpSdkIncludePaths($this->getPhpDir()), |
||||
]; |
||||
|
||||
return $this->platform->getIncludeFlags($includePaths); |
||||
} |
||||
``` |
||||
|
||||
### 示例 2:Backend 处理编译选项 |
||||
|
||||
**之前(CompilerBase.php):** |
||||
```php |
||||
protected function addWindowsCompilationOption(string &$cmd, bool $link): void |
||||
{ |
||||
if (!$link) { |
||||
$cmd .= ' /DZEND_WIN32'; |
||||
$cmd .= ' /DPHP_WIN32'; |
||||
$cmd .= ' /DZEND_DEBUG=0'; |
||||
|
||||
if ($this->isPhpZts) { |
||||
$cmd .= ' /DZTS'; |
||||
} |
||||
|
||||
// ... 100+ 行代码 |
||||
} |
||||
} |
||||
``` |
||||
|
||||
**之后(使用 Backend):** |
||||
```php |
||||
protected function addCompilationOption(string &$cmd, bool $link): void |
||||
{ |
||||
if ($this->compilerBackend === null) { |
||||
// 回退到旧逻辑 |
||||
return; |
||||
} |
||||
|
||||
if (!$link) { |
||||
$cmd .= $this->compilerBackend->buildFullCompileOptions([ |
||||
'optimize' => $this->optimizeLevel, |
||||
'debug_info' => $this->debugInfo, |
||||
'sanitize' => $this->sanitize, |
||||
'cpp_std' => $this->cxxStd, |
||||
'suppressed_warnings' => Constants::MSVC_SUPPRESSED_WARNINGS, |
||||
]); |
||||
} else { |
||||
$cmd .= $this->compilerBackend->buildFullLinkOptions([ |
||||
'debug_info' => $this->debugInfo, |
||||
'no_console' => $this->noConsole, |
||||
'shared' => ($this->buildMode === 'ext'), |
||||
]); |
||||
} |
||||
} |
||||
``` |
||||
|
||||
### 示例 3:检测 PHP Libs |
||||
|
||||
**之前(CompilerBase.php):** |
||||
```php |
||||
protected function detectWindowsPhpLibs(): void |
||||
{ |
||||
$phpDirs = [ |
||||
$this->getPhpDir() . '\SDK\lib', |
||||
$this->getPhpDir() . '\lib', |
||||
]; |
||||
|
||||
// ... 50+ 行检测逻辑 |
||||
|
||||
$this->windowsPhpEmbedLib = $embedLibPath; |
||||
$this->windowsPhpCoreLib = $coreLibPath; |
||||
$this->isPhpZts = $isZts; |
||||
} |
||||
``` |
||||
|
||||
**之后(使用 Platform):** |
||||
```php |
||||
protected function detectPlatform(): void |
||||
{ |
||||
$this->isWindows = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'; |
||||
|
||||
if ($this->isWindows) { |
||||
// 使用 Windows Platform 检测 |
||||
/** @var Windows $platform */ |
||||
$platform = PlatformFactory::create(); |
||||
|
||||
$libInfo = $platform->detectPhpLibs($this->getPhpDir()); |
||||
|
||||
$this->windowsPhpEmbedLib = $libInfo['embed']; |
||||
$this->windowsPhpCoreLib = $libInfo['core']; |
||||
$this->isPhpZts = $libInfo['is_zts']; |
||||
|
||||
// 重新创建带信息的 Platform 实例 |
||||
$this->platform = new Windows( |
||||
phpLibs: [$libInfo['embed'], $libInfo['core']], |
||||
isZts: $libInfo['is_zts'] |
||||
); |
||||
|
||||
$this->compilerBackend = CompilerFactory::create($this->platform); |
||||
} |
||||
} |
||||
``` |
||||
|
||||
## 预期收益 |
||||
|
||||
### 代码质量 |
||||
- ✅ CompilerBase.php 减少 ~500 行代码 |
||||
- ✅ 职责更清晰 |
||||
- ✅ 更易维护 |
||||
- ✅ 更易测试 |
||||
|
||||
### 可扩展性 |
||||
- ✅ 添加新平台只需创建新的 Platform 类 |
||||
- ✅ 添加新编译器只需创建新的 Backend 类 |
||||
- ✅ 无需修改 CompilerBase |
||||
|
||||
### 可测试性 |
||||
- ✅ 每个类可以独立测试 |
||||
- ✅ 易于 Mock |
||||
- ✅ 更高的测试覆盖率 |
||||
|
||||
## 风险评估 |
||||
|
||||
### 低风险 |
||||
- Platform 和 Backend 层已经存在并工作 |
||||
- 有完整的回退机制 |
||||
- 渐进式迁移 |
||||
|
||||
### 中风险 |
||||
- 需要充分测试确保功能一致 |
||||
- 可能需要调整一些边缘情况 |
||||
|
||||
### 缓解措施 |
||||
1. 保留旧代码作为回退 |
||||
2. 充分的单元测试 |
||||
3. 集成测试覆盖所有场景 |
||||
4. 灰度发布,逐步切换 |
||||
|
||||
## 时间估算 |
||||
|
||||
| 阶段 | 工作量 | 说明 | |
||||
|------|--------|------| |
||||
| Phase 1: Platform 增强 | 1-2 天 | 补充缺失方法 | |
||||
| Phase 2: Backend 增强 | 2-3 天 | 补充缺失方法 | |
||||
| Phase 3: 创建适配器 | 1 天 | 桥接新旧代码 | |
||||
| Phase 4: 逐个替换 | 3-5 天 | 迁移核心逻辑 | |
||||
| Phase 5: 移除旧代码 | 1-2 天 | 清理冗余代码 | |
||||
| Phase 6: 测试验证 | 2-3 天 | 全面测试 | |
||||
| **总计** | **10-16 天** | **约 2-3 周** | |
||||
|
||||
## 下一步行动 |
||||
|
||||
1. **立即开始:** |
||||
- 完善 Linux 和 macOS Platform 类 |
||||
- 完善 GCC 和 Clang Backend 类 |
||||
|
||||
2. **本周内:** |
||||
- 创建适配器层 |
||||
- 开始替换高优先级方法 |
||||
|
||||
3. **下周:** |
||||
- 完成所有方法迁移 |
||||
- 编写测试 |
||||
- 性能验证 |
||||
|
||||
4. **下下周:** |
||||
- 移除旧代码 |
||||
- 最终测试 |
||||
- 发布新版本 |
||||
|
||||
## 总结 |
||||
|
||||
这是一个**系统性的重构**,目标是: |
||||
- 🎯 完全解耦平台和编译器逻辑 |
||||
- 🎯 提高代码质量和可维护性 |
||||
- 🎯 保持向后兼容 |
||||
- 🎯 降低未来扩展成本 |
||||
|
||||
通过**渐进式迁移**和**充分的测试**,可以安全地完成这次重构! |
||||
Loading…
Reference in new issue