Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,12 @@ jobs:
brew install autoconf automake bison cmake gettext libtool re2c
echo "$(brew --prefix bison)/bin" >> "$GITHUB_PATH"

# The version is part of the lock's content hash, so the lock takes the new hash; its packages stay as committed.
- name: Set the version of the binary
if: env.VERSION != ''
run: composer config version "$VERSION"
run: |
composer config version "$VERSION"
composer update --lock --no-install --no-interaction --no-progress

- name: Install the dependencies
run: composer install --no-dev --no-interaction --no-progress
Expand Down
1 change: 1 addition & 0 deletions .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,7 @@ private function hasOnlyWhitespace(Tokens $tokens, int $startIndex, int $endInde
->name('*.php')
->in([
__DIR__ . '/bin',
__DIR__ . '/generator',
__DIR__ . '/src',
__DIR__ . '/tests',
])
Expand Down
23 changes: 17 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Everything SKERNEL downloads and builds lives in its home directory, `~/.skernel
~/.skernel/
├── cache/ php.net and PECL release answers and Zig mirrors, refreshed daily
├── downloads/ source archives, shared by every build
├── generator/<digest>/ the generator a standalone SKERNEL extracts for builds
├── pkgroot/<platform>/ Zig and the other packages static-php-cli installs
├── runtimes/<platform>/php-<version>/<extension-hash>/
│ ├── php the static PHP CLI
Expand Down Expand Up @@ -100,9 +101,9 @@ A directory that exists and is not empty, a Composer that is not found or fails,
run [-d|--working-dir=<dir>] [--php=<version>] [--watch] [--] [<arguments>...]
```

`run` runs the project from source with its managed PHP, in a separate process in the project directory. `<arguments>` go to the application, so `run swoole:start` starts its Swoole server; put options for the application after `--`. Without `--watch`, SKERNEL exits with the application's exit status.
`run` builds the project as `build` does and then runs it from source with its managed PHP, in a separate process in the project directory. `<arguments>` go to the application, so `run swoole:start` starts its Swoole server; put options for the application after `--`. Without `--watch`, SKERNEL exits with the application's exit status.

With `--watch`, SKERNEL restarts the application whenever a project file changes. It checks once a second for changes to PHP files, `.env` and `.env.*` files, and `composer.lock`, leaving out the vendor directory, `target/`, and directories whose name starts with a dot, so the logs and caches a running application writes do not restart it. It sends the application SIGTERM and then SIGKILL after 10 seconds. An application that exits on its own is started again by the next change.
With `--watch`, SKERNEL restarts the application whenever a project file changes. It checks once a second for changes to PHP files, `.env` and `.env.*` files, and `composer.lock`, leaving out the vendor directory, `target/`, and directories whose name starts with a dot, so the logs and caches a running application writes do not restart it. It sends the application SIGTERM and then SIGKILL after 10 seconds, and builds the project again before it restarts it. An application that exits on its own, or whose build fails, is started again by the next change.

SIGINT and SIGTERM stop the application before SKERNEL exits. The failures of `build`, and an application that cannot start, print a short message on STDERR and exit with status 1.

Expand All @@ -112,7 +113,7 @@ SIGINT and SIGTERM stop the application before SKERNEL exits. The failures of `b
clean [-d|--working-dir=<dir>]
```

`clean` removes the project's `target/` directory and its `<vendor>/.cache` scan caches, and says what it removed. A package written elsewhere with `--output` or the `package.output` setting stays. The project's dependencies do not have to be installed.
`clean` removes the project's `target/` directory and its `<vendor>/.cache` build artifacts, and says what it removed. A package written elsewhere with `--output` or the `package.output` setting stays. The project's dependencies do not have to be installed.

### self-update

Expand All @@ -130,15 +131,25 @@ Running from source, a latest release that cannot be read or has no verified bin
build [-d|--working-dir=<dir>] [--php=<version>]
```

`build` runs a full source scan of the project and writes the build artifacts that restore-only and Phar execution load to the project's `<vendor>/.cache` directory, honouring its `config.vendor-dir`: the scan snapshots, and whatever the project's components write when the build publishes `SuperKernel\Event\ApplicationBuild`, such as the prepared proxies of `super-kernel/aop`. The project must have its dependencies installed, including `super-kernel/context` and `super-kernel/di`, and the scan covers the packages of that installation.
`build` generates the build artifacts that the application loads at start and writes them to the project's `<vendor>/.cache` directory, honouring its `config.vendor-dir`: the package records with their class maps, the attributes collected from those classes, a build stamp, and whatever the project's components write when the build publishes `SuperKernel\Event\ApplicationBuild`, such as the prepared proxies of `super-kernel/aop`. A SuperKernel application started without them, or with artifacts from an older `composer.lock`, stops with a message that names `skernel build`. The project must have its dependencies installed, including `super-kernel/metadata`, `super-kernel/context`, and `super-kernel/di`, and the build covers the packages of that installation.

The build runs in a separate process of the managed PHP CLI. That process loads the project's own autoloader, bootstraps its container, and then publishes `ApplicationBuild` through the project's PSR-14 event dispatcher, when the project has both the event and a dispatcher, without resolving or running the application. Everything the process writes, including the project's scan diagnostics, goes to STDERR, and on success STDOUT carries one line:
The build runs in two separate processes of the managed PHP CLI, so SKERNEL never loads the project's code itself. The first loads the project's own autoloader, checks that the installed `super-kernel/metadata` uses the build protocol this SKERNEL generates, maps the classes of every installed package, collects the attributes of the classes that declare any, and publishes the records through the project's own `super-kernel/metadata` and `super-kernel/annotator`. A class that cannot be loaded or whose attribute cannot be created is skipped, even when loading it ends the process with a fatal error. The second process bootstraps the container from the records and then publishes `ApplicationBuild` through the project's PSR-14 event dispatcher, when the project has both the event and a dispatcher, without resolving or running the application.

Everything the processes write goes to STDERR, followed by the skipped classes, one per line, sorted by package and class:

```text
SKERNEL skipped 2 classes whose attributes could not be collected:
acme/app App\Broken\Listener: Error: Class "App\Missing" not found
acme/app App\Broken\Proxy: fatal error: Declaration of App\Broken\Proxy::run() must be compatible with ...
```

On success STDOUT carries one line:

```text
Build artifacts written to /path/to/my-app/vendor/.cache.
```

A missing project or dependencies, an invalid configuration file or `--php` value, a managed PHP that cannot be provided, or a failed build prints a short message on STDERR and exits with status 1.
When the project's `super-kernel/metadata` uses another build protocol, the build stops before it writes anything and says which side to upgrade: SKERNEL, for example with `skernel self-update`, or the project's SuperKernel packages. A project without `super-kernel/metadata` predates SKERNEL-generated artifacts and needs SuperKernel 1.0.0-alpha.2 or later. That, a missing project or dependencies, an invalid configuration file or `--php` value, a managed PHP that cannot be provided, or a failed build prints a short message on STDERR and exits with status 1.

### package

Expand Down
23 changes: 17 additions & 6 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ SKERNEL 下载和构建的所有内容都放在它的主目录 `~/.skernel` 中
~/.skernel/
├── cache/ php.net and PECL release answers and Zig mirrors, refreshed daily
├── downloads/ source archives, shared by every build
├── generator/<digest>/ the generator a standalone SKERNEL extracts for builds
├── pkgroot/<platform>/ Zig and the other packages static-php-cli installs
├── runtimes/<platform>/php-<version>/<extension-hash>/
│ ├── php the static PHP CLI
Expand Down Expand Up @@ -100,9 +101,9 @@ Project created in /path/to/my-app.
run [-d|--working-dir=<dir>] [--php=<version>] [--watch] [--] [<arguments>...]
```

`run` 用受管 PHP 从源码运行项目,在项目目录中以单独的进程执行。`<arguments>` 传给应用,所以 `run swoole:start` 会启动它的 Swoole 服务;要传给应用的选项放在 `--` 之后。不加 `--watch` 时,SKERNEL 以应用的退出码退出。
`run` 先像 `build` 一样构建项目,再用受管 PHP 从源码运行项目,在项目目录中以单独的进程执行。`<arguments>` 传给应用,所以 `run swoole:start` 会启动它的 Swoole 服务;要传给应用的选项放在 `--` 之后。不加 `--watch` 时,SKERNEL 以应用的退出码退出。

加上 `--watch` 后,项目文件变化时 SKERNEL 会重启应用。它每秒检查一次 PHP 文件、`.env` 和 `.env.*` 文件以及 `composer.lock` 的变化,并跳过 vendor 目录、`target/` 和名称以点开头的目录,所以运行中的应用写入日志和缓存不会触发重启。重启时先向应用发送 SIGTERM,10 秒后发送 SIGKILL。应用自行退出后,下一次变化会再次启动它。
加上 `--watch` 后,项目文件变化时 SKERNEL 会重启应用。它每秒检查一次 PHP 文件、`.env` 和 `.env.*` 文件以及 `composer.lock` 的变化,并跳过 vendor 目录、`target/` 和名称以点开头的目录,所以运行中的应用写入日志和缓存不会触发重启。重启时先向应用发送 SIGTERM,10 秒后发送 SIGKILL,并在重启前重新构建项目。应用自行退出或构建失败后,下一次变化会再次启动它。

SIGINT 和 SIGTERM 会先停止应用,SKERNEL 再退出。出现 `build` 的任一种失败或应用无法启动时,会在 STDERR 上打印一条简短的提示,退出码为 1。

Expand All @@ -112,7 +113,7 @@ SIGINT 和 SIGTERM 会先停止应用,SKERNEL 再退出。出现 `build` 的
clean [-d|--working-dir=<dir>]
```

`clean` 删除项目的 `target/` 目录和 `<vendor>/.cache` 扫描缓存,并说明删除了什么。用 `--output` 或 `package.output` 设置写到其他位置的包不会被删除。项目的依赖不必已安装。
`clean` 删除项目的 `target/` 目录和 `<vendor>/.cache` 构建产物,并说明删除了什么。用 `--output` 或 `package.output` 设置写到其他位置的包不会被删除。项目的依赖不必已安装。

### self-update

Expand All @@ -130,15 +131,25 @@ self-update
build [-d|--working-dir=<dir>] [--php=<version>]
```

`build` 对项目做一次完整的源码扫描,把只恢复快照运行和 Phar 运行要加载的构建产物写到项目的 `<vendor>/.cache` 目录,vendor 目录遵循项目的 `config.vendor-dir`:包括扫描快照,以及构建发布 `SuperKernel\Event\ApplicationBuild` 时项目各组件写出的产物,例如 `super-kernel/aop` 预先准备好的代理。项目必须已经安装好依赖,其中包括 `super-kernel/context` 和 `super-kernel/di`;扫描覆盖的包以这次安装为准。
`build` 生成应用启动时加载的构建产物,写到项目的 `<vendor>/.cache` 目录,vendor 目录遵循项目的 `config.vendor-dir`:包括带类映射的包记录、从这些类收集到的注解、构建戳,以及构建发布 `SuperKernel\Event\ApplicationBuild` 时项目各组件写出的产物,例如 `super-kernel/aop` 预先准备好的代理。SuperKernel 应用在缺少这些产物,或产物来自较旧的 `composer.lock` 时启动,会停止并给出提到 `skernel build` 的提示。项目必须已经安装好依赖,其中包括 `super-kernel/metadata`、`super-kernel/context` 和 `super-kernel/di`;构建覆盖的包以这次安装为准。

构建在受管 PHP CLI 的一个单独进程中运行。该进程加载项目自己的 autoloader,引导出项目的容器;项目同时具备该事件和事件分发器时,再通过项目的 PSR-14 事件分发器发布 `ApplicationBuild`。整个过程不解析也不运行应用。该进程写出的所有内容(包括项目的扫描诊断)都转到 STDERR;成功时 STDOUT 只有一行:
构建在受管 PHP CLI 的两个单独进程中运行,所以 SKERNEL 自己从不加载项目的代码。第一个进程加载项目自己的 autoloader,确认已安装的 `super-kernel/metadata` 使用本 SKERNEL 生成的构建协议,为每个已安装的包建立类映射,收集声明了注解的类的注解,再通过项目自己的 `super-kernel/metadata` 和 `super-kernel/annotator` 发布这些记录。无法加载的类,或注解无法创建的类,会被跳过,即使加载它时进程因致命错误而结束也是如此。第二个进程从这些记录引导出容器;项目同时具备该事件和事件分发器时,再通过项目的 PSR-14 事件分发器发布 `ApplicationBuild`。整个过程不解析也不运行应用。

这些进程写出的所有内容都转到 STDERR,之后列出被跳过的类,每行一个,按包和类排序:

```text
SKERNEL skipped 2 classes whose attributes could not be collected:
acme/app App\Broken\Listener: Error: Class "App\Missing" not found
acme/app App\Broken\Proxy: fatal error: Declaration of App\Broken\Proxy::run() must be compatible with ...
```

成功时 STDOUT 只有一行:

```text
Build artifacts written to /path/to/my-app/vendor/.cache.
```

项目或依赖不存在、配置文件或 `--php` 的值无效、无法提供受管 PHP,或构建失败时,会在 STDERR 上打印一条简短的提示,退出码为 1。
项目的 `super-kernel/metadata` 使用其他构建协议时,构建会在写入任何内容之前停止,并说明该升级哪一方:SKERNEL(例如用 `skernel self-update`),或项目的 SuperKernel 包。没有 `super-kernel/metadata` 的项目早于由 SKERNEL 生成产物的做法,需要 SuperKernel 1.0.0-alpha.2 或更高版本。出现这种情况,或项目或依赖不存在、配置文件或 `--php` 的值无效、无法提供受管 PHP、构建失败时,会在 STDERR 上打印一条简短的提示,退出码为 1。

### package

Expand Down
11 changes: 9 additions & 2 deletions bin/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,17 @@

declare(strict_types=1);

use SKERNEL\Generator\Entry\SelfBuild;
use SuperKernel\Context\ApplicationContext;
use SuperKernel\Contract\ApplicationInterface;

require dirname(__DIR__) . '/vendor/autoload.php';

// Isolate startup in an immediately invoked static closure; never requires the flow to exit or throw.
(static fn(): never => ApplicationContext::getContainer()->get(ApplicationInterface::class)->run())();
// From source, SKERNEL generates the build artifacts its container restores, and another start from the same tree
// waits until they are restored; a PHAR carries them from its build.
$lock = '' === Phar::running(false) ? SelfBuild::run(dirname(__DIR__)) : null;
$container = ApplicationContext::getContainer();
$lock?->release();

// Isolate the application run in an immediately invoked static closure; never requires the flow to exit or throw.
(static fn(): never => $container->get(ApplicationInterface::class)->run())();
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"ext-zlib": "*",
"composer/semver": "^3.6.0",
"psr/log": "^3.0.2",
"super-kernel/annotator": "dev-main",
"super-kernel/attribute": "dev-main",
"super-kernel/command": "dev-main",
"super-kernel/context": "dev-main",
Expand All @@ -21,6 +22,7 @@
"super-kernel/exception-dispatcher": "dev-main",
"super-kernel/framework": "dev-main",
"super-kernel/logger": "dev-main",
"super-kernel/metadata": "dev-main",
"symfony/console": "^8.1.9",
"symfony/process": "^8.1.10"
},
Expand All @@ -30,6 +32,7 @@
},
"autoload": {
"psr-4": {
"SKERNEL\\Generator\\": "generator/src/",
"Src\\": "src/"
}
},
Expand Down
Loading
Loading