From 51298c2d00fa761b3c0e610f45527fd8a7367eb1 Mon Sep 17 00:00:00 2001 From: rango Date: Fri, 8 May 2026 14:32:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(backend):=20=E6=B7=BB=E5=8A=A0=20C=20?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E7=BC=96=E8=AF=91=E5=91=BD=E4=BB=A4=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 Clang 类中实现 buildCCompileCommand 方法,支持 C 文件的编译命令构建 - 为 CompilerBackend 接口添加 buildCCompileCommand 抽象方法定义 - 在 Windows 平台下自动添加 MSVC 兼容性选项 - 支持调试模式下的优化级别控制和调试符号生成 - 添加警告级别设置确保代码质量检查 - 保持 C 文件编译时不使用 C++ 特定的编译选项 --- src/Php/Backend/Clang.php | 37 +++++++++++ src/Php/Backend/CompilerBackend.php | 9 +++ src/Php/Backend/Gcc.php | 27 ++++++++ src/Php/Backend/Msvc.php | 39 ++++++++++++ src/Php/CompilerBase.php | 34 ++++++++-- src/Php/Translator.php | 97 ++++++++++++++--------------- 6 files changed, 188 insertions(+), 55 deletions(-) diff --git a/src/Php/Backend/Clang.php b/src/Php/Backend/Clang.php index 9d252a78..e7fab172 100644 --- a/src/Php/Backend/Clang.php +++ b/src/Php/Backend/Clang.php @@ -149,6 +149,43 @@ class Clang extends CompilerBackend return $cmd; } + /** + * 构建 C 文件的编译命令(不包含 C++ 特定选项) + */ + public function buildCCompileCommand(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); + + // 优化级别(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; + } + public function buildLinkCommand(array $objectFiles, string $outputFile, array $options = []): string { $cmd = $this->getLinkerCommand(); diff --git a/src/Php/Backend/CompilerBackend.php b/src/Php/Backend/CompilerBackend.php index 2ec946ff..1073f63f 100644 --- a/src/Php/Backend/CompilerBackend.php +++ b/src/Php/Backend/CompilerBackend.php @@ -66,6 +66,15 @@ abstract class CompilerBackend array $options = [] ): string; + /** + * 构建 C 文件的编译命令(不包含 C++ 特定选项) + */ + abstract public function buildCCompileCommand( + string $sourceFile, + string $outputFile, + array $options = [] + ): string; + /** * 构建完整的链接命令 */ diff --git a/src/Php/Backend/Gcc.php b/src/Php/Backend/Gcc.php index 22519748..87035bac 100644 --- a/src/Php/Backend/Gcc.php +++ b/src/Php/Backend/Gcc.php @@ -117,6 +117,33 @@ class Gcc extends CompilerBackend return $cmd; } + /** + * 构建 C 文件的编译命令(不包含 C++ 特定选项) + */ + public function buildCCompileCommand(string $sourceFile, string $outputFile, array $options = []): string + { + $cmd = $this->getCompilerCommand(); + $cmd .= ' -c'; + $cmd .= ' ' . escapeshellarg($sourceFile); + $cmd .= ' -o ' . escapeshellarg($outputFile); + + // 优化级别(C 文件通常使用较低的优化) + $optimizeLevel = $options['optimize'] ?? 0; + $cmd .= ' -O' . $optimizeLevel; + + // 调试信息 + if (!empty($options['debug'])) { + $cmd .= ' -g'; + } + + // 警告级别 + $cmd .= ' -Wall'; + + // 注意:C 文件不使用 -std=c++17 等 C++ 特定选项 + + return $cmd; + } + public function buildLinkCommand(array $objectFiles, string $outputFile, array $options = []): string { $cmd = $this->getLinkerCommand(); diff --git a/src/Php/Backend/Msvc.php b/src/Php/Backend/Msvc.php index 6ed1fb8b..2b04b369 100644 --- a/src/Php/Backend/Msvc.php +++ b/src/Php/Backend/Msvc.php @@ -129,6 +129,45 @@ class Msvc extends CompilerBackend return $cmd; } + /** + * 构建 C 文件的编译命令(不包含 C++ 特定选项) + */ + public function buildCCompileCommand(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'; + } + + // 优化级别(C 文件通常使用较低的优化) + $optimizeLevel = $options['optimize'] ?? 0; + $cmd .= ' /O' . ($optimizeLevel >= 2 ? '2' : ($optimizeLevel === 0 ? 'd' : '1')); + + // 警告级别 + $cmd .= ' /W3'; + + // 禁用常见警告 + $suppressedWarnings = $options['suppressed_warnings'] ?? ['4244', '4146']; + foreach ($suppressedWarnings as $code) { + $cmd .= " /wd{$code}"; + } + + // nologo + $cmd .= ' /nologo'; + + // 注意:C 文件不使用 /EHsc, /std:c++17, /MD 等 C++ 特定选项 + + return $cmd; + } + public function buildLinkCommand(array $objectFiles, string $outputFile, array $options = []): string { $cmd = $this->getLinkerCommand(); diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 34f35a47..7d12efff 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -381,6 +381,23 @@ class CompilerBase extends \PhpAot\Core\Translator $this->platform = $result['platform']; $this->compilerBackend = $result['compiler']; + // Windows 平台:需要传递 ZTS 状态给 Platform 对象 + if ($this->platform instanceof \PhpAot\Php\Platform\Windows && $this->isWindows) { + // 重新创建 Windows Platform,传递正确的 ZTS 状态 + $phpSdkPath = $this->getPhpDir() . '\\SDK'; + $this->platform = new \PhpAot\Php\Platform\Windows( + phpLibs: [], + isZts: $this->isPhpZts, // ✅ 传递检测到的 ZTS 状态 + phpSdkPath: $phpSdkPath + ); + + // 重新创建 Backend,使用更新后的 Platform + $this->compilerBackend = \PhpAot\Php\Backend\CompilerFactory::createByName( + $this->cppCompiler, + $this->platform + ); + } + $this->climate->info( "Initialized new architecture: {$this->platform->getName()} + {$this->compilerBackend->getName()}" ); @@ -2468,7 +2485,7 @@ class CompilerBase extends \PhpAot\Core\Translator // Windows: phpx.lib (无 lib 前缀) $phpxLibPath = $this->getPhpxDir() . '\\lib\\phpx.lib'; if (file_exists($phpxLibPath)) { - $libraries[] = '"' . $phpxLibPath . '"'; + $libraries[] = $phpxLibPath; // 不添加引号,由 getLibraryFlags() 统一处理 } else { $this->error('phpx.lib not found at: ' . $phpxLibPath); } @@ -2493,13 +2510,22 @@ class CompilerBase extends \PhpAot\Core\Translator // extension 和 bin 模式都需要链接 PHP 库 if ($this->platform instanceof \PhpAot\Php\Platform\Windows) { - // Windows bin 模式使用已检测的库文件 + // Windows: 根据构建模式选择不同的库 if ($this->buildMode === 'bin') { + // bin 模式:需要同时链接 php8ts.lib 和 php8embed.lib + // 注意:php8ts.lib 必须在 php8embed.lib 之前,因为 embed 依赖 core + // php8ts.lib 提供 PHP 核心全局符号(executor_globals, compiler_globals, sapi_globals) + if (!empty($this->windowsPhpCoreLib)) { + $libraries[] = $this->windowsPhpCoreLib; // 不添加引号 + } + // php8embed.lib 提供嵌入 API if (!empty($this->windowsPhpEmbedLib)) { - $libraries[] = '"' . $this->windowsPhpEmbedLib . '"'; + $libraries[] = $this->windowsPhpEmbedLib; // 不添加引号 } + } else { + // ext 模式:只使用 php8ts.lib 或 php8.lib(PHP 扩展) if (!empty($this->windowsPhpCoreLib)) { - $libraries[] = '"' . $this->windowsPhpCoreLib . '"'; + $libraries[] = $this->windowsPhpCoreLib; // 不添加引号 } } diff --git a/src/Php/Translator.php b/src/Php/Translator.php index 5fc418c1..5cb95223 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -718,6 +718,15 @@ CODE; return false; } + /** + * 判断文件是否为 C++ 源文件 + */ + protected function isCppFile(string $filePath): bool + { + $extension = pathinfo($filePath, PATHINFO_EXTENSION); + return in_array($extension, ['cc', 'cpp', 'cxx'], true); + } + public function compileFile(string $cppFile, string $objectFile, bool $parallel = false): void { if ($this->hasObjectFileCache($cppFile)) { @@ -728,58 +737,44 @@ CODE; return; } - // 根据平台和编译器类型构建编译命令 - if ($this->isWindows()) { - // C 文件和 C++ 文件使用不同的选项 - $isCppFile = (pathinfo($cppFile, PATHINFO_EXTENSION) === 'cc' - || pathinfo($cppFile, PATHINFO_EXTENSION) === 'cpp' - || pathinfo($cppFile, PATHINFO_EXTENSION) === 'cxx'); - - // Windows 下根据编译器类型选择参数格式 - if ($this->cppCompiler === 'clang++' || $this->cppCompiler === 'clang') { - // Clang on Windows 使用 GCC 风格的参数 - if (!$isCppFile) { - // C 文件:在源文件前添加 -x c 标志 - $cmd = $this->cppCompiler . ' -x c -c ' . $cppFile . ' -o ' . $objectFile; - } else { - $cmd = $this->cppCompiler . ' -c ' . $cppFile . ' -o ' . $objectFile; - } - } else { - // MSVC 使用 /c 和 /Fo 参数 - $cmd = $this->cppCompiler . ' /c ' . $cppFile . ' /Fo' . $objectFile; - } - - // 添加编译选项(C 文件不需要 /EHsc 和 /std:c++17) - if ($isCppFile) { - $this->addCompilationOption($cmd, false); - } else { - // C 文件:只添加基本选项,不添加 C++ 特定选项 - // 使用 Platform 层获取包含路径 - if ($this->platform !== null) { - $cmd .= ' ' . $this->parseIncludes(); - } - - // 添加平台宏定义(根据编译器类型选择语法) - if ($this->cppCompiler === 'clang++' || $this->cppCompiler === 'clang') { - // Clang/GCC 风格 - $cmd .= ' -DZEND_WIN32 -DPHP_WIN32 -DZEND_DEBUG=0'; - if ($this->isPhpZts) { - $cmd .= ' -DZTS'; - } - $cmd .= ' -O0 -Wall'; - } else { - // MSVC 风格 - $cmd .= ' /DZEND_WIN32 /DPHP_WIN32 /DZEND_DEBUG=0'; - if ($this->isPhpZts) { - $cmd .= ' /DZTS'; - } - $cmd .= ' /Od /W3 /wd4244 /wd4146 /nologo'; - } - } + // 判断是否为 C++ 文件 + $isCppFile = $this->isCppFile($cppFile); + + // 使用 Backend 层构建编译命令 + if ($isCppFile) { + // C++ 文件:使用标准的编译命令构建 + $cmd = $this->compilerBackend->buildCompileCommand( + $cppFile, + $objectFile, + [ + 'optimize' => $this->optimizeLevel, + 'debug_info' => $this->debugInfo, + 'sanitize' => $this->sanitize, + 'cpp_std' => $this->cxxStd, + 'is_zts' => $this->isPhpZts, + 'build_mode' => $this->buildMode, + 'enable_profiler' => $this->enableProfiler, + 'suppressed_warnings' => Constants::MSVC_SUPPRESSED_WARNINGS ?? [], + 'cxxflags' => $this->cxxflags, + ] + ); + + // 添加包含路径(通过 Platform 层) + $cmd .= ' ' . $this->parseIncludes(); } else { - // Unix/Linux/macOS GCC 编译命令 - $cmd = $this->cppCompiler . ' -c ' . $cppFile . ' -o ' . $objectFile; - $this->addCompilationOption($cmd, false); + // C 文件:不能使用 C++ 特定选项(/EHsc, /std:c++17 等) + // 使用 Backend 的 buildCCompileCommand() 方法 + $cmd = $this->compilerBackend->buildCCompileCommand( + $cppFile, + $objectFile, + [ + 'optimize' => 0, + 'suppressed_warnings' => ['4244', '4146'], + ] + ); + + // 手动添加包含路径 + $cmd .= ' ' . $this->parseIncludes(); } if (!$parallel) {