pull/1/head
韩天峰 4 months ago
parent 4470c4597d
commit 7ad7657e28
  1. 4
      src/Php/AstNodeType.php
  2. 61
      src/Php/CompilerBase.php
  3. 1
      src/Php/Context/FunctionContext.php
  4. 13
      src/Php/Parser/StdArrayParser.php
  5. 2
      src/Php/Symbol.php
  6. 30
      src/Php/Translator.php

@ -102,10 +102,10 @@ trait AstNodeType
protected function isScalarBool(NodeAbstract $expr): bool protected function isScalarBool(NodeAbstract $expr): bool
{ {
return $expr instanceof Node\Expr\ConstFetch and in_array($expr->name->toString(), ['true', 'false']); return $expr instanceof Expr\ConstFetch and in_array($expr->name->toString(), ['true', 'false']);
} }
protected function getBoolValue(Node\Expr\ConstFetch $expr): string protected function getBoolValue(Expr\ConstFetch $expr): string
{ {
return $expr->name->toString() === 'true' ? self::VALUE_TRUE : self::VALUE_FALSE; return $expr->name->toString() === 'true' ? self::VALUE_TRUE : self::VALUE_FALSE;
} }

@ -353,14 +353,14 @@ class CompilerBase extends \PhpAot\Core\Translator
// 如果 PATH 中没有,尝试从 LLVM_HOME 环境变量获取 // 如果 PATH 中没有,尝试从 LLVM_HOME 环境变量获取
$llvmHome = getenv('LLVM_HOME'); $llvmHome = getenv('LLVM_HOME');
if ($llvmHome && is_dir($llvmHome)) { if ($llvmHome && is_dir($llvmHome)) {
$clangPath = rtrim($llvmHome, '\\/') . '\x64\bin\clang++.exe'; $clangPath = rtrim($llvmHome, '\/') . '\x64\bin\clang++.exe';
if (file_exists($clangPath)) { if (file_exists($clangPath)) {
// 验证是否可以执行 // 验证是否可以执行
exec('"' . $clangPath . '" --version 2>&1', $output, $returnCode); exec('"' . $clangPath . '" --version 2>&1', $output, $returnCode);
if ($returnCode === 0) { if ($returnCode === 0) {
// 将 Clang 路径添加到环境变量 // 将 Clang 路径添加到环境变量
$clangDir = dirname($clangPath); $clangDir = dirname($clangPath);
putenv("PATH=$clangDir;" . getenv('PATH')); putenv("PATH={$clangDir};" . getenv('PATH'));
// 检查是否有 lld-link // 检查是否有 lld-link
$this->checkLldLinker(); $this->checkLldLinker();
@ -391,13 +391,13 @@ class CompilerBase extends \PhpAot\Core\Translator
// 如果 PATH 中没有,尝试从 LLVM_HOME 获取 // 如果 PATH 中没有,尝试从 LLVM_HOME 获取
$llvmHome = getenv('LLVM_HOME'); $llvmHome = getenv('LLVM_HOME');
if ($llvmHome && is_dir($llvmHome)) { if ($llvmHome && is_dir($llvmHome)) {
$lldLinkPath = rtrim($llvmHome, '\\/') . '\x64\bin\lld-link.exe'; $lldLinkPath = rtrim($llvmHome, '\/') . '\x64\bin\lld-link.exe';
if (file_exists($lldLinkPath)) { if (file_exists($lldLinkPath)) {
exec('"' . $lldLinkPath . '" --version 2>&1', $output, $returnCode); exec('"' . $lldLinkPath . '" --version 2>&1', $output, $returnCode);
if ($returnCode === 0) { if ($returnCode === 0) {
// 将 lld-link 路径添加到环境变量 // 将 lld-link 路径添加到环境变量
$lldDir = dirname($lldLinkPath); $lldDir = dirname($lldLinkPath);
putenv("PATH=$lldDir;" . getenv('PATH')); putenv("PATH={$lldDir};" . getenv('PATH'));
$this->linker = 'lld-link'; $this->linker = 'lld-link';
$this->climate->info('Using lld-link linker from LLVM_HOME (faster than link.exe)'); $this->climate->info('Using lld-link linker from LLVM_HOME (faster than link.exe)');
return; return;
@ -415,7 +415,7 @@ class CompilerBase extends \PhpAot\Core\Translator
// 优先使用环境变量 PHPX_HOME // 优先使用环境变量 PHPX_HOME
$phpxDir = getenv('PHPX_HOME'); $phpxDir = getenv('PHPX_HOME');
if ($phpxDir && is_dir($phpxDir)) { if ($phpxDir && is_dir($phpxDir)) {
return rtrim($phpxDir, '\\/'); return rtrim($phpxDir, '\/');
} }
// 默认路径 // 默认路径
@ -438,7 +438,7 @@ class CompilerBase extends \PhpAot\Core\Translator
// Windows 下尝试从环境变量获取 PHP 路径 // Windows 下尝试从环境变量获取 PHP 路径
$phpDir = getenv('PHP_HOME'); $phpDir = getenv('PHP_HOME');
if ($phpDir && is_dir($phpDir)) { if ($phpDir && is_dir($phpDir)) {
return rtrim($phpDir, '\\/'); return rtrim($phpDir, '\/');
} }
// 尝试从 php.exe 路径推断(使用 where 命令) // 尝试从 php.exe 路径推断(使用 where 命令)
@ -446,12 +446,12 @@ class CompilerBase extends \PhpAot\Core\Translator
if ($phpExe) { if ($phpExe) {
$phpDir = dirname($phpExe); $phpDir = dirname($phpExe);
if (is_dir($phpDir)) { if (is_dir($phpDir)) {
return rtrim($phpDir, '\\/'); return rtrim($phpDir, '\/');
} }
} }
// 默认路径 // 默认路径
return 'C:\\php'; return 'C:\php';
} else { } else {
// Unix/Linux/macOS 下使用 php-config 获取 PHP 路径 // Unix/Linux/macOS 下使用 php-config 获取 PHP 路径
$phpDir = shell_exec('php-config --prefix 2>/dev/null'); $phpDir = shell_exec('php-config --prefix 2>/dev/null');
@ -2292,18 +2292,15 @@ class CompilerBase extends \PhpAot\Core\Translator
protected function parseWindowsIncludes(): string protected function parseWindowsIncludes(): string
{ {
$list = [ $list = [
$this->getPhpxDir() . '\\include', $this->getPhpxDir() . '\include',
$this->getBuildDir() . '\\include', $this->getBuildDir() . '\include',
$this->getPhpxDir() . '\\src\\misc', $this->getPhpxDir() . '\src\misc',
]; ];
// Windows 下 PHP 头文件必须从 SDK/include 读取 // Windows 下 PHP 头文件必须从 SDK/include 读取
$phpSdkInclude = $this->getPhpDir() . '\\SDK\\include'; $phpSdkInclude = $this->getPhpDir() . '\SDK\include';
if (!is_dir($phpSdkInclude)) { if (!is_dir($phpSdkInclude)) {
throw new \RuntimeException( throw new \RuntimeException("PHP SDK include directory not found: {$phpSdkInclude}\n" . 'Please ensure PHP is installed with SDK headers at the expected location.');
"PHP SDK include directory not found: {$phpSdkInclude}\n" .
"Please ensure PHP is installed with SDK headers at the expected location."
);
} }
// 添加主包含目录 // 添加主包含目录
@ -2375,19 +2372,19 @@ class CompilerBase extends \PhpAot\Core\Translator
$list = []; $list = [];
// Windows 下 PHP 库文件固定从 SDK/lib 读取 // Windows 下 PHP 库文件固定从 SDK/lib 读取
$phpLib = $this->getPhpDir() . '\\SDK\\lib'; $phpLib = $this->getPhpDir() . '\SDK\lib';
if (is_dir($phpLib)) { if (is_dir($phpLib)) {
$list[] = $phpLib; $list[] = $phpLib;
} else { } else {
// 备选:尝试直接从 lib 目录 // 备选:尝试直接从 lib 目录
$phpLibAlt = $this->getPhpDir() . '\\lib'; $phpLibAlt = $this->getPhpDir() . '\lib';
if (is_dir($phpLibAlt)) { if (is_dir($phpLibAlt)) {
$list[] = $phpLibAlt; $list[] = $phpLibAlt;
} }
} }
// phpx 库文件 // phpx 库文件
$phpxLib = $this->getPhpxDir() . '\\lib'; $phpxLib = $this->getPhpxDir() . '\lib';
if (is_dir($phpxLib)) { if (is_dir($phpxLib)) {
$list[] = $phpxLib; $list[] = $phpxLib;
} }
@ -2425,12 +2422,12 @@ class CompilerBase extends \PhpAot\Core\Translator
$list = []; $list = [];
// 优先使用 .lib 导入库 // 优先使用 .lib 导入库
$phpxLib = $this->getPhpxDir() . '\\lib\\phpx.lib'; $phpxLib = $this->getPhpxDir() . '\lib\phpx.lib';
if (file_exists($phpxLib)) { if (file_exists($phpxLib)) {
$list[] = '"' . $phpxLib . '"'; $list[] = '"' . $phpxLib . '"';
} else { } else {
// 如果没有 .lib,尝试直接使用 DLL(需要生成导入库) // 如果没有 .lib,尝试直接使用 DLL(需要生成导入库)
$phpxDll = $this->getPhpxDir() . '\\lib\\phpx.dll'; $phpxDll = $this->getPhpxDir() . '\lib\phpx.dll';
if (file_exists($phpxDll)) { if (file_exists($phpxDll)) {
$this->climate->magenta('phpx.lib not found, using phpx.dll directly'); $this->climate->magenta('phpx.lib not found, using phpx.dll directly');
$this->climate->info('Note: You may need to generate phpx.lib from phpx.dll using lib /def:phpx.def'); $this->climate->info('Note: You may need to generate phpx.lib from phpx.dll using lib /def:phpx.def');
@ -2448,16 +2445,18 @@ class CompilerBase extends \PhpAot\Core\Translator
// 6. lib/php8.lib // 6. lib/php8.lib
$phpDirs = [ $phpDirs = [
$this->getPhpDir() . '\\SDK\\lib', // 优先从 SDK/lib 查找 $this->getPhpDir() . '\SDK\lib', // 优先从 SDK/lib 查找
$this->getPhpDir() . '\\lib', // 备选从 lib 查找 $this->getPhpDir() . '\lib', // 备选从 lib 查找
]; ];
$found = false; $found = false;
foreach ($phpDirs as $phpDir) { foreach ($phpDirs as $phpDir) {
if (!is_dir($phpDir)) continue; if (!is_dir($phpDir)) {
continue;
}
// 尝试 php8embed.lib (嵌入模式) // 尝试 php8embed.lib (嵌入模式)
$phpEmbedLib = $phpDir . '\\php8embed.lib'; $phpEmbedLib = $phpDir . '\php8embed.lib';
if (file_exists($phpEmbedLib)) { if (file_exists($phpEmbedLib)) {
$list[] = '"' . $phpEmbedLib . '"'; $list[] = '"' . $phpEmbedLib . '"';
$found = true; $found = true;
@ -2465,7 +2464,7 @@ class CompilerBase extends \PhpAot\Core\Translator
} }
// 尝试 php8ts.lib // 尝试 php8ts.lib
$phpTsLib = $phpDir . '\\php8ts.lib'; $phpTsLib = $phpDir . '\php8ts.lib';
if (file_exists($phpTsLib)) { if (file_exists($phpTsLib)) {
$list[] = '"' . $phpTsLib . '"'; $list[] = '"' . $phpTsLib . '"';
$found = true; $found = true;
@ -2473,7 +2472,7 @@ class CompilerBase extends \PhpAot\Core\Translator
} }
// 尝试 php8.lib // 尝试 php8.lib
$phpLib = $phpDir . '\\php8.lib'; $phpLib = $phpDir . '\php8.lib';
if (file_exists($phpLib)) { if (file_exists($phpLib)) {
$list[] = '"' . $phpLib . '"'; $list[] = '"' . $phpLib . '"';
$found = true; $found = true;
@ -2483,14 +2482,14 @@ class CompilerBase extends \PhpAot\Core\Translator
// 如果都没找到 .lib,尝试直接使用根目录的 DLL // 如果都没找到 .lib,尝试直接使用根目录的 DLL
if (!$found) { if (!$found) {
$phpDll = $this->getPhpDir() . '\\php8.dll'; $phpDll = $this->getPhpDir() . '\php8.dll';
if (file_exists($phpDll)) { if (file_exists($phpDll)) {
$this->climate->magenta('php8embed.lib not found, using php8.dll directly'); $this->climate->magenta('php8embed.lib not found, using php8.dll directly');
$this->climate->info('Note: This may require additional setup'); $this->climate->info('Note: This may require additional setup');
$list[] = '"' . $phpDll . '"'; $list[] = '"' . $phpDll . '"';
} else { } else {
// 尝试 php8ts.dll // 尝试 php8ts.dll
$phpTsDll = $this->getPhpDir() . '\\php8ts.dll'; $phpTsDll = $this->getPhpDir() . '\php8ts.dll';
if (file_exists($phpTsDll)) { if (file_exists($phpTsDll)) {
$this->climate->magenta('php8embed.lib not found, using php8ts.dll directly'); $this->climate->magenta('php8embed.lib not found, using php8ts.dll directly');
$this->climate->info('Note: This may require additional setup'); $this->climate->info('Note: This may require additional setup');
@ -2678,7 +2677,7 @@ class CompilerBase extends \PhpAot\Core\Translator
if (in_array($san, $validSanitizers)) { if (in_array($san, $validSanitizers)) {
$enabledSanitizers[] = $san; $enabledSanitizers[] = $san;
} else { } else {
$this->climate->warning("Unsupported sanitizer: $san"); $this->climate->warning("Unsupported sanitizer: {$san}");
} }
} }
@ -2786,7 +2785,7 @@ class CompilerBase extends \PhpAot\Core\Translator
if (in_array($san, $validSanitizers)) { if (in_array($san, $validSanitizers)) {
$enabledSanitizers[] = $san; $enabledSanitizers[] = $san;
} else { } else {
$this->climate->warning("Unsupported sanitizer: $san"); $this->climate->warning("Unsupported sanitizer: {$san}");
} }
} }

@ -14,6 +14,7 @@ class FunctionContext
* @var array<string, string> * @var array<string, string>
*/ */
public array $objects = []; public array $objects = [];
/** /**
* @var array<string, array> * @var array<string, array>
*/ */

@ -1,4 +1,10 @@
<?php <?php
/**
* This file is part of Swoole-Compiler(AOT).
*
* @link https://www.swoole.com/
* @contact service@swoole.com
*/
namespace PhpAot\Php\Parser; namespace PhpAot\Php\Parser;
@ -28,7 +34,7 @@ trait StdArrayParser
$valueExpr = $this->parseExpr($expr->args[1]->value); $valueExpr = $this->parseExpr($expr->args[1]->value);
$type = $this->context->stdArrays[$array]['type']; $type = $this->context->stdArrays[$array]['type'];
$value = $this->convertExprFromType($type, $valueExpr); $value = $this->convertExprFromType($type, $valueExpr);
return "{$array}.fill({$value})"; return "{$array}.fill({$value})";
} }
protected function getStdArrayInfo(Expr\ArrayDimFetch $expr): ?array protected function getStdArrayInfo(Expr\ArrayDimFetch $expr): ?array
@ -103,7 +109,7 @@ trait StdArrayParser
$tmp = $expr; $tmp = $expr;
$nesting = []; $nesting = [];
while(true) { while (true) {
if (count($tmp->args) !== 2) { if (count($tmp->args) !== 2) {
$this->fatalError($tmp, 'std::array() expects two arguments'); $this->fatalError($tmp, 'std::array() expects two arguments');
} }
@ -132,7 +138,8 @@ trait StdArrayParser
break; break;
} }
break; break;
} elseif ($this->isStaticCall($typeExpr)) { }
if ($this->isStaticCall($typeExpr)) {
$tmp = $typeExpr; $tmp = $typeExpr;
if (!$this->isNameExpr($tmp->class) || !$this->isIdExpr($tmp->name) || $tmp->class->toString() !== 'std' || $tmp->name->toString() !== 'array') { if (!$this->isNameExpr($tmp->class) || !$this->isIdExpr($tmp->name) || $tmp->class->toString() !== 'std' || $tmp->name->toString() !== 'array') {
$this->fatalError($tmp, 'An incorrect `std::array` definition'); $this->fatalError($tmp, 'An incorrect `std::array` definition');

@ -57,6 +57,6 @@ class Symbol
public static function safeIndex(string $index, string $size): string public static function safeIndex(string $index, string $size): string
{ {
return "php::safeIndex($index, $size)"; return "php::safeIndex({$index}, {$size})";
} }
} }

@ -283,14 +283,14 @@ class Translator extends Preprocessor
// Windows 平台检查 dll 和 lib 文件 // Windows 平台检查 dll 和 lib 文件
// 按照新的路径规则检查:SDK/lib, lib, 根目录 // 按照新的路径规则检查:SDK/lib, lib, 根目录
$phpDirs = [ $phpDirs = [
$this->getPhpDir() . '\\SDK\\lib', $this->getPhpDir() . '\SDK\lib',
$this->getPhpDir() . '\\lib', $this->getPhpDir() . '\lib',
]; ];
$foundLib = false; $foundLib = false;
foreach ($phpDirs as $phpDir) { foreach ($phpDirs as $phpDir) {
if (is_dir($phpDir)) { if (is_dir($phpDir)) {
if (is_file($phpDir . '\\php8.lib') || is_file($phpDir . '\\php8ts.lib')) { if (is_file($phpDir . '\php8.lib') || is_file($phpDir . '\php8ts.lib')) {
$foundLib = true; $foundLib = true;
break; break;
} }
@ -299,18 +299,18 @@ class Translator extends Preprocessor
// 如果没找到 lib,检查根目录的 DLL // 如果没找到 lib,检查根目录的 DLL
if (!$foundLib) { if (!$foundLib) {
$phpDll = $this->getPhpDir() . '\\php8.dll'; $phpDll = $this->getPhpDir() . '\php8.dll';
$phpTsDll = $this->getPhpDir() . '\\php8ts.dll'; $phpTsDll = $this->getPhpDir() . '\php8ts.dll';
if (!is_file($phpDll) && !is_file($phpTsDll)) { if (!is_file($phpDll) && !is_file($phpTsDll)) {
$this->climate->warning("The `php8.lib` or `php8.dll` is not found in PHP directory, please check your PHP installation"); $this->climate->warning('The `php8.lib` or `php8.dll` is not found in PHP directory, please check your PHP installation');
} }
} }
$phpxLib = $this->getPhpxDir() . '\\lib\\phpx.lib'; $phpxLib = $this->getPhpxDir() . '\lib\phpx.lib';
$phpxDll = $this->getPhpxDir() . '\\lib\\phpx.dll'; $phpxDll = $this->getPhpxDir() . '\lib\phpx.dll';
if (!is_file($phpxLib) && !is_file($phpxDll)) { if (!is_file($phpxLib) && !is_file($phpxDll)) {
$this->climate->warning("The `phpx.lib` or `phpx.dll` is not found in PHX directory"); $this->climate->warning('The `phpx.lib` or `phpx.dll` is not found in PHX directory');
$this->climate->info("Note: If you are building an extension (-m ext), this is OK. For binary mode, please run `make` to build it"); $this->climate->info('Note: If you are building an extension (-m ext), this is OK. For binary mode, please run `make` to build it');
} }
} else { } else {
// Unix/Linux/macOS 平台检查 .so 或 .dylib 文件 // Unix/Linux/macOS 平台检查 .so 或 .dylib 文件
@ -320,11 +320,11 @@ class Translator extends Preprocessor
if (!is_file($phpLib)) { if (!is_file($phpLib)) {
$this->climate->warning("The `libphp.{$ext}` is not found"); $this->climate->warning("The `libphp.{$ext}` is not found");
$this->climate->info("Note: If you are building an extension (-m ext), this is OK. For binary mode, please run `make` to build it"); $this->climate->info('Note: If you are building an extension (-m ext), this is OK. For binary mode, please run `make` to build it');
} }
if (!is_file($phpxLib)) { if (!is_file($phpxLib)) {
$this->climate->warning("The `libphpx.{$ext}` is not found"); $this->climate->warning("The `libphpx.{$ext}` is not found");
$this->climate->info("Note: If you are building an extension (-m ext), this is OK. For binary mode, please run `make` to build it"); $this->climate->info('Note: If you are building an extension (-m ext), this is OK. For binary mode, please run `make` to build it');
} }
} }
} }
@ -727,9 +727,9 @@ CODE;
// 根据平台和编译器类型构建编译命令 // 根据平台和编译器类型构建编译命令
if ($this->isWindows()) { if ($this->isWindows()) {
// C 文件和 C++ 文件使用不同的选项 // C 文件和 C++ 文件使用不同的选项
$isCppFile = (pathinfo($cppFile, PATHINFO_EXTENSION) === 'cc' || $isCppFile = (pathinfo($cppFile, PATHINFO_EXTENSION) === 'cc'
pathinfo($cppFile, PATHINFO_EXTENSION) === 'cpp' || || pathinfo($cppFile, PATHINFO_EXTENSION) === 'cpp'
pathinfo($cppFile, PATHINFO_EXTENSION) === 'cxx'); || pathinfo($cppFile, PATHINFO_EXTENSION) === 'cxx');
// Windows 下根据编译器类型选择参数格式 // Windows 下根据编译器类型选择参数格式
if ($this->cppCompiler === 'clang++' || $this->cppCompiler === 'clang') { if ($this->cppCompiler === 'clang++' || $this->cppCompiler === 'clang') {

Loading…
Cancel
Save