Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
4f76942
toolchain fixes forward port from v2-pgo
henderkes May 10, 2026
6e32672
better deduplicate_flags
henderkes May 11, 2026
efdd2a7
update libraries to honour user flags
henderkes May 11, 2026
743934d
use resolved dependency tree instead of asking for with_suggests ever…
henderkes May 11, 2026
7e6e9d8
add pgo capabilities v3 style
henderkes May 11, 2026
bfaa7eb
Merge remote-tracking branch 'origin/v3' into feat/pgo-v3
henderkes May 11, 2026
a585359
reset registry
henderkes May 11, 2026
4172508
use {pkg_root_path} for packages, otherwise containers get confused w…
henderkes May 12, 2026
270e2d6
cant reset it because of the same reason x(
henderkes May 12, 2026
c1c34d8
trust filesystem, not downloads
henderkes May 12, 2026
8453f69
fix BUILD_CC=cc workaround root cause (minijit trips zig default unde…
henderkes May 12, 2026
57ef042
fix phpunit failure
henderkes May 12, 2026
defd50f
wrong exception type
henderkes May 12, 2026
814014e
array
henderkes May 12, 2026
2415b7d
we don't need this anymore
henderkes May 12, 2026
4754faf
also build curl exe on windows
henderkes May 12, 2026
445c0b3
don't add fno-sanitize=undefined for library builds
henderkes May 12, 2026
9addbe2
oops
henderkes May 12, 2026
b880ef7
allow * stage to subscribe to everything
henderkes May 12, 2026
db794bf
strange shit
henderkes May 12, 2026
09de4c9
drop ldflags fron watcher-c
henderkes May 15, 2026
6fda358
--build-frankenphp didn't actually build frankenphp
henderkes May 15, 2026
a88e426
clean cgo cache before rebuilding frankenphp (reports wrong version f…
henderkes May 15, 2026
70e717a
fix version reevaluating regression from v2
henderkes May 15, 2026
1707d21
don't extract local sources
henderkes May 15, 2026
4b19f4e
forward port #1138
henderkes May 15, 2026
07aae79
forward port #1142
henderkes May 16, 2026
19d1379
better cross compile compatibility
henderkes May 17, 2026
697040b
Trim base namespace for registry
crazywhalecc May 18, 2026
fdc75cb
Allow vendor mode loading default registry file
crazywhalecc May 18, 2026
ce70c0d
Register artifacts dynamically if not already initialized
crazywhalecc May 18, 2026
f27ec77
Refactor clang runtime bits support for zig integration
crazywhalecc May 18, 2026
32da708
Change gettext-win base to 0.18 (master is 1.0 now)
crazywhalecc May 18, 2026
3eca044
Whoops
crazywhalecc May 18, 2026
7bb4a09
turn llvm-tools into a doctor check. llvm-runtime is a target now
henderkes May 19, 2026
efa7946
build in SOURCE_PATH
henderkes May 19, 2026
b38c7b2
install runtime rt after zig init
henderkes May 19, 2026
433043c
fix macOS
henderkes May 19, 2026
f1525c0
Merge branch 'v3' into feat/pgo-v3
henderkes May 20, 2026
6fe55a4
Merge branch 'v3' into feat/pgo-v3
crazywhalecc May 22, 2026
735f126
Update discord invite link
crazywhalecc May 22, 2026
a23ad55
Add preInstall stage
crazywhalecc May 22, 2026
9d508f1
forward port v2 pgo changes
henderkes May 22, 2026
c40d069
address #1155
henderkes May 22, 2026
d93fdd9
use github tokens for package downloads
henderkes May 22, 2026
3c24c92
mongodb: export PHP_VERSION_ID for in-tree builds
luthermonson May 22, 2026
713f825
mongodb: export PHP_VERSION_ID for in-tree builds (#1156)
henderkes May 23, 2026
e7fb1e2
backport fixes from v2
henderkes May 23, 2026
1ae989d
simplify common zig code paths
henderkes May 23, 2026
203fed6
dont pass shared extension packages to SPCConfigUtil for building php…
henderkes May 23, 2026
5bdcd3f
dont pass all static exts to frankenphp build either
henderkes May 23, 2026
6ab52a5
cxxflags in spcconfigutil
henderkes May 23, 2026
80d8107
backport v2 passing correct libraries, not all
henderkes May 24, 2026
fe4803c
run shared ext builds after frankenphp build
henderkes May 24, 2026
15deecd
Merge remote-tracking branch 'origin/v3' into feat/pgo-v3
henderkes May 24, 2026
f068911
revert
henderkes May 24, 2026
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
8 changes: 7 additions & 1 deletion config/env.ini
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,10 @@ SPC_TARGET=${GNU_ARCH}-linux-musl
CC=${SPC_DEFAULT_CC}
CXX=${SPC_DEFAULT_CXX}
AR=${SPC_DEFAULT_AR}
RANLIB=${SPC_DEFAULT_RANLIB}
LD=${SPC_DEFAULT_LD}
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
SPC_DEFAULT_CFLAGS="-fPIC -O3 -pipe -fno-plt -fno-semantic-interposition -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffunction-sections -fdata-sections"
SPC_DEFAULT_CFLAGS="-fPIC -O3 -pipe -fno-plt -fno-semantic-interposition -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffunction-sections -fdata-sections -Wno-unused-command-line-argument"
SPC_DEFAULT_CXXFLAGS="${SPC_DEFAULT_CFLAGS}"
SPC_DEFAULT_LDFLAGS="-Wl,-z,relro -Wl,--as-needed -Wl,-z,now -Wl,-z,noexecstack -Wl,--gc-sections"
; upx executable path
Expand All @@ -125,6 +126,8 @@ SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fno-ident -fPIE
SPC_CMD_VAR_PHP_MAKE_EXTRA_CXXFLAGS="-g -fstack-protector-strong -fno-ident -fPIE -fvisibility=hidden -fvisibility-inlines-hidden ${SPC_DEFAULT_CXXFLAGS}"
; EXTRA_LDFLAGS for `make` php, can use -release to set a soname for libphp.so
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS=""
; EXTRA_LDFLAGS_PROGRAM for `make` php; appended only to SAPI executable links (cli/fpm/cgi/micro/embed). Used by PGO to inject -fprofile-use= without polluting libphp.{a,so}.
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM=""

; optional, path to openssl conf. This affects where openssl will look for the default CA.
; default on Debian/Alpine: /etc/ssl, default on RHEL: /etc/pki/tls
Expand All @@ -140,6 +143,7 @@ SPC_USE_LLVM=system
CC=${SPC_DEFAULT_CC}
CXX=${SPC_DEFAULT_CXX}
AR=${SPC_DEFAULT_AR}
RANLIB=${SPC_DEFAULT_RANLIB}
LD=${SPC_DEFAULT_LD}
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
SPC_DEFAULT_CFLAGS="--target=${MAC_ARCH}-apple-darwin -O3 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffunction-sections -fdata-sections"
Expand All @@ -163,5 +167,7 @@ SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fpic -fpie -fvis
SPC_CMD_VAR_PHP_MAKE_EXTRA_CXXFLAGS="-g -fstack-protector-strong -fno-ident -fpie -fvisibility=hidden -fvisibility-inlines-hidden -Werror=unknown-warning-option ${SPC_DEFAULT_CXXFLAGS}"
; EXTRA_LDFLAGS for `make` php, can use -release to set a soname for libphp.dylib
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS=""
; EXTRA_LDFLAGS_PROGRAM for `make` php; appended only to SAPI executable links (cli/fpm/cgi/micro/embed). Used by PGO to inject -fprofile-use= without polluting libphp.{a,dylib}.
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM=""
; minimum compatible macOS version (LLVM vars, availability not guaranteed)
MACOSX_DEPLOYMENT_TARGET=12.0
20 changes: 20 additions & 0 deletions config/pkg/ext/ext-fastchart.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
ext-fastchart:
type: php-extension
artifact:
source:
type: ghtar
repo: iliaal/fastchart
extract: php-src/ext/fastchart
prefer-stable: true
metadata:
license-files: [LICENSE]
depends:
- freetype
suggests:
- libpng
- libjpeg
- libwebp
php-extension:
os:
- Linux
- Darwin
14 changes: 14 additions & 0 deletions config/pkg/ext/ext-fastjson.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
ext-fastjson:
type: php-extension
artifact:
source:
type: ghtar
repo: iliaal/fastjson
extract: php-src/ext/fastjson
prefer-stable: true
metadata:
license-files: [LICENSE]
php-extension:
os:
- Linux
- Darwin
6 changes: 6 additions & 0 deletions config/pkg/target/llvm-compiler-rt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
llvm-compiler-rt:
type: target
artifact:
binary: custom
depends:
- zig
6 changes: 6 additions & 0 deletions config/pkg/target/llvm-tools.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
llvm-tools:
type: target
artifact:
binary: custom
depends:
- zig
4 changes: 1 addition & 3 deletions src/Package/Artifact/go_win.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ class go_win
])]
public function downBinary(ArtifactDownloader $downloader): DownloadResult
{
$pkgroot = PKG_ROOT_PATH;

// get version
[$version] = explode("\n", default_shell()->executeCurl('https://go.dev/VERSION?m=text', retries: $downloader->getRetry()) ?: '');
if ($version === '') {
Expand Down Expand Up @@ -52,7 +50,7 @@ public function downBinary(ArtifactDownloader $downloader): DownloadResult
throw new DownloaderException("Hash mismatch for downloaded go-win binary. Expected {$hash}, got {$file_hash}");
}

return DownloadResult::archive(basename($path), ['url' => $url, 'version' => $version], extract: "{$pkgroot}/go-win", verified: true, version: $version);
return DownloadResult::archive(basename($path), ['url' => $url, 'version' => $version], extract: '{pkg_root_path}/go-win', verified: true, version: $version);
}

#[CustomBinaryCheckUpdate('go-win', ['windows-x86_64'])]
Expand Down
5 changes: 2 additions & 3 deletions src/Package/Artifact/go_xcaddy.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ class go_xcaddy
])]
public function downBinary(ArtifactDownloader $downloader): DownloadResult
{
$pkgroot = PKG_ROOT_PATH;
$name = SystemTarget::getCurrentPlatformString();
$arch = match (explode('-', $name)[1]) {
'x86_64' => 'amd64',
Expand Down Expand Up @@ -64,7 +63,7 @@ public function downBinary(ArtifactDownloader $downloader): DownloadResult
if ($file_hash !== $hash) {
throw new DownloaderException("Hash mismatch for downloaded go-xcaddy binary. Expected {$hash}, got {$file_hash}");
}
return DownloadResult::archive(basename($path), ['url' => $url, 'version' => $version], extract: "{$pkgroot}/go-xcaddy", verified: true, version: $version);
return DownloadResult::archive(basename($path), ['url' => $url, 'version' => $version], extract: '{pkg_root_path}/go-xcaddy', verified: true, version: $version);
}

#[CustomBinaryCheckUpdate('go-xcaddy', [
Expand Down Expand Up @@ -109,7 +108,7 @@ public function afterExtract(string $target_path): void
'GOROOT' => "{$target_path}",
'GOBIN' => "{$target_path}/bin",
'GOPATH' => "{$target_path}/go",
])->exec('CC=cc go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest');
])->exec('CGO_ENABLED=0 go install github.com/caddyserver/xcaddy/cmd/xcaddy@master');
GlobalEnvManager::addPathIfNotExists("{$target_path}/bin");
}
}
147 changes: 147 additions & 0 deletions src/Package/Artifact/llvm_compiler_rt.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
<?php

declare(strict_types=1);

namespace Package\Artifact;

use StaticPHP\Artifact\ArtifactDownloader;
use StaticPHP\Artifact\Downloader\DownloadResult;
use StaticPHP\Artifact\Downloader\Type\CheckUpdateResult;
use StaticPHP\Artifact\Downloader\Type\GitHubTokenSetupTrait;
use StaticPHP\Attribute\Artifact\AfterBinaryExtract;
use StaticPHP\Attribute\Artifact\CustomBinary;
use StaticPHP\Attribute\Artifact\CustomBinaryCheckUpdate;
use StaticPHP\Exception\BuildFailureException;
use StaticPHP\Exception\DownloaderException;
use StaticPHP\Runtime\SystemTarget;

/**
* Builds the compiler-rt bits zig ships without — libclang_rt.profile.a (PGO instrumentation)
* and clang_rt.crtbegin.o/crtend.o (__dso_handle for shared libs). Target-arch specific:
* libs land in PKG_ROOT_PATH/zig/lib/{triple}.
*/
class llvm_compiler_rt
{
use GitHubTokenSetupTrait;

#[CustomBinary('llvm-compiler-rt', [
'linux-x86_64',
'linux-aarch64',
'macos-x86_64',
'macos-aarch64',
])]
public function downBinary(ArtifactDownloader $downloader): DownloadResult
{
$llvmVersion = $this->detectZigLlvmVersion()
?? throw new DownloaderException('llvm-compiler-rt: could not detect bundled clang version from zig cc --version');
$tarball = "compiler-rt-{$llvmVersion}.src.tar.xz";
$url = "https://github.com/llvm/llvm-project/releases/download/llvmorg-{$llvmVersion}/{$tarball}";
$tarballPath = DOWNLOAD_PATH . '/' . $tarball;
default_shell()->executeCurlDownload($url, $tarballPath, headers: $this->getGitHubTokenHeaders(), retries: $downloader->getRetry());
return DownloadResult::archive($tarball, ['url' => $url, 'version' => $llvmVersion], extract: '{source_path}/llvm-compiler-rt', verified: false, version: $llvmVersion);
}

#[CustomBinaryCheckUpdate('llvm-compiler-rt', [
'linux-x86_64',
'linux-aarch64',
'macos-x86_64',
'macos-aarch64',
])]
public function checkUpdateBinary(?string $old_version, ArtifactDownloader $downloader): CheckUpdateResult
{
$llvmVersion = $this->detectZigLlvmVersion()
?? throw new DownloaderException('llvm-compiler-rt: could not detect bundled clang version from zig cc --version');
return new CheckUpdateResult(
old: $old_version,
new: $llvmVersion,
needUpdate: $old_version === null || $llvmVersion !== $old_version,
);
}

#[AfterBinaryExtract('llvm-compiler-rt', [
'linux-x86_64',
'linux-aarch64',
'macos-x86_64',
'macos-aarch64',
])]
public function postExtract(string $target_path): void
{
$this->buildForTriple($target_path);
}

public function buildForTriple(?string $sourceDir = null, ?string $triple = null): void
{
$sourceDir ??= SOURCE_PATH . '/llvm-compiler-rt';
$triple ??= SystemTarget::getCanonicalTriple();
$libDir = zig::path() . '/lib/' . $triple;
if ($this->isBuilt($libDir)) {
return;
}
if (!is_dir($sourceDir) || !is_dir("{$sourceDir}/lib/profile")) {
throw new BuildFailureException("llvm-compiler-rt: missing source at {$sourceDir} (extraction layout changed?)");
}
f_mkdir($libDir, recursive: true);
$profileLib = "{$libDir}/libclang_rt.profile.a";
$crtBegin = "{$libDir}/clang_rt.crtbegin.o";
$crtEnd = "{$libDir}/clang_rt.crtend.o";
if (!file_exists($profileLib)) {
$this->buildProfileRuntime($sourceDir, $profileLib, $triple);
}
if (!file_exists($crtBegin) || !file_exists($crtEnd)) {
$this->buildCrtObjects($sourceDir, $crtBegin, $crtEnd, $triple);
}
}

public function isBuilt(string $libDir): bool
{
return file_exists("{$libDir}/libclang_rt.profile.a")
&& file_exists("{$libDir}/clang_rt.crtbegin.o")
&& file_exists("{$libDir}/clang_rt.crtend.o");
}

private function detectZigLlvmVersion(): ?string
{
if (!zig::isInstalled()) {
return null;
}
[$rc, $out] = shell()->execWithResult(escapeshellarg(zig::binary()) . ' cc --version', false);
if ($rc !== 0) {
return null;
}
return preg_match('/clang version (\d+\.\d+\.\d+)/', implode("\n", $out), $m) ? $m[1] : null;
}

private function buildProfileRuntime(string $srcRoot, string $libPath, string $triple): void
{
$profileSrc = "{$srcRoot}/lib/profile";
$profileInc = "{$srcRoot}/include";
// Skip OS-specific sources we can't satisfy without their SDKs.
$skip = ['/PlatformAIX', '/PlatformDarwin', '/PlatformFuchsia', '/PlatformOther', '/PlatformWindows', '/WindowsMMap'];
$sources = array_filter(
array_merge(glob("{$profileSrc}/*.c") ?: [], glob("{$profileSrc}/*.cpp") ?: []),
fn ($f) => !array_any($skip, fn ($s) => str_contains($f, $s)),
);

$objDir = "{$srcRoot}/obj-profile-{$triple}";
f_mkdir($objDir, recursive: true);
$cflags = "-target {$triple} -c -O2 -fPIC -fvisibility=hidden "
. '-I' . escapeshellarg($profileInc) . ' '
. '-DCOMPILER_RT_HAS_ATOMICS=1 -DCOMPILER_RT_HAS_FCNTL_LCK=1 -DCOMPILER_RT_HAS_UNAME=1';
$srcArgs = implode(' ', array_map('escapeshellarg', $sources));
shell()->cd($objDir)->exec("zig cc {$cflags} {$srcArgs}");
shell()->cd($objDir)->exec('zig ar rcs ' . escapeshellarg($libPath) . ' *.o');
}

private function buildCrtObjects(string $srcRoot, string $crtBegin, string $crtEnd, string $triple): void
{
$beginSrc = "{$srcRoot}/lib/builtins/crtbegin.c";
$endSrc = "{$srcRoot}/lib/builtins/crtend.c";
if (!is_file($beginSrc) || !is_file($endSrc)) {
throw new BuildFailureException("llvm-compiler-rt: crtbegin/crtend source missing under {$srcRoot}/lib/builtins");
}
$cflags = "-target {$triple} -c -O2 -fPIC -fvisibility=hidden -DCRT_HAS_INITFINI_ARRAY";
foreach ([[$beginSrc, $crtBegin], [$endSrc, $crtEnd]] as [$src, $dst]) {
shell()->exec("zig cc {$cflags} -o " . escapeshellarg($dst) . ' ' . escapeshellarg($src));
}
}
}
Loading
Loading