feat(translator): 更新编译器生成全局变量和常量功能

- 修改编译器将函数声明生成到构建目录的 include/php_func_decl.h 文件
- 添加全局变量源文件生成功能,输出到构建目录的 global_vars.cc 文件
- 添加 main.cc 文件到源文件列表中
- 将全局常量注册到 PHP 环境中
- 修改链接器合并二进制文件的方式,使用动态对象文件列表
- 添加文件写入安全检查和目录自动创建功能
- 移除独立的链接器脚本文件
- 添加常量示例文件用于测试
pull/1/head
韩天峰 8 months ago
parent 1036317e74
commit c601729ddc
  1. 10
      bin/compiler.php
  2. 19
      bin/linker.php
  3. 19
      examples/const.php
  4. 57
      src/Php/Translator.php
  5. 0
      src/cpp/main.cc

@ -68,7 +68,15 @@ if (empty($sourceFiles)) {
}
// 生成所有函数声明
$translator->genFunctionDeclaration("./php_func_decl.h");
$translator->genFunctionDeclaration($translator->getBuildDir() . "/include/php_func_decl.h");
// 生成所有全局变量源文件
$globalVarsSourceFile = $translator->getBuildDir() . '/global_vars.cc';
$translator->genGlobalVars($globalVarsSourceFile);
$sourceFiles[] = $globalVarsSourceFile;
// 添加 main.cc 文件
$sourceFiles[] = ROOT_PATH . '/src/cpp/main.cc';
// 编译所有 C++ 文件
foreach ($sourceFiles as $cppFile) {

@ -1,19 +0,0 @@
<?php
require __DIR__ . '/bootstrap.php';
use PhpAot\Php\Translator;
if (empty($argv[1])) {
die("php compiler.php [file]\n");
}
try {
$file = $argv[1];
$translator = new Translator(ROOT_PATH);
$info = pathinfo($file);
$objectFile = './tmp/' . $info['filename'] . '.cc.o';
$translator->compileBinary($info['filename'], $objectFile);
} catch (Error $error) {
echo "Parse error: {$error->getMessage()}\n";
return;
}

@ -0,0 +1,19 @@
<?php
const C_I = 11;
const C_F = 1.1;
const C_S = "str";
const C_B = true;
const C_N = null;
const C_A = [1, 2, 3];
const C_O = new stdClass();
const C_I2 = -C_I;
const C_F2 = C_F * 2;
const C_S2 = C_S . "hello";
function main()
{
var_dump(get_defined_constants());
}

@ -13,6 +13,7 @@ use PhpParser\NodeFinder;
use PhpParser\NodeTraverser;
use PhpParser\ParserFactory;
use PhpParser\PrettyPrinter;
use RuntimeException;
use stdClass;
class Translator extends \PhpAot\Core\Translator
@ -276,7 +277,7 @@ class Translator extends \PhpAot\Core\Translator
private function doConvert(string $phpCode): string
{
$this->climate->info('do convert: ' . $this->file);
$this->climate->info('convert: ' . $this->file);
$parser = (new ParserFactory())->createForNewestSupportedVersion();
$ast = $parser->parse($phpCode);
@ -345,11 +346,7 @@ class Translator extends \PhpAot\Core\Translator
public function save(string $code, string $file): void
{
$dir = dirname($file);
if (!is_dir($dir)) {
mkdir($dir, 0777, true);
}
file_put_contents($file, $code);
$this->writeFile($file, $code);
$this->formatCppCode($file);
}
@ -524,7 +521,7 @@ class Translator extends \PhpAot\Core\Translator
foreach ($params as $param) {
// .stub 存根定义 C++ Native 函数,必须设置函数的参数类型
if ($this->stubFile and !$param->type) {
throw new \RuntimeException('No type for ' . $this->parseIdentifier($param->var));
throw new RuntimeException('No type for ' . $this->parseIdentifier($param->var));
}
$type = $this->parseType($param->type);
$name = $this->parseIdentifier($param->var);
@ -1142,7 +1139,7 @@ class Translator extends \PhpAot\Core\Translator
{
$list = [
$this->phpxDir . '/include',
'./',
$this->getBuildDir() . '/include',
];
$out = '$(php-config --includes) ';
foreach ($list as $li) {
@ -1198,15 +1195,14 @@ class Translator extends \PhpAot\Core\Translator
public function compileBinary(string $targetFile, array $objectFiles): void
{
$this->genGlobalVars();
if ($this->climate->arguments->defined('output')) {
$targetFile = $this->climate->arguments->get('output');
}
$objectFile = implode(' ', $objectFiles);
$cmd = $this->cppCompiler . ' main.cc global_vars.cc ' . $objectFile . ' -o ' . $targetFile . ' ' . $this->parseLdflags() . $this->parseLibs();
$this->addCompilationOption($cmd);
$this->climate->comment($cmd);
shell_exec($cmd);
$objectList = implode(' ', $objectFiles);
$linkCmd = $this->cppCompiler . ' ' . $objectList . ' -o ' . $targetFile . ' ' . $this->parseLdflags() . $this->parseLibs();
$this->addCompilationOption($linkCmd);
$this->climate->comment($linkCmd);
shell_exec($linkCmd);
}
private function parseBinaryOpConcat(mixed $expr): string
@ -2295,9 +2291,8 @@ class Translator extends \PhpAot\Core\Translator
return array_key_exists($name, $this->globalVars);
}
private function genGlobalVars(): void
public function genGlobalVars(string $file): void
{
$file = 'global_vars.cc';
$code = $this->genIncludeHeaderFiles();
$lines = [];
// 全局变量只能是 var 类型
@ -2316,7 +2311,7 @@ class Translator extends \PhpAot\Core\Translator
$this->indentLevel--;
$code .= '};' . PHP_EOL;
// 生成全局常量
// 生成常量
$this->indentLevel++;
foreach ($this->nativeConstants as $name => $constant) {
$code .= $constant->type . ' ' . $name . ';' . PHP_EOL;
@ -2328,6 +2323,8 @@ class Translator extends \PhpAot\Core\Translator
$lines = [];
foreach ($this->nativeConstants as $name => $constant) {
$lines[] = $this->getIndent() . $name . ' = ' . $constant->value . ';';
// 注册到 PHP
$lines[] = $this->getIndent() . 'php::define("' . $name . '", ' . $name . ');';
}
$this->indentLevel--;
$code .= $this->genFunction(self::PREFIX . 'init_constant_vars', 'void', [], $lines);
@ -2358,7 +2355,8 @@ class Translator extends \PhpAot\Core\Translator
$this->indentLevel--;
$code .= $this->genFunction(self::PREFIX . 'unset_global_vars', 'void', [], $lines);
file_put_contents($file, $code);
$this->writeFile($file, $code);
$this->formatCppCode($file);
}
private function genFunction(string $name, string $returnType, array $args = [], array $lines = []): string
@ -2458,7 +2456,7 @@ class Translator extends \PhpAot\Core\Translator
$code .= 'extern ' . $constant->type . ' ' . $name . ';' . PHP_EOL;
}
file_put_contents($file, $code);
$this->writeFile($file, $code);
}
private function parseAssignRef(mixed $expr)
@ -2807,4 +2805,25 @@ class Translator extends \PhpAot\Core\Translator
$this->stubFile = $this->isStubFile($file);
return $phpCode;
}
/**
* @param string $file
* @param string $content
* @return void
*/
private function writeFile(string $file, string $content): void
{
$dir = dirname($file);
if (!is_dir($dir)) {
mkdir($dir, 0777, true);
}
if (!file_put_contents($file, $content)) {
throw new RuntimeException('Can not write file: ' . $file);
}
}
public function getBuildDir(): string
{
return $this->buildDir;
}
}

Loading…
Cancel
Save