From 9edb9417a125c52239fc9038779a1d15ca667f4d Mon Sep 17 00:00:00 2001 From: DubbleClick Date: Fri, 5 Sep 2025 21:36:25 +0700 Subject: [PATCH 01/11] add --with-frankenphp-app option to embed an app # Conflicts: # config/lib.json # src/SPC/builder/unix/UnixBuilderBase.php --- config/env.ini | 2 +- config/lib.json | 10 +++- config/source.json | 10 ++++ src/SPC/builder/unix/UnixBuilderBase.php | 61 +++++++++++++++++++++--- src/SPC/command/BuildPHPCommand.php | 1 + 5 files changed, 75 insertions(+), 9 deletions(-) diff --git a/config/env.ini b/config/env.ini index 1047c3f7..cfda622e 100644 --- a/config/env.ini +++ b/config/env.ini @@ -45,7 +45,7 @@ SPC_SKIP_PHP_VERSION_CHECK="no" ; Ignore some check item for bin/spc doctor command, comma separated (e.g. SPC_SKIP_DOCTOR_CHECK_ITEMS="if homebrew has installed") SPC_SKIP_DOCTOR_CHECK_ITEMS="" ; extra modules that xcaddy will include in the FrankenPHP build -SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES="--with github.com/dunglas/frankenphp/caddy --with github.com/dunglas/mercure/caddy --with github.com/dunglas/vulcain/caddy --with github.com/dunglas/caddy-cbrotli" +SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES="--with github.com/dunglas/mercure/caddy --with github.com/dunglas/vulcain/caddy --with github.com/dunglas/caddy-cbrotli" ; The display message for php version output (PHP >= 8.4 available) PHP_BUILD_PROVIDER="static-php-cli ${SPC_VERSION}" diff --git a/config/lib.json b/config/lib.json index 528777e1..640d4ea9 100644 --- a/config/lib.json +++ b/config/lib.json @@ -7,12 +7,14 @@ "source": "php-src", "lib-depends": [ "lib-base", - "micro" + "micro", + "frankenphp" ], "lib-depends-macos": [ "lib-base", "micro", - "libxml2" + "libxml2", + "frankenphp" ], "lib-suggests-linux": [ "libacl", @@ -968,5 +970,9 @@ "zstd.h", "zstd_errors.h" ] + }, + "frankenphp": { + "source": "frankenphp", + "type": "target" } } diff --git a/config/source.json b/config/source.json index ee3f8948..4a199081 100644 --- a/config/source.json +++ b/config/source.json @@ -363,6 +363,16 @@ "path": "LICENSE" } }, + "frankenphp": { + "type": "ghtar", + "repo": "php/frankenphp", + "prefer-stable": true, + "provide-pre-build": false, + "license": { + "type": "file", + "path": "LICENSE" + } + }, "icu-static-win": { "type": "url", "url": "https://dl.static-php.dev/static-php-cli/deps/icu-static-windows-x64/icu-static-windows-x64.zip", diff --git a/src/SPC/builder/unix/UnixBuilderBase.php b/src/SPC/builder/unix/UnixBuilderBase.php index 15488a67..0692d4a3 100644 --- a/src/SPC/builder/unix/UnixBuilderBase.php +++ b/src/SPC/builder/unix/UnixBuilderBase.php @@ -13,6 +13,7 @@ use SPC\exception\WrongUsageException; use SPC\store\Config; use SPC\store\FileSystem; use SPC\store\pkg\GoXcaddy; +use SPC\store\SourceManager; use SPC\toolchain\GccNativeToolchain; use SPC\toolchain\ToolchainManager; use SPC\util\DependencyUtil; @@ -344,22 +345,70 @@ abstract class UnixBuilderBase extends BuilderBase } } + /** + * Process the --with-frankenphp-app option + * Creates app.tar and app.checksum in source/frankenphp directory + */ + protected function processFrankenphpApp(): void + { + $frankenphpSourceDir = SOURCE_PATH . '/frankenphp'; + SourceManager::initSource(['frankenphp'], ['frankenphp']); + $frankenphpAppPath = $this->getOption('with-frankenphp-app'); + + if ($frankenphpAppPath) { + if (!is_dir($frankenphpAppPath)) { + throw new WrongUsageException("The path provided to --with-frankenphp-app is not a valid directory: {$frankenphpAppPath}"); + } + $appTarPath = $frankenphpSourceDir . '/app.tar'; + logger()->info("Creating app.tar from {$frankenphpAppPath}"); + + shell()->exec('tar -cf ' . escapeshellarg($appTarPath) . ' -C ' . escapeshellarg($frankenphpAppPath) . ' .'); + + $checksum = hash_file('md5', $appTarPath); + file_put_contents($frankenphpSourceDir . '/app_checksum.txt', $checksum); + } else { + FileSystem::removeFileIfExists($frankenphpSourceDir . '/app.tar'); + FileSystem::removeFileIfExists($frankenphpSourceDir . '/app_checksum.txt'); + file_put_contents($frankenphpSourceDir . '/app.tar', ''); + file_put_contents($frankenphpSourceDir . '/app_checksum.txt', ''); + } + } + + protected function getFrankenPHPVersion(): string + { + $goModPath = SOURCE_PATH . '/frankenphp/caddy/go.mod'; + + if (!file_exists($goModPath)) { + throw new SPCInternalException("FrankenPHP caddy/go.mod file not found at {$goModPath}, why did we not download FrankenPHP?"); + } + + $content = file_get_contents($goModPath); + if (preg_match('/github\.com\/dunglas\/frankenphp\s+v?(\d+\.\d+\.\d+)/', $content, $matches)) { + return $matches[1]; + } + + throw new SPCInternalException('Could not find FrankenPHP version in caddy/go.mod'); + } + protected function buildFrankenphp(): void { GlobalEnvManager::addPathIfNotExists(GoXcaddy::getPath()); + $this->processFrankenphpApp(); $nobrotli = $this->getLib('brotli') === null ? ',nobrotli' : ''; $nowatcher = $this->getLib('watcher') === null ? ',nowatcher' : ''; $xcaddyModules = getenv('SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES'); - // make it possible to build from a different frankenphp directory! - if (!str_contains($xcaddyModules, '--with github.com/dunglas/frankenphp')) { - $xcaddyModules = '--with github.com/dunglas/frankenphp ' . $xcaddyModules; - } + $frankenphpSourceDir = SOURCE_PATH . '/frankenphp'; + + $xcaddyModules = preg_replace('#--with github.com/dunglas/frankenphp(=\S+)?#', '', $xcaddyModules); + $xcaddyModules = preg_replace('#--with github.com/dunglas/frankenphp/caddy(=\S+)?#', '', $xcaddyModules); + $xcaddyModules = "--with github.com/dunglas/frankenphp={$frankenphpSourceDir} " . + "--with github.com/dunglas/frankenphp/caddy={$frankenphpSourceDir}/caddy {$xcaddyModules}"; if ($this->getLib('brotli') === null && str_contains($xcaddyModules, '--with github.com/dunglas/caddy-cbrotli')) { logger()->warning('caddy-cbrotli module is enabled, but brotli library is not built. Disabling caddy-cbrotli.'); $xcaddyModules = str_replace('--with github.com/dunglas/caddy-cbrotli', '', $xcaddyModules); } - [, $out] = shell()->execWithResult('go list -m github.com/dunglas/frankenphp@latest'); - $frankenPhpVersion = str_replace('github.com/dunglas/frankenphp v', '', $out[0]); + + $frankenPhpVersion = $this->getFrankenPHPVersion(); $libphpVersion = $this->getPHPVersion(); $dynamic_exports = ''; if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') { diff --git a/src/SPC/command/BuildPHPCommand.php b/src/SPC/command/BuildPHPCommand.php index b608b8f0..ad884b3b 100644 --- a/src/SPC/command/BuildPHPCommand.php +++ b/src/SPC/command/BuildPHPCommand.php @@ -48,6 +48,7 @@ class BuildPHPCommand extends BuildCommand $this->addOption('with-upx-pack', null, null, 'Compress / pack binary using UPX tool (linux/windows only)'); $this->addOption('with-micro-logo', null, InputOption::VALUE_REQUIRED, 'Use custom .ico for micro.sfx (windows only)'); $this->addOption('enable-micro-win32', null, null, 'Enable win32 mode for phpmicro (Windows only)'); + $this->addOption('with-frankenphp-app', null, InputOption::VALUE_REQUIRED, 'Path to a folder to be embedded in FrankenPHP'); } public function handle(): int From 081e2d284609f81821c825650394e2af6e429452 Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 28 Oct 2025 18:50:16 +0100 Subject: [PATCH 02/11] fix debugflags being backwards --- src/SPC/builder/unix/UnixBuilderBase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SPC/builder/unix/UnixBuilderBase.php b/src/SPC/builder/unix/UnixBuilderBase.php index 0692d4a3..0888f66e 100644 --- a/src/SPC/builder/unix/UnixBuilderBase.php +++ b/src/SPC/builder/unix/UnixBuilderBase.php @@ -418,7 +418,7 @@ abstract class UnixBuilderBase extends BuilderBase $dynamic_exports = ' ' . $dynamicSymbolsArgument; } } - $debugFlags = $this->getOption('no-strip') ? '-w -s ' : ''; + $debugFlags = $this->getOption('no-strip') ? '' : '-w -s '; $extLdFlags = "-extldflags '-pie{$dynamic_exports} {$this->arch_ld_flags}'"; $muslTags = ''; $staticFlags = ''; From fd2b7af1dcb24939dd203de37dd1487fa9031318 Mon Sep 17 00:00:00 2001 From: henderkes Date: Fri, 7 Nov 2025 11:06:50 +0100 Subject: [PATCH 03/11] make --with-frankenphp-app=dir work with docker scripts --- bin/spc-alpine-docker | 43 ++++++++++++++++++++++++++++++++++++++++++- bin/spc-gnu-docker | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/bin/spc-alpine-docker b/bin/spc-alpine-docker index 6365233c..0d618743 100755 --- a/bin/spc-alpine-docker +++ b/bin/spc-alpine-docker @@ -162,6 +162,47 @@ if [ ! -z "$GITHUB_TOKEN" ]; then ENV_LIST="$ENV_LIST -e GITHUB_TOKEN=$GITHUB_TOKEN" fi +# Intercept and rewrite --with-frankenphp-app option, and mount host path to /app/app +FRANKENPHP_APP_PATH="" +NEW_ARGS=() +while [ $# -gt 0 ]; do + case "$1" in + --with-frankenphp-app=*) + FRANKENPHP_APP_PATH="${1#*=}" + NEW_ARGS+=("--with-frankenphp-app=/app/app") + shift + ;; + --with-frankenphp-app) + if [ -n "${2:-}" ]; then + FRANKENPHP_APP_PATH="$2" + NEW_ARGS+=("--with-frankenphp-app=/app/app") + shift 2 + else + NEW_ARGS+=("$1") + shift + fi + ;; + *) + NEW_ARGS+=("$1") + shift + ;; + esac +done + +# Normalize the path and add mount if provided +if [ -n "$FRANKENPHP_APP_PATH" ]; then + # expand ~ to $HOME + if [ "${FRANKENPHP_APP_PATH#~}" != "$FRANKENPHP_APP_PATH" ]; then + FRANKENPHP_APP_PATH="$HOME${FRANKENPHP_APP_PATH#~}" + fi + # make absolute if relative + case "$FRANKENPHP_APP_PATH" in + /*) ABS_APP_PATH="$FRANKENPHP_APP_PATH" ;; + *) ABS_APP_PATH="$(pwd)/$FRANKENPHP_APP_PATH" ;; + esac + MOUNT_LIST="$MOUNT_LIST -v \"$ABS_APP_PATH\":/app/app" +fi + # Run docker # shellcheck disable=SC2068 # shellcheck disable=SC2086 @@ -183,5 +224,5 @@ if [ "$SPC_DOCKER_DEBUG" = "yes" ]; then set -ex $DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST $MOUNT_LIST cwcc-spc-$SPC_USE_ARCH-$SPC_DOCKER_VERSION /bin/bash else - $DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST $MOUNT_LIST cwcc-spc-$SPC_USE_ARCH-$SPC_DOCKER_VERSION bin/spc $@ + $DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST $MOUNT_LIST cwcc-spc-$SPC_USE_ARCH-$SPC_DOCKER_VERSION bin/spc "${NEW_ARGS[@]}" fi diff --git a/bin/spc-gnu-docker b/bin/spc-gnu-docker index 7fcf5d41..29c68ade 100755 --- a/bin/spc-gnu-docker +++ b/bin/spc-gnu-docker @@ -174,6 +174,47 @@ if [ ! -z "$GITHUB_TOKEN" ]; then ENV_LIST="$ENV_LIST -e GITHUB_TOKEN=$GITHUB_TOKEN" fi +# Intercept and rewrite --with-frankenphp-app option, and mount host path to /app/app +FRANKENPHP_APP_PATH="" +NEW_ARGS=() +while [ $# -gt 0 ]; do + case "$1" in + --with-frankenphp-app=*) + FRANKENPHP_APP_PATH="${1#*=}" + NEW_ARGS+=("--with-frankenphp-app=/app/app") + shift + ;; + --with-frankenphp-app) + if [ -n "${2:-}" ]; then + FRANKENPHP_APP_PATH="$2" + NEW_ARGS+=("--with-frankenphp-app=/app/app") + shift 2 + else + NEW_ARGS+=("$1") + shift + fi + ;; + *) + NEW_ARGS+=("$1") + shift + ;; + esac +done + +# Normalize the path and add mount if provided +if [ -n "$FRANKENPHP_APP_PATH" ]; then + # expand ~ to $HOME + if [ "${FRANKENPHP_APP_PATH#~}" != "$FRANKENPHP_APP_PATH" ]; then + FRANKENPHP_APP_PATH="$HOME${FRANKENPHP_APP_PATH#~}" + fi + # make absolute if relative + case "$FRANKENPHP_APP_PATH" in + /*) ABS_APP_PATH="$FRANKENPHP_APP_PATH" ;; + *) ABS_APP_PATH="$(pwd)/$FRANKENPHP_APP_PATH" ;; + esac + MOUNT_LIST="$MOUNT_LIST -v \"$ABS_APP_PATH\":/app/app" +fi + # Run docker # shellcheck disable=SC2068 # shellcheck disable=SC2086 @@ -196,5 +237,5 @@ if [ "$SPC_DOCKER_DEBUG" = "yes" ]; then set -ex $DOCKER_EXECUTABLE run $PLATFORM_ARG --privileged --rm -it $INTERACT $ENV_LIST --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION /bin/bash else - $DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION bin/spc $@ + $DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION bin/spc "${NEW_ARGS[@]}" fi From c91128995d63e5533c2ad40b5b203c5f656b15bb Mon Sep 17 00:00:00 2001 From: henderkes Date: Sat, 8 Nov 2025 09:40:16 +0100 Subject: [PATCH 04/11] update freetype download to get latest version --- config/source.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/source.json b/config/source.json index 4a199081..ca1edfb0 100644 --- a/config/source.json +++ b/config/source.json @@ -302,9 +302,9 @@ } }, "freetype": { - "type": "git", - "rev": "VER-2-13-2", - "url": "https://github.com/freetype/freetype", + "type": "ghtagtar", + "repo": "freetype/freetype", + "match": "VER-2-\\d+-\\d+", "license": { "type": "file", "path": "LICENSE.TXT" From 541889d17b2147508f0a947aa7215772c23c1b1f Mon Sep 17 00:00:00 2001 From: henderkes Date: Sun, 9 Nov 2025 10:01:19 +0100 Subject: [PATCH 05/11] update to rc4 --- src/SPC/store/source/PhpSource.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SPC/store/source/PhpSource.php b/src/SPC/store/source/PhpSource.php index 1c0be85f..e0b3ba27 100644 --- a/src/SPC/store/source/PhpSource.php +++ b/src/SPC/store/source/PhpSource.php @@ -16,7 +16,7 @@ class PhpSource extends CustomSourceBase { $major = defined('SPC_BUILD_PHP_VERSION') ? SPC_BUILD_PHP_VERSION : '8.4'; if ($major === '8.5') { - Downloader::downloadSource('php-src', ['type' => 'url', 'url' => 'https://downloads.php.net/~daniels/php-8.5.0RC3.tar.xz'], $force); + Downloader::downloadSource('php-src', ['type' => 'url', 'url' => 'https://downloads.php.net/~edorian/php-8.5.0RC4.tar.xz'], $force); } elseif ($major === 'git') { Downloader::downloadSource('php-src', ['type' => 'git', 'url' => 'https://github.com/php/php-src.git', 'rev' => 'master'], $force); } else { From 64079d93311d7cddf5a84f82b6ef46389a53955c Mon Sep 17 00:00:00 2001 From: henderkes Date: Sun, 9 Nov 2025 23:35:49 +0100 Subject: [PATCH 06/11] simplify regex --- src/SPC/builder/unix/UnixBuilderBase.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/SPC/builder/unix/UnixBuilderBase.php b/src/SPC/builder/unix/UnixBuilderBase.php index 0888f66e..429dace5 100644 --- a/src/SPC/builder/unix/UnixBuilderBase.php +++ b/src/SPC/builder/unix/UnixBuilderBase.php @@ -399,8 +399,7 @@ abstract class UnixBuilderBase extends BuilderBase $xcaddyModules = getenv('SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES'); $frankenphpSourceDir = SOURCE_PATH . '/frankenphp'; - $xcaddyModules = preg_replace('#--with github.com/dunglas/frankenphp(=\S+)?#', '', $xcaddyModules); - $xcaddyModules = preg_replace('#--with github.com/dunglas/frankenphp/caddy(=\S+)?#', '', $xcaddyModules); + $xcaddyModules = preg_replace('#--with github.com/dunglas/frankenphp\S*#', '', $xcaddyModules); $xcaddyModules = "--with github.com/dunglas/frankenphp={$frankenphpSourceDir} " . "--with github.com/dunglas/frankenphp/caddy={$frankenphpSourceDir}/caddy {$xcaddyModules}"; if ($this->getLib('brotli') === null && str_contains($xcaddyModules, '--with github.com/dunglas/caddy-cbrotli')) { From cff6ec17ea4dfa6de6dbfb4464855d67ff13d094 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Mon, 10 Nov 2025 13:26:17 +0800 Subject: [PATCH 07/11] Remove escape backslashes --- bin/spc-alpine-docker | 2 +- bin/spc-gnu-docker | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/spc-alpine-docker b/bin/spc-alpine-docker index 0d618743..2790a5c3 100755 --- a/bin/spc-alpine-docker +++ b/bin/spc-alpine-docker @@ -200,7 +200,7 @@ if [ -n "$FRANKENPHP_APP_PATH" ]; then /*) ABS_APP_PATH="$FRANKENPHP_APP_PATH" ;; *) ABS_APP_PATH="$(pwd)/$FRANKENPHP_APP_PATH" ;; esac - MOUNT_LIST="$MOUNT_LIST -v \"$ABS_APP_PATH\":/app/app" + MOUNT_LIST="$MOUNT_LIST -v $ABS_APP_PATH:/app/app" fi # Run docker diff --git a/bin/spc-gnu-docker b/bin/spc-gnu-docker index 29c68ade..68f85109 100755 --- a/bin/spc-gnu-docker +++ b/bin/spc-gnu-docker @@ -212,7 +212,7 @@ if [ -n "$FRANKENPHP_APP_PATH" ]; then /*) ABS_APP_PATH="$FRANKENPHP_APP_PATH" ;; *) ABS_APP_PATH="$(pwd)/$FRANKENPHP_APP_PATH" ;; esac - MOUNT_LIST="$MOUNT_LIST -v \"$ABS_APP_PATH\":/app/app" + MOUNT_LIST="$MOUNT_LIST -v $ABS_APP_PATH:/app/app" fi # Run docker From 09073c5517dbabd71bdec5e132201339d5f84e18 Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 11 Nov 2025 15:51:28 +0100 Subject: [PATCH 08/11] sort config and remove lonesome configure cflags --- config/env.ini | 10 +++------- config/lib.json | 8 ++++---- config/source.json | 20 ++++++++++---------- src/SPC/builder/linux/LinuxBuilder.php | 6 +++--- src/SPC/builder/macos/MacOSBuilder.php | 2 +- 5 files changed, 21 insertions(+), 25 deletions(-) diff --git a/config/env.ini b/config/env.ini index cfda622e..7448cc37 100644 --- a/config/env.ini +++ b/config/env.ini @@ -110,9 +110,7 @@ SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --disable ; *** default build vars for building php *** ; embed type for php, static (libphp.a) or shared (libphp.so) SPC_CMD_VAR_PHP_EMBED_TYPE="static" -; CFLAGS for configuring php -SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS="${SPC_DEFAULT_C_FLAGS} -fPIE" -; EXTRA_CFLAGS for `make` php +; EXTRA_CFLAGS for `configure` and `make` php SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fno-ident -fPIE ${SPC_DEFAULT_C_FLAGS}" ; EXTRA_LDFLAGS for `make` php, can use -release to set a soname for libphp.so SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS="" @@ -142,10 +140,8 @@ SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --enable- ; *** default build vars for building php *** ; embed type for php, static (libphp.a) or shared (libphp.dylib) SPC_CMD_VAR_PHP_EMBED_TYPE="static" -; CFLAGS for configuring php -SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS="${SPC_DEFAULT_C_FLAGS} -Werror=unknown-warning-option" -; EXTRA_CFLAGS for `make` php -SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fpic -fpie ${SPC_DEFAULT_C_FLAGS}" +; EXTRA_CFLAGS for `configure` and `make` php +SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fpic -fpie -Werror=unknown-warning-option ${SPC_DEFAULT_C_FLAGS}" [freebsd] ; compiler environments diff --git a/config/lib.json b/config/lib.json index 640d4ea9..aa7eb499 100644 --- a/config/lib.json +++ b/config/lib.json @@ -26,6 +26,10 @@ "watcher" ] }, + "frankenphp": { + "source": "frankenphp", + "type": "target" + }, "micro": { "type": "target", "source": "micro" @@ -970,9 +974,5 @@ "zstd.h", "zstd_errors.h" ] - }, - "frankenphp": { - "source": "frankenphp", - "type": "target" } } diff --git a/config/source.json b/config/source.json index ca1edfb0..fa16651c 100644 --- a/config/source.json +++ b/config/source.json @@ -301,6 +301,16 @@ "path": "LICENSE.MIT" } }, + "frankenphp": { + "type": "ghtar", + "repo": "php/frankenphp", + "prefer-stable": true, + "provide-pre-built": false, + "license": { + "type": "file", + "path": "LICENSE" + } + }, "freetype": { "type": "ghtagtar", "repo": "freetype/freetype", @@ -363,16 +373,6 @@ "path": "LICENSE" } }, - "frankenphp": { - "type": "ghtar", - "repo": "php/frankenphp", - "prefer-stable": true, - "provide-pre-build": false, - "license": { - "type": "file", - "path": "LICENSE" - } - }, "icu-static-win": { "type": "url", "url": "https://dl.static-php.dev/static-php-cli/deps/icu-static-windows-x64/icu-static-windows-x64.zip", diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index 68db5688..0d6f77fb 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -91,7 +91,7 @@ class LinuxBuilder extends UnixBuilderBase // prepare build php envs // $musl_flag = SPCTarget::getLibc() === 'musl' ? ' -D__MUSL__' : ' -U__MUSL__'; $php_configure_env = SystemUtil::makeEnvVarString([ - 'CFLAGS' => getenv('SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS'), + 'CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), 'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH, // . ' -Dsomethinghere', // . $musl_flag, 'LDFLAGS' => '-L' . BUILD_LIB_PATH, // 'LIBS' => SPCTarget::getRuntimeLibs(), // do not pass static libraries here yet, they may contain polyfills for libc functions! @@ -284,10 +284,10 @@ class LinuxBuilder extends UnixBuilderBase // process libphp.so for shared embed $libphpSo = BUILD_LIB_PATH . '/libphp.so'; if (file_exists($libphpSo)) { - // deploy libphp.so - $this->deployBinary($libphpSo, $libphpSo, false); // post actions: rename libphp.so to libphp-.so if -release is set in LDFLAGS $this->processLibphpSoFile($libphpSo); + // deploy libphp.so + $this->deployBinary($libphpSo, $libphpSo, false); } // process shared extensions build-with-php diff --git a/src/SPC/builder/macos/MacOSBuilder.php b/src/SPC/builder/macos/MacOSBuilder.php index 849b350f..07ef275d 100644 --- a/src/SPC/builder/macos/MacOSBuilder.php +++ b/src/SPC/builder/macos/MacOSBuilder.php @@ -106,7 +106,7 @@ class MacOSBuilder extends UnixBuilderBase // prepare build php envs $envs_build_php = SystemUtil::makeEnvVarString([ - 'CFLAGS' => getenv('SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS'), + 'CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), 'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH, 'LDFLAGS' => '-L' . BUILD_LIB_PATH, ]); From e2b80e7f03439a8f2eb180133bc671019f56812c Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 11 Nov 2025 15:53:44 +0100 Subject: [PATCH 09/11] update building of frankenphp --- src/SPC/builder/unix/UnixBuilderBase.php | 30 +++++++++++++++++------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/SPC/builder/unix/UnixBuilderBase.php b/src/SPC/builder/unix/UnixBuilderBase.php index 429dace5..fac3ca40 100644 --- a/src/SPC/builder/unix/UnixBuilderBase.php +++ b/src/SPC/builder/unix/UnixBuilderBase.php @@ -105,9 +105,16 @@ abstract class UnixBuilderBase extends BuilderBase if (PHP_OS_FAMILY === 'Darwin') { shell()->exec("dsymutil -f {$binary_path} -o {$debug_file}"); } elseif (PHP_OS_FAMILY === 'Linux') { - shell() - ->exec("objcopy --only-keep-debug {$binary_path} {$debug_file}") - ->exec("objcopy --add-gnu-debuglink={$debug_file} {$binary_path}"); + $has_eu_strip = shell()->execWithResult('which eu-strip')[0] === 0; + if ($has_eu_strip) { + shell() + ->exec("eu-strip -f {$debug_file} {$binary_path}") + ->exec("objcopy --add-gnu-debuglink={$debug_file} {$binary_path}"); + } else { + shell() + ->exec("objcopy --only-keep-debug {$binary_path} {$debug_file}") + ->exec("objcopy --add-gnu-debuglink={$debug_file} {$binary_path}"); + } } else { throw new SPCInternalException('extractDebugInfo is only supported on Linux and macOS'); } @@ -351,8 +358,10 @@ abstract class UnixBuilderBase extends BuilderBase */ protected function processFrankenphpApp(): void { - $frankenphpSourceDir = SOURCE_PATH . '/frankenphp'; - SourceManager::initSource(['frankenphp'], ['frankenphp']); + $frankenphpSourceDir = getenv('FRANKENPHP_SOURCE_PATH') ?: SOURCE_PATH . '/frankenphp'; + if (!is_dir($frankenphpSourceDir)) { + SourceManager::initSource(['frankenphp'], ['frankenphp']); + } $frankenphpAppPath = $this->getOption('with-frankenphp-app'); if ($frankenphpAppPath) { @@ -376,7 +385,11 @@ abstract class UnixBuilderBase extends BuilderBase protected function getFrankenPHPVersion(): string { - $goModPath = SOURCE_PATH . '/frankenphp/caddy/go.mod'; + if ($version = getenv('FRANKENPHP_VERSION')) { + return $version; + } + $frankenphpSourceDir = getenv('FRANKENPHP_SOURCE_PATH') ?: SOURCE_PATH . '/frankenphp'; + $goModPath = $frankenphpSourceDir . '/caddy/go.mod'; if (!file_exists($goModPath)) { throw new SPCInternalException("FrankenPHP caddy/go.mod file not found at {$goModPath}, why did we not download FrankenPHP?"); @@ -397,7 +410,7 @@ abstract class UnixBuilderBase extends BuilderBase $nobrotli = $this->getLib('brotli') === null ? ',nobrotli' : ''; $nowatcher = $this->getLib('watcher') === null ? ',nowatcher' : ''; $xcaddyModules = getenv('SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES'); - $frankenphpSourceDir = SOURCE_PATH . '/frankenphp'; + $frankenphpSourceDir = getenv('FRANKENPHP_SOURCE_PATH') ?: SOURCE_PATH . '/frankenphp'; $xcaddyModules = preg_replace('#--with github.com/dunglas/frankenphp\S*#', '', $xcaddyModules); $xcaddyModules = "--with github.com/dunglas/frankenphp={$frankenphpSourceDir} " . @@ -417,7 +430,6 @@ abstract class UnixBuilderBase extends BuilderBase $dynamic_exports = ' ' . $dynamicSymbolsArgument; } } - $debugFlags = $this->getOption('no-strip') ? '' : '-w -s '; $extLdFlags = "-extldflags '-pie{$dynamic_exports} {$this->arch_ld_flags}'"; $muslTags = ''; $staticFlags = ''; @@ -442,7 +454,7 @@ abstract class UnixBuilderBase extends BuilderBase 'CGO_CFLAGS' => clean_spaces($cflags), 'CGO_LDFLAGS' => "{$this->arch_ld_flags} {$staticFlags} {$config['ldflags']} {$libs}", 'XCADDY_GO_BUILD_FLAGS' => '-buildmode=pie ' . - '-ldflags \"-linkmode=external ' . $extLdFlags . ' ' . $debugFlags . + '-ldflags \"-linkmode=external ' . $extLdFlags . ' ' . '-X \'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ' . "v{$frankenPhpVersion} PHP {$libphpVersion} Caddy'\\\" " . "-tags={$muslTags}nobadger,nomysql,nopgx{$nobrotli}{$nowatcher}", From 8e4d4b7be53adcf942ed1a034f7f8d1502252886 Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 11 Nov 2025 16:51:30 +0100 Subject: [PATCH 10/11] suggestion --- src/SPC/builder/unix/UnixBuilderBase.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SPC/builder/unix/UnixBuilderBase.php b/src/SPC/builder/unix/UnixBuilderBase.php index fac3ca40..d8f3ae2b 100644 --- a/src/SPC/builder/unix/UnixBuilderBase.php +++ b/src/SPC/builder/unix/UnixBuilderBase.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace SPC\builder\unix; use SPC\builder\BuilderBase; +use SPC\builder\linux\SystemUtil; use SPC\builder\linux\SystemUtil as LinuxSystemUtil; use SPC\exception\SPCException; use SPC\exception\SPCInternalException; @@ -105,10 +106,9 @@ abstract class UnixBuilderBase extends BuilderBase if (PHP_OS_FAMILY === 'Darwin') { shell()->exec("dsymutil -f {$binary_path} -o {$debug_file}"); } elseif (PHP_OS_FAMILY === 'Linux') { - $has_eu_strip = shell()->execWithResult('which eu-strip')[0] === 0; - if ($has_eu_strip) { + if ($eu_strip = SystemUtil::findCommand('eu-strip')) { shell() - ->exec("eu-strip -f {$debug_file} {$binary_path}") + ->exec("{$eu_strip} -f {$debug_file} {$binary_path}") ->exec("objcopy --add-gnu-debuglink={$debug_file} {$binary_path}"); } else { shell() From 23c0d6f4aa88034286c5eef51dc16b4b39a607f1 Mon Sep 17 00:00:00 2001 From: henderkes Date: Wed, 12 Nov 2025 10:11:29 +0100 Subject: [PATCH 11/11] simplify deployBinary a little bit --- src/SPC/builder/unix/UnixBuilderBase.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/SPC/builder/unix/UnixBuilderBase.php b/src/SPC/builder/unix/UnixBuilderBase.php index d8f3ae2b..d98059cb 100644 --- a/src/SPC/builder/unix/UnixBuilderBase.php +++ b/src/SPC/builder/unix/UnixBuilderBase.php @@ -128,9 +128,6 @@ abstract class UnixBuilderBase extends BuilderBase { logger()->debug('Deploying binary from ' . $src . ' to ' . $dst); - // UPX for linux - $upx_option = (bool) $this->getOption('with-upx-pack', false); - // file must exists if (!file_exists($src)) { throw new SPCInternalException("Deploy failed. Cannot find file: {$src}"); @@ -152,13 +149,14 @@ abstract class UnixBuilderBase extends BuilderBase $this->extractDebugInfo($dst); // strip - if (!$this->getOption('no-strip', false)) { + if (!$this->getOption('no-strip')) { $this->stripBinary($dst); } - // Compress binary with UPX if needed (only for Linux) + // UPX for linux + $upx_option = $this->getOption('with-upx-pack'); if ($upx_option && PHP_OS_FAMILY === 'Linux' && $executable) { - if ($this->getOption('no-strip', false)) { + if ($this->getOption('no-strip')) { logger()->warning('UPX compression is not recommended when --no-strip is enabled.'); } logger()->info("Compressing {$dst} with UPX");