diff --git a/docs/en/develop/package-model.md b/docs/en/develop/package-model.md index 4bac3de2..a9143eec 100644 --- a/docs/en/develop/package-model.md +++ b/docs/en/develop/package-model.md @@ -4,14 +4,15 @@ 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. +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 optional recipe classes are in the corresponding subdirectories of `src/Package/`. -Packages are primarily divided into four types: +Packages are divided into five 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. +- **library**: A dependency library package, usually installed into `buildroot/` for other packages to compile and link against. - **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. +- **tool**: A host-side build tool package, installed separately under `pkgroot/` and not treated as a link-time library dependency. ```yaml {pkg-name}: @@ -21,7 +22,7 @@ Packages are primarily divided into four types: ## 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. +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. A Package can reference one Artifact via the `artifact` field to obtain the source or binary 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. @@ -40,7 +41,7 @@ For more on Artifact definitions, see the [Artifact Model](./artifact-model) cha ## 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. +A php-extension package represents a PHP extension. Its configuration file is located in the `config/pkg/ext/` directory. Optional recipe classes are normally placed in `src/Package/Extension/`, registered with `#[Extension]`, and receive the corresponding `PhpExtensionPackage` through callback context. Inheriting from `PhpExtensionPackage` is supported but is not required by the current core recipes. ```yaml ext-lz4: @@ -57,7 +58,7 @@ ext-lz4: depends: - liblz4 php-extension: - arg-type@unix: '--enable-lz4=@shared_suffix@ --with-lz4-includedir=@build_root_path@' + arg-type@unix: '--enable-lz4@shared_suffix@ --with-lz4-includedir=@build_root_path@' arg-type@windows: '--enable-lz4' ``` @@ -72,16 +73,18 @@ ext-{ext-name}: # Package name must start with ext- prefix 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 + artifact: '{artifact-name}' # Optional; when a string, references the named Artifact definition; + # when an object, it is an inline Artifact # (built-in extensions don't need this field) - # depends / suggests support @windows / @unix / @linux / @macos suffixes + # depends / suggests / tools 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: [] + tools: [] # Optional, host-side build tool dependencies; resolved separately + tools@windows: [] # Optional, platform-specific tool dependencies # ── php-extension Specific Fields (nested under php-extension: object) ──── php-extension: @@ -100,7 +103,7 @@ ext-{ext-name}: # Package name must start with ext- prefix # @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@unix: '--enable-my-extension@shared_suffix@' arg-type@windows: with-path zend-extension: false # Optional, true indicates this is a Zend extension (e.g., opcache, xdebug) @@ -121,7 +124,7 @@ ext-{ext-name}: # Package name must start with ext- prefix ## 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. +A library package represents a dependency library, such as openssl or zlib, installed from source or a pre-built binary. Its configuration file is located in the `config/pkg/lib/` directory. Optional recipe classes are normally placed in `src/Package/Library/`, registered with `#[Library]`, and receive a `LibraryPackage` through callback context; they do not need to inherit from it. Taking openssl as an example: @@ -161,22 +164,27 @@ Allowed fields for `library`: # ── Common Fields ───────────────────────────────────────────────────────── description: '..' # Optional, human-readable package description - license: MIT # Optional, SPDX license identifier (for license export) + license: # Optional, license material copied after a source build + type: file # type is file or text; a list of entries is also accepted + path: LICENSE 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 + artifact: '{artifact-name}' # Required; when a string, references the named Artifact definition; + # when an object, it is an inline Artifact - # depends / suggests support @windows / @unix / @linux / @macos suffixes + # depends / suggests / tools 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) + tools: [] # Optional, ToolPackage names required only while building + tools@windows: [] # ── 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. + # installed after the build. headers, static-libs, and static-bins 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 @@ -231,17 +239,49 @@ The following path placeholders are supported in string values of the `path`, `e | `{source_path}` | Extracted source directory (`source/`) | | `{spc_msys2_path}` | MSYS2 root directory (`msys64/`) — Windows only | +## tool Package Type + +A `tool` package represents an executable needed while building another package, rather than a library linked into the final target. Tool packages may use a pre-built binary or build from source, and install under `pkgroot/` by default, using either a shared `bin/` directory or a configured subdirectory. Packages request them through the top-level `tools` field; this dependency set is resolved independently of `depends` and `suggests`. + +```yaml +nasm: + type: tool + artifact: + binary: + windows-x86_64: + type: url + url: 'https://example.com/nasm-win64.zip' + extract: + nasm.exe: '{pkg_root_path}/bin/nasm.exe' + ndisasm.exe: '{pkg_root_path}/bin/ndisasm.exe' + tool: + provides: [nasm.exe, ndisasm.exe] + binary-subdir: bin + min-version: '2.16' +``` + +The nested `tool` object supports: + +| Field | Required | Meaning | +|---|---|---| +| `provides` | Yes | Executable filenames used to decide whether the tool is installed | +| `binary-subdir` | No | Directory below `install-root` containing the executables; defaults to the install root | +| `install-root` | No | Installation root; defaults to `PKG_ROOT_PATH` and supports path placeholders | +| `min-version` | No | Declared minimum version metadata exposed by `ToolPackage`; the installer does not currently enforce it | + +Fields inside `tool` may use `@windows`, `@unix`, `@linux`, and `@macos` suffixes. For example, `provides@windows` can list `.exe` names while `provides@unix` lists Unix names. + ## 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. +A `target` package represents a final build artifact. It inherits from `library`, so it includes all definition fields of `library`. Its configuration file is located in `config/pkg/target/`. Optional recipe classes are normally placed in `src/Package/Target/`, registered with `#[Target]`, and receive a `TargetPackage`; inheriting from `TargetPackage` is optional. 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: +Unlike `target`, a `virtual-target` may omit `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. Its configuration and optional recipe classes use the same directories and `#[Target]` registration mechanism as `target`. Its definition is otherwise essentially the same, 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. +Typical examples are the `php-cli` and `php-fpm` build targets. They have no independent source and depend on the `php` target, whose Artifact is `php-src`; build scheduling determines whether the CLI or FPM binary is produced. diff --git a/docs/zh/develop/package-model.md b/docs/zh/develop/package-model.md index af87a8da..f3ad1bf8 100644 --- a/docs/zh/develop/package-model.md +++ b/docs/zh/develop/package-model.md @@ -1,20 +1,18 @@ # Package 模型 - ## Package 定义 Package 是 StaticPHP 构建系统中的核心概念,代表一个可构建/可安装的单元,如 PHP 扩展、库、构建目标等。 -每个 Package 包含构建信息、依赖关系、构建逻辑等,构成了 StaticPHP 的构建模型。Package 的定义主要通过 YAML/JSON 配置文件来实现。`core` 注册表的包配置文件位于 `config/pkg/` 目录下,对应的构建类位于 `src/Package/` 目录下。 +每个 Package 包含构建信息、依赖关系、构建逻辑等,构成了 StaticPHP 的构建模型。Package 的定义主要通过 YAML/JSON 配置文件来实现。`core` Registry 的 Package 配置位于 `config/pkg/` 目录下,可选 recipe class 位于 `src/Package/` 对应的子目录中。 -Package 主要分为四种类型: +Package 分为五种类型: - **php-extension**:PHP 扩展包,包含 PHP 扩展的构建信息和构建逻辑。 -- **library**:库包,包含构建工具链、依赖库等的构建信息和构建逻辑。 +- **library**:依赖库 Package,通常安装到 `buildroot/`,供其他 Package 编译和链接。 - **target**:构建目标包,代表最终的构建产物,如 PHP 二进制、curl 二进制等,继承自 `library` 包类型。 - **virtual-target**:虚构建目标包,代表一个抽象的构建目标,不直接对应构建产物,主要用于依赖管理和构建调度。 +- **tool**:宿主机侧构建工具 Package,单独安装在 `pkgroot/` 下,不作为链接期库依赖处理。 ```yaml {pkg-name}: @@ -24,7 +22,7 @@ Package 主要分为四种类型: ## Artifact 定义 -Artifact 是独立于 Package 的定义,它包含构建包的源码归档文件或预构建的二进制文件。每个 Artifact 定义了下载 URL、解压方式、构建产物的文件路径等信息。Package 可以通过 `artifact` 字段引用一个或多个 Artifact 来获取构建所需的源码或二进制文件。 +Artifact 是独立于 Package 的定义,它包含构建包的源码归档文件或预构建的二进制文件。每个 Artifact 定义了下载 URL、解压方式、构建产物的文件路径等信息。一个 Package 可以通过 `artifact` 字段引用一个 Artifact,以获取构建所需的源码或二进制文件。 简单来说,默认情况下,一个 Package 对应一个 Artifact;如果多个 Package 共用一份源码时,可以定义一个 Artifact 供多个 Package 引用。Artifact 的定义位于 `config/artifact/` 目录下,对应的自定义下载/解压逻辑类位于 `src/Package/Artifact/` 目录下;对于虚拟目标、PHP 内置扩展等特殊包类型,Package 也可以不设置 Artifact 字段。 @@ -43,7 +41,7 @@ example-library-package: ## php-extension 包类型 -php-extension 一个包代表一个 PHP 扩展,它的配置文件位于 `config/pkg/ext/` 目录下,构建类继承自 `PhpExtensionPackage`,位于 `src/Package/Extension/` 目录下。PHP 扩展包的配置文件包含扩展名称、版本、依赖关系、构建选项等信息。 +php-extension Package 代表一个 PHP 扩展,它的配置文件位于 `config/pkg/ext/` 目录下。可选的 recipe class 通常放在 `src/Package/Extension/`,通过 `#[Extension]` 注册,并从 callback context 接收对应的 `PhpExtensionPackage`。当前 core recipe 支持继承 `PhpExtensionPackage`,但并不要求继承。 ```yaml ext-lz4: @@ -60,7 +58,7 @@ ext-lz4: depends: - liblz4 php-extension: - arg-type@unix: '--enable-lz4=@shared_suffix@ --with-lz4-includedir=@build_root_path@' + arg-type@unix: '--enable-lz4@shared_suffix@ --with-lz4-includedir=@build_root_path@' arg-type@windows: '--enable-lz4' ``` @@ -75,15 +73,17 @@ ext-{ext-name}: # 包名必须以 ext- 前缀开头 lang: c # 可选,扩展的实现语言(c / c++ 等) frameworks: [] # 可选,相关macOS框架依赖列表 - artifact: '{artifact-name}' # 可选;字符串时引用同名 Artifact 定义, + artifact: '{artifact-name}' # 可选;字符串时引用指定名称的 Artifact 定义, # 对象时为内联 Artifact(内置扩展无需此字段) - # depends / suggests 支持 @windows / @unix / @linux / @macos 后缀 + # depends / suggests / tools 支持 @windows / @unix / @linux / @macos 后缀 depends: [] # 可选,硬依赖列表(库名直接写,PHP 扩展需加 ext- 前缀) depends@unix: [] # 可选,仅 Unix 平台生效的硬依赖 depends@windows: [] # 可选,仅 Windows 平台生效的硬依赖 suggests: [] # 可选,可选依赖列表(格式同 depends) suggests@unix: [] + tools: [] # 可选,宿主机侧构建工具依赖,单独解析 + tools@windows: [] # 可选,特定平台的工具依赖 # ── php-extension 专属字段(嵌套在 php-extension: 对象中)───────────────── php-extension: @@ -101,7 +101,7 @@ ext-{ext-name}: # 包名必须以 ext- 前缀开头 # @shared_suffix@ → 共享构建时展开为 =shared,静态构建时为空 # @shared_path_suffix@ → 共享构建时展开为 =shared,{buildroot},静态构建时为 ={buildroot} arg-type: enable - arg-type@unix: '--enable-{extname}=@shared_suffix@' + arg-type@unix: '--enable-my-extension@shared_suffix@' arg-type@windows: with-path zend-extension: false # 可选,true 表示这是 Zend 扩展(如 opcache、xdebug) @@ -120,7 +120,7 @@ ext-{ext-name}: # 包名必须以 ext- 前缀开头 ## library 包类型 -library 包代表一个需要从源码编译的依赖库(如 openssl、zlib 等),其配置文件位于 `config/pkg/lib/` 目录下,构建类继承自 `LibraryPackage`,位于 `src/Package/Library/` 目录下。 +library Package 代表 openssl、zlib 等依赖库,可以从源码或预构建二进制安装。其配置文件位于 `config/pkg/lib/` 目录下。可选的 recipe class 通常放在 `src/Package/Library/`,通过 `#[Library]` 注册,并从 callback context 接收 `LibraryPackage`;不要求继承该类。 以 openssl 为例: @@ -160,20 +160,25 @@ openssl: # ── 通用字段 ───────────────────────────────────────────────────────────── description: '...' # 可选,人类可读的包描述 - license: MIT # 可选,SPDX 许可证标识符(用于许可证导出) + license: # 可选,从源码构建后复制的许可证内容 + type: file # type 可为 file 或 text,也可填写多个条目的列表 + path: LICENSE lang: c # 可选,库的实现语言(c / c++ 等) frameworks: [] # 可选,相关框架标签列表 - artifact: '{artifact-name}' # 必填;字符串时引用同名 Artifact 定义,对象时为内联 Artifact + artifact: '{artifact-name}' # 必填;字符串时引用指定名称的 Artifact 定义,对象时为内联 Artifact - # depends / suggests 支持 @windows / @unix / @linux / @macos 后缀 + # depends / suggests / tools 支持 @windows / @unix / @linux / @macos 后缀 depends: [] # 可选,硬依赖列表(库名或 ext- 前缀的 PHP 扩展名) depends@unix: [] depends@windows: [] suggests: [] # 可选,可选依赖列表(格式同 depends) + tools: [] # 可选,仅构建时需要的 ToolPackage 名称 + tools@windows: [] # ── library / target 专属字段 ──────────────────────────────────────────── - # 以下字段用于构建完成后验证产物是否已正确安装,支持 @unix / @windows / @linux / @macos 后缀 + # 以下字段用于构建完成后验证产物是否已正确安装;headers、static-libs、static-bins + # 支持 @unix / @windows / @linux / @macos 后缀 # 验证 buildroot/include/ 下是否存在指定头文件或目录 # 相对路径基于 buildroot/include/,绝对路径直接使用 @@ -225,17 +230,49 @@ openssl: | `{source_path}` | 解压源码目录(`source/`) | | `{spc_msys2_path}` | MSYS2 根目录(`msys64/`)——仅 Windows | +## tool 包类型 + +`tool` Package 表示构建其他 Package 时需要的可执行工具,而不是链接进最终 target 的库。Tool Package 可以使用预构建二进制,也可以从源码构建,默认安装在 `pkgroot/` 下的共享 `bin/` 或配置的子目录。其他 Package 通过顶层 `tools` 字段请求这些工具;该依赖集合与 `depends`、`suggests` 分开解析。 + +```yaml +nasm: + type: tool + artifact: + binary: + windows-x86_64: + type: url + url: 'https://example.com/nasm-win64.zip' + extract: + nasm.exe: '{pkg_root_path}/bin/nasm.exe' + ndisasm.exe: '{pkg_root_path}/bin/ndisasm.exe' + tool: + provides: [nasm.exe, ndisasm.exe] + binary-subdir: bin + min-version: '2.16' +``` + +嵌套的 `tool` 对象支持: + +| 字段 | 是否必填 | 含义 | +|---|---|---| +| `provides` | 是 | 用于判断工具是否已经安装的可执行文件名 | +| `binary-subdir` | 否 | `install-root` 下存放可执行文件的目录;默认就是安装根目录 | +| `install-root` | 否 | 安装根目录;默认为 `PKG_ROOT_PATH`,支持路径占位符 | +| `min-version` | 否 | 由 `ToolPackage` 暴露的最低版本元数据;installer 当前不会强制校验 | + +`tool` 内的字段可以使用 `@windows`、`@unix`、`@linux` 和 `@macos` 后缀。例如,`provides@windows` 可以列出 `.exe` 名称,`provides@unix` 列出 Unix 名称。 + ## target 包类型 -`target` 包代表一个最终的构建产物,它继承于 `library`,所以包含 `library` 的所有定义字段。`target` 包的配置文件位于 `config/pkg/target/` 目录下,构建类继承自 `TargetPackage`,位于 `src/Package/Target/` 目录下。 +`target` Package 代表一个最终的构建产物,它继承于 `library`,所以包含 `library` 的所有定义字段。其配置文件位于 `config/pkg/target/`。可选的 recipe class 通常放在 `src/Package/Target/`,通过 `#[Target]` 注册,并接收 `TargetPackage`;是否继承 `TargetPackage` 是可选的。 与 `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` 不同,`virtual-target` 可以省略 `artifact`,即不直接对应一个可构建的实体,而是用于依赖管理和构建调度的抽象构建目标。它与 `target` 使用相同的配置目录、可选 recipe class 目录和 `#[Target]` 注册方式。其余定义基本相同,但 `artifact` 字段可选且通常不设置。`virtual-target` 主要用于以下场景: - 定义一个抽象的构建目标,供其他包依赖,但不直接对应一个可构建的实体。 - 作为多个 `target` 包的公共依赖,简化依赖关系管理。 -典型例子就是 PHP 包的 `php-cli`、`php-fpm` 等构建目标,他们没有独立的源码,依赖于 `php-src`,通过构建调度来决定最终构建成 CLI 还是 FPM 二进制。 +典型例子是 `php-cli` 和 `php-fpm` 构建目标。它们没有独立源码,依赖 Artifact 为 `php-src` 的 `php` target;构建调度会决定最终生成 CLI 还是 FPM 二进制。