Compare commits

..

25 Commits

Author SHA1 Message Date
henderkes
637eadef0b phpstan 2026-03-10 08:36:30 +07:00
henderkes
3fee7deb6d force curl to absorb all k5 symbols 2026-03-10 08:36:30 +07:00
henderkes
d85f556a93 cs fix 2026-03-10 08:36:30 +07:00
henderkes
9564bae62b ld library path has to be set 2026-03-10 08:36:30 +07:00
henderkes
32678782fc cs fix 2026-03-10 08:36:30 +07:00
henderkes
1e6ddb86f2 support static-only libs 2026-03-10 08:36:30 +07:00
henderkes
fed477c81d lzma support was removed last year 2026-03-10 08:36:30 +07:00
henderkes
c3825a356b patch libxml2 for zig 2026-03-10 08:36:30 +07:00
henderkes
3d4b87b107 zig hasn't released 0.16 yet 2026-03-10 08:36:30 +07:00
henderkes
74906b89a2 libuuid fix 2026-03-10 08:36:30 +07:00
henderkes
1b2a09cb48 fix test 2026-03-10 08:36:30 +07:00
henderkes
7e9e3fb4fe fix krb5 liburing (no --enable-shared option) 2026-03-10 08:36:30 +07:00
henderkes
2511ee8a4c fix krb5 (can't do shared build with zig) 2026-03-10 08:36:30 +07:00
henderkes
17d699d4a5 fix xz shared build 2026-03-10 08:36:30 +07:00
henderkes
fa670cce4a fix pgsql shared build 2026-03-10 08:36:30 +07:00
henderkes
53385d5e2b cs fix 2026-03-10 08:36:30 +07:00
henderkes
ed1e02823a bring back setting, some libraries don't build a static version if the shared one should also be built... 2026-03-10 08:36:30 +07:00
henderkes
cc69a169a8 php-cs-fixer 2026-03-10 08:36:30 +07:00
henderkes
bae2eae2b0 bring back lib info 2026-03-10 08:36:30 +07:00
henderkes
b518237bb2 fix test 2026-03-10 08:36:30 +07:00
henderkes
17acb966de simplify 2026-03-10 08:36:30 +07:00
henderkes
101b4febb9 need to build zstd static 2026-03-10 08:36:30 +07:00
henderkes
7b8f1c4747 fixetyfix 2026-03-10 08:36:30 +07:00
henderkes
179626f989 need static libs because of lib.json 2026-03-10 08:36:30 +07:00
henderkes
cf69c02624 allow building and linking with shared instead of static libs 2026-03-10 08:36:30 +07:00
57 changed files with 271 additions and 535 deletions

View File

@@ -29,9 +29,6 @@ on:
description: Extensions to build (comma separated) description: Extensions to build (comma separated)
required: true required: true
type: string type: string
shared-extensions:
description: Shared extensions to build (optional, comma separated)
type: string
extra-libs: extra-libs:
description: Extra libraries to build (optional, comma separated) description: Extra libraries to build (optional, comma separated)
type: string type: string
@@ -45,14 +42,6 @@ on:
build-fpm: build-fpm:
description: Build fpm binary description: Build fpm binary
type: boolean type: boolean
build-frankenphp:
description: Build frankenphp binary (requires ZTS)
type: boolean
default: false
enable-zts:
description: Enable ZTS
type: boolean
default: false
prefer-pre-built: prefer-pre-built:
description: Prefer pre-built binaries (reduce build time) description: Prefer pre-built binaries (reduce build time)
type: boolean type: boolean
@@ -84,9 +73,6 @@ on:
description: Extensions to build (comma separated) description: Extensions to build (comma separated)
required: true required: true
type: string type: string
shared-extensions:
description: Shared extensions to build (optional, comma separated)
type: string
extra-libs: extra-libs:
description: Extra libraries to build (optional, comma separated) description: Extra libraries to build (optional, comma separated)
type: string type: string
@@ -100,14 +86,6 @@ on:
build-fpm: build-fpm:
description: Build fpm binary description: Build fpm binary
type: boolean type: boolean
build-frankenphp:
description: Build frankenphp binary (requires ZTS)
type: boolean
default: false
enable-zts:
description: Enable ZTS
type: boolean
default: false
prefer-pre-built: prefer-pre-built:
description: Prefer pre-built binaries (reduce build time) description: Prefer pre-built binaries (reduce build time)
type: boolean type: boolean
@@ -174,19 +152,8 @@ jobs:
RUNS_ON="macos-15" RUNS_ON="macos-15"
;; ;;
esac esac
STATIC_EXTS="${{ inputs.extensions }}" DOWN_CMD="$DOWN_CMD --with-php=${{ inputs.php-version }} --for-extensions=${{ inputs.extensions }} --ignore-cache-sources=php-src"
SHARED_EXTS="${{ inputs['shared-extensions'] }}" BUILD_CMD="$BUILD_CMD ${{ inputs.extensions }}"
BUILD_FRANKENPHP="${{ inputs['build-frankenphp'] }}"
ENABLE_ZTS="${{ inputs['enable-zts'] }}"
ALL_EXTS="$STATIC_EXTS"
if [ -n "$SHARED_EXTS" ]; then
ALL_EXTS="$ALL_EXTS,$SHARED_EXTS"
fi
DOWN_CMD="$DOWN_CMD --with-php=${{ inputs.php-version }} --for-extensions=$ALL_EXTS --ignore-cache-sources=php-src"
BUILD_CMD="$BUILD_CMD $STATIC_EXTS"
if [ -n "$SHARED_EXTS" ]; then
BUILD_CMD="$BUILD_CMD --build-shared=$SHARED_EXTS"
fi
if [ -n "${{ inputs.extra-libs }}" ]; then if [ -n "${{ inputs.extra-libs }}" ]; then
DOWN_CMD="$DOWN_CMD --for-libs=${{ inputs.extra-libs }}" DOWN_CMD="$DOWN_CMD --for-libs=${{ inputs.extra-libs }}"
BUILD_CMD="$BUILD_CMD --with-libs=${{ inputs.extra-libs }}" BUILD_CMD="$BUILD_CMD --with-libs=${{ inputs.extra-libs }}"
@@ -210,12 +177,6 @@ jobs:
if [ ${{ inputs.build-fpm }} == true ]; then if [ ${{ inputs.build-fpm }} == true ]; then
BUILD_CMD="$BUILD_CMD --build-fpm" BUILD_CMD="$BUILD_CMD --build-fpm"
fi fi
if [ "$BUILD_FRANKENPHP" = "true" ]; then
BUILD_CMD="$BUILD_CMD --build-frankenphp"
fi
if [ "$ENABLE_ZTS" = "true" ]; then
BUILD_CMD="$BUILD_CMD --enable-zts"
fi
echo 'download='"$DOWN_CMD" >> "$GITHUB_OUTPUT" echo 'download='"$DOWN_CMD" >> "$GITHUB_OUTPUT"
echo 'build='"$BUILD_CMD" >> "$GITHUB_OUTPUT" echo 'build='"$BUILD_CMD" >> "$GITHUB_OUTPUT"
echo 'run='"$RUNS_ON" >> "$GITHUB_OUTPUT" echo 'run='"$RUNS_ON" >> "$GITHUB_OUTPUT"
@@ -238,27 +199,6 @@ jobs:
env: env:
phpts: nts phpts: nts
- if: ${{ inputs['build-frankenphp'] == true }}
name: "Install go-xcaddy for FrankenPHP"
run: |
case "${{ inputs.os }}" in
linux-x86_64|linux-aarch64)
./bin/spc-alpine-docker install-pkg go-xcaddy
;;
linux-x86_64-glibc|linux-aarch64-glibc)
./bin/spc-gnu-docker install-pkg go-xcaddy
;;
macos-x86_64|macos-aarch64)
composer update --no-dev --classmap-authoritative
./bin/spc doctor --auto-fix
./bin/spc install-pkg go-xcaddy
;;
*)
echo "Unsupported OS for go-xcaddy install: ${{ inputs.os }}"
exit 1
;;
esac
# Cache downloaded source # Cache downloaded source
- id: cache-download - id: cache-download
uses: actions/cache@v4 uses: actions/cache@v4
@@ -305,22 +245,7 @@ jobs:
name: php-fpm-${{ inputs.php-version }}-${{ inputs.os }} name: php-fpm-${{ inputs.php-version }}-${{ inputs.os }}
path: buildroot/bin/php-fpm path: buildroot/bin/php-fpm
# Upload frankenphp executable
- if: ${{ inputs['build-frankenphp'] == true }}
name: "Upload FrankenPHP SAPI"
uses: actions/upload-artifact@v4
with:
name: php-frankenphp-${{ inputs.php-version }}-${{ inputs.os }}
path: buildroot/bin/frankenphp
# Upload extensions metadata # Upload extensions metadata
- if: ${{ inputs['shared-extensions'] != '' }}
name: "Upload shared extensions"
uses: actions/upload-artifact@v4
with:
name: php-shared-ext-${{ inputs.php-version }}-${{ inputs.os }}
path: |
buildroot/modules/*.so
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
name: "Upload License Files" name: "Upload License Files"
with: with:

View File

@@ -11,7 +11,6 @@
"require": { "require": {
"php": ">= 8.3", "php": ">= 8.3",
"ext-mbstring": "*", "ext-mbstring": "*",
"ext-simplexml": "*",
"ext-zlib": "*", "ext-zlib": "*",
"laravel/prompts": "^0.1.12", "laravel/prompts": "^0.1.12",
"symfony/console": "^5.4 || ^6 || ^7", "symfony/console": "^5.4 || ^6 || ^7",

View File

@@ -79,6 +79,7 @@ SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime
SPC_LIBC=musl SPC_LIBC=musl
; uncomment to link libc dynamically on musl ; uncomment to link libc dynamically on musl
; SPC_MUSL_DYNAMIC=true ; SPC_MUSL_DYNAMIC=true
SPC_LINK_STATIC=true
; Recommended: specify your target here. Zig toolchain will be used. ; Recommended: specify your target here. Zig toolchain will be used.
; examples: ; examples:
@@ -97,7 +98,7 @@ LD=${SPC_LINUX_DEFAULT_LD}
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build ; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
SPC_DEFAULT_C_FLAGS="-fPIC -Os" SPC_DEFAULT_C_FLAGS="-fPIC -Os"
SPC_DEFAULT_CXX_FLAGS="-fPIC -Os" SPC_DEFAULT_CXX_FLAGS="-fPIC -Os"
SPC_DEFAULT_LD_FLAGS="" SPC_DEFAULT_LD_FLAGS="-Wl,--as-needed"
; upx executable path ; upx executable path
UPX_EXEC=${PKG_ROOT_PATH}/bin/upx UPX_EXEC=${PKG_ROOT_PATH}/bin/upx
; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches ; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches
@@ -115,7 +116,7 @@ SPC_CMD_VAR_PHP_EMBED_TYPE="static"
; EXTRA_CFLAGS for `configure` and `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}" 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 ; EXTRA_LDFLAGS for `make` php, can use -release to set a soname for libphp.so
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS="" SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS="-Wl,--as-needed"
; optional, path to openssl conf. This affects where openssl will look for the default CA. ; 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 ; default on Debian/Alpine: /etc/ssl, default on RHEL: /etc/pki/tls
@@ -148,8 +149,6 @@ SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --enable-
SPC_CMD_VAR_PHP_EMBED_TYPE="static" SPC_CMD_VAR_PHP_EMBED_TYPE="static"
; EXTRA_CFLAGS for `configure` and `make` php ; 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}" SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fpic -fpie -Werror=unknown-warning-option ${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=""
; minimum compatible macOS version (LLVM vars, availability not guaranteed) ; minimum compatible macOS version (LLVM vars, availability not guaranteed)
MACOSX_DEPLOYMENT_TARGET=12.0 MACOSX_DEPLOYMENT_TARGET=12.0

View File

@@ -252,7 +252,6 @@
"arg-type-unix": "enable-path", "arg-type-unix": "enable-path",
"cpp-extension": true, "cpp-extension": true,
"lib-depends": [ "lib-depends": [
"grpc",
"zlib", "zlib",
"openssl", "openssl",
"libcares" "libcares"

View File

@@ -143,7 +143,9 @@
"zlib" "zlib"
], ],
"lib-suggests": [ "lib-suggests": [
"libpng" "libpng",
"bzip2",
"brotli"
] ]
}, },
"gettext": { "gettext": {
@@ -301,6 +303,9 @@
}, },
"krb5": { "krb5": {
"source": "krb5", "source": "krb5",
"target": [
"static"
],
"pkg-configs": [ "pkg-configs": [
"krb5-gssapi" "krb5-gssapi"
], ],
@@ -353,9 +358,6 @@
"static-libs-unix": [ "static-libs-unix": [
"libaom.a" "libaom.a"
], ],
"static-libs-windows": [
"aom.lib"
],
"cpp-library": true "cpp-library": true
}, },
"libargon2": { "libargon2": {
@@ -1027,7 +1029,7 @@
"pkg-configs": [ "pkg-configs": [
"zlib" "zlib"
], ],
"static-libs-unix": [ "static-libs": [
"libz.a" "libz.a"
], ],
"static-libs-windows": [ "static-libs-windows": [
@@ -1047,10 +1049,8 @@
"libzstd.a" "libzstd.a"
], ],
"static-libs-windows": [ "static-libs-windows": [
[ "zstd.lib",
"zstd.lib", "zstd_static.lib"
"zstd_static.lib"
]
], ],
"headers-unix": [ "headers-unix": [
"zdict.h", "zdict.h",

View File

@@ -8,25 +8,30 @@
"alt": false "alt": false
}, },
"amqp": { "amqp": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/amqp",
"path": "php-src/ext/amqp", "path": "php-src/ext/amqp",
"filename": "amqp.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"apcu": { "apcu": {
"type": "pecl", "type": "url",
"pecl": "APCu", "url": "https://pecl.php.net/get/APCu",
"path": "php-src/ext/apcu", "path": "php-src/ext/apcu",
"filename": "apcu.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"ast": { "ast": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/ast",
"path": "php-src/ext/ast", "path": "php-src/ext/ast",
"filename": "ast.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -80,16 +85,20 @@
} }
}, },
"dio": { "dio": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/dio",
"path": "php-src/ext/dio", "path": "php-src/ext/dio",
"filename": "dio.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"ev": { "ev": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/ev",
"path": "php-src/ext/ev", "path": "php-src/ext/ev",
"filename": "ev.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -106,8 +115,10 @@
} }
}, },
"ext-ds": { "ext-ds": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/ds",
"path": "php-src/ext/ds", "path": "php-src/ext/ds",
"filename": "ds.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -123,8 +134,10 @@
} }
}, },
"ext-excimer": { "ext-excimer": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/excimer",
"path": "php-src/ext/excimer", "path": "php-src/ext/excimer",
"filename": "excimer.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -149,8 +162,10 @@
} }
}, },
"ext-grpc": { "ext-grpc": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/grpc",
"path": "php-src/ext/grpc", "path": "php-src/ext/grpc",
"filename": "grpc.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": [ "path": [
@@ -159,16 +174,20 @@
} }
}, },
"ext-imagick": { "ext-imagick": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/imagick",
"path": "php-src/ext/imagick", "path": "php-src/ext/imagick",
"filename": "imagick.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"ext-imap": { "ext-imap": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/imap",
"path": "php-src/ext/imap", "path": "php-src/ext/imap",
"filename": "imap.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": [ "path": [
@@ -188,15 +207,19 @@
} }
}, },
"ext-maxminddb": { "ext-maxminddb": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/maxminddb",
"filename": "ext-maxminddb.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"ext-memcache": { "ext-memcache": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/memcache",
"path": "php-src/ext/memcache", "path": "php-src/ext/memcache",
"filename": "memcache.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -212,8 +235,10 @@
} }
}, },
"ext-simdjson": { "ext-simdjson": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/simdjson",
"path": "php-src/ext/simdjson", "path": "php-src/ext/simdjson",
"filename": "simdjson.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -230,32 +255,40 @@
} }
}, },
"ext-ssh2": { "ext-ssh2": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/ssh2",
"path": "php-src/ext/ssh2", "path": "php-src/ext/ssh2",
"filename": "ssh2.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"ext-trader": { "ext-trader": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/trader",
"path": "php-src/ext/trader", "path": "php-src/ext/trader",
"filename": "trader.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"ext-uuid": { "ext-uuid": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/uuid",
"path": "php-src/ext/uuid", "path": "php-src/ext/uuid",
"filename": "uuid.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"ext-uv": { "ext-uv": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/uv",
"path": "php-src/ext/uv", "path": "php-src/ext/uv",
"filename": "uv.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -272,7 +305,9 @@
} }
}, },
"ext-zip": { "ext-zip": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/zip",
"filename": "ext-zip.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -377,8 +412,10 @@
} }
}, },
"igbinary": { "igbinary": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/igbinary",
"path": "php-src/ext/igbinary", "path": "php-src/ext/igbinary",
"filename": "igbinary.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "COPYING" "path": "COPYING"
@@ -402,8 +439,10 @@
} }
}, },
"inotify": { "inotify": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/inotify",
"path": "php-src/ext/inotify", "path": "php-src/ext/inotify",
"filename": "inotify.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -805,8 +844,10 @@
} }
}, },
"memcached": { "memcached": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/memcached",
"path": "php-src/ext/memcached", "path": "php-src/ext/memcached",
"filename": "memcached.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -844,8 +885,10 @@
} }
}, },
"msgpack": { "msgpack": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/msgpack",
"path": "php-src/ext/msgpack", "path": "php-src/ext/msgpack",
"filename": "msgpack.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -945,31 +988,39 @@
} }
}, },
"opentelemetry": { "opentelemetry": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/opentelemetry",
"path": "php-src/ext/opentelemetry", "path": "php-src/ext/opentelemetry",
"filename": "opentelemetry.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"parallel": { "parallel": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/parallel",
"path": "php-src/ext/parallel", "path": "php-src/ext/parallel",
"filename": "parallel.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"pcov": { "pcov": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/pcov",
"filename": "pcov.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"pdo_sqlsrv": { "pdo_sqlsrv": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/pdo_sqlsrv",
"path": "php-src/ext/pdo_sqlsrv", "path": "php-src/ext/pdo_sqlsrv",
"filename": "pdo_sqlsrv.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -1002,8 +1053,10 @@
} }
}, },
"protobuf": { "protobuf": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/protobuf",
"path": "php-src/ext/protobuf", "path": "php-src/ext/protobuf",
"filename": "protobuf.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -1062,8 +1115,10 @@
} }
}, },
"redis": { "redis": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/redis",
"path": "php-src/ext/redis", "path": "php-src/ext/redis",
"filename": "redis.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": [ "path": [
@@ -1100,8 +1155,10 @@
} }
}, },
"sqlsrv": { "sqlsrv": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/sqlsrv",
"path": "php-src/ext/sqlsrv", "path": "php-src/ext/sqlsrv",
"filename": "sqlsrv.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -1164,16 +1221,20 @@
} }
}, },
"xhprof": { "xhprof": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/xhprof",
"path": "php-src/ext/xhprof-src", "path": "php-src/ext/xhprof-src",
"filename": "xhprof.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"xlswriter": { "xlswriter": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/xlswriter",
"path": "php-src/ext/xlswriter", "path": "php-src/ext/xlswriter",
"filename": "xlswriter.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -1191,8 +1252,10 @@
} }
}, },
"yac": { "yac": {
"type": "pecl", "type": "url",
"url": "https://pecl.php.net/get/yac",
"path": "php-src/ext/yac", "path": "php-src/ext/yac",
"filename": "yac.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"

View File

@@ -16,10 +16,8 @@ while also defining the extensions to compile.
1. Fork project. 1. Fork project.
2. Go to the Actions of the project and select `CI`. 2. Go to the Actions of the project and select `CI`.
3. Select `Run workflow`, fill in the PHP version you want to compile, the target type, and the list of static extensions. (comma separated, e.g. `bcmath,curl,mbstring`) 3. Select `Run workflow`, fill in the PHP version you want to compile, the target type, and the list of extensions. (extensions comma separated, e.g. `bcmath,curl,mbstring`)
4. If you need shared extensions (for example `xdebug`), set `shared-extensions` (comma separated, e.g. `xdebug`). 4. After waiting for about a period of time, enter the corresponding task and get `Artifacts`.
5. If you need FrankenPHP, enable `build-frankenphp` and also enable `enable-zts`.
6. After waiting for about a period of time, enter the corresponding task and get `Artifacts`.
If you enable `debug`, all logs will be output at build time, including compiled logs, for troubleshooting. If you enable `debug`, all logs will be output at build time, including compiled logs, for troubleshooting.

View File

@@ -14,9 +14,7 @@ Action 构建指的是直接使用 GitHub Action 进行编译。
1. Fork 本项目。 1. Fork 本项目。
2. 进入项目的 Actions选择 CI 开头的 Workflow根据你需要的操作系统选择 2. 进入项目的 Actions选择 CI 开头的 Workflow根据你需要的操作系统选择
3. 选择 `Run workflow`,填入你要编译的 PHP 版本、目标类型、扩展列表。(扩展列表使用英文逗号分割,例如 `bcmath,curl,mbstring` 3. 选择 `Run workflow`,填入你要编译的 PHP 版本、目标类型、扩展列表。(扩展列表使用英文逗号分割,例如 `bcmath,curl,mbstring`
4. 如果需要共享扩展(例如 `xdebug`),请设置 `shared-extensions`(使用英文逗号分割,例如 `xdebug` 4. 等待大约一段时间后,进入对应的任务中,获取 `Artifacts`
5. 如果需要 FrankenPHP请启用 `build-frankenphp`,同时也需要启用 `enable-zts`
6. 等待大约一段时间后,进入对应的任务中,获取 `Artifacts`
如果你选择了 `debug`,则会在构建时输出所有日志,包括编译的日志,以供排查错误。 如果你选择了 `debug`,则会在构建时输出所有日志,包括编译的日志,以供排查错误。

View File

@@ -34,7 +34,7 @@ use Symfony\Component\Console\Application;
*/ */
final class ConsoleApplication extends Application final class ConsoleApplication extends Application
{ {
public const string VERSION = '2.8.4'; public const string VERSION = '2.8.3';
public function __construct() public function __construct()
{ {

View File

@@ -365,7 +365,8 @@ abstract class LibraryBase
protected function isLibraryInstalled(): bool protected function isLibraryInstalled(): bool
{ {
if ($pkg_configs = Config::getLib(static::NAME, 'pkg-configs', [])) { $pkg_configs = Config::getLib(static::NAME, 'pkg-configs', []);
if (count($pkg_configs) !== 0) {
$pkg_config_path = getenv('PKG_CONFIG_PATH') ?: ''; $pkg_config_path = getenv('PKG_CONFIG_PATH') ?: '';
$search_paths = array_unique(array_filter(explode(is_unix() ? ':' : ';', $pkg_config_path))); $search_paths = array_unique(array_filter(explode(is_unix() ? ':' : ';', $pkg_config_path)));
@@ -381,13 +382,14 @@ abstract class LibraryBase
return false; return false;
} }
} }
// allow using system dependencies if pkg_config_path is explicitly defined return true; // allow using system dependencies if pkg_config_path is explicitly defined
if (count($search_paths) > 1) {
return true;
}
} }
foreach (Config::getLib(static::NAME, 'static-libs', []) as $name) { foreach (Config::getLib(static::NAME, 'static-libs', []) as $name) {
if (!file_exists(BUILD_LIB_PATH . "/{$name}")) { if (!file_exists(BUILD_LIB_PATH . "/{$name}")) {
$sharedLib = str_replace('.a', '.so', $name);
if (!getenv('SPC_LINK_STATIC') && file_exists(BUILD_LIB_PATH . "/{$sharedLib}")) {
continue;
}
return false; return false;
} }
} }
@@ -396,20 +398,6 @@ abstract class LibraryBase
return false; return false;
} }
} }
$pkg_config_path = getenv('PKG_CONFIG_PATH') ?: '';
$search_paths = array_filter(explode(is_unix() ? ':' : ';', $pkg_config_path));
foreach (Config::getLib(static::NAME, 'pkg-configs', []) as $name) {
$found = false;
foreach ($search_paths as $path) {
if (file_exists($path . "/{$name}.pc")) {
$found = true;
break;
}
}
if (!$found) {
return false;
}
}
foreach (Config::getLib(static::NAME, 'bin', []) as $name) { foreach (Config::getLib(static::NAME, 'bin', []) as $name) {
if (!file_exists(BUILD_BIN_PATH . "/{$name}")) { if (!file_exists(BUILD_BIN_PATH . "/{$name}")) {
return false; return false;

View File

@@ -11,6 +11,7 @@ use SPC\store\FileSystem;
use SPC\util\CustomExt; use SPC\util\CustomExt;
use SPC\util\GlobalEnvManager; use SPC\util\GlobalEnvManager;
use SPC\util\SPCConfigUtil; use SPC\util\SPCConfigUtil;
use SPC\util\SPCTarget;
#[CustomExt('grpc')] #[CustomExt('grpc')]
class grpc extends Extension class grpc extends Extension
@@ -20,50 +21,18 @@ class grpc extends Extension
if ($this->builder instanceof WindowsBuilder) { if ($this->builder instanceof WindowsBuilder) {
throw new ValidationException('grpc extension does not support windows yet'); throw new ValidationException('grpc extension does not support windows yet');
} }
// Fix deprecated PHP API usage in call.c
FileSystem::replaceFileStr( FileSystem::replaceFileStr(
"{$this->source_dir}/src/php/ext/grpc/call.c", $this->source_dir . '/src/php/ext/grpc/call.c',
'zend_exception_get_default(TSRMLS_C),', 'zend_exception_get_default(TSRMLS_C),',
'zend_ce_exception,', 'zend_ce_exception,',
); );
if (SPCTarget::getTargetOS() === 'Darwin') {
$config_m4 = <<<'M4' FileSystem::replaceFileRegex(
PHP_ARG_ENABLE(grpc, [whether to enable grpc support], [AS_HELP_STRING([--enable-grpc], [Enable grpc support])]) $this->source_dir . '/config.m4',
'/GRPC_LIBDIR=.*$/m',
if test "$PHP_GRPC" != "no"; then 'GRPC_LIBDIR=' . BUILD_LIB_PATH . "\n" . 'LDFLAGS="$LDFLAGS -framework CoreFoundation"'
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include) );
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc) }
GRPC_LIBDIR=@@build_lib_path@@
PHP_ADD_LIBPATH($GRPC_LIBDIR)
PHP_ADD_LIBRARY(grpc,,GRPC_SHARED_LIBADD)
LIBS="-lpthread $LIBS"
PHP_ADD_LIBRARY(pthread)
case $host in
*darwin*)
PHP_ADD_LIBRARY(c++,1,GRPC_SHARED_LIBADD)
;;
*)
PHP_ADD_LIBRARY(stdc++,1,GRPC_SHARED_LIBADD)
PHP_ADD_LIBRARY(rt,,GRPC_SHARED_LIBADD)
PHP_ADD_LIBRARY(rt)
;;
esac
PHP_NEW_EXTENSION(grpc, @grpc_c_files@, $ext_shared, , -DGRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK=1)
PHP_SUBST(GRPC_SHARED_LIBADD)
PHP_INSTALL_HEADERS([ext/grpc], [php_grpc.h])
fi
M4;
$replace = get_pack_replace();
// load grpc c files from src/php/ext/grpc
$c_files = glob($this->source_dir . '/src/php/ext/grpc/*.c');
$replace['@grpc_c_files@'] = implode(" \\\n ", array_map(fn ($f) => 'src/php/ext/grpc/' . basename($f), $c_files));
$config_m4 = str_replace(array_keys($replace), array_values($replace), $config_m4);
file_put_contents($this->source_dir . '/config.m4', $config_m4);
copy($this->source_dir . '/src/php/ext/grpc/php_grpc.h', $this->source_dir . '/php_grpc.h');
return true; return true;
} }
@@ -79,6 +48,7 @@ M4;
public function patchBeforeMake(): bool public function patchBeforeMake(): bool
{ {
parent::patchBeforeMake(); parent::patchBeforeMake();
// add -Wno-strict-prototypes
GlobalEnvManager::putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -Wno-strict-prototypes'); GlobalEnvManager::putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -Wno-strict-prototypes');
return true; return true;
} }

View File

@@ -25,8 +25,8 @@ class pgsql extends Extension
{ {
if ($this->builder->getPHPVersionID() >= 80400) { if ($this->builder->getPHPVersionID() >= 80400) {
$libfiles = $this->getLibFilesString(); $libfiles = $this->getLibFilesString();
$libfiles = str_replace(BUILD_LIB_PATH . '/lib', '-l', $libfiles); $libfiles = deduplicate_flags($libfiles);
$libfiles = str_replace('.a', '', $libfiles); $libfiles = clean_spaces($libfiles);
return '--with-pgsql' . ($shared ? '=shared' : '') . return '--with-pgsql' . ($shared ? '=shared' : '') .
' PGSQL_CFLAGS=-I' . BUILD_INCLUDE_PATH . ' PGSQL_CFLAGS=-I' . BUILD_INCLUDE_PATH .
' PGSQL_LIBS="-L' . BUILD_LIB_PATH . ' ' . $libfiles . '"'; ' PGSQL_LIBS="-L' . BUILD_LIB_PATH . ' ' . $libfiles . '"';

View File

@@ -50,16 +50,19 @@ class swoole extends Extension
// commonly used feature: coroutine-time // commonly used feature: coroutine-time
$arg .= ' --enable-swoole-coro-time --with-pic'; $arg .= ' --enable-swoole-coro-time --with-pic';
$arg .= ' --enable-swoole-ssh --enable-swoole-curl';
$arg .= $this->builder->getOption('enable-zts') ? ' --enable-swoole-thread --disable-thread-context' : ' --disable-swoole-thread --enable-thread-context'; $arg .= $this->builder->getOption('enable-zts') ? ' --enable-swoole-thread --disable-thread-context' : ' --disable-swoole-thread --enable-thread-context';
// required features: curl, openssl (but curl hook is buggy for php 8.0)
$arg .= $this->builder->getPHPVersionID() >= 80100 ? ' --enable-swoole-curl' : ' --disable-swoole-curl';
$arg .= ' --enable-openssl';
// additional features that only require libraries // additional features that only require libraries
$arg .= $this->builder->getLib('libcares') ? ' --enable-cares' : ''; $arg .= $this->builder->getLib('libcares') ? ' --enable-cares' : '';
$arg .= $this->builder->getLib('brotli') ? (' --enable-brotli --with-brotli-dir=' . BUILD_ROOT_PATH) : ''; $arg .= $this->builder->getLib('brotli') ? (' --enable-brotli --with-brotli-dir=' . BUILD_ROOT_PATH) : '';
$arg .= $this->builder->getLib('nghttp2') ? (' --with-nghttp2-dir=' . BUILD_ROOT_PATH) : ''; $arg .= $this->builder->getLib('nghttp2') ? (' --with-nghttp2-dir=' . BUILD_ROOT_PATH) : '';
$arg .= $this->builder->getLib('zstd') ? ' --enable-zstd' : ''; $arg .= $this->builder->getLib('zstd') ? ' --enable-zstd' : '';
$arg .= $this->builder->getLib('liburing') ? ' --enable-iouring --enable-uring-socket' : ''; $arg .= $this->builder->getLib('liburing') ? ' --enable-iouring' : '';
$arg .= $this->builder->getExt('sockets') ? ' --enable-sockets' : ''; $arg .= $this->builder->getExt('sockets') ? ' --enable-sockets' : '';
// enable additional features that require the pdo extension, but conflict with pdo_* extensions // enable additional features that require the pdo extension, but conflict with pdo_* extensions
@@ -71,7 +74,6 @@ class swoole extends Extension
$config = (new SPCConfigUtil($this->builder))->getLibraryConfig($this->builder->getLib('unixodbc')); $config = (new SPCConfigUtil($this->builder))->getLibraryConfig($this->builder->getLib('unixodbc'));
$arg .= ' --with-swoole-odbc=unixODBC,' . BUILD_ROOT_PATH . ' SWOOLE_ODBC_LIBS="' . $config['libs'] . '"'; $arg .= ' --with-swoole-odbc=unixODBC,' . BUILD_ROOT_PATH . ' SWOOLE_ODBC_LIBS="' . $config['libs'] . '"';
} }
$arg .= $this->builder->getExt('ftp')?->isBuildStatic() ? ' --disable-swoole-ftp' : ' --enable-swoole-ftp';
if ($this->getExtVersion() >= '6.1.0') { if ($this->getExtVersion() >= '6.1.0') {
$arg .= ' --enable-swoole-stdext'; $arg .= ' --enable-swoole-stdext';

View File

@@ -42,7 +42,7 @@ class openssl extends BSDLibraryBase
shell()->cd($this->source_dir)->initializeEnv($this) shell()->cd($this->source_dir)->initializeEnv($this)
->exec( ->exec(
"./Configure no-shared {$extra} " . "./Configure {$extra} " .
'--prefix=/ ' . // use prefix=/ '--prefix=/ ' . // use prefix=/
"--libdir={$lib} " . "--libdir={$lib} " .
'--openssldir=/etc/ssl ' . '--openssldir=/etc/ssl ' .

View File

@@ -94,6 +94,7 @@ class LinuxBuilder extends UnixBuilderBase
'CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), 'CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'),
'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH, // . ' -Dsomethinghere', // . $musl_flag, 'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH, // . ' -Dsomethinghere', // . $musl_flag,
'LDFLAGS' => '-L' . BUILD_LIB_PATH, 'LDFLAGS' => '-L' . BUILD_LIB_PATH,
'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
// 'LIBS' => SPCTarget::getRuntimeLibs(), // do not pass static libraries here yet, they may contain polyfills for libc functions! // 'LIBS' => SPCTarget::getRuntimeLibs(), // do not pass static libraries here yet, they may contain polyfills for libc functions!
]); ]);
@@ -162,7 +163,7 @@ class LinuxBuilder extends UnixBuilderBase
throw new WrongUsageException( throw new WrongUsageException(
"You're building against musl libc statically (the default on Linux), but you're trying to build shared extensions.\n" . "You're building against musl libc statically (the default on Linux), but you're trying to build shared extensions.\n" .
'Static musl libc does not implement `dlopen`, so your php binary is not able to load shared extensions.' . "\n" . 'Static musl libc does not implement `dlopen`, so your php binary is not able to load shared extensions.' . "\n" .
'Either use SPC_LIBC=glibc to link against glibc on a glibc OS, use SPC_TARGET="native-native-musl -dynamic" to link against musl libc dynamically using `zig cc` or use SPC_MUSL_DYNAMIC=true on alpine.' 'Either use SPC_LIBC=glibc to link against glibc on a glibc OS, or use SPC_TARGET="native-native-musl -dynamic" to link against musl libc dynamically using `zig cc`.'
); );
} }
logger()->info('Building shared extensions...'); logger()->info('Building shared extensions...');
@@ -316,7 +317,7 @@ class LinuxBuilder extends UnixBuilderBase
*/ */
private function getMakeExtraVars(): array private function getMakeExtraVars(): array
{ {
$config = (new SPCConfigUtil($this, ['libs_only_deps' => true, 'absolute_libs' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs')); $config = (new SPCConfigUtil($this, ['libs_only_deps' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs'));
$static = SPCTarget::isStatic() ? '-all-static' : ''; $static = SPCTarget::isStatic() ? '-all-static' : '';
$lib = BUILD_LIB_PATH; $lib = BUILD_LIB_PATH;
return array_filter([ return array_filter([

View File

@@ -35,10 +35,13 @@ class liburing extends LinuxLibraryBase
]); ]);
} }
$shared = getenv('SPC_LINK_STATIC') ? 'ENABLE_SHARED=0' : 'ENABLE_SHARED=1';
$make $make
->removeConfigureArgs( ->removeConfigureArgs(
'--disable-shared',
'--enable-static', '--enable-static',
'--disable-static',
'--enable-shared',
'--disable-shared',
'--with-pic', '--with-pic',
'--enable-pic', '--enable-pic',
) )
@@ -46,7 +49,7 @@ class liburing extends LinuxLibraryBase
$use_libc ? '--use-libc' : '', $use_libc ? '--use-libc' : '',
) )
->configure() ->configure()
->make('library ENABLE_SHARED=0', 'install ENABLE_SHARED=0', with_clean: false); ->make("library {$shared}", "install {$shared}", with_clean: false);
$this->patchPkgconfPrefix(); $this->patchPkgconfPrefix();
} }

View File

@@ -56,10 +56,11 @@ class openssl extends LinuxLibraryBase
// TODO: in v3 use the following: $openssl_dir ??= SystemUtil::getOSRelease()['dist'] === 'redhat' ? '/etc/pki/tls' : '/etc/ssl'; // TODO: in v3 use the following: $openssl_dir ??= SystemUtil::getOSRelease()['dist'] === 'redhat' ? '/etc/pki/tls' : '/etc/ssl';
$openssl_dir ??= '/etc/ssl'; $openssl_dir ??= '/etc/ssl';
$ex_lib = trim($ex_lib); $ex_lib = trim($ex_lib);
$noShared = getenv('SPC_LINK_STATIC') ? 'no-shared' : '';
shell()->cd($this->source_dir)->initializeEnv($this) shell()->cd($this->source_dir)->initializeEnv($this)
->exec( ->exec(
"{$env} ./Configure no-shared {$extra} " . "./Configure {$noShared} {$extra} " .
'--prefix=' . BUILD_ROOT_PATH . ' ' . '--prefix=' . BUILD_ROOT_PATH . ' ' .
'--libdir=' . BUILD_LIB_PATH . ' ' . '--libdir=' . BUILD_LIB_PATH . ' ' .
"--openssldir={$openssl_dir} " . "--openssldir={$openssl_dir} " .

View File

@@ -43,7 +43,7 @@ class openssl extends MacOSLibraryBase
shell()->cd($this->source_dir)->initializeEnv($this) shell()->cd($this->source_dir)->initializeEnv($this)
->exec( ->exec(
"./Configure no-shared {$extra} " . "./Configure {$extra} " .
'--prefix=' . BUILD_ROOT_PATH . ' ' . // use prefix=/ '--prefix=' . BUILD_ROOT_PATH . ' ' . // use prefix=/
'--libdir=lib ' . '--libdir=lib ' .
'--openssldir=/etc/ssl ' . '--openssldir=/etc/ssl ' .

View File

@@ -15,7 +15,7 @@ trait UnixLibraryTrait
{ {
$libs = $include_self ? [$this] : []; $libs = $include_self ? [$this] : [];
array_unshift($libs, ...array_values($this->getDependencies(recursive: true))); array_unshift($libs, ...array_values($this->getDependencies(recursive: true)));
$config = new SPCConfigUtil($this->builder, options: ['libs_only_deps' => true, 'absolute_libs' => true]); $config = new SPCConfigUtil($this->builder, options: ['libs_only_deps' => true]);
$res = $config->config(libraries: array_map(fn ($x) => $x->getName(), $libs)); $res = $config->config(libraries: array_map(fn ($x) => $x->getName(), $libs));
return $res['libs']; return $res['libs'];
} }

View File

@@ -7,6 +7,7 @@ namespace SPC\builder\traits;
use SPC\exception\ExecutionException; use SPC\exception\ExecutionException;
use SPC\exception\SPCInternalException; use SPC\exception\SPCInternalException;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
use SPC\store\pkg\Zig;
use SPC\toolchain\ToolchainManager; use SPC\toolchain\ToolchainManager;
use SPC\toolchain\ZigToolchain; use SPC\toolchain\ZigToolchain;
use SPC\util\SPCTarget; use SPC\util\SPCTarget;
@@ -72,11 +73,11 @@ trait UnixSystemUtilTrait
if (!is_file($symbol_file)) { if (!is_file($symbol_file)) {
throw new SPCInternalException("The symbol file {$symbol_file} does not exist, please check if nm command is available."); throw new SPCInternalException("The symbol file {$symbol_file} does not exist, please check if nm command is available.");
} }
// macOS/zig
// https://github.com/ziglang/zig/issues/24662 // https://github.com/ziglang/zig/issues/24662
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) { if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
return '-Wl,--export-dynamic'; // needs release 0.16, can be removed then return '-Wl,--export-dynamic'; // needs release 0.16, can be removed then
} }
// macOS/zig
if (SPCTarget::getTargetOS() !== 'Linux' || ToolchainManager::getToolchainClass() === ZigToolchain::class) { if (SPCTarget::getTargetOS() !== 'Linux' || ToolchainManager::getToolchainClass() === ZigToolchain::class) {
return "-Wl,-exported_symbols_list,{$symbol_file}"; return "-Wl,-exported_symbols_list,{$symbol_file}";
} }

View File

@@ -457,7 +457,6 @@ abstract class UnixBuilderBase extends BuilderBase
'XCADDY_GO_BUILD_FLAGS' => '-buildmode=pie ' . 'XCADDY_GO_BUILD_FLAGS' => '-buildmode=pie ' .
'-ldflags \"-linkmode=external ' . $extLdFlags . ' ' . '-ldflags \"-linkmode=external ' . $extLdFlags . ' ' .
'-X \'github.com/caddyserver/caddy/v2/modules/caddyhttp.ServerHeader=FrankenPHP Caddy\' ' . '-X \'github.com/caddyserver/caddy/v2/modules/caddyhttp.ServerHeader=FrankenPHP Caddy\' ' .
'-X \'github.com/caddyserver/caddy/v2.CustomBinaryName=frankenphp\' ' .
'-X \'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ' . '-X \'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ' .
"v{$frankenPhpVersion} PHP {$libphpVersion} Caddy'\\\" " . "v{$frankenPhpVersion} PHP {$libphpVersion} Caddy'\\\" " .
"-tags={$muslTags}nobadger,nomysql,nopgx{$nobrotli}{$nowatcher}", "-tags={$muslTags}nobadger,nomysql,nopgx{$nobrotli}{$nowatcher}",

View File

@@ -20,11 +20,6 @@ trait brotli
FileSystem::replaceFileLineContainsString(BUILD_LIB_PATH . '/pkgconfig/libbrotlidec.pc', 'Libs: -L${libdir} -lbrotlidec', 'Libs: -L${libdir} -lbrotlidec -lbrotlicommon'); FileSystem::replaceFileLineContainsString(BUILD_LIB_PATH . '/pkgconfig/libbrotlidec.pc', 'Libs: -L${libdir} -lbrotlidec', 'Libs: -L${libdir} -lbrotlidec -lbrotlicommon');
FileSystem::replaceFileLineContainsString(BUILD_LIB_PATH . '/pkgconfig/libbrotlienc.pc', 'Libs: -L${libdir} -lbrotlienc', 'Libs: -L${libdir} -lbrotlienc -lbrotlicommon'); FileSystem::replaceFileLineContainsString(BUILD_LIB_PATH . '/pkgconfig/libbrotlienc.pc', 'Libs: -L${libdir} -lbrotlienc', 'Libs: -L${libdir} -lbrotlienc -lbrotlicommon');
shell()->cd(BUILD_ROOT_PATH . '/lib')->exec('ln -sf libbrotlicommon.a libbrotli.a'); shell()->cd(BUILD_ROOT_PATH . '/lib')->exec('ln -sf libbrotlicommon.a libbrotli.a');
foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) {
if (str_starts_with($filename, 'libbrotli') && (str_contains($filename, '.so') || str_ends_with($filename, '.dylib'))) {
unlink(BUILD_ROOT_PATH . '/lib/' . $filename);
}
}
if (file_exists(BUILD_BIN_PATH . '/brotli')) { if (file_exists(BUILD_BIN_PATH . '/brotli')) {
unlink(BUILD_BIN_PATH . '/brotli'); unlink(BUILD_BIN_PATH . '/brotli');

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\unix\library; namespace SPC\builder\unix\library;
use SPC\util\executor\UnixCMakeExecutor; use SPC\util\executor\UnixCMakeExecutor;
use SPC\util\SPCConfigUtil;
trait curl trait curl
{ {
@@ -12,6 +13,13 @@ trait curl
{ {
shell()->cd($this->source_dir)->exec('sed -i.save s@\${CMAKE_C_IMPLICIT_LINK_LIBRARIES}@@ ./CMakeLists.txt'); shell()->cd($this->source_dir)->exec('sed -i.save s@\${CMAKE_C_IMPLICIT_LINK_LIBRARIES}@@ ./CMakeLists.txt');
$linkerFlags = null;
if ($this->builder->getLib('krb5') && !getenv('SPC_LINK_STATIC')) {
$util = new SPCConfigUtil($this->builder, ['libs_only_deps' => true]);
$config = $util->config(libraries: ['krb5']);
$linkerFlags = $config['ldflags'] . ' -Wl,--whole-archive -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -lkrb5support -Wl,--no-whole-archive -Wl,--no-undefined';
}
UnixCMakeExecutor::create($this) UnixCMakeExecutor::create($this)
->optionalLib('openssl', '-DCURL_USE_OPENSSL=ON -DCURL_CA_BUNDLE=OFF -DCURL_CA_PATH=OFF -DCURL_CA_FALLBACK=ON', '-DCURL_USE_OPENSSL=OFF -DCURL_ENABLE_SSL=OFF') ->optionalLib('openssl', '-DCURL_USE_OPENSSL=ON -DCURL_CA_BUNDLE=OFF -DCURL_CA_PATH=OFF -DCURL_CA_FALLBACK=ON', '-DCURL_USE_OPENSSL=OFF -DCURL_ENABLE_SSL=OFF')
->optionalLib('brotli', ...cmake_boolean_args('CURL_BROTLI')) ->optionalLib('brotli', ...cmake_boolean_args('CURL_BROTLI'))
@@ -29,6 +37,7 @@ trait curl
->addConfigureArgs( ->addConfigureArgs(
'-DBUILD_CURL_EXE=OFF', '-DBUILD_CURL_EXE=OFF',
'-DBUILD_LIBCURL_DOCS=OFF', '-DBUILD_LIBCURL_DOCS=OFF',
$linkerFlags ? "-DCMAKE_SHARED_LINKER_FLAGS='{$linkerFlags}'" : null
) )
->build(); ->build();

View File

@@ -13,8 +13,8 @@ trait freetype
{ {
$cmake = UnixCMakeExecutor::create($this) $cmake = UnixCMakeExecutor::create($this)
->optionalLib('libpng', ...cmake_boolean_args('FT_DISABLE_PNG', true)) ->optionalLib('libpng', ...cmake_boolean_args('FT_DISABLE_PNG', true))
->addConfigureArgs('-DFT_DISABLE_BZIP2=ON') ->optionalLib('bzip2', ...cmake_boolean_args('FT_DISABLE_BZIP2', true))
->addConfigureArgs('-DFT_DISABLE_BROTLI=ON') ->optionalLib('brotli', ...cmake_boolean_args('FT_DISABLE_BROTLI', true))
->addConfigureArgs('-DFT_DISABLE_HARFBUZZ=ON'); ->addConfigureArgs('-DFT_DISABLE_HARFBUZZ=ON');
// fix cmake 4.0 compatibility // fix cmake 4.0 compatibility

View File

@@ -40,6 +40,16 @@ trait krb5
->appendEnv($extraEnv) ->appendEnv($extraEnv)
->optionalLib('ldap', '--with-ldap', '--without-ldap') ->optionalLib('ldap', '--with-ldap', '--without-ldap')
->optionalLib('libedit', '--with-libedit', '--without-libedit') ->optionalLib('libedit', '--with-libedit', '--without-libedit')
->removeConfigureArgs(
'--enable-static',
'--disable-static',
'--enable-shared',
'--disable-shared'
)
->addConfigureArgs(
'--enable-static',
'--disable-shared'
)
->configure(...$args) ->configure(...$args)
->make(); ->make();
$this->patchPkgconfPrefix([ $this->patchPkgconfPrefix([

View File

@@ -4,8 +4,6 @@ declare(strict_types=1);
namespace SPC\builder\unix\library; namespace SPC\builder\unix\library;
use SPC\store\FileSystem;
trait libargon2 trait libargon2
{ {
protected function build() protected function build()
@@ -17,12 +15,6 @@ trait libargon2
$this->patchPkgconfPrefix(['libargon2.pc']); $this->patchPkgconfPrefix(['libargon2.pc']);
foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) {
if (str_starts_with($filename, 'libargon2') && (str_contains($filename, '.so') || str_ends_with($filename, '.dylib'))) {
unlink(BUILD_ROOT_PATH . '/lib/' . $filename);
}
}
if (file_exists(BUILD_BIN_PATH . '/argon2')) { if (file_exists(BUILD_BIN_PATH . '/argon2')) {
unlink(BUILD_BIN_PATH . '/argon2'); unlink(BUILD_BIN_PATH . '/argon2');
} }

View File

@@ -11,10 +11,7 @@ trait libde265
protected function build(): void protected function build(): void
{ {
UnixCMakeExecutor::create($this) UnixCMakeExecutor::create($this)
->addConfigureArgs( ->addConfigureArgs('-DENABLE_SDL=OFF')
'-DENABLE_SDL=OFF',
'-DENABLE_DECODER=OFF'
)
->build(); ->build();
$this->patchPkgconfPrefix(['libde265.pc']); $this->patchPkgconfPrefix(['libde265.pc']);
} }

View File

@@ -27,11 +27,5 @@ trait liblz4
->exec("make install PREFIX='' DESTDIR=" . BUILD_ROOT_PATH); ->exec("make install PREFIX='' DESTDIR=" . BUILD_ROOT_PATH);
$this->patchPkgconfPrefix(['liblz4.pc']); $this->patchPkgconfPrefix(['liblz4.pc']);
foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) {
if (str_starts_with($filename, 'liblz4') && (str_contains($filename, '.so') || str_ends_with($filename, '.dylib'))) {
unlink(BUILD_ROOT_PATH . '/lib/' . $filename);
}
}
} }
} }

View File

@@ -13,6 +13,7 @@ trait libuuid
{ {
UnixCMakeExecutor::create($this)->toStep(2)->build(); UnixCMakeExecutor::create($this)->toStep(2)->build();
copy($this->source_dir . '/build/libuuid.a', BUILD_LIB_PATH . '/libuuid.a'); copy($this->source_dir . '/build/libuuid.a', BUILD_LIB_PATH . '/libuuid.a');
copy($this->source_dir . '/build/libuuid.so', BUILD_LIB_PATH . '/libuuid.so');
FileSystem::createDir(BUILD_INCLUDE_PATH . '/uuid'); FileSystem::createDir(BUILD_INCLUDE_PATH . '/uuid');
copy($this->source_dir . '/uuid.h', BUILD_INCLUDE_PATH . '/uuid/uuid.h'); copy($this->source_dir . '/uuid.h', BUILD_INCLUDE_PATH . '/uuid/uuid.h');
$pc = FileSystem::readFile($this->source_dir . '/uuid.pc.in'); $pc = FileSystem::readFile($this->source_dir . '/uuid.pc.in');

View File

@@ -11,7 +11,7 @@ trait libuv
protected function build(): void protected function build(): void
{ {
UnixCMakeExecutor::create($this) UnixCMakeExecutor::create($this)
->addConfigureArgs('-DLIBUV_BUILD_SHARED=OFF') ->addConfigureArgs('-DLIBUV_BUILD_SHARED=' . (getenv('SPC_LINK_STATIC') ? 'OFF' : 'ON'))
->build(); ->build();
// patch pkgconfig // patch pkgconfig
$this->patchPkgconfPrefix(['libuv-static.pc']); $this->patchPkgconfPrefix(['libuv-static.pc']);

View File

@@ -6,10 +6,29 @@ namespace SPC\builder\unix\library;
use SPC\builder\linux\library\LinuxLibraryBase; use SPC\builder\linux\library\LinuxLibraryBase;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\toolchain\ToolchainManager;
use SPC\toolchain\ZigToolchain;
use SPC\util\executor\UnixCMakeExecutor; use SPC\util\executor\UnixCMakeExecutor;
trait libxml2 trait libxml2
{ {
public function patchBeforeBuild(): bool
{
if (ToolchainManager::getToolchainClass() !== ZigToolchain::class) {
return false;
}
$patched = (bool) FileSystem::replaceFileStr(
$this->source_dir . '/configure.ac',
'AX_APPEND_FLAG([-Wl,--version-script=], [VERSION_SCRIPT_FLAGS])',
'',
);
return $patched || FileSystem::replaceFileStr(
$this->source_dir . '/CMakeLists.txt',
'target_link_options(LibXml2 PRIVATE "LINKER:--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libxml2.syms")',
'',
);
}
public function build(): void public function build(): void
{ {
$cmake = UnixCMakeExecutor::create($this) $cmake = UnixCMakeExecutor::create($this)
@@ -20,7 +39,6 @@ trait libxml2
"-DZLIB_INCLUDE_DIR={$this->getIncludeDir()}", "-DZLIB_INCLUDE_DIR={$this->getIncludeDir()}",
'-DLIBXML2_WITH_ZLIB=OFF', '-DLIBXML2_WITH_ZLIB=OFF',
) )
->optionalLib('xz', ...cmake_boolean_args('LIBXML2_WITH_LZMA'))
->addConfigureArgs( ->addConfigureArgs(
'-DLIBXML2_WITH_ICONV=ON', '-DLIBXML2_WITH_ICONV=ON',
'-DLIBXML2_WITH_ICU=OFF', // optional, but discouraged: https://gitlab.gnome.org/GNOME/libxml2/-/blob/master/README.md '-DLIBXML2_WITH_ICU=OFF', // optional, but discouraged: https://gitlab.gnome.org/GNOME/libxml2/-/blob/master/README.md

View File

@@ -13,7 +13,7 @@ trait mimalloc
{ {
$cmake = UnixCMakeExecutor::create($this) $cmake = UnixCMakeExecutor::create($this)
->addConfigureArgs( ->addConfigureArgs(
'-DMI_BUILD_SHARED=OFF', '-DMI_BUILD_SHARED=' . (getenv('SPC_LINK_STATIC') ? 'OFF' : 'ON'),
'-DMI_BUILD_OBJECT=OFF', '-DMI_BUILD_OBJECT=OFF',
'-DMI_INSTALL_TOPLEVEL=ON', '-DMI_INSTALL_TOPLEVEL=ON',
); );

View File

@@ -12,6 +12,9 @@ trait postgresql
{ {
public function patchBeforeBuild(): bool public function patchBeforeBuild(): bool
{ {
if (!getenv('SPC_LINK_STATIC')) {
return false;
}
// skip the test on platforms where libpq infrastructure may be provided by statically-linked libraries // skip the test on platforms where libpq infrastructure may be provided by statically-linked libraries
FileSystem::replaceFileStr("{$this->source_dir}/src/interfaces/libpq/Makefile", 'invokes exit\'; exit 1;', 'invokes exit\';'); FileSystem::replaceFileStr("{$this->source_dir}/src/interfaces/libpq/Makefile", 'invokes exit\'; exit 1;', 'invokes exit\';');
// disable shared libs build // disable shared libs build
@@ -92,10 +95,11 @@ trait postgresql
->exec('make -C src/interfaces/libpq install'); ->exec('make -C src/interfaces/libpq install');
// remove dynamic libs // remove dynamic libs
shell()->cd($this->source_dir . '/build') if (getenv('SPC_LINK_STATIC')) {
->exec("rm -rf {$this->getBuildRootPath()}/lib/*.so*") shell()->cd($this->source_dir . '/build')
->exec("rm -rf {$this->getBuildRootPath()}/lib/*.dylib"); ->exec("rm -rf {$this->getBuildRootPath()}/lib/*.so*")
->exec("rm -rf {$this->getBuildRootPath()}/lib/*.dylib");
}
FileSystem::replaceFileStr("{$this->getLibDir()}/pkgconfig/libpq.pc", '-lldap', '-lldap -llber'); FileSystem::replaceFileStr("{$this->getLibDir()}/pkgconfig/libpq.pc", '-lldap', '-lldap -llber');
} }
} }

View File

@@ -14,7 +14,7 @@ trait tidy
->setBuildDir("{$this->source_dir}/build-dir") ->setBuildDir("{$this->source_dir}/build-dir")
->addConfigureArgs( ->addConfigureArgs(
'-DSUPPORT_CONSOLE_APP=OFF', '-DSUPPORT_CONSOLE_APP=OFF',
'-DBUILD_SHARED_LIB=OFF' '-DBUILD_SHARED_LIB=' . (getenv('SPC_LINK_STATIC') ? 'OFF' : 'ON')
); );
if (version_compare(get_cmake_version(), '4.0.0', '>=')) { if (version_compare(get_cmake_version(), '4.0.0', '>=')) {
$cmake->addConfigureArgs('-DCMAKE_POLICY_VERSION_MINIMUM=3.5'); $cmake->addConfigureArgs('-DCMAKE_POLICY_VERSION_MINIMUM=3.5');

View File

@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace SPC\builder\unix\library; namespace SPC\builder\unix\library;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
use SPC\store\FileSystem;
use SPC\util\executor\UnixAutoconfExecutor; use SPC\util\executor\UnixAutoconfExecutor;
trait unixodbc trait unixodbc
@@ -31,15 +30,7 @@ trait unixodbc
'--enable-gui=no', '--enable-gui=no',
) )
->make(); ->make();
$pkgConfigs = ['odbc.pc', 'odbccr.pc', 'odbcinst.pc']; $this->patchPkgconfPrefix(['odbc.pc', 'odbccr.pc', 'odbcinst.pc']);
$this->patchPkgconfPrefix($pkgConfigs);
foreach ($pkgConfigs as $file) {
FileSystem::replaceFileStr(
BUILD_LIB_PATH . "/pkgconfig/{$file}",
'$(top_build_prefix)libltdl/libltdlc.la',
''
);
}
$this->patchLaDependencyPrefix(); $this->patchLaDependencyPrefix();
} }
} }

View File

@@ -10,7 +10,14 @@ trait xz
{ {
public function build(): void public function build(): void
{ {
UnixAutoconfExecutor::create($this) $make = UnixAutoconfExecutor::create($this);
if (!getenv('SPC_LINK_STATIC')) {
// liblzma can only build one of static or shared at a time
$make
->removeConfigureArgs('--enable-static')
->addConfigureArgs('--disable-static');
}
$make
->configure( ->configure(
'--disable-scripts', '--disable-scripts',
'--disable-doc', '--disable-doc',

View File

@@ -10,7 +10,8 @@ trait zlib
{ {
protected function build(): void protected function build(): void
{ {
UnixAutoconfExecutor::create($this)->exec("./configure --static --prefix={$this->getBuildRootPath()}")->make(); $static = getenv('SPC_LINK_STATIC') ? '--static' : '';
UnixAutoconfExecutor::create($this)->exec("./configure {$static} --prefix={$this->getBuildRootPath()}")->make();
$this->patchPkgconfPrefix(['zlib.pc']); $this->patchPkgconfPrefix(['zlib.pc']);
} }
} }

View File

@@ -14,9 +14,9 @@ trait zstd
->setBuildDir("{$this->source_dir}/build/cmake/build") ->setBuildDir("{$this->source_dir}/build/cmake/build")
->addConfigureArgs( ->addConfigureArgs(
'-DZSTD_BUILD_STATIC=ON', '-DZSTD_BUILD_STATIC=ON',
'-DZSTD_BUILD_SHARED=OFF', '-DZSTD_BUILD_SHARED=' . (getenv('SPC_LINK_STATIC') ? 'OFF' : 'ON'),
) )
->build(); ->build();
$this->patchPkgconfPrefix(['libzstd.pc']); $this->patchPkgconfPrefix();
} }
} }

View File

@@ -1,36 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\windows\library;
use SPC\store\FileSystem;
class brotli extends WindowsLibraryBase
{
public const NAME = 'brotli';
protected function build(): void
{
// reset cmake
FileSystem::resetDir($this->source_dir . '\build');
// start build
cmd()->cd($this->source_dir)
->execWithWrapper(
$this->builder->makeSimpleWrapper('cmake'),
'-B build ' .
'-A x64 ' .
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
'-DCMAKE_BUILD_TYPE=Release ' .
'-DBUILD_SHARED_LIBS=OFF ' .
'-DBROTLI_BUILD_TOOLS=OFF ' .
'-DBROTLI_BUNDLED_MODE=OFF ' .
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' '
)
->execWithWrapper(
$this->builder->makeSimpleWrapper('cmake'),
"--build build --config Release --target install -j{$this->builder->concurrency}"
);
}
}

View File

@@ -24,8 +24,6 @@ class freetype extends WindowsLibraryBase
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
'-DCMAKE_BUILD_TYPE=Release ' . '-DCMAKE_BUILD_TYPE=Release ' .
'-DBUILD_SHARED_LIBS=OFF ' . '-DBUILD_SHARED_LIBS=OFF ' .
'-DFT_DISABLE_BROTLI=TRUE ' .
'-DFT_DISABLE_BZIP2=TRUE ' .
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' '
) )
->execWithWrapper( ->execWithWrapper(

View File

@@ -1,41 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\windows\library;
use SPC\store\FileSystem;
class libaom extends WindowsLibraryBase
{
public const NAME = 'libaom';
protected function build(): void
{
// libaom source tree contains a build/cmake/ directory with its own
// cmake modules, so we must use a different name for the build dir.
FileSystem::resetDir($this->source_dir . '\builddir');
// start build
cmd()->cd($this->source_dir)
->execWithWrapper(
$this->builder->makeSimpleWrapper('cmake'),
'-S . -B builddir ' .
'-A x64 ' .
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
'-DCMAKE_BUILD_TYPE=Release ' .
'-DBUILD_SHARED_LIBS=OFF ' .
'-DAOM_TARGET_CPU=generic ' .
'-DENABLE_DOCS=OFF ' .
'-DENABLE_EXAMPLES=OFF ' .
'-DENABLE_TESTDATA=OFF ' .
'-DENABLE_TESTS=OFF ' .
'-DENABLE_TOOLS=OFF ' .
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' '
)
->execWithWrapper(
$this->builder->makeSimpleWrapper('cmake'),
"--build builddir --config Release --target install -j{$this->builder->concurrency}"
);
}
}

View File

@@ -33,7 +33,6 @@ class openssl extends WindowsLibraryBase
->execWithWrapper( ->execWithWrapper(
$this->builder->makeSimpleWrapper($this->perl), $this->builder->makeSimpleWrapper($this->perl),
'Configure zlib VC-WIN64A ' . 'Configure zlib VC-WIN64A ' .
'no-shared ' .
'--prefix=' . quote(BUILD_ROOT_PATH) . ' ' . '--prefix=' . quote(BUILD_ROOT_PATH) . ' ' .
'--with-zlib-lib=' . quote(BUILD_LIB_PATH) . ' ' . '--with-zlib-lib=' . quote(BUILD_LIB_PATH) . ' ' .
'--with-zlib-include=' . quote(BUILD_INCLUDE_PATH) . ' ' . '--with-zlib-include=' . quote(BUILD_INCLUDE_PATH) . ' ' .

View File

@@ -31,24 +31,8 @@ class zlib extends WindowsLibraryBase
$this->builder->makeSimpleWrapper('cmake'), $this->builder->makeSimpleWrapper('cmake'),
"--build build --config Release --target install -j{$this->builder->concurrency}" "--build build --config Release --target install -j{$this->builder->concurrency}"
); );
$detect_list = [ copy(BUILD_LIB_PATH . '\zlibstatic.lib', BUILD_LIB_PATH . '\zlib_a.lib');
'zlibstatic.lib', unlink(BUILD_ROOT_PATH . '\bin\zlib.dll');
'zs.lib', unlink(BUILD_LIB_PATH . '\zlib.lib');
'libzs.lib',
'libz.lib',
];
foreach ($detect_list as $item) {
if (file_exists(BUILD_LIB_PATH . '\\' . $item)) {
FileSystem::copy(BUILD_LIB_PATH . '\\' . $item, BUILD_LIB_PATH . '\zlib_a.lib');
FileSystem::copy(BUILD_LIB_PATH . '\\' . $item, BUILD_LIB_PATH . '\zlibstatic.lib');
break;
}
}
FileSystem::removeFileIfExists(BUILD_ROOT_PATH . '\bin\zlib.dll');
FileSystem::removeFileIfExists(BUILD_LIB_PATH . '\zlib.lib');
FileSystem::removeFileIfExists(BUILD_LIB_PATH . '\libz.dll');
FileSystem::removeFileIfExists(BUILD_LIB_PATH . '\libz.lib');
FileSystem::removeFileIfExists(BUILD_LIB_PATH . '\z.lib');
FileSystem::removeFileIfExists(BUILD_LIB_PATH . '\z.dll');
} }
} }

View File

@@ -30,7 +30,7 @@ class DownloadCommand extends BaseCommand
$this->addArgument('sources', InputArgument::REQUIRED, 'The sources will be compiled, comma separated'); $this->addArgument('sources', InputArgument::REQUIRED, 'The sources will be compiled, comma separated');
$this->addOption('shallow-clone', null, null, 'Clone shallow'); $this->addOption('shallow-clone', null, null, 'Clone shallow');
$this->addOption('with-openssl11', null, null, 'Use openssl 1.1'); $this->addOption('with-openssl11', null, null, 'Use openssl 1.1');
$this->addOption('with-php', null, InputOption::VALUE_REQUIRED, 'version in major.minor format (default 8.5)', '8.5'); $this->addOption('with-php', null, InputOption::VALUE_REQUIRED, 'version in major.minor format (default 8.4)', '8.4');
$this->addOption('clean', null, null, 'Clean old download cache and source before fetch'); $this->addOption('clean', null, null, 'Clean old download cache and source before fetch');
$this->addOption('all', 'A', null, 'Fetch all sources that static-php-cli needed'); $this->addOption('all', 'A', null, 'Fetch all sources that static-php-cli needed');
$this->addOption('custom-url', 'U', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Specify custom source download url, e.g "php-src:https://downloads.php.net/~eric/php-8.3.0beta1.tar.gz"'); $this->addOption('custom-url', 'U', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Specify custom source download url, e.g "php-src:https://downloads.php.net/~eric/php-8.3.0beta1.tar.gz"');

View File

@@ -39,7 +39,6 @@ class SPCConfigCommand extends BaseCommand
$util = new SPCConfigUtil(options: [ $util = new SPCConfigUtil(options: [
'no_php' => $this->getOption('no-php'), 'no_php' => $this->getOption('no-php'),
'libs_only_deps' => $this->getOption('libs-only-deps'), 'libs_only_deps' => $this->getOption('libs-only-deps'),
'absolute_libs' => $this->getOption('absolute-libs'),
]); ]);
$config = $util->config($extensions, $libraries, $include_suggest_ext, $include_suggest_lib); $config = $util->config($extensions, $libraries, $include_suggest_ext, $include_suggest_lib);

View File

@@ -16,43 +16,6 @@ use SPC\util\SPCTarget;
*/ */
class Downloader class Downloader
{ {
/**
* Get latest stable version from PECL
*
* @param string $name Source name
* @param array $source Source meta info: [pecl?]
* @return array<int, string> [url, filename]
*/
public static function getPECLInfo(string $name, array $source): array
{
$package = $source['pecl'] ?? (str_starts_with($name, 'ext-') ? substr($name, 4) : $name);
$lp = strtolower($package);
$api_url = "https://pecl.php.net/rest/r/{$lp}/allreleases.xml";
logger()->debug("Fetching {$name} source from PECL: {$api_url}");
$xml = self::curlExec(
url: $api_url,
retries: self::getRetryAttempts()
);
$dom = new \SimpleXMLElement($xml);
$version = null;
if ($source['prefer-stable'] ?? false) {
foreach ($dom->r as $release) {
if ((string) $release->s === 'stable') {
$version = (string) $release->v;
break;
}
}
}
$version ??= isset($dom->r[0]) ? (string) $dom->r[0]->v : null;
if ($version === null) {
throw new DownloaderException("failed to find any release for {$name} on PECL");
}
$url = "https://pecl.php.net/get/{$package}-{$version}.tgz";
$filename = "{$package}-{$version}.tgz";
logger()->info("Found {$name} PECL version: {$version}");
return [$url, $filename];
}
/** /**
* Get latest version from PIE config (Packagist) * Get latest version from PIE config (Packagist)
* *
@@ -649,7 +612,6 @@ class Downloader
* @param array{ * @param array{
* url?: string, * url?: string,
* repo?: string, * repo?: string,
* pecl?: string,
* rev?: string, * rev?: string,
* path?: string, * path?: string,
* filename?: string, * filename?: string,
@@ -669,10 +631,6 @@ class Downloader
{ {
try { try {
switch ($type) { switch ($type) {
case 'pecl': // PECL (latest stable)
[$url, $filename] = self::getPECLInfo($name, $conf);
self::downloadFile($name, $url, $filename, $conf['path'] ?? $conf['extract'] ?? null, $download_as);
break;
case 'pie': // Packagist case 'pie': // Packagist
[$url, $filename] = self::getPIEInfo($name, $conf); [$url, $filename] = self::getPIEInfo($name, $conf);
self::downloadFile($name, $url, $filename, $conf['path'] ?? $conf['extract'] ?? null, $download_as, hooks: [[CurlHook::class, 'setupGithubToken']]); self::downloadFile($name, $url, $filename, $conf['path'] ?? $conf['extract'] ?? null, $download_as, hooks: [[CurlHook::class, 'setupGithubToken']]);

View File

@@ -634,13 +634,7 @@ class SourcePatcher
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/gd/libgd/gdft.c', '#ifndef MSWIN32', '#ifndef _WIN32'); FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/gd/libgd/gdft.c', '#ifndef MSWIN32', '#ifndef _WIN32');
} }
// custom config.w32, because official config.w32 is hard-coded many things // custom config.w32, because official config.w32 is hard-coded many things
if ($ver_id >= 80500) { $origin = $ver_id >= 80100 ? file_get_contents(ROOT_DIR . '/src/globals/extra/gd_config_81.w32') : file_get_contents(ROOT_DIR . '/src/globals/extra/gd_config_80.w32');
$origin = file_get_contents(ROOT_DIR . '/src/globals/extra/gd_config_85.w32');
} elseif ($ver_id >= 80100) {
$origin = file_get_contents(ROOT_DIR . '/src/globals/extra/gd_config_81.w32');
} else {
$origin = file_get_contents(ROOT_DIR . '/src/globals/extra/gd_config_80.w32');
}
file_put_contents(SOURCE_PATH . '/php-src/ext/gd/config.w32.bak', file_get_contents(SOURCE_PATH . '/php-src/ext/gd/config.w32')); file_put_contents(SOURCE_PATH . '/php-src/ext/gd/config.w32.bak', file_get_contents(SOURCE_PATH . '/php-src/ext/gd/config.w32'));
return file_put_contents(SOURCE_PATH . '/php-src/ext/gd/config.w32', $origin) !== false; return file_put_contents(SOURCE_PATH . '/php-src/ext/gd/config.w32', $origin) !== false;
} }

View File

@@ -20,7 +20,7 @@ class PhpSource extends CustomSourceBase
public function fetch(bool $force = false, ?array $config = null, int $lock_as = SPC_DOWNLOAD_SOURCE): void public function fetch(bool $force = false, ?array $config = null, int $lock_as = SPC_DOWNLOAD_SOURCE): void
{ {
$major = defined('SPC_BUILD_PHP_VERSION') ? SPC_BUILD_PHP_VERSION : '8.5'; $major = defined('SPC_BUILD_PHP_VERSION') ? SPC_BUILD_PHP_VERSION : '8.4';
if ($major === 'git') { if ($major === 'git') {
Downloader::downloadSource('php-src', ['type' => 'git', 'url' => 'https://github.com/php/php-src.git', 'rev' => 'master'], $force); Downloader::downloadSource('php-src', ['type' => 'git', 'url' => 'https://github.com/php/php-src.git', 'rev' => 'master'], $force);
} else { } else {

View File

@@ -58,6 +58,10 @@ class ZigToolchain implements ToolchainInterface
GlobalEnvManager::putenv("SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS={$extraCflags}"); GlobalEnvManager::putenv("SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS={$extraCflags}");
GlobalEnvManager::putenv('RANLIB=zig-ranlib'); GlobalEnvManager::putenv('RANLIB=zig-ranlib');
GlobalEnvManager::putenv('OBJCOPY=zig-objcopy'); GlobalEnvManager::putenv('OBJCOPY=zig-objcopy');
$defaultLdFlags = getenv('SPC_DEFAULT_LD_FLAGS') ?: '';
if (!str_contains($defaultLdFlags, '-Wl,--undefined-version') && !getenv('SPC_LINK_STATIC')) {
GlobalEnvManager::putenv("SPC_DEFAULT_LD_FLAGS={$defaultLdFlags} -Wl,--undefined-version");
}
$extra_libs = getenv('SPC_EXTRA_LIBS') ?: ''; $extra_libs = getenv('SPC_EXTRA_LIBS') ?: '';
if (!str_contains($extra_libs, '-lunwind')) { if (!str_contains($extra_libs, '-lunwind')) {
// Add unwind library if not already present // Add unwind library if not already present

View File

@@ -22,9 +22,7 @@ class ConfigValidator
'regex' => 'string', // regex pattern 'regex' => 'string', // regex pattern
'rev' => 'string', // revision/branch 'rev' => 'string', // revision/branch
'repo' => 'string', // repository name 'repo' => 'string', // repository name
'pecl' => 'string', // PECL package name
'match' => 'string', // match pattern (aaa*bbb) 'match' => 'string', // match pattern (aaa*bbb)
'query' => 'string', // query string for API requests
'filename' => 'string', // filename 'filename' => 'string', // filename
'path' => 'string', // copy path 'path' => 'string', // copy path
'extract' => 'string', // copy path (alias of path) 'extract' => 'string', // copy path (alias of path)
@@ -75,13 +73,12 @@ class ConfigValidator
private const array SOURCE_TYPE_FIELDS = [ private const array SOURCE_TYPE_FIELDS = [
'filelist' => [['url', 'regex'], []], 'filelist' => [['url', 'regex'], []],
'git' => [['url', 'rev'], ['path', 'extract', 'submodules']], 'git' => [['url', 'rev'], ['path', 'extract', 'submodules']],
'ghtagtar' => [['repo'], ['path', 'extract', 'prefer-stable', 'match', 'query']], 'ghtagtar' => [['repo'], ['path', 'extract', 'prefer-stable', 'match']],
'ghtar' => [['repo'], ['path', 'extract', 'prefer-stable', 'match', 'query']], 'ghtar' => [['repo'], ['path', 'extract', 'prefer-stable', 'match']],
'ghrel' => [['repo', 'match'], ['path', 'extract', 'prefer-stable']], 'ghrel' => [['repo', 'match'], ['path', 'extract', 'prefer-stable']],
'url' => [['url'], ['filename', 'path', 'extract']], 'url' => [['url'], ['filename', 'path', 'extract']],
'bitbuckettag' => [['repo'], ['path', 'extract']], 'bitbuckettag' => [['repo'], ['path', 'extract']],
'local' => [['dirname'], ['path', 'extract']], 'local' => [['dirname'], ['path', 'extract']],
'pecl' => [[], ['pecl', 'path', 'prefer-stable']],
'pie' => [['repo'], ['path']], 'pie' => [['repo'], ['path']],
'custom' => [[], ['func']], 'custom' => [[], ['func']],
]; ];
@@ -396,7 +393,7 @@ class ConfigValidator
} }
// check php-version // check php-version
if (isset($craft['php-version'])) { if (isset($craft['php-version'])) {
// validate version, accept 8.x, 7.x, 8.x.x, 7.x.x, 8, 7 // validdate version, accept 8.x, 7.x, 8.x.x, 7.x.x, 8, 7
$version = strval($craft['php-version']); $version = strval($craft['php-version']);
if (!preg_match('/^(\d+)(\.\d+)?(\.\d+)?$/', $version, $matches)) { if (!preg_match('/^(\d+)(\.\d+)?(\.\d+)?$/', $version, $matches)) {
throw new ValidationException('Craft file php-version is invalid'); throw new ValidationException('Craft file php-version is invalid');

View File

@@ -38,6 +38,13 @@ class GlobalEnvManager
// Define env vars for unix // Define env vars for unix
if (is_unix()) { if (is_unix()) {
if (!getenv('SPC_LINK_STATIC')) {
$ldLibPath = getenv('LD_LIBRARY_PATH=' . BUILD_LIB_PATH);
if ($ldLibPath) {
$ldLibPath = ":{$ldLibPath}";
}
self::putenv('LD_LIBRARY_PATH=' . BUILD_LIB_PATH . $ldLibPath);
}
self::addPathIfNotExists(BUILD_BIN_PATH); self::addPathIfNotExists(BUILD_BIN_PATH);
self::addPathIfNotExists(PKG_ROOT_PATH . '/bin'); self::addPathIfNotExists(PKG_ROOT_PATH . '/bin');
$pkgConfigPath = getenv('PKG_CONFIG_PATH'); $pkgConfigPath = getenv('PKG_CONFIG_PATH');

View File

@@ -59,10 +59,10 @@ class PkgConfigUtil
* @param string $pkg_config_str .pc file string, accepts multiple files * @param string $pkg_config_str .pc file string, accepts multiple files
* @return string CFLAGS string, e.g. "-Wno-implicit-int-float-conversion ..." * @return string CFLAGS string, e.g. "-Wno-implicit-int-float-conversion ..."
*/ */
public static function getCflags(string $pkg_config_str): string public static function getCflags(string $pkg_config_str, string $extra = '--static'): string
{ {
// get other things // get other things
$result = self::execWithResult("pkg-config --static --cflags-only-other {$pkg_config_str}"); $result = self::execWithResult("pkg-config {$extra} --cflags-only-other {$pkg_config_str}");
return trim($result); return trim($result);
} }
@@ -75,14 +75,14 @@ class PkgConfigUtil
* @param string $pkg_config_str .pc file string, accepts multiple files * @param string $pkg_config_str .pc file string, accepts multiple files
* @return array Unique libs array, e.g. [-lz, -lxml, ...] * @return array Unique libs array, e.g. [-lz, -lxml, ...]
*/ */
public static function getLibsArray(string $pkg_config_str): array public static function getLibsArray(string $pkg_config_str, string $extra = '--static'): array
{ {
// Use this instead of shell() to avoid unnecessary outputs // Use this instead of shell() to avoid unnecessary outputs
$result = self::execWithResult("pkg-config --static --libs-only-l {$pkg_config_str}"); $result = self::execWithResult("pkg-config {$extra} --libs-only-l {$pkg_config_str}");
$libs = explode(' ', trim($result)); $libs = explode(' ', trim($result));
// get other things // get other things
$result = self::execWithResult("pkg-config --static --libs-only-other {$pkg_config_str}"); $result = self::execWithResult("pkg-config {$extra} --libs-only-other {$pkg_config_str}");
// convert libxxx.a to -L{path} -lxxx // convert libxxx.a to -L{path} -lxxx
$exp = explode(' ', trim($result)); $exp = explode(' ', trim($result));
foreach ($exp as $item) { foreach ($exp as $item) {

View File

@@ -20,13 +20,10 @@ class SPCConfigUtil
private bool $libs_only_deps; private bool $libs_only_deps;
private bool $absolute_libs;
/** /**
* @param array{ * @param array{
* no_php?: bool, * no_php?: bool,
* libs_only_deps?: bool, * libs_only_deps?: bool
* absolute_libs?: bool
* } $options Options pass to spc-config * } $options Options pass to spc-config
*/ */
public function __construct(?BuilderBase $builder = null, array $options = []) public function __construct(?BuilderBase $builder = null, array $options = [])
@@ -36,7 +33,6 @@ class SPCConfigUtil
} }
$this->no_php = $options['no_php'] ?? false; $this->no_php = $options['no_php'] ?? false;
$this->libs_only_deps = $options['libs_only_deps'] ?? false; $this->libs_only_deps = $options['libs_only_deps'] ?? false;
$this->absolute_libs = $options['absolute_libs'] ?? false;
} }
/** /**
@@ -77,7 +73,7 @@ class SPCConfigUtil
ob_get_clean(); ob_get_clean();
$ldflags = $this->getLdflagsString(); $ldflags = $this->getLdflagsString();
$cflags = $this->getIncludesString($libraries); $cflags = $this->getIncludesString($libraries);
$libs = $this->getLibsString($libraries, !$this->absolute_libs); $libs = $this->getLibsString($libraries);
// additional OS-specific libraries (e.g. macOS -lresolv) // additional OS-specific libraries (e.g. macOS -lresolv)
if ($extra_libs = SPCTarget::getRuntimeLibs()) { if ($extra_libs = SPCTarget::getRuntimeLibs()) {
@@ -239,7 +235,8 @@ class SPCConfigUtil
} }
} }
$pc_cflags = implode(' ', $pc); $pc_cflags = implode(' ', $pc);
if ($pc_cflags !== '' && ($pc_cflags = PkgConfigUtil::getCflags($pc_cflags)) !== '') { $static = getenv('SPC_LINK_STATIC') ? '--static' : '';
if ($pc_cflags !== '' && ($pc_cflags = PkgConfigUtil::getCflags($pc_cflags, $static)) !== '') {
$arr = explode(' ', $pc_cflags); $arr = explode(' ', $pc_cflags);
$arr = array_unique($arr); $arr = array_unique($arr);
$arr = array_filter($arr, fn ($x) => !str_starts_with($x, 'SHELL:-Xarch_')); $arr = array_filter($arr, fn ($x) => !str_starts_with($x, 'SHELL:-Xarch_'));
@@ -256,7 +253,7 @@ class SPCConfigUtil
return '-L' . BUILD_LIB_PATH; return '-L' . BUILD_LIB_PATH;
} }
private function getLibsString(array $libraries, bool $use_short_libs = true): string private function getLibsString(array $libraries): string
{ {
$lib_names = []; $lib_names = [];
$frameworks = []; $frameworks = [];
@@ -264,6 +261,11 @@ class SPCConfigUtil
foreach ($libraries as $library) { foreach ($libraries as $library) {
// add pkg-configs libs // add pkg-configs libs
$pkg_configs = Config::getLib($library, 'pkg-configs', []); $pkg_configs = Config::getLib($library, 'pkg-configs', []);
$static = getenv('SPC_LINK_STATIC') ? '--static' : null;
if (!$static) {
$target = Config::getLib($library, 'target');
$static = $target && !in_array('shared', $target) ? '--static' : '';
}
$pkg_config_path = getenv('PKG_CONFIG_PATH') ?: ''; $pkg_config_path = getenv('PKG_CONFIG_PATH') ?: '';
$search_paths = array_filter(explode(is_unix() ? ':' : ';', $pkg_config_path)); $search_paths = array_filter(explode(is_unix() ? ':' : ';', $pkg_config_path));
foreach ($pkg_configs as $file) { foreach ($pkg_configs as $file) {
@@ -280,14 +282,14 @@ class SPCConfigUtil
$pkg_configs = implode(' ', $pkg_configs); $pkg_configs = implode(' ', $pkg_configs);
if ($pkg_configs !== '') { if ($pkg_configs !== '') {
// static libs with dependencies come in reverse order, so reverse this too // static libs with dependencies come in reverse order, so reverse this too
$pc_libs = array_reverse(PkgConfigUtil::getLibsArray($pkg_configs)); $pc_libs = array_reverse(PkgConfigUtil::getLibsArray($static, $pkg_configs));
$lib_names = [...$lib_names, ...$pc_libs]; $lib_names = [...$lib_names, ...$pc_libs];
} }
// convert all static-libs to short names // convert all static-libs to short names
$libs = array_reverse(Config::getLib($library, 'static-libs', [])); $libs = array_reverse(Config::getLib($library, 'static-libs', []));
foreach ($libs as $lib) { foreach ($libs as $lib) {
// check file existence // check file existence
if (!file_exists(BUILD_LIB_PATH . "/{$lib}")) { if (!file_exists(BUILD_LIB_PATH . "/{$lib}") && getenv('SPC_LINK_STATIC')) {
throw new WrongUsageException("Library file '{$lib}' for lib [{$library}] does not exist in '" . BUILD_LIB_PATH . "'. Please build it first."); throw new WrongUsageException("Library file '{$lib}' for lib [{$library}] does not exist in '" . BUILD_LIB_PATH . "'. Please build it first.");
} }
$lib_names[] = $this->getShortLibName($lib); $lib_names[] = $this->getShortLibName($lib);
@@ -316,8 +318,8 @@ class SPCConfigUtil
if (in_array('imap', $libraries) && SPCTarget::getLibc() === 'glibc') { if (in_array('imap', $libraries) && SPCTarget::getLibc() === 'glibc') {
$lib_names[] = '-lcrypt'; $lib_names[] = '-lcrypt';
} }
if (!$use_short_libs) { if (getenv('SPC_LINK_STATIC')) {
$lib_names = array_map(fn ($l) => $this->getFullLibName($l), $lib_names); $lib_names = array_map(fn ($l) => $this->getStaticLibname($l), $lib_names);
} }
return implode(' ', $lib_names); return implode(' ', $lib_names);
} }
@@ -331,7 +333,7 @@ class SPCConfigUtil
return '-l' . substr($lib, 3, -2); return '-l' . substr($lib, 3, -2);
} }
private function getFullLibName(string $lib) private function getStaticLibname(string $lib)
{ {
if (!str_starts_with($lib, '-l')) { if (!str_starts_with($lib, '-l')) {
return $lib; return $lib;
@@ -339,7 +341,7 @@ class SPCConfigUtil
$libname = substr($lib, 2); $libname = substr($lib, 2);
$staticLib = BUILD_LIB_PATH . '/' . "lib{$libname}.a"; $staticLib = BUILD_LIB_PATH . '/' . "lib{$libname}.a";
if (file_exists($staticLib)) { if (file_exists($staticLib)) {
return $staticLib; return "-l:lib{$libname}.a";
} }
return $lib; return $lib;
} }

View File

@@ -126,7 +126,7 @@ class UnixAutoconfExecutor extends Executor
{ {
return [ return [
'--enable-static', '--enable-static',
'--disable-shared', getenv('SPC_LINK_STATIC') ? '--disable-shared' : '--enable-shared',
"--prefix={$this->library->getBuildRootPath()}", "--prefix={$this->library->getBuildRootPath()}",
'--with-pic', '--with-pic',
'--enable-pic', '--enable-pic',

View File

@@ -151,7 +151,7 @@ class UnixCMakeExecutor extends Executor
'-DCMAKE_INSTALL_LIBDIR=lib', '-DCMAKE_INSTALL_LIBDIR=lib',
'-DCMAKE_INSTALL_INCLUDEDIR=include', '-DCMAKE_INSTALL_INCLUDEDIR=include',
'-DPOSITION_INDEPENDENT_CODE=ON', '-DPOSITION_INDEPENDENT_CODE=ON',
'-DBUILD_SHARED_LIBS=OFF', '-DBUILD_SHARED_LIBS=' . (getenv('SPC_LINK_STATIC') ? 'OFF' : 'ON'),
"-DCMAKE_TOOLCHAIN_FILE={$this->makeCmakeToolchainFile()}", "-DCMAKE_TOOLCHAIN_FILE={$this->makeCmakeToolchainFile()}",
]); ]);
} }

View File

@@ -1,94 +0,0 @@
// vim:ft=javascript
ARG_WITH("gd", "Bundled GD support", "yes");
if (PHP_GD != "no") {
// check for gd.h (required)
if (!CHECK_HEADER_ADD_INCLUDE("gd.h", "CFLAGS_GD", PHP_GD + ";ext\\gd\\libgd")) {
ERROR("gd not enabled; libraries and headers not found");
}
// zlib ext support (required)
if (!CHECK_LIB("zlib_a.lib;zlib.lib", "gd", PHP_GD)) {
ERROR("gd not enabled; zlib not enabled");
}
// libjpeg lib support
if (CHECK_LIB("libjpeg_a.lib;libjpeg.lib", "gd", PHP_GD) &&
CHECK_HEADER_ADD_INCLUDE("jpeglib.h", "CFLAGS_GD", PHP_GD + ";" + PHP_PHP_BUILD + "\\include")) {
AC_DEFINE("HAVE_LIBJPEG", 1, "JPEG support");
AC_DEFINE("HAVE_GD_JPG", 1, "JPEG support");
}
// libpng16 lib support
if (CHECK_LIB("libpng_a.lib;libpng.lib", "gd", PHP_GD) &&
CHECK_HEADER_ADD_INCLUDE("png.h", "CFLAGS_GD", PHP_GD + ";" + PHP_PHP_BUILD + "\\include\\libpng16")) {
AC_DEFINE("HAVE_LIBPNG", 1, "PNG support");
AC_DEFINE("HAVE_GD_PNG", 1, "PNG support");
}
// freetype lib support
if (CHECK_LIB("libfreetype_a.lib;libfreetype.lib", "gd", PHP_GD) &&
CHECK_HEADER_ADD_INCLUDE("ft2build.h", "CFLAGS_GD", PHP_GD + ";" + PHP_PHP_BUILD + "\\include\\freetype2;" + PHP_PHP_BUILD + "\\include\\freetype")) {
AC_DEFINE("HAVE_LIBFREETYPE", 1, "FreeType support");
AC_DEFINE("HAVE_GD_FREETYPE", 1, "FreeType support");
}
// xpm lib support
if (CHECK_LIB("libXpm_a.lib", "gd", PHP_GD) &&
CHECK_HEADER_ADD_INCLUDE("xpm.h", "CFLAGS_GD", PHP_GD + ";" + PHP_PHP_BUILD + "\\include\\X11")) {
AC_DEFINE("HAVE_LIBXPM", 1, "XPM support");
AC_DEFINE("HAVE_GD_XPM", 1, "XPM support");
}
// iconv lib support
if ((CHECK_LIB("libiconv_a.lib;libiconv.lib", "gd", PHP_GD) || CHECK_LIB("iconv_a.lib;iconv.lib", "gd", PHP_GD)) &&
CHECK_HEADER_ADD_INCLUDE("iconv.h", "CFLAGS_GD", PHP_GD)) {
AC_DEFINE("HAVE_LIBICONV", 1, "Iconv support");
}
// libwebp lib support
if ((CHECK_LIB("libwebp_a.lib", "gd", PHP_GD) || CHECK_LIB("libwebp.lib", "gd", PHP_GD)) &&
CHECK_LIB("libsharpyuv.lib", "gd", PHP_GD) &&
CHECK_HEADER_ADD_INCLUDE("decode.h", "CFLAGS_GD", PHP_GD + ";" + PHP_PHP_BUILD + "\\include\\webp") &&
CHECK_HEADER_ADD_INCLUDE("encode.h", "CFLAGS_GD", PHP_GD + ";" + PHP_PHP_BUILD + "\\include\\webp")) {
AC_DEFINE("HAVE_LIBWEBP", 1, "WebP support");
AC_DEFINE("HAVE_GD_WEBP", 1, "WebP support");
}
// libavif lib support
if (CHECK_LIB("avif_a.lib", "gd", PHP_GD) &&
CHECK_LIB("aom_a.lib", "gd", PHP_GD) &&
CHECK_HEADER_ADD_INCLUDE("avif.h", "CFLAGS_GD", PHP_GD + ";" + PHP_PHP_BUILD + "\\include\\avif")) {
ADD_FLAG("CFLAGS_GD", "/D HAVE_LIBAVIF /D HAVE_GD_AVIF");
} else if (CHECK_LIB("avif.lib", "gd", PHP_GD) &&
CHECK_HEADER_ADD_INCLUDE("avif.h", "CFLAGS_GD", PHP_GD + ";" + PHP_PHP_BUILD + "\\include\\avif")) {
ADD_FLAG("CFLAGS_GD", "/D HAVE_LIBAVIF /D HAVE_GD_AVIF");
}
CHECK_LIB("User32.lib", "gd", PHP_GD);
CHECK_LIB("Gdi32.lib", "gd", PHP_GD);
EXTENSION("gd", "gd.c", null, "-Iext/gd/libgd");
ADD_SOURCES("ext/gd/libgd", "gd.c \
gdcache.c gdfontg.c gdfontl.c gdfontmb.c gdfonts.c gdfontt.c \
gdft.c gd_gd2.c gd_gd.c gd_gif_in.c gd_gif_out.c gdhelpers.c gd_io.c gd_io_dp.c \
gd_io_file.c gd_io_ss.c gd_jpeg.c gdkanji.c gd_png.c gd_ss.c \
gdtables.c gd_topal.c gd_wbmp.c gdxpm.c wbmp.c gd_xbm.c gd_security.c gd_transform.c \
gd_filter.c gd_rotate.c gd_color_match.c gd_webp.c gd_avif.c \
gd_crop.c gd_interpolation.c gd_matrix.c gd_bmp.c gd_tga.c", "gd");
AC_DEFINE('HAVE_LIBGD', 1, 'GD support');
AC_DEFINE('HAVE_GD_BUNDLED', 1, "Bundled GD");
AC_DEFINE('HAVE_GD_BMP', 1, "BMP support");
AC_DEFINE('HAVE_GD_TGA', 1, "TGA support");
ADD_FLAG("CFLAGS_GD", " \
/D PHP_GD_EXPORTS=1 \
/D HAVE_GD_GET_INTERPOLATION \
");
if (ICC_TOOLSET) {
ADD_FLAG("LDFLAGS_GD", "/nodefaultlib:libcmt");
}
PHP_INSTALL_HEADERS("", "ext/gd ext/gd/libgd");
}

View File

@@ -13,10 +13,10 @@ declare(strict_types=1);
// test php version (8.1 ~ 8.4 available, multiple for matrix) // test php version (8.1 ~ 8.4 available, multiple for matrix)
$test_php_version = [ $test_php_version = [
'8.1', // '8.1',
// '8.2', // '8.2',
// '8.3', // '8.3',
'8.4', // '8.4',
'8.5', '8.5',
// 'git', // 'git',
]; ];
@@ -26,12 +26,12 @@ $test_os = [
// 'macos-15-intel', // bin/spc for x86_64 // 'macos-15-intel', // bin/spc for x86_64
// 'macos-15', // bin/spc for arm64 // 'macos-15', // bin/spc for arm64
// 'ubuntu-latest', // bin/spc-alpine-docker for x86_64 // 'ubuntu-latest', // bin/spc-alpine-docker for x86_64
// 'ubuntu-22.04', // bin/spc-gnu-docker for x86_64 'ubuntu-22.04', // bin/spc-gnu-docker for x86_64
// 'ubuntu-24.04', // bin/spc for x86_64 'ubuntu-24.04', // bin/spc for x86_64
// 'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64 'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64
// 'ubuntu-24.04-arm', // bin/spc for arm64 'ubuntu-24.04-arm', // bin/spc for arm64
// 'windows-2022', // .\bin\spc.ps1 // 'windows-2022', // .\bin\spc.ps1
'windows-2025', // 'windows-2025',
]; ];
// whether enable thread safe // whether enable thread safe
@@ -51,7 +51,7 @@ $prefer_pre_built = false;
// If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`). // If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`).
$extensions = match (PHP_OS_FAMILY) { $extensions = match (PHP_OS_FAMILY) {
'Linux', 'Darwin' => 'pgsql', 'Linux', 'Darwin' => 'pgsql',
'Windows' => 'gd,zlib,mbstring,filter', 'Windows' => 'com_dotnet',
}; };
// If you want to test shared extensions, add them below (comma separated, example `bcmath,openssl`). // If you want to test shared extensions, add them below (comma separated, example `bcmath,openssl`).
@@ -62,7 +62,7 @@ $shared_extensions = match (PHP_OS_FAMILY) {
}; };
// If you want to test lib-suggests for all extensions and libraries, set it to true. // If you want to test lib-suggests for all extensions and libraries, set it to true.
$with_suggested_libs = true; $with_suggested_libs = false;
// If you want to test extra libs for extensions, add them below (comma separated, example `libwebp,libavif`). Unnecessary, when $with_suggested_libs is true. // If you want to test extra libs for extensions, add them below (comma separated, example `libwebp,libavif`). Unnecessary, when $with_suggested_libs is true.
$with_libs = match (PHP_OS_FAMILY) { $with_libs = match (PHP_OS_FAMILY) {