aboutsummaryrefslogtreecommitdiffhomepage
path: root/docs/dev/composer-runtime-bundle.md
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-15 07:37:45 +0900
committernsfisis <nsfisis@gmail.com>2026-08-15 07:37:45 +0900
commit548463bad1f72c97f68b47f54a263a4f4ad87b3a (patch)
tree1285d740611be3ad175f9e57c61d880b500dd818 /docs/dev/composer-runtime-bundle.md
parented8694f89eb7702eb7e617af29f8f444f32b8d3c (diff)
downloadphp-shirabe-548463bad1f72c97f68b47f54a263a4f4ad87b3a.tar.gz
php-shirabe-548463bad1f72c97f68b47f54a263a4f4ad87b3a.tar.zst
php-shirabe-548463bad1f72c97f68b47f54a263a4f4ad87b3a.zip
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) <noreply@anthropic.com>
Diffstat (limited to 'docs/dev/composer-runtime-bundle.md')
-rw-r--r--docs/dev/composer-runtime-bundle.md40
1 files changed, 40 insertions, 0 deletions
diff --git a/docs/dev/composer-runtime-bundle.md b/docs/dev/composer-runtime-bundle.md
new file mode 100644
index 00000000..f152897f
--- /dev/null
+++ b/docs/dev/composer-runtime-bundle.md
@@ -0,0 +1,40 @@
+# Composer runtime bundle
+
+Composer plugins and scripts expect the real PHP classes in `Composer\` itself
+and packages that Composer depends on to be available. Shirabe embeds the
+runtime PHP sources into the binary at compile time.
+
+## Building and embedding the bundle
+
+Shirabe archives all PHP sources and resources of Composer and its dependencies,
+and embeds the archived phar file into the binary. Shirabe also calculates a
+hash value from all included files and puts a file that contains the hash,
+`shirabe/bundle-id`. It is used for verifying the bundle. See
+`crates/shirabe-php-rpc/build.rs` for details.
+
+### Phar signature
+
+A phar signature is an optional signature to verify the archive's integrity, and
+must be appended to the end of the file. Shirabe's runtime bundle has no
+signature because the bundle is not always at the end of the executable file.
+To disable phar verification, the PHP worker is started with `-d phar.require_hash=0`.
+The worker restores it to `1` right after opening the bundle, so that the rest
+of the process still verifies the phars it opens. A verification result is
+cached per file, and the bundle is never re-verified.
+
+### `__HALT_COMPILER();` tokens
+
+A phar file consists of 3 or 4 sections: a stub, a manifest, the actual contents
+and an optional signature. The stub and the manifest are separated by
+`__HALT_COMPILER();` tokens, which means that Shirabe's executable binary
+must not contain the tokens except for phar's one.
+
+## Accessing files at runtime
+
+Shirabe tries to open the embedded bundle, and sets the executable as the base
+path of autoloading. If loading phar fails for some reason, e.g., no phar ext,
+Shirabe unpacks the archive to `<Shirabe's cache dir>/runtime/<bundle id>` once,
+and uses that directory for the base path instead.
+
+NOTE: the environment variable `SHIRABE_COMPOSER_PHP_DIR` can override the
+location for development.