mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-02 22:35:43 +08:00
Update latest docs
This commit is contained in:
@@ -33,14 +33,14 @@ export default {
|
||||
items: [
|
||||
{ text: 'Get Started', link: '/en/develop/' },
|
||||
{ text: 'Project Structure', link: '/en/develop/structure' },
|
||||
{ text: 'PHP Source Modifications', link: '/en/develop/php-src-changes' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Concepts',
|
||||
items: [
|
||||
{ text: 'Registry', link: '/en/develop/registry' },
|
||||
{ text: 'Package Model', link: '/en/develop/package-model' },
|
||||
{ text: 'Registry & Plugin System', link: '/en/develop/registry' },
|
||||
{ text: 'Artifact Model', link: '/en/develop/artifact-model' },
|
||||
{ text: 'Build Lifecycle', link: '/en/develop/build-lifecycle' },
|
||||
],
|
||||
},
|
||||
@@ -58,11 +58,17 @@ export default {
|
||||
items: [
|
||||
{ text: 'Introduction', link: '/en/develop/vendor-mode/' },
|
||||
{ text: 'Writing Package Classes', link: '/en/develop/vendor-mode/package-classes' },
|
||||
{ text: 'Annotations Reference', link: '/en/develop/vendor-mode/annotations' },
|
||||
{ text: 'Dependency Injection', link: '/en/develop/vendor-mode/dependency-injection' },
|
||||
{ text: 'Annotations Reference', link: '/en/develop/vendor-mode/annotations' },
|
||||
{ text: 'Lifecycle Hooks', link: '/en/develop/vendor-mode/lifecycle-hooks' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Miscellaneous',
|
||||
items: [
|
||||
{ text: 'PHP Source Modifications', link: '/en/develop/php-src-changes' },
|
||||
],
|
||||
},
|
||||
],
|
||||
'/en/contributing/': [
|
||||
{
|
||||
|
||||
@@ -33,14 +33,14 @@ export default {
|
||||
items: [
|
||||
{ text: '开发简介', link: '/zh/develop/' },
|
||||
{ text: '项目结构', link: '/zh/develop/structure' },
|
||||
{ text: '对 PHP 源码的修改', link: '/zh/develop/php-src-changes' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '核心概念',
|
||||
items: [
|
||||
{ text: 'Package 模型', link: '/zh/develop/package-model' },
|
||||
{ text: 'Registry 与插件系统', link: '/zh/develop/registry' },
|
||||
{ text: 'Package 模型', link: '/zh/develop/package-model' },
|
||||
{ text: 'Artifact 模型', link: '/zh/develop/artifact-model' },
|
||||
{ text: '构建生命周期', link: '/zh/develop/build-lifecycle' },
|
||||
],
|
||||
},
|
||||
@@ -58,11 +58,17 @@ export default {
|
||||
items: [
|
||||
{ text: '简介', link: '/zh/develop/vendor-mode/' },
|
||||
{ text: '编写 Package 类', link: '/zh/develop/vendor-mode/package-classes' },
|
||||
{ text: '注解参考', link: '/zh/develop/vendor-mode/annotations' },
|
||||
{ text: '依赖注入', link: '/zh/develop/vendor-mode/dependency-injection' },
|
||||
{ text: '注解参考', link: '/zh/develop/vendor-mode/annotations' },
|
||||
{ text: '生命周期 Hook', link: '/zh/develop/vendor-mode/lifecycle-hooks' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '杂项',
|
||||
items: [
|
||||
{ text: '对 PHP 源码的修改', link: '/zh/develop/php-src-changes' },
|
||||
]
|
||||
}
|
||||
],
|
||||
'/zh/contributing/': [
|
||||
{
|
||||
|
||||
@@ -1,4 +1,49 @@
|
||||
# Start Developing
|
||||
# Developer Guide
|
||||
|
||||
<!-- TODO: Developer introduction, environment setup, required PHP extensions.
|
||||
Link to Vendor Mode for library authors, and Contributing for code contributors. -->
|
||||
This section covers the StaticPHP development workflow and the foundational knowledge needed to understand how StaticPHP works under the hood.
|
||||
|
||||
## Overview
|
||||
|
||||
StaticPHP is a binary build tool whose core purpose is managing the build pipeline — downloading and configuring PHP source code, resolving extension dependencies, and invoking the underlying build system (e.g., Docker or a local compiler).
|
||||
|
||||
From a development perspective, StaticPHP is an open framework that provides the ability to statically build PHP and other open-source tools together. The project is maintained by [@crazywhalecc](https://github.com/crazywhalecc) and [@henderkes](https://github.com/henderkes), with contributions from the community.
|
||||
|
||||
You can think of StaticPHP as a typical PHP CLI project built on [symfony/console](https://symfony.com/doc/current/components/console.html).
|
||||
|
||||
## Development Environment
|
||||
|
||||
To get started with StaticPHP development, you'll need a PHP development environment with the required dependencies installed.
|
||||
|
||||
Requirements:
|
||||
|
||||
- PHP 8.4 or later
|
||||
- Composer
|
||||
- Git
|
||||
- PHP extensions: `curl, dom, filter, mbstring, openssl, pcntl, phar, posix, sodium, tokenizer, xml, xmlwriter`
|
||||
|
||||
> These PHP extensions are required for StaticPHP's `dev` environment.
|
||||
|
||||
### Setup Steps
|
||||
|
||||
1. Clone the repository:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/crazywhalecc/static-php-cli.git
|
||||
cd static-php-cli
|
||||
```
|
||||
|
||||
2. Install PHP dependencies:
|
||||
|
||||
```bash
|
||||
composer install
|
||||
```
|
||||
|
||||
3. Verify the setup:
|
||||
|
||||
```bash
|
||||
bin/spc --version
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
You can continue reading [Project Structure](./structure) to learn more about StaticPHP's framework architecture.
|
||||
|
||||
@@ -1,6 +1,247 @@
|
||||
# Package Model
|
||||
|
||||
<!-- TODO: Explain the unified package model: library / php-extension / target types.
|
||||
Cover the per-package YAML format (config/pkg/), the `depends` field,
|
||||
platform overrides (@windows / @unix notation), artifact.source and artifact.binary.
|
||||
Show annotated example YAML for a library and an extension. -->
|
||||
## Package Definition
|
||||
|
||||
A Package is the core concept in StaticPHP's build system, representing a buildable/installable unit such as a PHP extension, library, or build target.
|
||||
|
||||
Each Package contains build information, dependencies, and build logic, forming StaticPHP's build model. Package definitions are primarily implemented through YAML/JSON configuration files. The package configuration files for the `core` registry are located in the `config/pkg/` directory, and the corresponding build classes are in the `src/Package/` directory.
|
||||
|
||||
Packages are primarily divided into four types:
|
||||
|
||||
- **php-extension**: A PHP extension package containing build information and logic for a PHP extension.
|
||||
- **library**: A library package containing build information and logic for build tools, dependency libraries, etc.
|
||||
- **target**: A build target package representing the final build artifact, such as a PHP binary or curl binary. Inherits from the `library` package type.
|
||||
- **virtual-target**: A virtual build target package representing an abstract build target that doesn't directly correspond to a build artifact, primarily used for dependency management and build scheduling.
|
||||
|
||||
```yaml
|
||||
{pkg-name}:
|
||||
type: {pkg-type}
|
||||
...
|
||||
```
|
||||
|
||||
## Artifact Definition
|
||||
|
||||
An Artifact is a definition independent of Packages. It contains the source archive file or pre-built binary for building packages. Each Artifact defines download URLs, extraction methods, and build artifact file paths. Packages can reference one or more Artifacts via the `artifact` field to obtain the source or binaries needed for building.
|
||||
|
||||
In simple terms, by default one Package corresponds to one Artifact; if multiple Packages share the same source, you can define a single Artifact for multiple Packages to reference. Artifact definitions are located in the `config/artifact/` directory, and the corresponding custom download/extract logic classes are in the `src/Package/Artifact/` directory. For special package types like virtual targets and PHP built-in extensions, a Package may also omit the Artifact field entirely.
|
||||
|
||||
Assuming `example-library-package` is a dependency library whose source archive is hosted at `https://example.com/example-library.tar.gz`, its Package and Artifact definitions would look like this:
|
||||
|
||||
```yaml
|
||||
example-library-package:
|
||||
type: library
|
||||
artifact:
|
||||
source:
|
||||
type: url
|
||||
url: 'https://example.com/example-library.tar.gz'
|
||||
```
|
||||
|
||||
For more on Artifact definitions, see the [Artifact Model](./artifact-model) chapter.
|
||||
|
||||
## php-extension Package Type
|
||||
|
||||
A php-extension package represents a PHP extension. Its configuration file is located in the `config/pkg/ext/` directory, and its build class inherits from `PhpExtensionPackage` in the `src/Package/Extension/` directory. PHP extension package configurations include extension name, version, dependencies, build options, and more.
|
||||
|
||||
```yaml
|
||||
ext-lz4:
|
||||
type: php-extension
|
||||
artifact:
|
||||
source:
|
||||
type: git
|
||||
url: 'https://github.com/kjdev/php-ext-lz4.git'
|
||||
rev: master
|
||||
extract: php-src/ext/lz4
|
||||
metadata:
|
||||
license-files: [LICENSE]
|
||||
license: MIT
|
||||
depends:
|
||||
- liblz4
|
||||
php-extension:
|
||||
arg-type@unix: '--enable-lz4=@shared_suffix@ --with-lz4-includedir=@build_root_path@'
|
||||
arg-type@windows: '--enable-lz4'
|
||||
```
|
||||
|
||||
Allowed fields for `php-extension`:
|
||||
|
||||
```yaml
|
||||
ext-{ext-name}: # Package name must start with ext- prefix
|
||||
type: php-extension
|
||||
|
||||
# ── Common Fields ────────────────────────────────────────────────────────
|
||||
description: '..' # Optional, human-readable package description
|
||||
lang: c # Optional, implementation language of the extension (c / c++ etc.)
|
||||
frameworks: [] # Optional, list of related macOS framework dependencies
|
||||
|
||||
artifact: '{artifact-name}' # Optional; when a string, references an Artifact definition
|
||||
# with the same name; when an object, is an inline Artifact
|
||||
# (built-in extensions don't need this field)
|
||||
|
||||
# depends / suggests support @windows / @unix / @linux / @macos suffixes
|
||||
depends: [] # Optional, hard dependency list (library names as-is, PHP extensions need ext- prefix)
|
||||
depends@unix: [] # Optional, hard dependencies only effective on Unix platforms
|
||||
depends@windows: [] # Optional, hard dependencies only effective on Windows platforms
|
||||
suggests: [] # Optional, optional dependency list (same format as depends)
|
||||
suggests@unix: []
|
||||
|
||||
# ── php-extension Specific Fields (nested under php-extension: object) ────
|
||||
php-extension:
|
||||
# arg-type determines the form of arguments passed to ./configure, supports platform suffixes
|
||||
# Supported platform suffixes: @unix (Linux + macOS), @linux, @macos, @windows
|
||||
# Priority (using Linux as example): arg-type@linux > arg-type@unix > arg-type (no suffix)
|
||||
# Built-in keywords:
|
||||
# enable → --enable-{extname} (default value, used when not configured)
|
||||
# enable-path → --enable-{extname}={buildroot}
|
||||
# with → --with-{extname}
|
||||
# with-path → --with-{extname}={buildroot}
|
||||
# custom/none → Pass no arguments (handled by the #[CustomPhpConfigureArg] method in the PHP class)
|
||||
# You can also write the full argument string directly, supporting the following placeholders:
|
||||
# @build_root_path@ → BUILD_ROOT_PATH (absolute path of buildroot)
|
||||
# @shared_suffix@ → Expands to =shared in shared builds, empty in static builds
|
||||
# @shared_path_suffix@ → Expands to =shared,{buildroot} in shared builds,
|
||||
# expands to ={buildroot} in static builds
|
||||
arg-type: enable
|
||||
arg-type@unix: '--enable-{extname}=@shared_suffix@'
|
||||
arg-type@windows: with-path
|
||||
|
||||
zend-extension: false # Optional, true indicates this is a Zend extension (e.g., opcache, xdebug)
|
||||
build-shared: true # Optional, whether building as a shared extension (.so) is allowed, default true
|
||||
build-static: true # Optional, whether inline static building (compiled into PHP) is allowed, default true
|
||||
build-with-php: true # Optional, true means the extension is built together via the PHP source tree
|
||||
# (used for built-in extensions)
|
||||
|
||||
# display-name affects the php --ri argument in smoke tests and the license export display name
|
||||
# If not set, defaults to the extension name (the part after ext-); if set to empty string, skips --ri check
|
||||
display-name: 'My Extension'
|
||||
|
||||
# os restricts the extension to be available only on specified platforms;
|
||||
# platforms not in the list will be rejected for building
|
||||
# Allowed values: Linux, Darwin, Windows
|
||||
os: [Linux, Darwin]
|
||||
```
|
||||
|
||||
## library Package Type
|
||||
|
||||
A library package represents a dependency library that needs to be compiled from source (such as openssl, zlib, etc.). Its configuration file is located in the `config/pkg/lib/` directory, and its build class inherits from `LibraryPackage` in the `src/Package/Library/` directory.
|
||||
|
||||
Taking openssl as an example:
|
||||
|
||||
```yaml
|
||||
openssl:
|
||||
type: library
|
||||
artifact:
|
||||
source:
|
||||
type: ghrel
|
||||
repo: openssl/openssl
|
||||
match: openssl.+\.tar\.gz
|
||||
prefer-stable: true
|
||||
binary: hosted
|
||||
metadata:
|
||||
license-files: [LICENSE.txt]
|
||||
license: OpenSSL
|
||||
depends:
|
||||
- zlib
|
||||
depends@windows:
|
||||
- zlib
|
||||
- jom
|
||||
headers:
|
||||
- openssl
|
||||
static-libs@unix:
|
||||
- libssl.a
|
||||
- libcrypto.a
|
||||
static-libs@windows:
|
||||
- libssl.lib
|
||||
- libcrypto.lib
|
||||
```
|
||||
|
||||
Allowed fields for `library`:
|
||||
|
||||
```yaml
|
||||
{lib-name}:
|
||||
type: library # library or target (target inherits all fields from library)
|
||||
|
||||
# ── Common Fields ─────────────────────────────────────────────────────────
|
||||
description: '..' # Optional, human-readable package description
|
||||
license: MIT # Optional, SPDX license identifier (for license export)
|
||||
lang: c # Optional, implementation language of the library (c / c++ etc.)
|
||||
frameworks: [] # Optional, list of related framework tags
|
||||
|
||||
artifact: '{artifact-name}' # Required; when a string, references an Artifact definition
|
||||
# with the same name; when an object, is an inline Artifact
|
||||
|
||||
# depends / suggests support @windows / @unix / @linux / @macos suffixes
|
||||
depends: [] # Optional, hard dependency list (library names or PHP extension names with ext- prefix)
|
||||
depends@unix: []
|
||||
depends@windows: []
|
||||
suggests: [] # Optional, optional dependency list (same format as depends)
|
||||
|
||||
# ── library / target Specific Fields ───────────────────────────────────────
|
||||
# The following fields are used to verify that artifacts have been correctly
|
||||
# installed after the build. They support @unix / @windows / @linux / @macos suffixes.
|
||||
|
||||
# Verify that specified header files or directories exist under buildroot/include/
|
||||
# Relative paths are based on buildroot/include/, absolute paths are used directly
|
||||
headers:
|
||||
- openssl # Corresponds to buildroot/include/openssl/
|
||||
- zlib.h # Corresponds to buildroot/include/zlib.h
|
||||
headers@unix:
|
||||
- ffi.h
|
||||
|
||||
# Verify that specified static library files exist under buildroot/lib/
|
||||
# Relative paths are based on buildroot/lib/, absolute paths are used directly
|
||||
static-libs@unix:
|
||||
- libssl.a
|
||||
static-libs@windows:
|
||||
- libssl.lib
|
||||
|
||||
# Verify that specified .pc files exist under buildroot/lib/pkgconfig/
|
||||
# Only checked on non-Windows platforms (pkg-config is not applicable on Windows)
|
||||
pkg-configs:
|
||||
- openssl # Corresponds to buildroot/lib/pkgconfig/openssl.pc
|
||||
- libssl # Auto-completes .pc suffix
|
||||
|
||||
# Verify that specified executable files exist under buildroot/bin/
|
||||
# Relative paths are based on buildroot/bin/, absolute paths are used directly
|
||||
static-bins:
|
||||
- my-tool
|
||||
|
||||
# List of directories injected into the global PATH after the package is installed.
|
||||
# Path placeholders are supported (see below for details).
|
||||
path:
|
||||
- '{pkg_root_path}/rust/bin'
|
||||
|
||||
# Environment variables set after the package is installed (overwrites existing values).
|
||||
# Path placeholders are supported.
|
||||
env:
|
||||
MY_VAR: '{build_root_path}/lib'
|
||||
|
||||
# Values appended to the end of existing environment variables after the package is installed.
|
||||
# Path placeholders are supported.
|
||||
append-env:
|
||||
CFLAGS: ' -I{build_root_path}/include'
|
||||
```
|
||||
|
||||
The following path placeholders are supported in string values of the `path`, `env`, and `append-env` fields:
|
||||
|
||||
| Placeholder | Actual Path |
|
||||
|---|---|
|
||||
| `{build_root_path}` | buildroot directory (`buildroot/`) |
|
||||
| `{pkg_root_path}` | pkgroot directory (`pkgroot/`) |
|
||||
| `{working_dir}` | Working directory (project root) |
|
||||
| `{download_path}` | Download cache directory (`downloads/`) |
|
||||
| `{source_path}` | Extracted source directory (`source/`) |
|
||||
| `{php_sdk_path}` | Windows PHP SDK directory |
|
||||
|
||||
## target Package Type
|
||||
|
||||
A `target` package represents a final build artifact. It inherits from `library`, so it includes all definition fields of `library`. The configuration file for `target` packages is located in the `config/pkg/target/` directory, and its build class inherits from `TargetPackage` in the `src/Package/Target/` directory.
|
||||
|
||||
The only difference from `library` is that a `target` package can be registered as a build target and automatically registers the build command `spc build:{target-name}`.
|
||||
|
||||
## virtual-target Package Type
|
||||
|
||||
Unlike `target`, a `virtual-target` may not include an `artifact`, meaning it doesn't directly correspond to a buildable entity but is instead an abstract build target, primarily used for dependency management and build scheduling. The configuration file for `virtual-target` is located in the `config/pkg/target/` directory, and its build class inherits from `TargetPackage` in the `src/Package/Target/` directory. Its definition is essentially the same as `target`, but the `artifact` field is optional and typically not set. `virtual-target` is primarily used in the following scenarios:
|
||||
|
||||
- Defining an abstract build target for other packages to depend on, without directly corresponding to a buildable entity.
|
||||
- Serving as a common dependency for multiple `target` packages, simplifying dependency management.
|
||||
|
||||
A typical example is the `php-cli`, `php-fpm` build targets for PHP. They have no independent source code and depend on `php-src`, with the final build outcome (CLI or FPM binary) determined through build scheduling.
|
||||
|
||||
@@ -1,6 +1,81 @@
|
||||
# Registry & Plugin System
|
||||
|
||||
<!-- TODO: Explain spc.registry.yml structure.
|
||||
How to add an external registry via SPC_REGISTRIES env var.
|
||||
Vendor-specific configurations, overriding core packages.
|
||||
Registry resolution order and conflict rules. -->
|
||||
## Overview
|
||||
|
||||
The **Registry** is StaticPHP's core extension mechanism. Think of it as a "plugin package": a Registry consists of a declaration file (`spc.registry.yml`) and the configuration files and PHP classes it points to, describing a set of package definitions (YAML configuration) and their corresponding build logic (PHP classes). The build system loads all registered Registries at startup and merges their package definitions for use throughout the entire build process.
|
||||
|
||||
StaticPHP ships with a built-in core registry (`core`) that contains all definitions for PHP and related extensions, libraries, build tools, and more. The declaration file for the `core` registry is `spc.registry.yml` in the project root, which describes the mapping between the configuration file directory (`config/pkg/`, `config/artifact/`) and the build class PSR-4 namespace (`src/Package/`).
|
||||
|
||||
External Registries can only define new packages that don't already exist in `core`; they cannot override or modify existing definitions in the core registry. Depending on your needs, there are three ways to extend or modify StaticPHP's build capabilities:
|
||||
|
||||
- **Modify the `core` registry**: Directly edit files under `src/Package` and `config/pkg/`, suitable when you want to contribute changes back to the StaticPHP mainline. Please read the [Contributing Guide](../contributing/) section on contributing new packages before submitting a PR.
|
||||
- **Vendor Mode**: Package your custom packages as a standalone sub-registry distributed as a Composer package, suitable for private packages or scenarios where you want to reuse build logic as a library. See [Vendor Mode](./vendor-mode/) for details.
|
||||
- **External Registry (`SPC_REGISTRIES`)**: Specify one or more external registry file paths via the `SPC_REGISTRIES` environment variable, which StaticPHP loads at startup. Suitable for temporary extensions or scenarios where packaging as a Composer package isn't practical, similar to external source mechanisms in other package managers.
|
||||
|
||||
## Registry Declaration File
|
||||
|
||||
Each Registry has a declaration file, typically named `spc.registry.yml`, located in the project root or the root of a Composer package. The file format supports YAML (`.yml` / `.yaml`) and JSON (`.json`). All paths within the file are resolved relative to the directory containing the declaration file itself.
|
||||
|
||||
In source mode (direct git clone), StaticPHP loads `spc.registry.yml` in the project root as the core registry (`core`) by default. In Vendor mode, it automatically detects whether `spc.registry.yml` exists in the current Composer package root and loads it as a standalone registry. External registries specified via the `SPC_REGISTRIES` environment variable must also contain a valid declaration file.
|
||||
|
||||
Below is a complete example with all available fields (based on the `core` registry):
|
||||
|
||||
```yaml
|
||||
# [Required] Unique registry name; loading a registry with a duplicate name is automatically skipped
|
||||
name: my-registry
|
||||
|
||||
# [Optional] Composer autoload file path, used when an external registry has its own dependencies
|
||||
autoload: vendor/autoload.php
|
||||
|
||||
# Package (library / php-extension / target) related configuration
|
||||
package:
|
||||
# YAML configuration file directory or specific file paths for packages, can be an array
|
||||
config:
|
||||
- config/pkg/lib/
|
||||
- config/pkg/target/
|
||||
- config/pkg/ext/
|
||||
# PSR-4 namespace → directory path mapping for package build classes; the loader scans all PHP classes in the directory
|
||||
psr-4:
|
||||
Package: src/Package
|
||||
# You can also load specific classes as needed, supporting array format or {"ClassName": "file path"} mapping
|
||||
# classes:
|
||||
# - Package\Library\MyLib
|
||||
# MyLib: src/Package/Library/MyLib.php
|
||||
|
||||
# Artifact (build artifact) related configuration
|
||||
artifact:
|
||||
# YAML configuration file directory or specific file paths for artifacts
|
||||
config:
|
||||
- config/artifact/
|
||||
# PSR-4 namespace → directory path mapping for custom artifact download/extract classes
|
||||
psr-4:
|
||||
Package\Artifact: src/Package/Artifact
|
||||
# classes: ... (same format as package.classes)
|
||||
|
||||
# Doctor environment check configuration
|
||||
doctor:
|
||||
# PSR-4 namespace → directory path mapping for Doctor check item classes
|
||||
psr-4:
|
||||
StaticPHP\Doctor\Item: src/StaticPHP/Doctor/Item
|
||||
# classes: ... (same format as package.classes)
|
||||
|
||||
# Additional CLI command configuration
|
||||
command:
|
||||
# PSR-4 namespace → directory path mapping for custom command classes
|
||||
psr-4:
|
||||
Package\Command: src/Package\Command
|
||||
# classes: ... (same format as package.classes)
|
||||
```
|
||||
|
||||
Top-level field descriptions:
|
||||
|
||||
| Field | Required | Description |
|
||||
|---|---|---|
|
||||
| `name` | ✅ | Unique registry name; loading a registry with a duplicate name is automatically skipped |
|
||||
| `autoload` | | Composer autoload file path, for external registries that carry their own dependencies |
|
||||
| `package` | | Package definition, including YAML config (`config`) and build classes (`psr-4` / `classes`) |
|
||||
| `artifact` | | Artifact definition, including YAML config (`config`) and custom classes (`psr-4` / `classes`) |
|
||||
| `doctor` | | Doctor check item definition, class loading only (`psr-4` / `classes`) |
|
||||
| `command` | | Additional CLI command definition, class loading only (`psr-4` / `classes`) |
|
||||
|
||||
The difference between `psr-4` and `classes`: `psr-4` scans all PHP classes in the entire directory that match the namespace rules and registers them in bulk; `classes` is used to precisely specify individual classes, supporting plain array format (`["ClassName"]`, must already be available in autoload) or key-value mapping format (`{"ClassName": "path/to/file.php"}`, the loader will automatically `require` the corresponding file).
|
||||
|
||||
@@ -1,5 +1,84 @@
|
||||
# Project Structure
|
||||
|
||||
<!-- TODO: v3 directory layout (bin/, config/pkg/, src/StaticPHP/, src/Package/, etc.).
|
||||
Explain the role of each top-level directory. Internal class structure kept brief;
|
||||
deep dives belong in the Concepts pages. -->
|
||||
## Concepts
|
||||
|
||||
StaticPHP is a CLI application built on `symfony/console`, with core code located in the `src/StaticPHP` directory. It is organized into several modules:
|
||||
|
||||
- **Registry**: Manages registry data. Each registry contains multiple packages (Package), and the StaticPHP project ships with a built-in `core` registry that includes PHP and related extensions, dependencies, and more.
|
||||
- **Package**: Represents a single package. There are four package types: `php-extension` (PHP extension), `library` (library), `target` (build target), and `virtual-target` (virtual build target). Each package contains build information, dependencies, and more.
|
||||
- **Installer/Builder**: Handles installation and build logic for packages — executing build commands, extracting build artifacts, processing build results, etc.
|
||||
- **Doctor**: Provides system environment checking, responsible for installing and verifying system-level dependencies such as `make`, `cmake`, `autoconf`, and more.
|
||||
- **Runtime/Executor**: Contains runtime-related utility classes, such as shell command execution and CMake build execution.
|
||||
- **Toolchain**: Provides toolchain abstraction interfaces for different operating systems and environments, handling system-level differences during the build process.
|
||||
- **Utils**: General-purpose utility classes, such as file system operations, logging, and OS-specific helper methods.
|
||||
- **DependencyResolver**: Resolves dependencies between packages and generates build order.
|
||||
|
||||
## Directory Layout
|
||||
|
||||
```
|
||||
static-php-cli/
|
||||
├── bin/ # Executable entry scripts (spc, spc.ps1, setup-runtime, etc.)
|
||||
├── config/
|
||||
│ ├── env.ini # Default environment variable configuration
|
||||
│ ├── env.custom.ini # User-defined environment variables (overrides env.ini)
|
||||
│ ├── artifact/ # Build artifact configuration (toolchain downloads, pre-built binaries, etc.)
|
||||
│ └── pkg/ # Package configuration files (YAML)
|
||||
│ ├── ext/ # PHP extension package config (ext-*.yml, builtin-extensions.yml)
|
||||
│ ├── lib/ # Library package config (*.yml)
|
||||
│ └── target/ # Build target config (php.yml, curl.yml, etc.)
|
||||
├── src/
|
||||
│ ├── bootstrap.php # Application bootstrap (auto-loading, DI container, etc.)
|
||||
│ ├── globals/ # Global helper functions
|
||||
│ ├── Package/ # Build logic implementations for each package (PHP classes)
|
||||
│ │ ├── Artifact/ # Custom download/extract logic for build artifacts
|
||||
│ │ ├── Command/ # Package-level custom commands
|
||||
│ │ ├── Extension/ # PHP extension build classes (ext-*.php)
|
||||
│ │ ├── Library/ # Library build classes (*.php)
|
||||
│ │ └── Target/ # Build target classes (php.php, curl.php, etc.)
|
||||
│ └── StaticPHP/ # Framework core code
|
||||
│ ├── ConsoleApplication.php # Symfony Console application entry
|
||||
│ ├── Artifact/ # Build artifact download and extraction (Downloader, Extractor, etc.)
|
||||
│ ├── Attribute/ # PHP attribute definitions
|
||||
│ │ ├── Artifact/ # Artifact-related attributes (CustomSource, BinaryExtract, etc.)
|
||||
│ │ ├── Doctor/ # Doctor-related attributes (CheckItem, FixItem, etc.)
|
||||
│ │ └── Package/ # Package build-related attributes (BuildFor, BeforeStage, AfterStage,
|
||||
│ │ # CustomPhpConfigureArg, PatchBeforeBuild, etc.)
|
||||
│ ├── Command/ # CLI command implementations (build-libs, build-target, doctor, etc.)
|
||||
│ ├── Config/ # Configuration loading and validation (PackageConfig, ArtifactConfig, etc.)
|
||||
│ ├── DI/ # Dependency injection container (ApplicationContext, CallbackInvoker, etc.)
|
||||
│ ├── Doctor/ # System environment checking and fixing (Doctor, CheckResult)
|
||||
│ ├── Exception/ # Custom exception classes
|
||||
│ ├── Package/ # Core package models and build scheduling
|
||||
│ │ ├── Package.php # Base package class
|
||||
│ │ ├── LibraryPackage.php # Library package type
|
||||
│ │ ├── PhpExtensionPackage.php # PHP extension package type
|
||||
│ │ ├── TargetPackage.php # Build target package type
|
||||
│ │ ├── PackageInstaller.php # Package installer (download, extract source)
|
||||
│ │ └── PackageBuilder.php # Package builder (execute build pipeline)
|
||||
│ ├── Registry/ # Registry management (Registry, PackageLoader, ArtifactLoader)
|
||||
│ ├── Runtime/ # Runtime utilities
|
||||
│ │ ├── Executor/ # Command executors (UnixAutoconfExecutor, UnixCMakeExecutor,
|
||||
│ │ │ # WindowsCMakeExecutor, Executor base class)
|
||||
│ │ ├── Shell/ # Shell abstraction (UnixShell, WindowsCmd, etc.)
|
||||
│ │ └── SystemTarget.php # System target information
|
||||
│ ├── Toolchain/ # Toolchain abstraction (GccNative, Musl, MSVC, Zig, ClangBrew, etc.)
|
||||
│ └── Util/ # General utility classes
|
||||
│ ├── System/ # OS platform utilities (LinuxUtil, MacOSUtil, WindowsUtil, etc.)
|
||||
│ ├── BuildRootTracker.php # buildroot file tracking
|
||||
│ ├── DependencyResolver.php # Dependency resolution and build order
|
||||
│ ├── FileSystem.php # File system operations
|
||||
│ ├── GlobalEnvManager.php # Global environment variable management
|
||||
│ ├── InteractiveTerm.php # Interactive terminal output
|
||||
│ ├── LicenseDumper.php # License export
|
||||
│ ├── PkgConfigUtil.php # pkg-config utility wrapper
|
||||
│ ├── SourcePatcher.php # Source code patching utility
|
||||
│ └── SPCConfigUtil.php # SPC configuration reader
|
||||
├── tests/ # Unit tests and integration tests
|
||||
├── downloads/ # Download cache directory (source packages, pre-built binaries)
|
||||
├── source/ # Extracted source code directory
|
||||
├── buildroot/ # Build output directory (headers, static libraries, etc.)
|
||||
├── pkgroot/ # Platform-archived build artifacts
|
||||
└── spc.registry.yml # core registry definition file
|
||||
```
|
||||
|
||||
Note that the classes in `src/Package` are responsible for implementing the build logic of specific packages, while the classes in `src/StaticPHP` provide the core functionality of the build framework, such as command scheduling, environment checking, and toolchain abstraction. The two are decoupled: `src/Package` corresponds to the packages in the `core` registry (including PHP, extensions, libraries, and build targets), while `src/StaticPHP` is the infrastructure that supports build needs across different registries and packages.
|
||||
|
||||
@@ -1,4 +1,48 @@
|
||||
# 开发简介
|
||||
|
||||
<!-- TODO: 开发者简介、环境准备、所需 PHP 扩展。
|
||||
Vendor 模式链接到 vendor-mode/,代码贡献链接到 contributing/。 -->
|
||||
本章节将介绍 StaticPHP 的开发流程,以及了解 StaticPHP 内部工作原理所需的基础知识。
|
||||
|
||||
## 概述
|
||||
|
||||
StaticPHP 是一个静态二进制的构建工具,核心功能是管理构建流程,包括下载和配置 PHP 源码、处理扩展依赖、调用底层构建系统(如 Docker 或本地编译器)等。
|
||||
|
||||
从开发的角度来看,StaticPHP 本身是一个开放的框架,它提供了静态构建包括 PHP 在内的各种开源工具的能力。项目主要由 [@crazywhalecc](https://github.com/crazywhalecc) 和 [@henderkes](https://github.com/henderkes) 维护,由广大社区成员贡献代码、完善构建脚本和修复问题。
|
||||
|
||||
你可以将 StaticPHP 当作一个典型的 PHP 开发的 CLI 项目来看待,它使用了 [symfony/console](https://symfony.com/doc/current/components/console.html) 来构建命令行界面。
|
||||
|
||||
## 开发环境
|
||||
|
||||
要开始开发 StaticPHP,你需要设置一个 PHP 开发环境,安装必要的依赖,并了解项目的构建流程。
|
||||
|
||||
StaticPHP 的开发环境要求如下:
|
||||
|
||||
- PHP 8.4 或更高版本
|
||||
- Composer
|
||||
- Git
|
||||
- PHP 扩展:`curl,dom,filter,mbstring,openssl,pcntl,phar,posix,sodium,tokenizer,xml,xmlwriter`
|
||||
|
||||
> 这些 PHP 扩展是 StaticPHP 的 `dev` 环境依赖。
|
||||
|
||||
以下是一些基本步骤:
|
||||
|
||||
1. 克隆项目代码:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/crazywhalecc/static-php-cli.git
|
||||
cd static-php-cli
|
||||
```
|
||||
2. 安装 PHP 依赖:
|
||||
|
||||
```bash
|
||||
composer install
|
||||
```
|
||||
|
||||
3. 运行测试:
|
||||
|
||||
```bash
|
||||
bin/spc --version
|
||||
```
|
||||
|
||||
------------------------------
|
||||
|
||||
你可以继续阅读 [项目结构](./structure) 来深入了解 StaticPHP 的框架结构。
|
||||
|
||||
@@ -3,3 +3,239 @@
|
||||
<!-- TODO: 统一 Package 模型说明:library / php-extension / target 类型。
|
||||
config/pkg/ 下 per-package YAML 格式、depends 字段、平台覆盖(@windows / @unix 写法)。
|
||||
artifact.source 和 artifact.binary 字段。附注释的 library 和 extension YAML 示例。 -->
|
||||
## Package 定义
|
||||
|
||||
Package 是 StaticPHP 构建系统中的核心概念,代表一个可构建/可安装的单元,如 PHP 扩展、库、构建目标等。
|
||||
|
||||
每个 Package 包含构建信息、依赖关系、构建逻辑等,构成了 StaticPHP 的构建模型。Package 的定义主要通过 YAML/JSON 配置文件来实现。`core` 注册表的包配置文件位于 `config/pkg/` 目录下,对应的构建类位于 `src/Package/` 目录下。
|
||||
|
||||
Package 主要分为四种类型:
|
||||
|
||||
- **php-extension**:PHP 扩展包,包含 PHP 扩展的构建信息和构建逻辑。
|
||||
- **library**:库包,包含构建工具链、依赖库等的构建信息和构建逻辑。
|
||||
- **target**:构建目标包,代表最终的构建产物,如 PHP 二进制、curl 二进制等,继承自 `library` 包类型。
|
||||
- **virtual-target**:虚构建目标包,代表一个抽象的构建目标,不直接对应构建产物,主要用于依赖管理和构建调度。
|
||||
|
||||
```yaml
|
||||
{pkg-name}:
|
||||
type: {pkg-type}
|
||||
...
|
||||
```
|
||||
|
||||
## Artifact 定义
|
||||
|
||||
Artifact 是独立于 Package 的定义,它包含构建包的源码归档文件或预构建的二进制文件。每个 Artifact 定义了下载 URL、解压方式、构建产物的文件路径等信息。Package 可以通过 `artifact` 字段引用一个或多个 Artifact 来获取构建所需的源码或二进制文件。
|
||||
|
||||
简单来说,默认情况下,一个 Package 对应一个 Artifact;如果多个 Package 共用一份源码时,可以定义一个 Artifact 供多个 Package 引用。Artifact 的定义位于 `config/artifact/` 目录下,对应的自定义下载/解压逻辑类位于 `src/Package/Artifact/` 目录下;对于虚拟目标、PHP 内置扩展等特殊包类型,Package 也可以不设置 Artifact 字段。
|
||||
|
||||
我们假设 `example-library-package` 是一个依赖库,它的源码归档文件托管在 `https://example.com/example-library.tar.gz`,则它的 Package 定义和 Artifact 定义可以如下所示:
|
||||
|
||||
```yaml
|
||||
example-library-package:
|
||||
type: library
|
||||
artifact:
|
||||
source:
|
||||
type: url
|
||||
url: 'https://example.com/example-library.tar.gz'
|
||||
```
|
||||
|
||||
更多有关 Artifact 定义的内容,请参阅 [Artifact 模型](./artifact-model) 章节。
|
||||
|
||||
## php-extension 包类型
|
||||
|
||||
php-extension 一个包代表一个 PHP 扩展,它的配置文件位于 `config/pkg/ext/` 目录下,构建类继承自 `PhpExtensionPackage`,位于 `src/Package/Extension/` 目录下。PHP 扩展包的配置文件包含扩展名称、版本、依赖关系、构建选项等信息。
|
||||
|
||||
```yaml
|
||||
ext-lz4:
|
||||
type: php-extension
|
||||
artifact:
|
||||
source:
|
||||
type: git
|
||||
url: 'https://github.com/kjdev/php-ext-lz4.git'
|
||||
rev: master
|
||||
extract: php-src/ext/lz4
|
||||
metadata:
|
||||
license-files: [LICENSE]
|
||||
license: MIT
|
||||
depends:
|
||||
- liblz4
|
||||
php-extension:
|
||||
arg-type@unix: '--enable-lz4=@shared_suffix@ --with-lz4-includedir=@build_root_path@'
|
||||
arg-type@windows: '--enable-lz4'
|
||||
```
|
||||
|
||||
`php-extension` 允许的定义字段:
|
||||
|
||||
```yaml
|
||||
ext-{ext-name}: # 包名必须以 ext- 前缀开头
|
||||
type: php-extension
|
||||
|
||||
# ── 通用字段 ─────────────────────────────────────────────────────────────
|
||||
description: '...' # 可选,人类可读的包描述
|
||||
lang: c # 可选,扩展的实现语言(c / c++ 等)
|
||||
frameworks: [] # 可选,相关macOS框架依赖列表
|
||||
|
||||
artifact: '{artifact-name}' # 可选;字符串时引用同名 Artifact 定义,
|
||||
# 对象时为内联 Artifact(内置扩展无需此字段)
|
||||
|
||||
# depends / suggests 支持 @windows / @unix / @linux / @macos 后缀
|
||||
depends: [] # 可选,硬依赖列表(库名直接写,PHP 扩展需加 ext- 前缀)
|
||||
depends@unix: [] # 可选,仅 Unix 平台生效的硬依赖
|
||||
depends@windows: [] # 可选,仅 Windows 平台生效的硬依赖
|
||||
suggests: [] # 可选,可选依赖列表(格式同 depends)
|
||||
suggests@unix: []
|
||||
|
||||
# ── php-extension 专属字段(嵌套在 php-extension: 对象中)─────────────────
|
||||
php-extension:
|
||||
# arg-type 决定传递给 ./configure 的参数形式,支持平台后缀
|
||||
# 支持的平台后缀:@unix(Linux + macOS)、@linux、@macos、@windows
|
||||
# 优先级(以 Linux 为例):arg-type@linux > arg-type@unix > arg-type(无后缀)
|
||||
# 内置关键字:
|
||||
# enable → --enable-{extname}(默认值,未配置时使用)
|
||||
# enable-path → --enable-{extname}={buildroot}
|
||||
# with → --with-{extname}
|
||||
# with-path → --with-{extname}={buildroot}
|
||||
# custom/none → 不传递任何参数(由 PHP 类的 #[CustomPhpConfigureArg] 方法处理)
|
||||
# 也可直接写完整参数字符串,支持以下占位符:
|
||||
# @build_root_path@ → BUILD_ROOT_PATH(buildroot 绝对路径)
|
||||
# @shared_suffix@ → 共享构建时展开为 =shared,静态构建时为空
|
||||
# @shared_path_suffix@ → 共享构建时展开为 =shared,{buildroot},静态构建时为 ={buildroot}
|
||||
arg-type: enable
|
||||
arg-type@unix: '--enable-{extname}=@shared_suffix@'
|
||||
arg-type@windows: with-path
|
||||
|
||||
zend-extension: false # 可选,true 表示这是 Zend 扩展(如 opcache、xdebug)
|
||||
build-shared: true # 可选,是否允许构建为共享扩展(.so),默认 true
|
||||
build-static: true # 可选,是否允许内联静态构建(编译进 PHP),默认 true
|
||||
build-with-php: true # 可选,true 表示该扩展通过 PHP 源码树一同编译(内置扩展使用)
|
||||
|
||||
# display-name 影响 smoke test 中 php --ri 的参数及许可证导出显示名称
|
||||
# 不填时默认使用扩展名(ext- 后缀部分);填空字符串则跳过 --ri 检查
|
||||
display-name: 'My Extension'
|
||||
|
||||
# os 限制该扩展仅在指定平台上可用,不在列表内的平台会拒绝构建
|
||||
# 可选值:Linux、Darwin、Windows
|
||||
os: [Linux, Darwin]
|
||||
```
|
||||
|
||||
## library 包类型
|
||||
|
||||
library 包代表一个需要从源码编译的依赖库(如 openssl、zlib 等),其配置文件位于 `config/pkg/lib/` 目录下,构建类继承自 `LibraryPackage`,位于 `src/Package/Library/` 目录下。
|
||||
|
||||
以 openssl 为例:
|
||||
|
||||
```yaml
|
||||
openssl:
|
||||
type: library
|
||||
artifact:
|
||||
source:
|
||||
type: ghrel
|
||||
repo: openssl/openssl
|
||||
match: openssl.+\.tar\.gz
|
||||
prefer-stable: true
|
||||
binary: hosted
|
||||
metadata:
|
||||
license-files: [LICENSE.txt]
|
||||
license: OpenSSL
|
||||
depends:
|
||||
- zlib
|
||||
depends@windows:
|
||||
- zlib
|
||||
- jom
|
||||
headers:
|
||||
- openssl
|
||||
static-libs@unix:
|
||||
- libssl.a
|
||||
- libcrypto.a
|
||||
static-libs@windows:
|
||||
- libssl.lib
|
||||
- libcrypto.lib
|
||||
```
|
||||
|
||||
`library` 允许的定义字段:
|
||||
|
||||
```yaml
|
||||
{lib-name}:
|
||||
type: library # library 或 target(target 继承 library 的所有字段)
|
||||
|
||||
# ── 通用字段 ─────────────────────────────────────────────────────────────
|
||||
description: '...' # 可选,人类可读的包描述
|
||||
license: MIT # 可选,SPDX 许可证标识符(用于许可证导出)
|
||||
lang: c # 可选,库的实现语言(c / c++ 等)
|
||||
frameworks: [] # 可选,相关框架标签列表
|
||||
|
||||
artifact: '{artifact-name}' # 必填;字符串时引用同名 Artifact 定义,对象时为内联 Artifact
|
||||
|
||||
# depends / suggests 支持 @windows / @unix / @linux / @macos 后缀
|
||||
depends: [] # 可选,硬依赖列表(库名或 ext- 前缀的 PHP 扩展名)
|
||||
depends@unix: []
|
||||
depends@windows: []
|
||||
suggests: [] # 可选,可选依赖列表(格式同 depends)
|
||||
|
||||
# ── library / target 专属字段 ────────────────────────────────────────────
|
||||
# 以下字段用于构建完成后验证产物是否已正确安装,支持 @unix / @windows / @linux / @macos 后缀
|
||||
|
||||
# 验证 buildroot/include/ 下是否存在指定头文件或目录
|
||||
# 相对路径基于 buildroot/include/,绝对路径直接使用
|
||||
headers:
|
||||
- openssl # 对应 buildroot/include/openssl/
|
||||
- zlib.h # 对应 buildroot/include/zlib.h
|
||||
headers@unix:
|
||||
- ffi.h
|
||||
|
||||
# 验证 buildroot/lib/ 下是否存在指定静态库文件
|
||||
# 相对路径基于 buildroot/lib/,绝对路径直接使用
|
||||
static-libs@unix:
|
||||
- libssl.a
|
||||
static-libs@windows:
|
||||
- libssl.lib
|
||||
|
||||
# 验证 buildroot/lib/pkgconfig/ 下是否存在指定 .pc 文件
|
||||
# 仅在非 Windows 平台检查(pkg-config 在 Windows 上不适用)
|
||||
pkg-configs:
|
||||
- openssl # 对应 buildroot/lib/pkgconfig/openssl.pc
|
||||
- libssl # 自动补全 .pc 后缀
|
||||
|
||||
# 验证 buildroot/bin/ 下是否存在指定可执行文件
|
||||
# 相对路径基于 buildroot/bin/,绝对路径直接使用
|
||||
static-bins:
|
||||
- my-tool
|
||||
|
||||
# 包安装完成后注入到全局 PATH 的目录列表,支持路径占位符(见下方说明)
|
||||
path:
|
||||
- '{pkg_root_path}/rust/bin'
|
||||
|
||||
# 包安装完成后设置的环境变量(覆盖已有值),支持路径占位符
|
||||
env:
|
||||
MY_VAR: '{build_root_path}/lib'
|
||||
|
||||
# 包安装完成后追加到已有环境变量末尾的值,支持路径占位符
|
||||
append-env:
|
||||
CFLAGS: ' -I{build_root_path}/include'
|
||||
```
|
||||
|
||||
`path`、`env`、`append-env` 字段的字符串值中支持以下路径占位符:
|
||||
|
||||
| 占位符 | 实际路径 |
|
||||
|---|---|
|
||||
| `{build_root_path}` | buildroot 目录(`buildroot/`) |
|
||||
| `{pkg_root_path}` | pkgroot 目录(`pkgroot/`) |
|
||||
| `{working_dir}` | 工作目录(项目根目录) |
|
||||
| `{download_path}` | 下载缓存目录(`downloads/`) |
|
||||
| `{source_path}` | 解压源码目录(`source/`) |
|
||||
| `{php_sdk_path}` | Windows PHP SDK 目录 |
|
||||
|
||||
## target 包类型
|
||||
|
||||
`target` 包代表一个最终的构建产物,它继承于 `library`,所以包含 `library` 的所有定义字段。`target` 包的配置文件位于 `config/pkg/target/` 目录下,构建类继承自 `TargetPackage`,位于 `src/Package/Target/` 目录下。
|
||||
|
||||
与 `library` 的唯一区别是,`target` 包可以注册成为构建目标,且自动注册构建命令 `spc build:{target-name}`。
|
||||
|
||||
## virtual-target 包类型
|
||||
|
||||
与 `target` 不同的是,`virtual-target` 可以不包含 `artifact`,即不直接对应一个可构建的实体,而是一个抽象的构建目标,主要用于依赖管理和构建调度。`virtual-target` 的配置文件位于 `config/pkg/target/` 目录下,构建类继承自 `TargetPackage`,位于 `src/Package/Target/` 目录下。它的定义与 `target` 基本相同,但 `artifact` 字段可选且通常不设置。`virtual-target` 主要用于以下场景:
|
||||
|
||||
- 定义一个抽象的构建目标,供其他包依赖,但不直接对应一个可构建的实体。
|
||||
- 作为多个 `target` 包的公共依赖,简化依赖关系管理。
|
||||
|
||||
典型例子就是 PHP 包的 `php-cli`、`php-fpm` 等构建目标,他们没有独立的源码,依赖于 `php-src`,通过构建调度来决定最终构建成 CLI 还是 FPM 二进制。
|
||||
|
||||
@@ -3,3 +3,82 @@
|
||||
<!-- TODO: spc.registry.yml 结构说明。
|
||||
通过 SPC_REGISTRIES 环境变量添加外部 Registry。
|
||||
Vendor 特定配置、覆盖核心包。Registry 解析顺序与冲突规则。 -->
|
||||
## 概述
|
||||
|
||||
**Registry(注册表)** 是 StaticPHP 的核心扩展机制。你可以把它理解成一个"插件包":一个 Registry 由一个声明文件(`spc.registry.yml`)和它所指向的配置文件、PHP 类共同组成,描述了一组包的定义(YAML 配置)和对应的构建逻辑(PHP 类)。构建系统在启动时会加载所有已注册的 Registry,将它们的包定义合并后用于整个构建流程。
|
||||
|
||||
StaticPHP 本身携带一个内置的核心注册表(`core`),其中包含了 PHP 及相关扩展、库、构建工具等的全部定义。`core` 注册表的声明文件即项目根目录下的 `spc.registry.yml`,它描述了配置文件目录(`config/pkg/`、`config/artifact/`)和构建类的 PSR-4 命名空间(`src/Package/`)之间的映射关系。
|
||||
|
||||
外部 Registry 只能定义 `core` 中尚不存在的新包,不能覆盖或修改核心注册表中已有的定义。根据你的需求,有以下三种方式来扩展或修改 StaticPHP 的构建能力:
|
||||
|
||||
- **修改 `core` 注册表**:直接修改 `src/Package` 和 `config/pkg/` 下的文件,适用于希望将改动合并回 StaticPHP 主线的情况。请先阅读 [贡献指南](../contributing/) 中关于贡献新包的部分,再提交 PR。
|
||||
- **Vendor 模式**:将自定义包封装为一个独立的子注册表,以 Composer 包的形式分发,适用于需要私有包或希望以库的形式复用构建逻辑的场景。详见 [Vendor 模式](./vendor-mode/)。
|
||||
- **外部注册表(`SPC_REGISTRIES`)**:通过环境变量 `SPC_REGISTRIES` 指定一个或多个外部注册表文件的路径,StaticPHP 会在启动时加载它们。适用于临时扩展或不便打包为 Composer 包的场景,与其他包管理器的外部源机制类似。
|
||||
|
||||
## Registry 定义文件
|
||||
|
||||
每个 Registry 都有一个声明文件,通常命名为 `spc.registry.yml`,位于项目根目录或 Composer 包的根目录下。文件格式支持 YAML(`.yml` / `.yaml`)和 JSON(`.json`)。文件中所有路径均相对于声明文件自身所在目录解析。
|
||||
|
||||
StaticPHP 在源码模式(直接 git clone)下,会默认加载项目根目录下的 `spc.registry.yml` 作为核心注册表(`core`)。在 Vendor 模式下,会自动检测当前 Composer 包根目录下是否存在 `spc.registry.yml`,如果存在则加载为一个独立的注册表。通过 `SPC_REGISTRIES` 环境变量指定的外部注册表也必须包含一个有效的声明文件。
|
||||
|
||||
下面是一个包含所有可用字段的完整示例(参照 `core` 注册表):
|
||||
|
||||
```yaml
|
||||
# [必填] 注册表唯一名称,重复加载同名注册表时会自动跳过
|
||||
name: my-registry
|
||||
|
||||
# [可选] Composer autoload 文件路径,外部注册表有自己的依赖时使用
|
||||
autoload: vendor/autoload.php
|
||||
|
||||
# 包(library / php-extension / target)相关配置
|
||||
package:
|
||||
# 包的 YAML 配置文件目录或具体文件路径,可以是数组
|
||||
config:
|
||||
- config/pkg/lib/
|
||||
- config/pkg/target/
|
||||
- config/pkg/ext/
|
||||
# 包构建类的 PSR-4 命名空间 → 目录路径映射,加载器会扫描目录下所有 PHP 类
|
||||
psr-4:
|
||||
Package: src/Package
|
||||
# 也可以按需加载指定的类,支持数组格式或 {"类名": "文件路径"} 映射格式
|
||||
# classes:
|
||||
# - Package\Library\MyLib
|
||||
# MyLib: src/Package/Library/MyLib.php
|
||||
|
||||
# 构建产物(Artifact)相关配置
|
||||
artifact:
|
||||
# Artifact 的 YAML 配置文件目录或具体文件路径
|
||||
config:
|
||||
- config/artifact/
|
||||
# Artifact 自定义下载/解压类的 PSR-4 命名空间 → 目录路径映射
|
||||
psr-4:
|
||||
Package\Artifact: src/Package/Artifact
|
||||
# classes: ...(同 package.classes 格式)
|
||||
|
||||
# Doctor 环境检查项配置
|
||||
doctor:
|
||||
# Doctor 检查项类的 PSR-4 命名空间 → 目录路径映射
|
||||
psr-4:
|
||||
StaticPHP\Doctor\Item: src/StaticPHP/Doctor/Item
|
||||
# classes: ...(同 package.classes 格式)
|
||||
|
||||
# 额外的 CLI 命令配置
|
||||
command:
|
||||
# 自定义命令类的 PSR-4 命名空间 → 目录路径映射
|
||||
psr-4:
|
||||
Package\Command: src/Package/Command
|
||||
# classes: ...(同 package.classes 格式)
|
||||
```
|
||||
|
||||
各顶层字段说明:
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
|---|---|---|
|
||||
| `name` | ✅ | 注册表唯一名称,重复加载同名注册表时自动跳过 |
|
||||
| `autoload` | | Composer autoload 文件路径,适用于外部注册表携带自己的依赖时 |
|
||||
| `package` | | 包定义,含 YAML 配置(`config`)和构建类(`psr-4` / `classes`) |
|
||||
| `artifact` | | Artifact 定义,含 YAML 配置(`config`)和自定义类(`psr-4` / `classes`) |
|
||||
| `doctor` | | Doctor 检查项定义,仅含类加载(`psr-4` / `classes`) |
|
||||
| `command` | | 额外的 CLI 命令定义,仅含类加载(`psr-4` / `classes`) |
|
||||
|
||||
其中 `psr-4` 和 `classes` 的区别:`psr-4` 会扫描整个目录下所有符合命名空间规则的 PHP 类并批量注册;`classes` 则用于精确指定某几个类,支持纯数组格式(`["ClassName"]`,需已在 autoload 中可用)或键值映射格式(`{"ClassName": "path/to/file.php"}`,加载器会自动 `require` 对应文件)。
|
||||
|
||||
@@ -1,4 +1,85 @@
|
||||
# 项目结构
|
||||
|
||||
<!-- TODO: v3 目录结构说明(bin/、config/pkg/、src/StaticPHP/、src/Package/ 等)。
|
||||
每个顶层目录的职责说明。内部类结构简述,深入内容见核心概念页。 -->
|
||||
## 概念
|
||||
|
||||
StaticPHP 本身是一个基于 `symfony/console` 的 CLI 应用,核心代码位于 `src/StaticPHP` 目录下。
|
||||
它主要分为几个模块:
|
||||
|
||||
- **Registry**:负责管理注册表数据,每个注册表含有多个包(Package),StaticPHP 项目本身内置一个 `core` 注册表,包含 PHP 及相关扩展、依赖等。
|
||||
- **Package**:代表一个包,包的种类有四种:`php-extension`(PHP 扩展)、`library`(库)、`target`(构建目标)、`virtual-target`(虚构建目标)。每个包包含构建信息、依赖关系等。
|
||||
- **Installer/Builder**:负责处理包的安装和构建逻辑,调用构建命令、解压构建产物、处理构建结果等。
|
||||
- **Doctor**:提供系统环境检查功能,负责安装和检查系统层面依赖的工具、需要的文件等,如 `make`、`cmake`、`autoconf` 等。
|
||||
- **Runtime/Executor**:包含运行时相关的工具类,如执行 shell 命令、执行 CMake 构建等。
|
||||
- **Toolchain**:对不同操作系统及环境,提供对应系统的工具链抽象接口,负责处理构建过程中与系统环境相关的差异。
|
||||
- **Utils**:一些通用的工具类,如文件系统操作、日志记录、操作系统相关助手方法等。
|
||||
- **DependencyResolver**:负责解析包之间的依赖关系,生成构建顺序等。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
static-php-cli/
|
||||
├── bin/ # 可执行入口脚本(spc、spc.ps1、setup-runtime 等)
|
||||
├── config/
|
||||
│ ├── env.ini # 默认环境变量配置
|
||||
│ ├── env.custom.ini # 用户自定义环境变量(覆盖 env.ini)
|
||||
│ ├── artifact/ # 构建产物配置(下载工具链、预构建二进制等)
|
||||
│ └── pkg/ # 包配置文件(YAML)
|
||||
│ ├── ext/ # PHP 扩展包配置(ext-*.yml、builtin-extensions.yml)
|
||||
│ ├── lib/ # 库包配置(*.yml)
|
||||
│ └── target/ # 构建目标配置(php.yml、curl.yml 等)
|
||||
├── src/
|
||||
│ ├── bootstrap.php # 应用引导(注册自动加载、DI 容器等)
|
||||
│ ├── globals/ # 全局辅助函数
|
||||
│ ├── Package/ # 各包的构建逻辑实现(PHP 类)
|
||||
│ │ ├── Artifact/ # 构建产物的自定义下载/解压逻辑
|
||||
│ │ ├── Command/ # 包级别自定义命令
|
||||
│ │ ├── Extension/ # PHP 扩展构建类(ext-*.php)
|
||||
│ │ ├── Library/ # 库构建类(*.php)
|
||||
│ │ └── Target/ # 构建目标类(php.php、curl.php 等)
|
||||
│ └── StaticPHP/ # 框架核心代码
|
||||
│ ├── ConsoleApplication.php # Symfony Console 应用入口
|
||||
│ ├── Artifact/ # 构建产物下载与解压(Downloader、Extractor 等)
|
||||
│ ├── Attribute/ # PHP 注解定义
|
||||
│ │ ├── Artifact/ # 产物相关注解(CustomSource、BinaryExtract 等)
|
||||
│ │ ├── Doctor/ # Doctor 相关注解(CheckItem、FixItem 等)
|
||||
│ │ └── Package/ # 包构建相关注解(BuildFor、BeforeStage、AfterStage、
|
||||
│ │ # CustomPhpConfigureArg、PatchBeforeBuild 等)
|
||||
│ ├── Command/ # CLI 命令实现(build-libs、build-target、doctor 等)
|
||||
│ ├── Config/ # 配置加载与验证(PackageConfig、ArtifactConfig 等)
|
||||
│ ├── DI/ # 依赖注入容器(ApplicationContext、CallbackInvoker)
|
||||
│ ├── Doctor/ # 系统环境检查与修复(Doctor、CheckResult)
|
||||
│ ├── Exception/ # 自定义异常类
|
||||
│ ├── Package/ # 包核心模型与构建调度
|
||||
│ │ ├── Package.php # 包基类
|
||||
│ │ ├── LibraryPackage.php # 库包类型
|
||||
│ │ ├── PhpExtensionPackage.php # PHP 扩展包类型
|
||||
│ │ ├── TargetPackage.php # 构建目标包类型
|
||||
│ │ ├── PackageInstaller.php # 包安装器(下载、解压源码)
|
||||
│ │ └── PackageBuilder.php # 包构建器(执行构建流程)
|
||||
│ ├── Registry/ # 注册表管理(Registry、PackageLoader、ArtifactLoader)
|
||||
│ ├── Runtime/ # 运行时工具
|
||||
│ │ ├── Executor/ # 命令执行器(UnixAutoconfExecutor、UnixCMakeExecutor、
|
||||
│ │ │ # WindowsCMakeExecutor、Executor 基类)
|
||||
│ │ ├── Shell/ # Shell 抽象(UnixShell、WindowsCmd 等)
|
||||
│ │ └── SystemTarget.php # 系统目标信息
|
||||
│ ├── Toolchain/ # 工具链抽象(GccNative、Musl、MSVC、Zig、ClangBrew 等)
|
||||
│ └── Util/ # 通用工具类
|
||||
│ ├── System/ # 系统平台工具(LinuxUtil、MacOSUtil、WindowsUtil 等)
|
||||
│ ├── BuildRootTracker.php # buildroot 文件追踪
|
||||
│ ├── DependencyResolver.php # 依赖解析与构建顺序
|
||||
│ ├── FileSystem.php # 文件系统操作
|
||||
│ ├── GlobalEnvManager.php # 全局环境变量管理
|
||||
│ ├── InteractiveTerm.php # 交互式终端输出
|
||||
│ ├── LicenseDumper.php # 开源协议导出
|
||||
│ ├── PkgConfigUtil.php # pkg-config 工具封装
|
||||
│ ├── SourcePatcher.php # 源码补丁工具
|
||||
│ └── SPCConfigUtil.php # SPC 配置读取工具
|
||||
├── tests/ # 单元测试与集成测试
|
||||
├── downloads/ # 下载缓存目录(源码包、预构建二进制)
|
||||
├── source/ # 解压后的源码目录
|
||||
├── buildroot/ # 构建输出目录(头文件、静态库等)
|
||||
├── pkgroot/ # 按平台归档的构建产物
|
||||
└── spc.registry.yml # core 注册表定义文件
|
||||
```
|
||||
|
||||
需要注意的是,`src/Package` 目录下的类主要负责实现具体包的构建逻辑,而 `src/StaticPHP` 目录下的类则提供了构建框架的核心功能,如命令调度、环境检查、工具链抽象等,两者是解耦的。`src/Package` 对应的是 `core` 注册表中的包,其中包含 PHP 及相关扩展、库、构建目标等的具体实现,而 `src/StaticPHP` 则是整个构建系统的基础设施,支持不同注册表和包的构建需求。
|
||||
|
||||
Reference in New Issue
Block a user