Files
static-php-cli/docs/zh/develop/package-model.md

13 KiB
Raw Blame History

Package 模型

Package 定义

Package 是 StaticPHP 构建系统中的核心概念,代表一个可构建/可安装的单元,如 PHP 扩展、库、构建目标等。

每个 Package 包含构建信息、依赖关系、构建逻辑等,构成了 StaticPHP 的构建模型。Package 的定义主要通过 YAML/JSON 配置文件来实现。core Registry 的 Package 配置位于 config/pkg/ 目录下,可选 recipe class 位于 src/Package/ 对应的子目录中。

Package 分为五种类型:

  • php-extensionPHP 扩展包,包含 PHP 扩展的构建信息和构建逻辑。
  • library:依赖库 Package通常安装到 buildroot/,供其他 Package 编译和链接。
  • target:构建目标包,代表最终的构建产物,如 PHP 二进制、curl 二进制等,继承自 library 包类型。
  • virtual-target:虚构建目标包,代表一个抽象的构建目标,不直接对应构建产物,主要用于依赖管理和构建调度。
  • tool:宿主机侧构建工具 Package单独安装在 pkgroot/ 下,不作为链接期库依赖处理。
{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 定义可以如下所示:

example-library-package:
  type: library
  artifact:
    source:
      type: url
      url: 'https://example.com/example-library.tar.gz'

更多有关 Artifact 定义的内容,请参阅 Artifact 模型 章节。

php-extension 包类型

php-extension Package 代表一个 PHP 扩展,它的配置文件位于 config/pkg/ext/ 目录下。可选的 recipe class 通常放在 src/Package/Extension/,通过 #[Extension] 注册,并从 callback context 接收对应的 PhpExtensionPackage。当前 core recipe 支持继承 PhpExtensionPackage,但并不要求继承。

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 允许的定义字段:

ext-{ext-name}:          # 包名必须以 ext- 前缀开头
  type: php-extension

  # ── 通用字段 ─────────────────────────────────────────────────────────────
  description: '...'     # 可选,人类可读的包描述
  lang: c                # 可选扩展的实现语言c / c++ 等)
  frameworks: []         # 可选相关macOS框架依赖列表

  artifact: '{artifact-name}'  # 可选;字符串时引用指定名称的 Artifact 定义,
                               # 对象时为内联 Artifact内置扩展无需此字段

  # 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:
    # arg-type 决定传递给 ./configure 的参数形式,支持平台后缀
    # 支持的平台后缀:@unixLinux + 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_PATHbuildroot 绝对路径)
    #   @shared_suffix@     → 共享构建时展开为 =shared静态构建时为空
    #   @shared_path_suffix@ → 共享构建时展开为 =shared,{buildroot},静态构建时为 ={buildroot}
    arg-type: enable
    arg-type@unix: '--enable-my-extension@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 Package 代表 openssl、zlib 等依赖库,可以从源码或预构建二进制安装。其配置文件位于 config/pkg/lib/ 目录下。可选的 recipe class 通常放在 src/Package/Library/,通过 #[Library] 注册,并从 callback context 接收 LibraryPackage;不要求继承该类。

以 openssl 为例:

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 允许的定义字段:

{lib-name}:
  type: library           # library 或 targettarget 继承 library 的所有字段)

  # ── 通用字段 ─────────────────────────────────────────────────────────────
  description: '...'     # 可选,人类可读的包描述
  license:               # 可选,从源码构建后复制的许可证内容
    type: file           # type 可为 file 或 text也可填写多个条目的列表
    path: LICENSE
  lang: c                # 可选库的实现语言c / c++ 等)
  frameworks: []         # 可选,相关框架标签列表

  artifact: '{artifact-name}'  # 必填;字符串时引用指定名称的 Artifact 定义,对象时为内联 Artifact

  # depends / suggests / tools 支持 @windows / @unix / @linux / @macos 后缀
  depends: []            # 可选,硬依赖列表(库名或 ext- 前缀的 PHP 扩展名)
  depends@unix: []
  depends@windows: []
  suggests: []           # 可选,可选依赖列表(格式同 depends
  tools: []              # 可选,仅构建时需要的 ToolPackage 名称
  tools@windows: []

  # ── library / target 专属字段 ────────────────────────────────────────────
  # 以下字段用于构建完成后验证产物是否已正确安装headers、static-libs、static-bins
  # 支持 @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'

pathenvappend-env 字段的字符串值中支持以下路径占位符:

占位符 实际路径
{build_root_path} buildroot 目录(buildroot/
{pkg_root_path} pkgroot 目录(pkgroot/
{working_dir} 工作目录(项目根目录)
{download_path} 下载缓存目录(downloads/
{source_path} 解压源码目录(source/
{spc_msys2_path} MSYS2 根目录(msys64/)——仅 Windows

tool 包类型

tool Package 表示构建其他 Package 时需要的可执行工具,而不是链接进最终 target 的库。Tool Package 可以使用预构建二进制,也可以从源码构建,默认安装在 pkgroot/ 下的共享 bin/ 或配置的子目录。其他 Package 通过顶层 tools 字段请求这些工具;该依赖集合与 dependssuggests 分开解析。

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 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,即不直接对应一个可构建的实体,而是用于依赖管理和构建调度的抽象构建目标。它与 target 使用相同的配置目录、可选 recipe class 目录和 #[Target] 注册方式。其余定义基本相同,但 artifact 字段可选且通常不设置。virtual-target 主要用于以下场景:

  • 定义一个抽象的构建目标,供其他包依赖,但不直接对应一个可构建的实体。
  • 作为多个 target 包的公共依赖,简化依赖关系管理。

典型例子是 php-cliphp-fpm 构建目标。它们没有独立源码,依赖 Artifact 为 php-srcphp target构建调度会决定最终生成 CLI 还是 FPM 二进制。