From 28413e09240c0f5b7cd1f1fe6b9a6563b5c9edce Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Tue, 22 Sep 2026 12:01:13 +0800 Subject: [PATCH] refactor(build): encapsulate project build runner --- src/Build/ProjectBuildRunner.php | 106 +++++++++++++++++++++++++++++++ src/compiler.php | 66 +------------------ 2 files changed, 108 insertions(+), 64 deletions(-) create mode 100644 src/Build/ProjectBuildRunner.php diff --git a/src/Build/ProjectBuildRunner.php b/src/Build/ProjectBuildRunner.php new file mode 100644 index 00000000..cf8be731 --- /dev/null +++ b/src/Build/ProjectBuildRunner.php @@ -0,0 +1,106 @@ + $arguments */ + public function run(array $arguments): void + { + $this->translator->setIndent(' '); + $sourceFiles = $this->generateProjectSources($arguments); + $sourceFiles = $this->appendInternalWasmInterface($sourceFiles); + + if ($this->translator->isDryRun()) { + $this->finishDryRun($sourceFiles); + return; + } + + $target = $this->compileAndLink($sourceFiles); + if ($this->translator->isRunRequested()) { + $this->translator->run($target); + } + } + + /** @param list $arguments @return list */ + private function generateProjectSources(array $arguments): array + { + $project = $this->translator->parseArgv($arguments); + $files = $this->translator->prepare($project); + return $this->translator->convert($files); + } + + /** @param list $sourceFiles @return list */ + private function appendInternalWasmInterface(array $sourceFiles): array + { + $manifest = $this->environmentValue('TYPEPHP_WASM_INTERFACE_MANIFEST'); + if ($manifest === null) { + return $sourceFiles; + } + + $adapter = $this->requiredEnvironmentValue('TYPEPHP_WASM_INTERFACE_ADAPTER'); + $this->translator->writeWasmInterface( + $manifest, + $this->requiredEnvironmentValue('TYPEPHP_WASM_INTERFACE_WIT'), + $adapter, + $this->requiredEnvironmentValue('TYPEPHP_WASM_INTERFACE_ASYNC_EXPORTS'), + $this->requiredEnvironmentValue('TYPEPHP_WASM_PACKAGE'), + $this->requiredEnvironmentValue('TYPEPHP_WASM_WORLD'), + ); + $sourceFiles[] = $adapter; + return $sourceFiles; + } + + private function environmentValue(string $name): ?string + { + $value = getenv($name); + return is_string($value) && $value !== '' ? $value : null; + } + + private function requiredEnvironmentValue(string $name): string + { + $value = $this->environmentValue($name); + if ($value === null) { + throw new \RuntimeException('Incomplete internal WASM interface configuration: ' . $name); + } + return $value; + } + + /** @param list $sourceFiles */ + private function finishDryRun(array $sourceFiles): void + { + $sourceList = $this->environmentValue('TYPEPHP_GENERATED_SOURCE_LIST'); + if ($sourceList !== null) { + AtomicFile::write($sourceList, implode(PHP_EOL, $sourceFiles) . PHP_EOL); + } + + $count = count($sourceFiles); + $buildDir = $this->translator->getBuildDir(); + $this->translator->output( + "Dry run completed: {$count} C++ source file(s) generated in {$buildDir}", + 'lightBlue', + ); + } + + /** @param list $sourceFiles */ + private function compileAndLink(array $sourceFiles): string + { + $objectFiles = [ + ...$this->translator->compile($sourceFiles), + ...$this->translator->getProjectObjectFiles(), + ]; + return $this->translator->build($objectFiles); + } +} diff --git a/src/compiler.php b/src/compiler.php index ccfa114b..22409c75 100644 --- a/src/compiler.php +++ b/src/compiler.php @@ -5,6 +5,7 @@ use TypePhp\Build\WasiProjectConfig; use TypePhp\Build\PhpxLocator; use TypePhp\Build\NativeSourceProjectBuilder; use TypePhp\Build\NativeSourceProjectConfig; +use TypePhp\Build\ProjectBuildRunner; use TypePhp\PythonTools\Command as PythonToolsCommand; use TypePhp\Cli\CompletionCommand; @@ -72,67 +73,7 @@ function main(int $argc, array $argv): void return; } - $translator = Translator::getInstance(); - $translator->setIndent(' '); - // Scan all PHP files and preprocess them. - $files = $translator->prepare($translator->parseArgv($argv)); - // Generate the C++ source files. - $sourceFiles = $translator->convert($files); - - $wasmManifest = getenv('TYPEPHP_WASM_INTERFACE_MANIFEST'); - if (is_string($wasmManifest) && $wasmManifest !== '') { - $wasmWit = getenv('TYPEPHP_WASM_INTERFACE_WIT'); - $wasmAdapter = getenv('TYPEPHP_WASM_INTERFACE_ADAPTER'); - $wasmAsyncExports = getenv('TYPEPHP_WASM_INTERFACE_ASYNC_EXPORTS'); - $wasmPackage = getenv('TYPEPHP_WASM_PACKAGE'); - $wasmWorld = getenv('TYPEPHP_WASM_WORLD'); - if (!is_string($wasmWit) || $wasmWit === '' - || !is_string($wasmAdapter) || $wasmAdapter === '' - || !is_string($wasmAsyncExports) || $wasmAsyncExports === '' - || !is_string($wasmPackage) || $wasmPackage === '' - || !is_string($wasmWorld) || $wasmWorld === '') { - throw new RuntimeException('Incomplete internal WASM interface configuration'); - } - $translator->writeWasmInterface( - $wasmManifest, - $wasmWit, - $wasmAdapter, - $wasmAsyncExports, - $wasmPackage, - $wasmWorld, - ); - $sourceFiles[] = $wasmAdapter; - } - - // --dry mode: only generate the C++ code, without compiling. - if ($translator->isDryRun()) { - $buildDir = $translator->getBuildDir(); - $count = count($sourceFiles); - $sourceListFile = getenv('TYPEPHP_GENERATED_SOURCE_LIST'); - if (is_string($sourceListFile) && $sourceListFile !== '') { - $sourceListDir = dirname($sourceListFile); - if (!is_dir($sourceListDir) && !mkdir($sourceListDir, 0777, true) && !is_dir($sourceListDir)) { - throw new RuntimeException("Unable to create generated source manifest directory: {$sourceListDir}"); - } - if (file_put_contents($sourceListFile, implode(PHP_EOL, $sourceFiles) . PHP_EOL) === false) { - throw new RuntimeException("Unable to write generated source manifest: {$sourceListFile}"); - } - } - $translator->output("Dry run completed: {$count} C++ source file(s) generated in {$buildDir}", 'lightBlue'); - return; - } - - // Compile all C++ source files. - $objectFiles = [ - ...$translator->compile($sourceFiles), - ...$translator->getProjectObjectFiles(), - ]; - // Link all object files to produce the executable. - $binaryFile = $translator->build($objectFiles); - // If --run / -r was specified, execute immediately after compilation. - if ($translator->isRunRequested()) { - $translator->run($binaryFile); // never returns - } + (new ProjectBuildRunner(Translator::getInstance()))->run($argv); } function shouldCompileNativeSourceProject(array $argv): bool @@ -321,9 +262,6 @@ function compileWasmProgram(array $argv): void } $environment = getenv(); - if (!is_array($environment)) { - $environment = []; - } $environment['TYPEPHP_WASI_CC'] = $tools['clang']; $environment['TYPEPHP_WASI_CXX'] = $tools['clang++']; $environment['TYPEPHP_WASI_AR'] = $tools['llvm-ar'];