From 0c2a25ea520f658727f2914aca9dc4e92e22b9af Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Mon, 18 May 2026 11:07:33 +0800 Subject: [PATCH] =?UTF-8?q?feat(compiler):=20=E6=B7=BB=E5=8A=A0=E5=AF=B9?= =?UTF-8?q?=E5=A4=9A=E7=A7=8D=E5=8E=9F=E7=94=9F=E6=BA=90=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E7=9A=84=E7=BC=96=E8=AF=91=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现了对 C、汇编、Objective-C、Objective-C++ 等源文件的识别和分类 - 为 Clang、GCC、MSVC 编译器后端添加了 buildNativeCompileCommand 方法 - 在编译命令中添加 -x 参数指定源文件语言类型 - 重构了文件扫描逻辑,统一处理多种原生源文件格式 - 为不同语言类型的源文件生成相应的编译选项配置 - 更新了翻译器逻辑,根据文件扩展名自动检测并选择合适的编译方法 --- src/Php/Backend/Clang.php | 48 +++++++++++++++++++++++----- src/Php/Backend/CompilerBackend.php | 12 +++++++ src/Php/Backend/Gcc.php | 35 ++++++++++++++++++--- src/Php/Backend/Msvc.php | 35 ++++++++++++++++----- src/Php/CompilerBase.php | 19 +++++++++++ src/Php/FileScanner.php | 20 ++++++++++-- src/Php/Translator.php | 49 ++++++++++++++++++++++++----- 7 files changed, 188 insertions(+), 30 deletions(-) diff --git a/src/Php/Backend/Clang.php b/src/Php/Backend/Clang.php index 1d5bb444..8374746c 100644 --- a/src/Php/Backend/Clang.php +++ b/src/Php/Backend/Clang.php @@ -177,7 +177,7 @@ class Clang extends CompilerBackend 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'; @@ -185,30 +185,64 @@ class Clang extends CompilerBackend $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; + } + + /** + * 构建原生源文件的编译命令(汇编/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(); + + // 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; } diff --git a/src/Php/Backend/CompilerBackend.php b/src/Php/Backend/CompilerBackend.php index 1073f63f..2bdc6ec5 100644 --- a/src/Php/Backend/CompilerBackend.php +++ b/src/Php/Backend/CompilerBackend.php @@ -75,6 +75,18 @@ abstract class CompilerBackend array $options = [] ): string; + /** + * 构建原生源文件的编译命令(汇编/Objective-C 等,使用 -x 指定语言) + * + * @param string $language GCC/Clang 语言标识(assembler, objective-c, objective-c++ 等) + */ + abstract public function buildNativeCompileCommand( + string $sourceFile, + string $outputFile, + array $options = [], + string $language = '' + ): string; + /** * 构建完整的链接命令 */ diff --git a/src/Php/Backend/Gcc.php b/src/Php/Backend/Gcc.php index 1f43a816..79d6b53e 100644 --- a/src/Php/Backend/Gcc.php +++ b/src/Php/Backend/Gcc.php @@ -119,27 +119,52 @@ class Gcc extends CompilerBackend { $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; } diff --git a/src/Php/Backend/Msvc.php b/src/Php/Backend/Msvc.php index 46750c07..4121a3bf 100644 --- a/src/Php/Backend/Msvc.php +++ b/src/Php/Backend/Msvc.php @@ -120,43 +120,62 @@ class Msvc extends CompilerBackend { $cmd = $this->getCompilerCommand(); $cmd .= ' /c'; + $cmd .= ' /TC'; $cmd .= ' ' . escapeshellarg($sourceFile); $cmd .= ' /Fo' . escapeshellarg($outputFile); if (!empty($options['include_paths'])) { $cmd .= ' ' . $this->formatIncludePaths($options['include_paths']); } - + // 平台宏定义 $cmd .= ' /DZEND_WIN32 /DPHP_WIN32 /DZEND_DEBUG=0'; - + // ZTS 支持 if ($this->platform instanceof Windows && $this->platform->isZts()) { $cmd .= ' /DZTS'; } - + // 优化级别(C 文件通常使用较低的优化) $optimizeLevel = $options['optimize'] ?? 0; $optMap = [0 => '/Od', 1 => '/O1', 2 => '/O2', 3 => '/Ox']; $cmd .= ' ' . ($optMap[$optimizeLevel] ?? '/O2'); - + // 警告级别 $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; } + /** + * 构建原生源文件的编译命令 + * + * MSVC 仅支持 C 文件(/TC),汇编和 ObjC 文件不受支持 + * + * @param string $language 语言标识 + */ + public function buildNativeCompileCommand(string $sourceFile, string $outputFile, array $options = [], string $language = ''): string + { + if ($language === 'c') { + return $this->buildCCompileCommand($sourceFile, $outputFile, $options); + } + + throw new \RuntimeException( + "MSVC does not support compiling source file of language '{$language}': {$sourceFile}" + ); + } + 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 963ea948..4eaded66 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -2581,6 +2581,25 @@ class CompilerBase extends \PhpAot\Core\Translator ]; } + /** + * 获取原生源文件(汇编/ObjC 等)的编译选项,不含 C++ 特定标志. + * + * @param string $language 语言标识(assembler, objective-c, objective-c++) + */ + protected function getNativeCompileCommandOptions(string $language = ''): array + { + return [ + 'include_paths' => $this->getIncludePaths(), + 'optimize' => $this->optimizeLevel, + 'debug' => $this->debug, + 'sanitize' => $this->sanitize, + 'is_zts' => $this->isPhpZts, + 'build_mode' => $this->buildMode, + 'enable_profiler' => $this->enableProfiler, + 'suppressed_warnings' => Constants::MSVC_SUPPRESSED_WARNINGS ?? [], + ]; + } + protected function getLinkCommandOptions(): array { $options = [ diff --git a/src/Php/FileScanner.php b/src/Php/FileScanner.php index 33957414..3094610f 100644 --- a/src/Php/FileScanner.php +++ b/src/Php/FileScanner.php @@ -13,6 +13,17 @@ class FileScanner public const array PHP_EXT = ['php']; public const array CPP_EXT = ['cpp', 'cxx', 'cc']; + + public const array C_EXT = ['c']; + + public const array ASM_EXT = ['s', 'S']; + + public const array OBJC_EXT = ['m']; + + public const array OBJCXX_EXT = ['mm']; + + public const array NATIVE_SRC_EXT = ['cpp', 'cxx', 'cc', 'c', 's', 'S', 'm', 'mm']; + private string $directory; private array $excludePatterns; @@ -46,6 +57,11 @@ class FileScanner return in_array(self::getFileExt($file), self::CPP_EXT); } + public static function isNativeSourceFile(string $file): bool + { + return in_array(self::getFileExt($file), self::NATIVE_SRC_EXT); + } + public function addExcludePattern(string $pattern): self { $this->excludePatterns[] = $pattern; @@ -74,9 +90,7 @@ class FileScanner foreach ($iterator as $file) { if ($file->isFile()) { - if (self::isPhpFile($file)) { - $filePath = $file->getPathname(); - } elseif (self::isCppFile($file)) { + if (self::isPhpFile($file) || self::isNativeSourceFile($file)) { $filePath = $file->getPathname(); } else { continue; diff --git a/src/Php/Translator.php b/src/Php/Translator.php index 17a3e95e..cc41cc8c 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -341,7 +341,7 @@ class Translator extends Preprocessor try { if (FileScanner::isPhpFile($file)) { $cppFile = $this->convertFile($file); - } elseif (FileScanner::isCppFile($file)) { + } elseif (FileScanner::isNativeSourceFile($file)) { $cppFile = $file; } else { continue; @@ -689,6 +689,33 @@ CODE; return in_array($extension, ['cc', 'cpp', 'cxx'], true); } + /** + * 根据文件扩展名获取语言类型标识(用于 -x 参数). + * + * @return string|null 语言标识(c, assembler, objective-c, objective-c++), + * 或 null 表示使用默认检测(C++ 文件) + */ + protected function getLanguageFromExtension(string $filePath): ?string + { + $ext = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); + return match ($ext) { + 'c' => 'c', + 's', 'S' => 'assembler', + 'm' => 'objective-c', + 'mm' => 'objective-c++', + 'cc', 'cpp', 'cxx' => null, + default => null, + }; + } + + /** + * 判断文件是否为原生编译型源文件(C/C++/汇编/ObjC 等). + */ + protected function isNativeSourceFile(string $filePath): bool + { + return FileScanner::isNativeSourceFile($filePath); + } + public function compileFile(string $cppFile, string $objectFile, bool $parallel = false): void { if ($this->hasObjectFileCache($cppFile)) { @@ -699,25 +726,33 @@ CODE; return; } - // 判断是否为 C++ 文件 - $isCppFile = $this->isCppFile($cppFile); + // 检测文件语言类型 + $language = $this->getLanguageFromExtension($cppFile); // 使用 Backend 层构建编译命令 - if ($isCppFile) { + if ($language === null) { // C++ 文件:使用标准的编译命令构建 $cmd = $this->getCompilerBackend()->buildCompileCommand( $cppFile, $objectFile, $this->getCompileCommandOptions() ); - } else { - // C 文件:不能使用 C++ 特定选项(/EHsc, /std:c++17 等) - // 使用 Backend 的 buildCCompileCommand() 方法 + } elseif ($language === 'c') { + // C 文件:使用 buildCCompileCommand,后端自动添加 -x c 或 /TC $cmd = $this->getCompilerBackend()->buildCCompileCommand( $cppFile, $objectFile, $this->getCCompileCommandOptions() ); + } else { + // 其他原生源文件(assembler, objective-c, objective-c++) + // 使用 buildNativeCompileCommand,传入语言类型以添加 -x 标志 + $cmd = $this->getCompilerBackend()->buildNativeCompileCommand( + $cppFile, + $objectFile, + $this->getNativeCompileCommandOptions($language), + $language + ); } if (!$parallel) {