diff --git a/.github/workflows/build-php-exts-windows.yml b/.github/workflows/build-php-exts-windows.yml index c6e04b4..325869e 100644 --- a/.github/workflows/build-php-exts-windows.yml +++ b/.github/workflows/build-php-exts-windows.yml @@ -7,6 +7,8 @@ # version as "@PACKAGE_VERSION@" on Windows, as in the imagick maintainers' own # Windows DLLs. # mongodb the MongoDB maintainers' own signed DLLs (PHP 8.1+), checked against GitHub's SHA-256 +# imap the PHP team's PECL DLLs (PHP 8.4+; the official builds have it up to 8.3), checked +# against the SHA-256 pinned in php.windows.extensions.imap # Published as php-exts--build-windows-x64.zip on the php-exts- release: # ext/php_.dll the extensions # *.dll libraries they need next to php.exe (ImageMagick's for imagick) diff --git a/.github/workflows/build-php-linux.yml b/.github/workflows/build-php-linux.yml index ea5f961..a37b5c7 100644 --- a/.github/workflows/build-php-linux.yml +++ b/.github/workflows/build-php-linux.yml @@ -72,7 +72,9 @@ jobs: - name: Read versions.json id: config run: | - jq -r '.php.linux | "SPC_VERSION=\(.spc)\nSTATIC_EXTS=\(.static_extensions)\nSHARED_EXTS=\(.shared_extensions)"' versions.json >> "$GITHUB_ENV" + # FrankenPHP (ZTS) leaves out frankenphp.skip_extensions: imap isn't thread-safe. + jq -r --arg pkg "$PKG" '(if $pkg == "frankenphp" then (.frankenphp.skip_extensions // "") | split(",") else [] end) as $skip + | .php.linux | "SPC_VERSION=\(.spc)\nSTATIC_EXTS=\(.static_extensions)\nSHARED_EXTS=\(.shared_extensions | split(",") - $skip | join(","))"' versions.json >> "$GITHUB_ENV" echo "MINOR=$(cut -d. -f1-2 <<<"$VERSION")" >> "$GITHUB_ENV" case "$PKG" in php) build="$(jq -r .php.linux.build versions.json)" ;; @@ -145,7 +147,9 @@ jobs: with: name: ${{ env.ASSET }} - name: Read versions.json - run: jq -r '.php.linux | "STATIC_EXTS=\(.static_extensions)\nSHARED_EXTS=\(.shared_extensions)"' versions.json >> "$GITHUB_ENV" + run: | + jq -r --arg pkg "$PKG" '(if $pkg == "frankenphp" then (.frankenphp.skip_extensions // "") | split(",") else [] end) as $skip + | .php.linux | "STATIC_EXTS=\(.static_extensions)\nSHARED_EXTS=\(.shared_extensions | split(",") - $skip | join(","))"' versions.json >> "$GITHUB_ENV" - name: Smoke test run: | mkdir pkg && tar -C pkg -xzf "$ASSET" diff --git a/.github/workflows/build-php-macos.yml b/.github/workflows/build-php-macos.yml index b941bb5..e48324a 100644 --- a/.github/workflows/build-php-macos.yml +++ b/.github/workflows/build-php-macos.yml @@ -63,7 +63,9 @@ jobs: - name: Read versions.json id: config run: | - jq -r '.php.macos | "SPC_VERSION=\(.spc)\nMIN_OS=\(.min_os)\nSTATIC_EXTS=\(.static_extensions)\nSHARED_EXTS=\(.shared_extensions)"' versions.json >> "$GITHUB_ENV" + # FrankenPHP (ZTS) leaves out frankenphp.skip_extensions: imap isn't thread-safe. + jq -r --arg pkg "$PKG" '(if $pkg == "frankenphp" then (.frankenphp.skip_extensions // "") | split(",") else [] end) as $skip + | .php.macos | "SPC_VERSION=\(.spc)\nMIN_OS=\(.min_os)\nSTATIC_EXTS=\(.static_extensions)\nSHARED_EXTS=\(.shared_extensions | split(",") - $skip | join(","))"' versions.json >> "$GITHUB_ENV" echo "MINOR=$(cut -d. -f1-2 <<<"$VERSION")" >> "$GITHUB_ENV" case "$PKG" in php) build="$(jq -r .php.macos.build versions.json)" ;; @@ -136,7 +138,9 @@ jobs: name: ${{ env.ASSET }} # Before Homebrew goes: jq is one of its tools. - name: Read versions.json - run: jq -r '.php.macos | "STATIC_EXTS=\(.static_extensions)\nSHARED_EXTS=\(.shared_extensions)"' versions.json >> "$GITHUB_ENV" + run: | + jq -r --arg pkg "$PKG" '(if $pkg == "frankenphp" then (.frankenphp.skip_extensions // "") | split(",") else [] end) as $skip + | .php.macos | "STATIC_EXTS=\(.static_extensions)\nSHARED_EXTS=\(.shared_extensions | split(",") - $skip | join(","))"' versions.json >> "$GITHUB_ENV" - name: Hide Homebrew run: sudo mv /opt/homebrew /opt/homebrew.hidden - name: Smoke test diff --git a/README.md b/README.md index 2cab50a..5218dc0 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,8 @@ its source). [php-windows-builder](https://github.com/php/php-windows-builder) against the official build of that minor, so they load into both `php` and `frankenphp` for Windows: apcu, igbinary, imagick (with ImageMagick), pcov, redis, xdebug and opentelemetry (from PHP 8.0 on, `min_php`), plus the -MongoDB maintainers' own DLLs from PHP 8.1 on. Releases per extension, and per minor where one +MongoDB maintainers' own DLLs from PHP 8.1 on and the PHP team's imap DLLs from PHP 8.4 on (see +imap). Releases per extension, and per minor where one needs another release (xdebug 3.1 for PHP 7.4), are in `php.windows.extensions`. memcached is macOS only. On Windows, imagick reports its version as `@PACKAGE_VERSION@` (`phpversion('imagick')`), like the imagick maintainers' own Windows DLLs: @@ -80,6 +81,20 @@ repository keeps the extension in `ext/`). It has no `composer.json` for php-win read its configure option from, so `--enable-opentelemetry` is passed explicitly. The smoke tests check that hooks fire (`scripts/smoke-opentelemetry.php`), not just that the extension loads. +### imap + +imap left PHP's core in 8.4 for [PECL](https://pecl.php.net/package/imap). The macOS and Linux +`php` packages have it as a shared extension, `ext/imap.so`, for every minor: 8.1–8.3 build the +extension in php-src, 8.4 and newer the PECL release pinned in `packages/php//build.sh`. +Both link static-php-cli's build of the UW IMAP c-client with OpenSSL, without Kerberos (GSSAPI). +The 8.4+ tarballs still ship `ext/imap/tests`, which static-php-cli takes for the extracted +extension, so `build.sh` removes it first. `frankenphp` doesn't have imap: it isn't thread-safe, +and `frankenphp.skip_extensions` leaves it out of the ZTS build. + +On Windows, the official builds have `php_imap.dll` up to PHP 8.3. For 8.4 and newer, the packs +add the PHP team's own PECL DLL from downloads.php.net. Those come without a published checksum, +so `php.windows.extensions.imap` pins the SHA-256 of each minor's zip. + ### PostgreSQL extensions An extension (`pgvector`; PostGIS, pgRouting and TimescaleDB follow) is built for every diff --git a/packages/php/linux/build.sh b/packages/php/linux/build.sh index 8800e6c..c19d5a7 100644 --- a/packages/php/linux/build.sh +++ b/packages/php/linux/build.sh @@ -52,6 +52,8 @@ DOWNLOAD_ARGS="${DOWNLOAD_ARGS:-} --custom-url=xdebug:https://xdebug.org/files/x # opentelemetry (only its hook() is used, by Flock's runtime capture): static-php-cli takes # whatever PECL's newest is; pin it like xdebug. Shared and not loaded by default. DOWNLOAD_ARGS="$DOWNLOAD_ARGS --custom-url=opentelemetry:https://pecl.php.net/get/opentelemetry-1.4.2.tgz" +# imap (PECL from PHP 8.4 on; 8.1–8.3 build the one in php-src): pinned like opentelemetry. +DOWNLOAD_ARGS="$DOWNLOAD_ARGS --custom-url=ext-imap:https://pecl.php.net/get/imap-1.0.3.tgz" echo "::group::static-php-cli $SPC_VERSION" if [[ ! -x ./spc ]]; then @@ -121,6 +123,13 @@ for attempt in 1 2 3 4; do # Start clean: libraries built for an extension we dropped would otherwise be linked # without their dependencies. Pre-built libraries unpack quickly. rm -rf buildroot source/php-src + # PHP 8.4+ tarballs still ship ext/imap/tests although imap moved to PECL: static-php-cli then + # takes ext/imap as extracted and skips the PECL source. Extract php-src first and drop the + # leftover (8.3 and older have the full extension, with config.m4, and keep it). + if [[ ",$all," == *",imap,"* ]]; then + ./spc extract php-src --source-only + [[ -f source/php-src/ext/imap/config.m4 ]] || rm -rf source/php-src/ext/imap + fi ok=1 # static-php-cli's post-build sanity checks are stricter than we need; the smoke test verifies. ./spc build "$STATIC_EXTS" ${pending:+--build-shared="$pending"} "${build_flags[@]}" 2>&1 | tee spc-build.out || ok=0 diff --git a/packages/php/macos/build.sh b/packages/php/macos/build.sh index 044fbd8..1cf3ec4 100644 --- a/packages/php/macos/build.sh +++ b/packages/php/macos/build.sh @@ -50,6 +50,8 @@ DOWNLOAD_ARGS="${DOWNLOAD_ARGS:-} --custom-url=xdebug:https://xdebug.org/files/x # opentelemetry (only its hook() is used, by Flock's runtime capture): static-php-cli takes # whatever PECL's newest is; pin it like xdebug. Shared and not loaded by default. DOWNLOAD_ARGS="$DOWNLOAD_ARGS --custom-url=opentelemetry:https://pecl.php.net/get/opentelemetry-1.4.2.tgz" +# imap (PECL from PHP 8.4 on; 8.1–8.3 build the one in php-src): pinned like opentelemetry. +DOWNLOAD_ARGS="$DOWNLOAD_ARGS --custom-url=ext-imap:https://pecl.php.net/get/imap-1.0.3.tgz" echo "::group::static-php-cli $SPC_VERSION" if [[ ! -x ./spc ]]; then @@ -119,6 +121,13 @@ for attempt in 1 2 3 4; do # Start clean: libraries built for an extension we dropped would otherwise be linked # without their dependencies. Pre-built libraries unpack quickly. rm -rf buildroot source/php-src + # PHP 8.4+ tarballs still ship ext/imap/tests although imap moved to PECL: static-php-cli then + # takes ext/imap as extracted and skips the PECL source. Extract php-src first and drop the + # leftover (8.3 and older have the full extension, with config.m4, and keep it). + if [[ ",$all," == *",imap,"* ]]; then + ./spc extract php-src --source-only + [[ -f source/php-src/ext/imap/config.m4 ]] || rm -rf source/php-src/ext/imap + fi ok=1 # static-php-cli's post-build sanity checks are stricter than we need; the smoke test verifies. ./spc build "$STATIC_EXTS" ${pending:+--build-shared="$pending"} "${build_flags[@]}" 2>&1 | tee spc-build.out || ok=0 diff --git a/scripts/windows/package-php-exts.ps1 b/scripts/windows/package-php-exts.ps1 index f328a4d..83f027b 100644 --- a/scripts/windows/package-php-exts.ps1 +++ b/scripts/windows/package-php-exts.ps1 @@ -4,6 +4,7 @@ # -Exts the build jobs' artifacts, one directory ext-- per extension # -MongoDB version of the MongoDB maintainers' own DLLs to add (PHP 8.1+), checked against # GitHub's SHA-256 of the release asset +# imap comes from php.windows.extensions.imap in versions.json (PHP 8.4+, the PHP team's PECL DLLs). # $env:EXTENSIONS lists the extensions built from source (JSON: name, repo, ref), as computed by the # workflow's config job from versions.json. Results go to stdout and $GITHUB_STEP_SUMMARY. # Usage: scripts/windows/package-php-exts.ps1 -Minor 8.4 -Exts exts -Out pkg [-MongoDB 2.5.5] @@ -87,6 +88,22 @@ if ($MongoDB -and [version]$Minor -ge [version]'8.1') { $built['mongodb'] = $MongoDB } +# imap: the official builds have it up to PHP 8.3; from 8.4 on it's PECL's, and the PHP team's own +# DLLs come without a published checksum, so php.windows.extensions.imap pins their SHA-256. +$imap = $versions.php.windows.extensions.imap +$imapSum = $imap.sha256.$Minor +if ($imapSum) { + $name = "php_imap-$($imap.version)-$Minor-ts-$vs-x64.zip" + $zip = Join-Path $work $name + Invoke-WebRequest "https://downloads.php.net/~windows/pecl/releases/imap/$($imap.version)/$name" -OutFile $zip + $sum = (Get-FileHash $zip -Algorithm SHA256).Hash.ToLower() + if ($sum -ne $imapSum) { throw "$name`: SHA-256 $sum, expected $imapSum" } + Expand-Archive $zip -DestinationPath (Join-Path $work 'imap') + Copy-Item (Join-Path $work 'imap/php_imap.dll') (Join-Path $extDir 'php_imap.dll') + Get-RepoLicense 'php/pecl-mail-imap' $imap.version 'imap' + $built['imap'] = $imap.version +} + # Load every DLL into the official build, as Flock will install it (ext\ and next to php.exe). Copy-Item (Join-Path $extDir '*') (Join-Path $php 'ext') -Force Get-ChildItem $Out -Filter *.dll | Copy-Item -Destination $php -Force diff --git a/versions.json b/versions.json index 9038a3b..d917d8b 100644 --- a/versions.json +++ b/versions.json @@ -2,24 +2,24 @@ "php": { "macos": { "minors": ["8.1", "8.2", "8.3", "8.4", "8.5"], - "build": 2, + "build": 3, "spc": "2.8.5", "min_os": "13.0", "static_extensions": "bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,gd,gmp,iconv,igbinary,intl,ldap,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pdo_pgsql,pdo_sqlite,pgsql,phar,posix,readline,redis,session,shmop,simplexml,soap,sockets,sodium,sqlite3,sysvmsg,sysvsem,sysvshm,tokenizer,xml,xmlreader,xmlwriter,xsl,zip,zlib,apcu", - "shared_extensions": "xdebug,imagick,pcov,mongodb,memcached,opentelemetry" + "shared_extensions": "xdebug,imagick,pcov,mongodb,memcached,opentelemetry,imap" }, "linux": { "minors": ["8.1", "8.2", "8.3", "8.4", "8.5"], - "build": 1, + "build": 2, "spc": "2.8.5", "static_extensions": "bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,gd,gmp,iconv,igbinary,intl,ldap,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pdo_pgsql,pdo_sqlite,pgsql,phar,posix,readline,redis,session,shmop,simplexml,soap,sockets,sodium,sqlite3,sysvmsg,sysvsem,sysvshm,tokenizer,xml,xmlreader,xmlwriter,xsl,zip,zlib,apcu", - "shared_extensions": "xdebug,imagick,pcov,mongodb,memcached,opentelemetry" + "shared_extensions": "xdebug,imagick,pcov,mongodb,memcached,opentelemetry,imap" }, "windows": { "minors": ["7.4", "8.0", "8.1", "8.2", "8.3", "8.4", "8.5"], "build": 1, "extensions": { - "build": 2, + "build": 3, "from_source": { "apcu": { "repo": "krakjoe/apcu", "ref": "v5.1.28" }, "igbinary": { "repo": "igbinary/igbinary", "ref": "3.2.16", "refs": { "8.5": "3.2.17RC1" }, "args": "--enable-igbinary=yes" }, @@ -29,13 +29,21 @@ "xdebug": { "repo": "xdebug/xdebug", "ref": "3.5.3", "refs": { "7.4": "3.1.6", "8.6": "3.6.0alpha1" }, "args": "--with-xdebug=shared" }, "opentelemetry": { "repo": "open-telemetry/opentelemetry-php-instrumentation", "url": "https://pecl.php.net/package/opentelemetry", "ref": "1.4.2", "min_php": "8.0", "args": "--enable-opentelemetry" } }, - "mongodb": "2.5.5" + "mongodb": "2.5.5", + "imap": { + "version": "1.0.3", + "sha256": { + "8.4": "999b6041b0b6120a8b62da3e4011f3a79ee6731184e16f1b2c7cf4896b48367a", + "8.5": "fac1258ffab3425411770fdb0b1bfdd66f51eecbf22345aa259aec4ca873c342" + } + } } } }, "frankenphp": { "version": "1.13.0", "minors": ["8.2", "8.3", "8.4", "8.5"], + "skip_extensions": "imap", "macos": { "build": 2 }, "windows": { "build": 1 }, "linux": { "build": 1 }