Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

114 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

php-sdk

Pre-built PHP embed SAPI static libraries (libphp.a / php8embed.lib) plus headers, for the OS/arch/PHP-version combinations ePHPm supports.

Built with static-php-cli — specifically the luthermonson/static-php-cli fork, pinned by SPC_VERSION in .github/workflows/build.yml. Every SDK is a spc build --build-embed output: a static libphp.a, never a shared libphp.so.

What this builds

Platform Tarball suffix Output
Linux x86_64 (glibc, floor 2.28) -linux-x86_64-gnu lib/libphp.a + headers, ZTS
Linux aarch64 (glibc, floor 2.28) -linux-aarch64-gnu lib/libphp.a + headers, ZTS
Linux x86_64 (musl, fully static) -linux-x86_64 lib/libphp.a + headers, ZTS
Linux aarch64 (musl, fully static) -linux-aarch64 lib/libphp.a + headers, ZTS
macOS aarch64 -macos-aarch64 lib/libphp.a + headers, ZTS
Windows x86_64 -windows-x86_64 lib/php8embed.lib + dep .libs + headers, ZTS
Linux x86_64 (glibc, NTS) -linux-x86_64-gnu-nts lib/libphp.a + headers, non-thread-safe
Linux aarch64 (glibc, NTS) -linux-aarch64-gnu-nts lib/libphp.a + headers, non-thread-safe

The glibc floor is 2.28 (built on AlmaLinux 8 with gcc-toolset-13), so a consumer binary linked against these runs on RHEL/Alma 8, Ubuntu 20.04+, Debian 10+, Amazon Linux 2023 and Fedora 40+.

ZTS and NTS

ZTS is the default and is unsuffixed. ePHPm is a threaded server and links the ZTS SDK; renaming those assets breaks it. The -gnu-nts variants exist for consumers that cannot use a thread-safe build.

Detect which one you have from include/php/main/php_config.h: thread-safe builds define ZTS 1, non-thread-safe builds do not define ZTS at all.

NTS tarballs:

  • are Linux-glibc only (x86_64 and aarch64),
  • are not part of a platform=all build and do not gate release completeness — a failed NTS build never blocks a release,
  • carry ffi in addition to the shared extension set (see below),
  • are kept current only for the minors listed under minors_nts in versions.json.

Tarball layout

lib/                       libphp.a (or php8embed.lib) + every static dep archive
include/php/
  main/                    includes php_config.h (ZTS marker) and php_version.h
  Zend/
  TSRM/
  ext/
  sapi/embed/php_embed.h
bin/php-config             Linux and macOS only
THIRD-PARTY-NOTICES.txt

Assets are named:

php-sdk-{php_version}-{os}-{arch}[-gnu][-nts].tar.gz

bin/php-config

A relocatable POSIX-sh shim, generated by tools/mk-sdk-metadata.sh at package time. It resolves its own prefix at run time, so the tarball can be extracted anywhere. It exists because build scripts that expect a system PHP (php-config --includes) run it unconditionally.

Supported: --prefix, --includes, --include-dir, --ldflags, --libs, --extension-dir, --version, --vernum, --php-sapis, --help.

Deliberately refused, with a message and a non-zero exit, rather than answered with a plausible lie:

  • --php-binary — this SDK ships no PHP executable.
  • --configure-options — static-php-cli strips the configure line from the build.

--libs enumerates the static archives in lib/. It is a starting point, not a verified link line: whole-archive and symbol-ordering decisions belong to the consumer. See ePHPm's crates/ephpm/build.rs for a working static link against these tarballs, including the -Wl,--export-dynamic that lets extension=-loaded .so files resolve zend_* symbols against the host binary.

No php-config is generated on Windows — it is a shell script and nothing in the MSVC toolchain consumes one.

Extensions

Compiled into libphp.a on Linux and macOS:

bcmath, bz2, calendar, ctype, curl, dom, exif, fileinfo, filter, ftp, gd,
gettext, gmp, hash, iconv, intl, mbregex, mbstring, mysqli, mysqlnd, opcache,
openssl, pcntl, pcre, pdo, pdo_mysql, pdo_pgsql, pdo_sqlite, pgsql, phar,
posix, session, shmop, simplexml, soap, sockets, sodium, sqlite3, sysvmsg,
sysvsem, sysvshm, tokenizer, xml, xmlreader, xmlwriter, xsl, zip, zlib

The NTS variants additionally include ffi.

Windows drops the Unix-only entries (pcntl, posix, sysv*), plus gmp, pgsql and pdo_pgsql, which static-php-cli cannot build statically on Windows today. It also does not yet carry shmop or sockets — PHP supports both there, but neither has been validated through spc's Windows toolchain from this repo.

ffi is not in the shared extension set on purpose. static-php-cli's ext-ffi passes --enable-zend-signals, and extension arguments land after the target arguments on the configure line, so it would override the --disable-zend-signals that spc emits for ZTS builds — silently changing signal behavior in the SDK ePHPm links. NTS builds emit no --disable-zend-signals, so ffi rides along there.

Loadable shared ZTS extensions (igbinary, msgpack, apcu, redis, mongodb) are a separate artifact built by .github/workflows/extensions.yml and published under ext-<version> tags. That catalog is ZTS-only by design: Debian and Sury publish no ZTS builds, which is the gap it fills. There is no NTS catalog.

Building

# full release
gh workflow run build.yml -f php_version=8.5.2

# one platform (uploads to the existing release, leaves other assets alone)
gh workflow run build.yml -f php_version=8.5.2 -f platform=linux-aarch64-gnu

# non-thread-safe variant
gh workflow run build.yml -f php_version=8.4.23 -f platform=linux-x86_64-gnu-nts

Any dispatch from a branch other than main MUST set release_tag_suffix. On 2026-07-13 a validation build from a side branch uploaded to the plain v8.5.7 tag and overwrote four production assets. The input exists to make that impossible:

gh workflow run build.yml --ref my-branch \
  -f php_version=8.5.7 -f platform=linux-x86_64-gnu -f release_tag_suffix=-mytest

watch-php.yml polls php.net every 6 hours, mirrors new php-src tarballs to the php-sources release tag, and dispatches builds for anything missing.

Dependency mirror

Builds do not fetch PHP or its GNU dependencies from upstream. Both come from this repo's own php-sources release tag, fetched with plain curl and handed to static-php-cli as file:// custom URLs.

Asset on php-sources Populated by Consumed by
php-X.Y.Z.tar.gz watch-php.yml build.yml, extensions.yml
libiconv-*, gettext-*, ncurses-*, libunistring-*, libidn2-* mirror-deps.yml build.yml, extensions.yml
gnu-deps-manifest.txt, SHA256SUMS mirror-deps.yml build.yml, extensions.yml

Those libraries resolve through static-php-cli type: filelist sources pointed at https://ftpmirror.gnu.org/gnu/<pkg>/. That host is a redirector to volunteer backend mirrors and returns HTTP errors when it picks a bad one. None of the five has a source-mirror fallback in spc, so a single bad backend fails the whole spc download and therefore the build. That took every scheduled build in this repo down from 2026-08-06 onward.

gmp is also GNU-hosted but is not in the mirror: it is the one GNU dependency with its own source-mirror fallback in spc, so mirror-deps.yml resolved it from there and correctly did not select it. The mirrored set is whatever spc actually resolved from ftpmirror.gnu.org, not a fixed list.

Refresh the mirror when you want newer dependency versions:

gh workflow run mirror-deps.yml                      # resolve + upload
gh workflow run mirror-deps.yml -f dry_run=true      # resolve + print only

mirror-deps.yml runs on a GitHub-hosted runner (different egress from the self-hosted fleet) but resolves inside the same almalinux:8 container with the same SPC_TARGET, so it picks exactly the artifacts the fleet would have. The set is derived from spc's own downloads/.cache.json — every artifact whose source URL is on ftpmirror.gnu.org.

Note the tradeoff: filelist sources normally track the newest tarball in the directory index on every build. Once mirrored, builds pin to whatever was current when mirror-deps.yml last ran. That is the same tradeoff php-src already makes, and it stops builds drifting underneath us.

If the manifest is missing from the release tag, builds log a warning and fall back to fetching from upstream GNU mirrors — the pre-mirror behaviour, and the known failure mode.

Consuming

ePHPm's release workflow:

- name: Download PHP SDK
  run: |
    gh release download v${{ matrix.php }} \
      --repo ephpm/php-sdk \
      --pattern "php-sdk-*-${{ matrix.os }}-${{ matrix.arch }}.tar.gz" \
      --output php-sdk.tar.gz
    mkdir -p php-sdk && tar xzf php-sdk.tar.gz -C php-sdk

then builds with PHP_SDK_PATH=php-sdk cargo build --release.

Licensing

The MIT license in this repository covers the workflows and scripts here. It does not cover the contents of the published tarballs: those are an aggregate of PHP (PHP License 3.01 / Zend Engine License 2.00) and roughly twenty upstream libraries, each under its own terms — including a bundled libstdc++.a carrying the GCC Runtime Library Exception.

Every tarball ships a THIRD-PARTY-NOTICES.txt listing the components, their SPDX identifiers, and where to get the full license texts. Read it before redistributing anything built from this SDK.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages