feat(compiler): 添加对多种原生源文件格式的编译支持

- 实现了对 C、汇编、Objective-C、Objective-C++ 等源文件的识别和分类
- 为 Clang、GCC、MSVC 编译器后端添加了 buildNativeCompileCommand 方法
- 在编译命令中添加 -x 参数指定源文件语言类型
- 重构了文件扫描逻辑,统一处理多种原生源文件格式
- 为不同语言类型的源文件生成相应的编译选项配置
- 更新了翻译器逻辑,根据文件扩展名自动检测并选择合适的编译方法
pull/1/head
韩天峰 4 months ago
parent 519ad7b292
commit 0c2a25ea52
  1. 34
      src/Php/Backend/Clang.php
  2. 12
      src/Php/Backend/CompilerBackend.php
  3. 25
      src/Php/Backend/Gcc.php
  4. 19
      src/Php/Backend/Msvc.php
  5. 19
      src/Php/CompilerBase.php
  6. 20
      src/Php/FileScanner.php
  7. 49
      src/Php/Translator.php

@ -187,6 +187,7 @@ class Clang extends CompilerBackend
} }
$cmd .= ' -c'; $cmd .= ' -c';
$cmd .= ' -x c';
$cmd .= ' ' . escapeshellarg($sourceFile); $cmd .= ' ' . escapeshellarg($sourceFile);
$cmd .= ' -o ' . escapeshellarg($outputFile); $cmd .= ' -o ' . escapeshellarg($outputFile);
@ -212,6 +213,39 @@ class Clang extends CompilerBackend
return $cmd; 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;
}
public function buildLinkCommand(array $objectFiles, string $outputFile, array $options = []): string public function buildLinkCommand(array $objectFiles, string $outputFile, array $options = []): string
{ {
$cmd = $this->getLinkerCommand(); $cmd = $this->getLinkerCommand();

@ -75,6 +75,18 @@ abstract class CompilerBackend
array $options = [] array $options = []
): string; ): 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;
/** /**
* 构建完整的链接命令 * 构建完整的链接命令
*/ */

@ -119,6 +119,7 @@ class Gcc extends CompilerBackend
{ {
$cmd = $this->getCompilerCommand(); $cmd = $this->getCompilerCommand();
$cmd .= ' -c'; $cmd .= ' -c';
$cmd .= ' -x c';
$cmd .= ' ' . escapeshellarg($sourceFile); $cmd .= ' ' . escapeshellarg($sourceFile);
$cmd .= ' -o ' . escapeshellarg($outputFile); $cmd .= ' -o ' . escapeshellarg($outputFile);
@ -143,6 +144,30 @@ class Gcc extends CompilerBackend
return $cmd; return $cmd;
} }
/**
* 构建原生源文件的编译命令(汇编/Objective-C 等)
*
* @param string $language 语言标识(assembler, objective-c, objective-c++)
*/
public function buildNativeCompileCommand(string $sourceFile, string $outputFile, array $options = [], string $language = ''): string
{
$cmd = $this->getCompilerCommand();
$cmd .= ' -c';
if ($language !== '') {
$cmd .= ' -x ' . $language;
}
$cmd .= ' ' . escapeshellarg($sourceFile);
$cmd .= ' -o ' . escapeshellarg($outputFile);
if (!empty($options['include_paths'])) {
$cmd .= ' ' . $this->formatIncludePaths($options['include_paths']);
}
$cmd .= $this->buildCompileOptions($options);
return $cmd;
}
public function buildLinkCommand(array $objectFiles, string $outputFile, array $options = []): string public function buildLinkCommand(array $objectFiles, string $outputFile, array $options = []): string
{ {
$cmd = $this->getLinkerCommand(); $cmd = $this->getLinkerCommand();

@ -120,6 +120,7 @@ class Msvc extends CompilerBackend
{ {
$cmd = $this->getCompilerCommand(); $cmd = $this->getCompilerCommand();
$cmd .= ' /c'; $cmd .= ' /c';
$cmd .= ' /TC';
$cmd .= ' ' . escapeshellarg($sourceFile); $cmd .= ' ' . escapeshellarg($sourceFile);
$cmd .= ' /Fo' . escapeshellarg($outputFile); $cmd .= ' /Fo' . escapeshellarg($outputFile);
@ -157,6 +158,24 @@ class Msvc extends CompilerBackend
return $cmd; 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 public function buildLinkCommand(array $objectFiles, string $outputFile, array $options = []): string
{ {
$cmd = $this->getLinkerCommand(); $cmd = $this->getLinkerCommand();

@ -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 protected function getLinkCommandOptions(): array
{ {
$options = [ $options = [

@ -13,6 +13,17 @@ class FileScanner
public const array PHP_EXT = ['php']; public const array PHP_EXT = ['php'];
public const array CPP_EXT = ['cpp', 'cxx', 'cc']; 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 string $directory;
private array $excludePatterns; private array $excludePatterns;
@ -46,6 +57,11 @@ class FileScanner
return in_array(self::getFileExt($file), self::CPP_EXT); 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 public function addExcludePattern(string $pattern): self
{ {
$this->excludePatterns[] = $pattern; $this->excludePatterns[] = $pattern;
@ -74,9 +90,7 @@ class FileScanner
foreach ($iterator as $file) { foreach ($iterator as $file) {
if ($file->isFile()) { if ($file->isFile()) {
if (self::isPhpFile($file)) { if (self::isPhpFile($file) || self::isNativeSourceFile($file)) {
$filePath = $file->getPathname();
} elseif (self::isCppFile($file)) {
$filePath = $file->getPathname(); $filePath = $file->getPathname();
} else { } else {
continue; continue;

@ -341,7 +341,7 @@ class Translator extends Preprocessor
try { try {
if (FileScanner::isPhpFile($file)) { if (FileScanner::isPhpFile($file)) {
$cppFile = $this->convertFile($file); $cppFile = $this->convertFile($file);
} elseif (FileScanner::isCppFile($file)) { } elseif (FileScanner::isNativeSourceFile($file)) {
$cppFile = $file; $cppFile = $file;
} else { } else {
continue; continue;
@ -689,6 +689,33 @@ CODE;
return in_array($extension, ['cc', 'cpp', 'cxx'], true); 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 public function compileFile(string $cppFile, string $objectFile, bool $parallel = false): void
{ {
if ($this->hasObjectFileCache($cppFile)) { if ($this->hasObjectFileCache($cppFile)) {
@ -699,25 +726,33 @@ CODE;
return; return;
} }
// 判断是否为 C++ 文件 // 检测文件语言类型
$isCppFile = $this->isCppFile($cppFile); $language = $this->getLanguageFromExtension($cppFile);
// 使用 Backend 层构建编译命令 // 使用 Backend 层构建编译命令
if ($isCppFile) { if ($language === null) {
// C++ 文件:使用标准的编译命令构建 // C++ 文件:使用标准的编译命令构建
$cmd = $this->getCompilerBackend()->buildCompileCommand( $cmd = $this->getCompilerBackend()->buildCompileCommand(
$cppFile, $cppFile,
$objectFile, $objectFile,
$this->getCompileCommandOptions() $this->getCompileCommandOptions()
); );
} else { } elseif ($language === 'c') {
// C 文件:不能使用 C++ 特定选项(/EHsc, /std:c++17 等) // C 文件:使用 buildCCompileCommand,后端自动添加 -x c 或 /TC
// 使用 Backend 的 buildCCompileCommand() 方法
$cmd = $this->getCompilerBackend()->buildCCompileCommand( $cmd = $this->getCompilerBackend()->buildCCompileCommand(
$cppFile, $cppFile,
$objectFile, $objectFile,
$this->getCCompileCommandOptions() $this->getCCompileCommandOptions()
); );
} else {
// 其他原生源文件(assembler, objective-c, objective-c++)
// 使用 buildNativeCompileCommand,传入语言类型以添加 -x 标志
$cmd = $this->getCompilerBackend()->buildNativeCompileCommand(
$cppFile,
$objectFile,
$this->getNativeCompileCommandOptions($language),
$language
);
} }
if (!$parallel) { if (!$parallel) {

Loading…
Cancel
Save