Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions .github/scripts/install-alpine-php.sh
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
#!/bin/sh
# Installs PHP $PHP_MINOR and the extension's build tools into the Alpine
# containers of the musl turbo legs in phar.yml. With PHP_ZTS=1 it builds a
# thread-safe PHP from the release tarball instead (build-php.sh): Alpine
# packages no thread-safe PHP, while the official php:*-alpine Docker images
# are thread-safe from 8.6 on.
# containers of the musl turbo legs in phar.yml. It builds PHP from the
# release tarball instead (build-php.sh) with PHP_ZTS=1 — Alpine packages
# no thread-safe PHP, while the official php:*-alpine Docker images are
# thread-safe from 8.6 on — and for a minor the Alpine release no longer
# packages (8.2).
set -eu

apk add --no-cache bash curl git make g++ musl-dev linux-headers patch tar zstd

if [ "${PHP_ZTS:-0}" = "1" ]; then
apk add --no-cache jq pkgconf xz libxml2-dev oniguruma-dev curl-dev openssl-dev zlib-dev
PHP_MINOR="$PHP_MINOR" PHP_ZTS=1 sh "$(dirname "$0")/../turbo-build/build-php.sh"
exit 0
fi

V="$(echo "$PHP_MINOR" | tr -d .)"
# Alpine's php86 packages are currently only in edge/testing.
if [ "$PHP_MINOR" = "8.6" ]; then
echo 'https://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories
fi

if [ "${PHP_ZTS:-0}" = "1" ] || [ -z "$(apk search -q -x "php$V")" ]; then
apk add --no-cache jq pkgconf xz libxml2-dev oniguruma-dev curl-dev openssl-dev zlib-dev
PHP_MINOR="$PHP_MINOR" PHP_ZTS="${PHP_ZTS:-0}" sh "$(dirname "$0")/../turbo-build/build-php.sh"
exit 0
fi

apk add --no-cache \
"php$V" "php$V-dev" "php$V-ctype" "php$V-curl" "php$V-mbstring" \
"php$V-tokenizer" "php$V-iconv" "php$V-openssl" "php$V-phar" \
Expand Down
6 changes: 3 additions & 3 deletions .github/turbo-build/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Prebuilt image for the turbo-compile gnu legs in phar.yml, published to
# ghcr.io/phpstan/turbo-build by turbo-build-image.yml (tags gnu-php8.3,
# gnu-php8.4, gnu-php8.5, gnu-php8.6 and the thread-safe gnu-php8.3-zts to
# gnu-php8.6-zts; each a linux/amd64 + linux/arm64 manifest).
# ghcr.io/phpstan/turbo-build by turbo-build-image.yml (tags gnu-php8.2 to
# gnu-php8.6 and the thread-safe gnu-php8.2-zts to gnu-php8.6-zts; each a
# linux/amd64 + linux/arm64 manifest).
#
# Baking the PHP toolchain in keeps apt and the ondrej/php PPA out of the
# compile jobs entirely: ports.ubuntu.com (the only Ubuntu arm64 mirror,
Expand Down
12 changes: 10 additions & 2 deletions .github/turbo-build/build-php.sh
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,14 @@ tar -xJf php.tar.xz -C php-src --strip-components=1
rm php.tar.xz

cd php-src
# shellcheck disable=SC2086 # ZTS_FLAG is empty or a single word
# PHP 8.2's x86-64 JIT does not assemble for musl ZTS with binutils 2.43+
# (alpine:3.24): "@TLSGD operator requires `%rdi' as dest register", fixed
# only from 8.3. Nothing these builds run uses the JIT.
JIT_FLAG=""
case "$PHP_VERSION" in
8.2.*) JIT_FLAG="--disable-opcache-jit" ;;
esac
# shellcheck disable=SC2086 # ZTS_FLAG and JIT_FLAG are empty or a single word
./configure \
--prefix=/usr/local \
--disable-cgi \
Expand All @@ -72,7 +79,8 @@ cd php-src
--with-curl \
--with-openssl \
--with-zlib \
$ZTS_FLAG
$ZTS_FLAG \
$JIT_FLAG
make -j"$(nproc)"
make install

Expand Down
47 changes: 32 additions & 15 deletions .github/workflows/phar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ jobs:
with:
egress-policy: audit

# the compiler-tests job runs the phar on PHP 8.2, where no binary exists
# and the note is not printed
# the compiler-tests job runs the phar only for `list`, which prints
# no note
- name: "Install PHP"
uses: "shivammathur/setup-php@eb7c497e18156a6bbabfef1d3a82760b9eda3962" # 2.40.0
with:
Expand Down Expand Up @@ -828,7 +828,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php-version: ["8.3", "8.4", "8.5", "8.6"]
php-version: ["8.2", "8.3", "8.4", "8.5", "8.6"]
# the musl arm64 legs are in turbo-compile-musl-arm64
target:
- name: "linux-gnu-x86_64"
Expand Down Expand Up @@ -1002,7 +1002,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php-version: ["8.3", "8.4", "8.5", "8.6"]
php-version: ["8.2", "8.3", "8.4", "8.5", "8.6"]
# thread-safe for every minor too, see turbo-compile
ts: ["nts", "zts"]
# see turbo-compile
Expand Down Expand Up @@ -1125,7 +1125,7 @@ jobs:
fail-fast: false
matrix:
# every PHP the cores run on; thread-safe builds are "<minor>-zts"
php-version: ["8.3", "8.4", "8.5", "8.6", "8.3-zts", "8.4-zts", "8.5-zts", "8.6-zts"]
php-version: ["8.2", "8.3", "8.4", "8.5", "8.6", "8.2-zts", "8.3-zts", "8.4-zts", "8.5-zts", "8.6-zts"]

steps:
- name: Harden the runner (Audit all outbound calls)
Expand Down Expand Up @@ -1257,6 +1257,7 @@ jobs:
fail-fast: false
matrix:
image:
- "php:8.2-cli-bookworm"
- "php:8.3.21-cli-bookworm"
- "php:8.3.22-cli-bookworm"
- "php:8.4-cli-bookworm"
Expand All @@ -1267,6 +1268,9 @@ jobs:
- "php:8.6-rc-cli-alpine"
check: ["tests", "phpstan"]
include:
- image: "php:8.2-cli-bookworm"
php-version: "8.2"
binary: "linux-gnu-x86_64-php8.2"
- image: "php:8.3.21-cli-bookworm"
php-version: "8.3"
binary: "linux-gnu-x86_64-php8.3"
Expand Down Expand Up @@ -1562,16 +1566,19 @@ jobs:
strategy:
fail-fast: false
matrix:
php-version: ["8.3", "8.4", "8.5", "8.6"]
php-version: ["8.2", "8.3", "8.4", "8.5", "8.6"]
ts: ["nts", "zts"]
# see turbo-compile
variant: ${{ fromJSON((startsWith(github.ref, 'refs/tags/') || contains(github.event.pull_request.labels.*.name, 'turbo-pie')) && '["split", "pie"]' || '["split"]') }}
# The official 8.3 Windows binaries are built with VS16 (linker
# 14.2x) and PHP's module loader is one-directional (module toolset
# generation <= core's), so the 8.3 DLL must be linked with the v142
# toolset — which the windows-2022 image ships alongside the default
# v143. The devel pack name carries the same vs infix.
# The official 8.2 and 8.3 Windows binaries are built with VS16
# (linker 14.2x) and PHP's module loader is one-directional (module
# toolset generation <= core's), so their DLLs must be linked with
# the v142 toolset — which the windows-2022 image ships alongside the
# default v143. The devel pack name carries the same vs infix.
include:
- php-version: "8.2"
vs: "vs16"
toolset: "14.29"
- php-version: "8.3"
vs: "vs16"
toolset: "14.29"
Expand Down Expand Up @@ -1851,7 +1858,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php-version: ["8.3", "8.4", "8.5", "8.6"]
php-version: ["8.2", "8.3", "8.4", "8.5", "8.6"]
target: ["linux-gnu-x86_64", "linux-gnu-arm64", "macos-arm64", "windows-x86_64"]
ts: ["nts", "zts"]
# macOS ships no ZTS binary (see turbo-compile)
Expand All @@ -1878,6 +1885,16 @@ jobs:
container: "ghcr.io/phpstan/turbo-build:gnu-php8.6"
# the linux-gnu ZTS legs, in the image the binary is compiled in
# (see above); the official php:*-zts images get turbo-docker-run
- target: "linux-gnu-x86_64"
php-version: "8.2"
ts: "zts"
runs-on: "ubuntu-latest"
container: "ghcr.io/phpstan/turbo-build:gnu-php8.2-zts"
- target: "linux-gnu-arm64"
php-version: "8.2"
ts: "zts"
runs-on: "ubuntu-24.04-arm"
container: "ghcr.io/phpstan/turbo-build:gnu-php8.2-zts"
- target: "linux-gnu-x86_64"
php-version: "8.3"
ts: "zts"
Expand Down Expand Up @@ -2049,7 +2066,7 @@ jobs:
fail-fast: false
matrix:
arch: ["x86_64", "arm64"]
php-version: ["8.3", "8.4", "8.5", "8.6"]
php-version: ["8.2", "8.3", "8.4", "8.5", "8.6"]
# thread-safe for every minor too, see turbo-compile
ts: ["nts", "zts"]

Expand Down Expand Up @@ -2148,7 +2165,7 @@ jobs:
# vs17-built official PHP loads it fine.
matrix:
operating-system: ["ubuntu-latest", "windows-latest"]
php-version: ["8.3", "8.4", "8.5", "8.6"]
php-version: ["8.2", "8.3", "8.4", "8.5", "8.6"]
ts: ["nts", "zts"]
script: ["make tests", "make phpstan"]
# The Linux ZTS binaries run the same checks in turbo-docker-run, in
Expand Down Expand Up @@ -2346,7 +2363,7 @@ jobs:
include:
# below TurboExtensionSelector::MINIMUM_PHP_VERSION_ID there is no
# binary to find: the workers get the OPcache entries alone
- php-version: "8.2"
- php-version: "8.1"
turbo: "off"
- php-version: "8.5"
turbo: "on"
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/turbo-build-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
name: "Build Turbo compile images"

# Builds .github/turbo-build/Dockerfile natively on x86_64 and arm64
# runners and publishes ghcr.io/phpstan/turbo-build:gnu-php{8.3,8.4,8.5,8.6}
# and the thread-safe gnu-php{8.3,8.4,8.5,8.6}-zts as multi-arch manifests. The
# runners and publishes ghcr.io/phpstan/turbo-build:gnu-php{8.2,8.3,8.4,8.5,8.6}
# and the thread-safe gnu-php{8.2,8.3,8.4,8.5,8.6}-zts as multi-arch manifests. The
# turbo-compile gnu legs in phar.yml run in these images, so their only
# network dependency is a GHCR pull — no apt, no ports.ubuntu.com, no PPA at
# compile time.
Expand Down Expand Up @@ -47,7 +47,7 @@ jobs:
fail-fast: false
matrix:
# <minor>[-zts]; a -zts tag builds a thread-safe PHP of that minor
tag: ["8.3", "8.4", "8.5", "8.6", "8.3-zts", "8.4-zts", "8.5-zts", "8.6-zts"]
tag: ["8.2", "8.3", "8.4", "8.5", "8.6", "8.2-zts", "8.3-zts", "8.4-zts", "8.5-zts", "8.6-zts"]
platform:
- arch: "amd64"
runs-on: "ubuntu-latest"
Expand Down Expand Up @@ -106,7 +106,7 @@ jobs:

strategy:
matrix:
tag: ["8.3", "8.4", "8.5", "8.6", "8.3-zts", "8.4-zts", "8.5-zts", "8.6-zts"]
tag: ["8.2", "8.3", "8.4", "8.5", "8.6", "8.2-zts", "8.3-zts", "8.4-zts", "8.5-zts", "8.6-zts"]

env:
TAG: "ghcr.io/phpstan/turbo-build:gnu-php${{ matrix.tag }}"
Expand Down
2 changes: 1 addition & 1 deletion src/Turbo/TurboExtensionSelector.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ final class TurboExtensionSelector
* matrix. Older runtimes have no binary to find, so they skip the lookup
* (and with it the process restart) entirely.
*/
public const MINIMUM_PHP_VERSION_ID = 80300;
public const MINIMUM_PHP_VERSION_ID = 80200;

/** @api */
public const EXTENSION_PATH_INI = 'phpstan.turboExtensionPath';
Expand Down
8 changes: 6 additions & 2 deletions turbo-ext/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ self-analysis).
**Most users do not need to install anything.** The
[phpstan/phpstan](https://github.com/phpstan/phpstan) Composer package ships
prebuilt binaries for the most common platforms — Linux (glibc and musl,
x86_64 and arm64), macOS (arm64), and Windows (x86_64), for PHP 8.3 and newer — and
x86_64 and arm64), macOS (arm64), and Windows (x86_64), for PHP 8.2 and newer — and
PHPStan automatically loads the one matching your runtime into its worker
processes.

Expand Down Expand Up @@ -420,6 +420,10 @@ layout moved through `abi.h`:
| `ZSTR_KNOWN()` ids, `IS_REFERENCE_EX`, `ZEND_ACC_USE_GUARDS`, lazy-object flags | `pt_abi` values (`PT_ABI_KNOWN_STRINGS`, …) |
| ZPP error codes / `Z_EXPECTED_*` numbering, parse slow paths (8.6) | neutral ZPP macros in `abi.h`, translated by `Abi.cpp` |
| functions whose signature or behaviour changed (`zend_create_closure`, `zend_dval_to_lval`, …) or that stopped being exported (`zend_call_known_function`, …) | function pointers in `pt_abi`, implemented in `Abi.cpp` |
| `EG(stack_base)` / `EG(stack_limit)` and `zend_call_stack.h` (8.3) | `pt_abi.eg_stack_*`; before 8.3, `Abi.cpp`'s own pair, determined like 8.3 does, and the two inline helpers spelled out in `abi.h` |
| `zend_fcall_info_cache.closure` (8.3 appended it) | 8.3's layout declared over the older headers' struct (`support.h`, `abi.h`); the older engines use the first four members, the shared code never reads `closure` |
| class names of internal arginfo (`_ZEND_TYPE_LITERAL_NAME_BIT`, 8.3) | pinned in `abi.h`, turned into the plain name bit by `Abi.cpp` before 8.3 |
| `zend_zval_value_name()` (8.3; 8.2's type errors use `zend_zval_type_name()`) | `pt_abi.zval_value_name` |
| `#if PHP_VERSION_ID` gates | `PT_ABI_SINCE(version, then, otherwise)`, decided at run time |
| helpers re-spelled without changing behaviour (macro → inline function) | one definition pinned in `abi.h` ("codegen pins") |

Expand Down Expand Up @@ -459,7 +463,7 @@ against them (the import library expected in `turbo-ext/`).

In CI (`.github/workflows/phar.yml`), `turbo-compile-core*` build one core
per platform — profile-guided, against `php-version` of its matrix (Windows:
against 8.3 with VS16, the oldest toolset, since PHP checks the toolset of
against 8.3 with VS16, the oldest toolset — 8.2's too — since PHP checks the toolset of
the DLL it loads, the extension, and a core linked with an older one runs on
any newer VC runtime) — and are what `turbo-origins` reuses from earlier
runs; `turbo-compile*` link each version's extension against them in a
Expand Down
2 changes: 1 addition & 1 deletion turbo-ext/bin/shared-core/check-linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ set -euo pipefail
S=${SHARED_CORE_WORK_DIR:?set SHARED_CORE_WORK_DIR to a scratch directory}
HERE=$(cd "$(dirname "$0")" && pwd)
REFERENCE=${GATE_REFERENCE:-8.5}
VERSIONS=${GATE_VERSIONS:-8.3 8.4 8.5 8.6 8.3-zts 8.4-zts 8.5-zts 8.6-zts}
VERSIONS=${GATE_VERSIONS:-8.2 8.3 8.4 8.5 8.6 8.2-zts 8.3-zts 8.4-zts 8.5-zts 8.6-zts}
case " $VERSIONS " in
*" $REFERENCE "*) ;;
*) VERSIONS="$REFERENCE $VERSIONS" ;;
Expand Down
6 changes: 4 additions & 2 deletions turbo-ext/bin/shared-core/fingerprint-linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
# one version each; gate.py compare then needs only the .tsv files.
#
# Needs docker and an llvm-objdump (LLVM_OBJDUMP, else the newest found).
# GATE_BASE_IMAGE replaces ghcr.io/phpstan/turbo-build, e.g. with images
# built locally from .github/turbo-build.
# Usage: SHARED_CORE_WORK_DIR=<scratch directory> [GATE_VERSIONS="8.4 8.6-zts"] fingerprint-linux.sh
set -euo pipefail

S=${SHARED_CORE_WORK_DIR:?set SHARED_CORE_WORK_DIR to a scratch directory}
HERE=$(cd "$(dirname "$0")" && pwd)
VERSIONS=${GATE_VERSIONS:-8.3 8.4 8.5 8.6 8.3-zts 8.4-zts 8.5-zts 8.6-zts}
VERSIONS=${GATE_VERSIONS:-8.2 8.3 8.4 8.5 8.6 8.2-zts 8.3-zts 8.4-zts 8.5-zts 8.6-zts}
if [ -z "${LLVM_OBJDUMP:-}" ]; then
LLVM_OBJDUMP=$(command -v llvm-objdump || { ls /usr/bin/llvm-objdump-* /opt/homebrew/opt/llvm/bin/llvm-objdump 2>/dev/null || true; } | sort -V | tail -1)
fi
Expand All @@ -21,7 +23,7 @@ export LLVM_OBJDUMP

# the CI build images plus clang
for v in $VERSIONS; do
printf 'FROM ghcr.io/phpstan/turbo-build:gnu-php%s\nRUN apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq clang-14 > /dev/null && rm -rf /var/lib/apt/lists/*\n' "$v" \
printf 'FROM %s:gnu-php%s\nRUN apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq clang-14 > /dev/null && rm -rf /var/lib/apt/lists/*\n' "${GATE_BASE_IMAGE:-ghcr.io/phpstan/turbo-build}" "$v" \
| docker build -q ${GATE_PLATFORM:+--platform "$GATE_PLATFORM"} -t "turbo-build-clang:gnu-php$v" - > /dev/null
done

Expand Down
2 changes: 1 addition & 1 deletion turbo-ext/bin/shared-core/gate-linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# compares the results function by function.
S=${SHARED_CORE_WORK_DIR:?set SHARED_CORE_WORK_DIR to a scratch directory}
WT=$(cd "$(dirname "$0")/../.." && pwd)
VERSIONS=${GATE_VERSIONS:-8.3 8.4 8.5 8.6}
VERSIONS=${GATE_VERSIONS:-8.2 8.3 8.4 8.5 8.6}
JOBS=${GATE_JOBS:-3} # per version; the versions build at the same time
# GATE_PLATFORM (e.g. linux/amd64) runs the images of another architecture —
# code generation differs between them, and CI gates on x86_64
Expand Down
6 changes: 3 additions & 3 deletions turbo-ext/bin/shared-core/link-split-linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
set -e
S=${SHARED_CORE_WORK_DIR:?set SHARED_CORE_WORK_DIR to a scratch directory}
REPO=$(cd "$(dirname "$0")/../../.." && pwd)
VERSIONS=${GATE_VERSIONS:-8.3 8.4 8.5 8.6}
VERSIONS=${GATE_VERSIONS:-8.2 8.3 8.4 8.5 8.6}
CORE_FROM=${CORE_FROM:-8.4}
OUT=$S/split-linux
rm -rf "$OUT"; mkdir -p "$OUT"
Expand All @@ -17,14 +17,14 @@ SHIM='src/Abi.o src/Shadow.o src/TrustedTypes.o src/main.o src/TerminateHandler.
# statically folded libstdc++ out of both dynamic symbol tables
FLAGS='-static-libstdc++ -static-libgcc -Wl,--exclude-libs,ALL -Wl,--gc-sections -Wl,-z,relro,-z,now -Wl,-z,noexecstack'

docker run --rm -v "$S/lx-$CORE_FROM:/build" -v "$OUT:/out" -w /build "ghcr.io/phpstan/turbo-build:gnu-php$CORE_FROM" sh -ec "
docker run --rm -v "$S/lx-$CORE_FROM:/build" -v "$OUT:/out" -w /build "${GATE_IMAGE:-ghcr.io/phpstan/turbo-build}:gnu-php$CORE_FROM" sh -ec "
core=\$(find src -name '*.o' | grep -v -E 'src/(Abi|Shadow|TrustedTypes|main)\.o\$' | sort)
g++ -shared $FLAGS -Wl,-soname,libphpstan_turbo_core.so -o /out/libphpstan_turbo_core.so \$core
echo \"core exports: \$(nm -D --defined-only /out/libphpstan_turbo_core.so | wc -l)\"
"

for v in $VERSIONS; do
docker run --rm -v "$S/lx-$v:/build" -v "$OUT:/out" -v "$REPO:/repo:ro" -w /build "ghcr.io/phpstan/turbo-build:gnu-php$v" sh -ec "
docker run --rm -v "$S/lx-$v:/build" -v "$OUT:/out" -v "$REPO:/repo:ro" -w /build "${GATE_IMAGE:-ghcr.io/phpstan/turbo-build}:gnu-php$v" sh -ec "
g++ -shared $FLAGS -Wl,-rpath,'\$ORIGIN' -o /out/phpstan_turbo-$v.so $SHIM -L/out -lphpstan_turbo_core
# every extension symbol must come from the core: undefined pt_*
# symbols would only fail at load time
Expand Down
2 changes: 1 addition & 1 deletion turbo-ext/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"type": "php-ext",
"homepage": "https://phpstan.org",
"require": {
"php": "~8.3.0 || ~8.4.0 || ~8.5.0 || ~8.6.0"
"php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0 || ~8.6.0"
},
"php-ext": {
"extension-name": "phpstan_turbo",
Expand Down
Loading
Loading