From 548463bad1f72c97f68b47f54a263a4f4ad87b3a Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 15 Aug 2026 07:37:45 +0900 Subject: feat(php-rpc): embed the Composer PHP runtime in the executable Plugins and scripts need the real `Composer\` classes and the packages Composer depends on, which so far came from a checkout found through SHIRABE_COMPOSER_PHP_DIR or a path next to the workspace. Neither exists for a distributed binary. The build script now archives those PHP sources into a phar the way Compiler.php does and the executable carries it. The worker maps it with Phar::loadPhar and reads a content-addressed sentinel back to tell a bundle it can use from one it cannot; where its PHP cannot open the phar, the bundle is unpacked once into the cache directory and autoloaded from there. SHIRABE_COMPOSER_PHP_DIR still overrides both for development. PHP locates a phar's manifest by the first __HALT_COMPILER(); token in the file, so the executable must hold no other copy of it: phar.rs builds the token at run time, and a linter keeps further literals out of the sources that reach the binary. Co-Authored-By: Claude Opus 5 (1M context) --- .../linters/src/Linters/NoHaltCompilerLiteral.php | 79 ++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 scripts/linters/src/Linters/NoHaltCompilerLiteral.php (limited to 'scripts/linters/src') diff --git a/scripts/linters/src/Linters/NoHaltCompilerLiteral.php b/scripts/linters/src/Linters/NoHaltCompilerLiteral.php new file mode 100644 index 00000000..30520ff7 --- /dev/null +++ b/scripts/linters/src/Linters/NoHaltCompilerLiteral.php @@ -0,0 +1,79 @@ +embeddedFiles($rootDir) as $path) { + $relative = Paths::relativeTo($rootDir, $path); + if (in_array($relative, $excludes, true)) { + continue; + } + + foreach (file($path) as $idx => $raw) { + if (!str_contains($raw, self::TOKEN)) { + continue; + } + + $errors[] = "{$relative}:" . ($idx + 1) . ': ' . trim($raw); + } + } + + return $errors; + } + + /** + * The sources whose bytes reach the binary: Rust code, and the PHP files the Rust code + * embeds with `include_str!`. + * + * @return list + */ + private function embeddedFiles(string $rootDir): array + { + $paths = FileFinder::rustFiles($rootDir); + + foreach (glob("{$rootDir}/crates/*/php", GLOB_ONLYDIR) ?: [] as $phpDir) { + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($phpDir, \FilesystemIterator::SKIP_DOTS), + ); + foreach ($iterator as $file) { + /** @var \SplFileInfo $file */ + if ($file->isFile()) { + $paths[] = $file->getPathname(); + } + } + } + + sort($paths); + + return $paths; + } +} -- cgit v1.3.1-4-g156e