Artifacts are built and published by .github/workflows/release.yml on a v* tag.
git tag v0.1.0
git push origin v0.1.0This runs the matrix (PHP minor × cell), verifies each artifact, and creates a GitHub Release containing:
yerd-dump-<minor>-<os>-<arch>.{so,dll}for every cell (.soLinux/macOS,.dllWindows),SHA256SUMS,manifest.json(the download contract Yerd verifies),- build-provenance attestations.
PHP minors: 8.2, 8.3, 8.4, 8.5.
Floor is 8.2:
ext-php-rs0.15.15 requires PHP ≥ 8.1, andzend_observeronly observes internal functions (PDO queries) from 8.2+. PHP 8.0/8.1 are also EOL.
| cell | runner |
|---|---|
| macOS arm64 | macos-14 |
| linux x86_64 | ubuntu-22.04 |
| linux aarch64 | ubuntu-22.04-arm |
| windows x86_64 | windows-2022 |
16 artifacts total (4 minors × 4 cells). Yerd is Apple-Silicon-only, so there is no
Intel macOS cell. Windows is NTS x86_64 only — there is no native arm64 cell (no public
arm64-Windows runners and no arm64 PHP dev packs / winlibs; Windows-on-ARM runs the x64 PHP
under emulation, into which the x64 .dll loads). The publish job fails if any cell is
missing.
Windows toolchain note. Unlike Unix, the Windows
yerd-dumpcell needs nightly Rust (ext-php-rsuses the unstableabi_vectorcallfeature on Windows — seesrc/lib.rs), LLVM (libclangfor bindgen,lld-linkas linker) and MSVCcl.exe.ext-php-rsauto-downloads the matching PHP dev pack fromwindows.php.netkeyed on thesetup-phpphp.exe, so the VS toolset aligns per minor automatically. The artifact is a.dll(yerd-dump-<minor>-windows-x86_64.dll).
A PHP extension's compatibility is fixed by ZEND_MODULE_API_NO (stable within a minor) +
NTS + non-debug. The build-id guard in CI asserts the build PHP is NTS and
non-debug; that, plus building per minor, is what makes each artifact load into Yerd's
PHP of the same minor.
The same-runner build-id is not self-compared (that is tautological — ext-php-rs
derives ZTS/debug from the PHP it built against). For a stronger guarantee, set the repo/CI
variable EXPECTED_PHP_EXTENSION_BUILD to the exact PHP Extension Build string that
Yerd's static-php.dev PHP reports for that minor; the guard then asserts equality. On
Windows that string includes the VS toolset token (e.g. VS16/VS17), so this is also
how you pin the toolset axis (see below).
Windows adds a 4th ABI axis: the VS toolset. A Windows extension must also match the Visual Studio toolset the target PHP was built with (8.2/8.3 →
VS16, 8.4/8.5 →VS17). Because both our build and Yerd's PHP come fromwindows.php.netper minor, the toolset aligns by construction. The Windows cells additionally assert this: theyerd-dumpleg via the build-id guard (andEXPECTED_PHP_EXTENSION_BUILDwhen set), and thepcovleg by matching the built.dll'svsNN(from thephp-windows-builderzip name) against the loader PHP'sPHP Extension Build. The Unix legs do not and cannot assert a toolset.
- glibc floor. Linux cells currently build on
ubuntu-22.04(glibc 2.35). If Yerd supports end-user hosts older than glibc 2.35, switch the Linux cells to build inside an old-glibc container (e.g.debian:bullseye, glibc 2.31) and validate thatshivammathur/setup-phpworks in-container or install PHP headers directly there. - Adding a PHP minor. Add it to the
phpmatrix list inrelease.yml(theminorscount check derives from it) and re-tag. Each minor needs its own build (ZEND_MODULE_API_NOis per-minor).
This repo also publishes the upstream krakjoe/pcov
code-coverage driver, so Yerd can download and load it the same way it loads yerd-dump.
pcov is upstream C, not Rust — the build-pcov job in release.yml builds it per
(PHP minor × cell); no Rust, bindgen, or libclang. On the Unix cells it uses the
standard PHP extension toolchain (phpize && ./configure --enable-pcov && make); on the
Windows cell it builds from source via the php/php-windows-builder
action (config.w32 + nmake), producing a .dll.
pcov is built and attached to the same v* release as yerd-dump (not a separate
pcov-v* tag). This is deliberate:
- Yerd's
yerd-dumpconsumer fetches…/releases/latest/download/manifest.json. A separate pcov release would become the repo's "latest" and that URL would 404 (a pcov release has nomanifest.json). One release stream keeps "latest" correct. - The
build-pcovjob is required —publishneeds it, so if pcov fails to build the entire release is blocked (all-or-nothing; every release carries both extensions).
The Yerd consumer (bin/yerdd/src/ext_install.rs) matches manifest entries on
(php, os, arch) only — there is no extension-name field. So pcov gets its own
manifest; its files are never listed in yerd-dump's manifest.json:
yerd-dump |
pcov |
|
|---|---|---|
| Build job | build (Rust) |
build-pcov (upstream C) |
| Manifest | manifest.json |
pcov-manifest.json |
| Checksums | SHA256SUMS |
SHA256SUMS-pcov |
| Artifact name | yerd-dump-<minor>-<os>-<arch>.{so,dll} |
pcov-<minor>-<os>-<arch>.{so,dll} |
(.so on Linux/macOS, .dll on Windows. The consumer matches on (php, os, arch) and
takes the filename from the manifest, so the extension suffix is immaterial to matching.)
Both manifests share the identical schema (version / php_minors /
files[{name,php,os,arch,sha256,size}]) and are attached to the same release. Yerd's
yerd-dump downloader reads manifest.json; Yerd's pcov downloader reads
pcov-manifest.json from …/releases/latest/download/. manifest.json content is
unchanged.
pcov is pinned to v1.0.12 (latest upstream tag, 2024-12-04) via the PCOV_VERSION
env in release.yml, fetched as a tagged tarball in CI (no submodule). Its source has no
upper-bound PHP_VERSION_ID gate, so it compiles across 8.2, 8.3, 8.4, 8.5 (8.5 takes
the >= 80400 branch; PECL/windows.php.net also ship 1.0.12 for 8.5). Every leg runs a
load + pcov\start/pcov\collect namespace smoke test, so an unsupported minor fails its
build and the count guard blocks the release. To adopt a newer pcov, bump PCOV_VERSION in
both release.yml and ci.yml. (The pcov-manifest.json version field is the v* tag,
not the pcov upstream version — yerd matches on file php/os/arch, not version.)
macOS build note. On the macOS cell pcov needs the Homebrew
pcre2keg's headers onCPPFLAGS(PHP'sphp_pcre.h#include "pcre2.h"); the job installspcre2and sets the flag. Linux ships those headers inline.
Windows build note. The Windows cell builds pcov from the same pinned
v1.0.12tag viaphp/php-windows-builder/extension(pinned action version) withrun-tests: false(we gate via our own load + namespace smoke, not pcov's upstream.phptsuite). The action emits a build zip inartifacts/; the staging step asserts it is-nts-/64-bit, extracts the versionedphp_pcov*.dll, and renames it topcov-<minor>-windows-x86_64.dll.windows.php.netships prebuilt1.0.12DLLs for 8.2–8.5 (incl. 8.5/VS17), so the from-source build is expected to succeed across all minors.
Nothing changes from the yerd-dump flow above — a single v* tag now produces both. The
release contains, in addition to the yerd-dump assets: pcov-<minor>-<os>-<arch>.{so,dll}
for every cell, SHA256SUMS-pcov, and pcov-manifest.json. 16 pcov artifacts (4 × 4); the
publish job fails if any cell is missing.
{ "version": "v0.1.0", "php_minors": ["8.2", "8.3", "8.4", "8.5"], "files": [ { "name": "yerd-dump-8.3-linux-x86_64.so", "php": "8.3", "os": "linux", "arch": "x86_64", "sha256": "…", "size": 123456 } ] }