From 3045259ae04dc0b9affabec9a809c2f0aa9fa2b8 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Sat, 30 May 2026 15:15:47 +0800 Subject: [PATCH] =?UTF-8?q?feat(compiler):=20=E6=B7=BB=E5=8A=A0=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E5=90=8E=E8=BF=90=E8=A1=8C=E5=8A=9F=E8=83=BD=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现命令行参数解析功能,支持路径和选项参数 - 添加 --run/-r 选项用于编译完成后立即执行二进制文件 - 更新帮助信息显示新的运行选项 - 修改 build 方法返回目标文件路径而不是 void - 实现 run 方法执行编译后的二进制文件 - 添加目标参数获取功能支持传递给执行程序 - 移除简单的文件参数检查逻辑 --- bin/compiler.php | 13 +++++----- src/Php/Constants.php | 6 +++++ src/Php/Translator.php | 54 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 65 insertions(+), 8 deletions(-) diff --git a/bin/compiler.php b/bin/compiler.php index 93dabdc4..5ae7e1e1 100755 --- a/bin/compiler.php +++ b/bin/compiler.php @@ -6,18 +6,17 @@ require __DIR__ . '/../src/gen_stub.php'; use PhpAot\Php\Translator; -if (empty($argv[1])) { - die("php compiler.php [file]\n"); -} - -$path = $argv[1]; $translator = new Translator(ROOT_PATH); $translator->setIndent(' '); // 扫描所有 PHP 文件,预处理 -$files = $translator->prepare($path); +$files = $translator->prepare($translator->parseArgv($argv)); // 生成 C++ 文件 $sourceFiles = $translator->convert($files); // 编译所有 C++ 文件 $objectFiles = $translator->compile($sourceFiles); // 连接所有目标文件,生成可执行文件 -$translator->build($objectFiles); +$binaryFile = $translator->build($objectFiles); +// 如果指定了 --run / -r,编译完成后立即执行 +if ($translator->isRunRequested()) { + $translator->run($binaryFile); // never returns +} diff --git a/src/Php/Constants.php b/src/Php/Constants.php index a72d8360..4c2572be 100644 --- a/src/Php/Constants.php +++ b/src/Php/Constants.php @@ -118,6 +118,12 @@ class Constants 'required' => false, 'defaultValue' => CompilerBase::BUILD_MODE_BIN, ], + 'run' => [ + 'prefix' => 'r', + 'longPrefix' => 'run', + 'description' => 'Run the compiled binary after build', + 'noValue' => true, + ], // 内部开发选项,用于定位特定行的翻译问题,请勿写入用户文档 'debug-line' => [ 'longPrefix' => 'debug-line', diff --git a/src/Php/Translator.php b/src/Php/Translator.php index e4442e97..4caf3248 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -78,6 +78,22 @@ class Translator extends Preprocessor $this->detectPlatform(); } + public function parseArgv(array $argv) + { + $path = null; + for ($i = 1; $i < count($argv); $i++) { + if ($argv[$i] !== '' && $argv[$i][0] !== '-') { + $path = $argv[$i]; + break; + } + } + if (empty($path)) { + $this->showUsage(); + exit(1); + } + return $path; + } + public function showUsage(): void { $climate = $this->climate; @@ -105,6 +121,7 @@ class Translator extends Preprocessor $climate->tab()->out('-h, --help Show this help message'); $climate->tab()->out('-f, --force Force compile even if cache exists'); $climate->tab()->out('-m, --mode Compilation mode, -m bin(binary) or -m ext(extension), default: bin'); + $climate->tab()->out('-r, --run Run the compiled binary after build'); $climate->tab()->out('-j, --job Number of parallel compilation jobs (default: 4)'); $climate->tab()->out('--no-literal-strings Disable literal strings optimization'); $climate->tab()->out('--no-console Hide console window (Windows only, GUI application)'); @@ -121,6 +138,7 @@ class Translator extends Preprocessor $climate->tab()->out($cmd . ' app.php --sanitize=address (Enable AddressSanitizer)'); $climate->tab()->out($cmd . ' app.php --cxx-std=c++17 (Use C++17 standard)'); $climate->tab()->out($cmd . ' app.php --no-literal-strings (Disable string optimization)'); + $climate->tab()->out($cmd . ' app.php -r -O2 -- --flag1 value1'); $climate->br(); } @@ -1039,7 +1057,7 @@ CODE; } } - public function build(array $objectFiles): void + public function build(array $objectFiles): string { $targetFile = $this->getTargetFileName(); @@ -1075,6 +1093,40 @@ CODE; } $this->climate->green('Build successful: ' . $targetFile); + + return $targetFile; + } + + public function isRunRequested(): bool + { + return $this->climate->arguments->defined('run'); + } + + public function run(string $targetFile): never + { + if ($this->buildMode !== self::BUILD_MODE_BIN) { + $this->climate->error('--run is only supported in binary mode (-m bin), not extension mode (-m ext)'); + exit(1); + } + + if (DIRECTORY_SEPARATOR !== '\\' && !str_starts_with($targetFile, '/')) { + $targetFile = './' . $targetFile; + } + + $targetArgs = $this->getTargetArgs(); + $command = escapeshellcmd($targetFile); + if (!empty($targetArgs)) { + $command .= ' ' . implode(' ', array_map('escapeshellarg', $targetArgs)); + } + + fwrite(STDERR, "Running: {$command}\n"); + passthru($command, $exitCode); + exit($exitCode); + } + + public function getTargetArgs(): array + { + return $this->climate->arguments->trailingArray() ?? []; } public function genFunctionDeclaration(string $file): void