Compare commits

..

4 Commits

Author SHA1 Message Date
crazywhalecc
1bbf83872f Change phpmicro base link 2025-11-26 13:28:15 +08:00
crazywhalecc
fadb1ce6c9 Rename static-php-cli to StaticPHP 2025-11-26 13:24:38 +08:00
crazywhalecc
58bf51e9c9 Next version yeah 2025-11-26 12:55:14 +08:00
crazywhalecc
b60ea8e3d6 Add maxminddb extension and libmaxminddb 2025-11-26 12:54:52 +08:00
81 changed files with 661 additions and 1013 deletions

View File

@@ -46,10 +46,6 @@ on:
description: Prefer pre-built binaries (reduce build time) description: Prefer pre-built binaries (reduce build time)
type: boolean type: boolean
default: true default: true
with-suggested-libs:
description: Build with suggested libs
type: boolean
default: false
debug: debug:
description: Show full build logs description: Show full build logs
type: boolean type: boolean
@@ -90,10 +86,6 @@ on:
description: Prefer pre-built binaries (reduce build time) description: Prefer pre-built binaries (reduce build time)
type: boolean type: boolean
default: true default: true
with-suggested-libs:
description: Include suggested libs
type: boolean
default: false
debug: debug:
description: Show full build logs description: Show full build logs
type: boolean type: boolean
@@ -165,9 +157,6 @@ jobs:
if [ ${{ inputs.prefer-pre-built }} == true ]; then if [ ${{ inputs.prefer-pre-built }} == true ]; then
DOWN_CMD="$DOWN_CMD --prefer-pre-built" DOWN_CMD="$DOWN_CMD --prefer-pre-built"
fi fi
if [ ${{ inputs.with-suggested-libs }} == true ]; then
BUILD_CMD="$BUILD_CMD --with-suggested-libs"
fi
if [ ${{ inputs.build-cli }} == true ]; then if [ ${{ inputs.build-cli }} == true ]; then
BUILD_CMD="$BUILD_CMD --build-cli" BUILD_CMD="$BUILD_CMD --build-cli"
fi fi
@@ -213,14 +202,6 @@ jobs:
# if: ${{ failure() }} # if: ${{ failure() }}
# uses: mxschmitt/action-tmate@v3 # uses: mxschmitt/action-tmate@v3
# Upload debug logs
- if: ${{ inputs.debug && failure() }}
name: "Upload build logs on failure"
uses: actions/upload-artifact@v4
with:
name: spc-logs-${{ inputs.php-version }}-${{ inputs.os }}
path: log/*.log
# Upload cli executable # Upload cli executable
- if: ${{ inputs.build-cli == true }} - if: ${{ inputs.build-cli == true }}
name: "Upload PHP cli SAPI" name: "Upload PHP cli SAPI"

View File

@@ -1,24 +1,24 @@
# static-php-cli # StaticPHP
[![English readme](https://img.shields.io/badge/README-English%20%F0%9F%87%AC%F0%9F%87%A7-moccasin?style=flat-square)](README.md)
[![Chinese readme](https://img.shields.io/badge/README-%E4%B8%AD%E6%96%87%20%F0%9F%87%A8%F0%9F%87%B3-moccasin?style=flat-square)](README-zh.md) [![Chinese readme](https://img.shields.io/badge/README-%E4%B8%AD%E6%96%87%20%F0%9F%87%A8%F0%9F%87%B3-moccasin?style=flat-square)](README-zh.md)
[![English readme](https://img.shields.io/badge/README-English%20%F0%9F%87%AC%F0%9F%87%A7-moccasin?style=flat-square)](README.md)
[![Releases](https://img.shields.io/packagist/v/crazywhalecc/static-php-cli?include_prereleases&label=Release&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/releases) [![Releases](https://img.shields.io/packagist/v/crazywhalecc/static-php-cli?include_prereleases&label=Release&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/releases)
[![CI](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/tests.yml?branch=main&label=Build%20Test&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/tests.yml) [![CI](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/tests.yml?branch=main&label=Build%20Test&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/tests.yml)
[![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](https://github.com/crazywhalecc/static-php-cli/blob/main/LICENSE) [![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](https://github.com/crazywhalecc/static-php-cli/blob/main/LICENSE)
**static-php-cli** 是一个用于构建静态、独立 PHP 运行时的强大工具,支持众多流行扩展。 **StaticPHP**(原名 **static-php-cli**是一个用于构建静态、独立 PHP 运行时的强大工具,支持众多流行扩展。
## 特性 ## 特性
- :elephant: **支持多 PHP 版本** - 支持 PHP 8.1, 8.2, 8.3, 8.4, 8.5 - :elephant: **支持多 PHP 版本** - 支持 PHP 8.1, 8.2, 8.3, 8.4, 8.5
- :handbag: **单文件 PHP 可执行文件** - 构建零依赖的独立 PHP - :handbag: **单文件 PHP 可执行文件** - 构建零依赖的独立 PHP
- :hamburger: **phpmicro 集成** - 构建 **[phpmicro](https://github.com/dixyes/phpmicro)** 自解压可执行文件(将 PHP 二进制文件和源代码合并为一个文件) - :hamburger: **phpmicro 集成** - 构建 **[phpmicro](https://github.com/static-php/phpmicro)** 自解压可执行文件(将 PHP 二进制文件和源代码合并为一个文件)
- :pill: **智能环境检查器** - 自动构建环境检查器,具备自动修复功能 - :pill: **智能环境检查器** - 自动构建环境检查器,具备自动修复功能
- :zap: **跨平台支持** - 支持 Linux、macOS、FreeBSD 和 Windows - :zap: **跨平台支持** - 支持 Linux、macOS、FreeBSD 和 Windows
- :wrench: **可配置补丁** - 可自定义的源代码补丁系统 - :wrench: **可配置补丁** - 可自定义的源代码补丁系统
- :books: **智能依赖管理** - 自动处理构建依赖 - :books: **智能依赖管理** - 自动处理构建依赖
- 📦 **自包含工具** - 提供使用 [box](https://github.com/box-project/box) 构建的 `spc` 可执行文件 - 📦 **自包含工具** - 提供使用 [box](https://github.com/box-project/box) 构建的 `spc` 可执行文件
- :fire: **广泛的扩展支持** - 支持 75+ 流行 [扩展](https://static-php.dev/zh/guide/extensions.html) - :fire: **广泛的扩展支持** - 支持 100+ 流行 [扩展](https://static-php.dev/zh/guide/extensions.html)
- :floppy_disk: **UPX 压缩** - 减小二进制文件大小 30-50%(仅 Linux/Windows - :floppy_disk: **UPX 压缩** - 减小二进制文件大小 30-50%(仅 Linux/Windows
**单文件独立 php-cli** **单文件独立 php-cli**
@@ -33,6 +33,8 @@
### 1. 下载 spc 二进制文件 ### 1. 下载 spc 二进制文件
`spc` 二进制文件是 StaticPHP 项目的 CLI 工具,打包为单个可执行文件。
```bash ```bash
# Linux x86_64 # Linux x86_64
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-x86_64 curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-x86_64
@@ -107,7 +109,7 @@ buildroot/bin/php-fpm -v
以下是几个具有不同扩展组合的预编译静态 PHP 二进制文件, 以下是几个具有不同扩展组合的预编译静态 PHP 二进制文件,
您可以根据需要直接下载。 您可以根据需要直接下载。
| 组合名称 | 扩展数量 | 系统 | 备注 | | 组合名称 | 扩展数量 | 系统 | 备注 |
|----------------------------------------------------------------------|----------------------------------------------------------------------------|--------------|--------------------| |----------------------------------------------------------------------|----------------------------------------------------------------------------|--------------|--------------------|
| [common](https://dl.static-php.dev/static-php-cli/common/) | [30+](https://dl.static-php.dev/static-php-cli/common/README.txt) | Linux, macOS | 二进制文件大小约为 7.5MB | | [common](https://dl.static-php.dev/static-php-cli/common/) | [30+](https://dl.static-php.dev/static-php-cli/common/README.txt) | Linux, macOS | 二进制文件大小约为 7.5MB |
| [bulk](https://dl.static-php.dev/static-php-cli/bulk/) | [50+](https://dl.static-php.dev/static-php-cli/bulk/README.txt) | Linux, macOS | 二进制文件大小约为 25MB | | [bulk](https://dl.static-php.dev/static-php-cli/bulk/) | [50+](https://dl.static-php.dev/static-php-cli/bulk/README.txt) | Linux, macOS | 二进制文件大小约为 25MB |

View File

@@ -1,4 +1,4 @@
# static-php-cli # StaticPHP
[![Chinese readme](https://img.shields.io/badge/README-%E4%B8%AD%E6%96%87%20%F0%9F%87%A8%F0%9F%87%B3-moccasin?style=flat-square)](README-zh.md) [![Chinese readme](https://img.shields.io/badge/README-%E4%B8%AD%E6%96%87%20%F0%9F%87%A8%F0%9F%87%B3-moccasin?style=flat-square)](README-zh.md)
[![English readme](https://img.shields.io/badge/README-English%20%F0%9F%87%AC%F0%9F%87%A7-moccasin?style=flat-square)](README.md) [![English readme](https://img.shields.io/badge/README-English%20%F0%9F%87%AC%F0%9F%87%A7-moccasin?style=flat-square)](README.md)
@@ -6,14 +6,13 @@
[![CI](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/tests.yml?branch=main&label=Build%20Test&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/tests.yml) [![CI](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/tests.yml?branch=main&label=Build%20Test&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/tests.yml)
[![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](https://github.com/crazywhalecc/static-php-cli/blob/main/LICENSE) [![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](https://github.com/crazywhalecc/static-php-cli/blob/main/LICENSE)
**static-php-cli** is a powerful tool designed for building static, standalone PHP runtime **StaticPHP** (formerly **static-php-cli**) is a powerful tool designed for building static, standalone PHP runtime with popular extensions.
with popular extensions.
## Features ## Features
- :elephant: Support multiple PHP versions - PHP 8.1, 8.2, 8.3, 8.4, 8.5 - :elephant: Support multiple PHP versions - PHP 8.1, 8.2, 8.3, 8.4, 8.5
- :handbag: Build single-file PHP executable with zero dependencies - :handbag: Build single-file PHP executable with zero dependencies
- :hamburger:Build **[phpmicro](https://github.com/dixyes/phpmicro)** self-extracting executables (combines PHP binary and source code into one file) - :hamburger:Build **[phpmicro](https://github.com/static-php/phpmicro)** self-extracting executables (combines PHP binary and source code into one file)
- :pill: Automatic build environment checker with auto-fix capabilities - :pill: Automatic build environment checker with auto-fix capabilities
- :zap: `Linux`, `macOS`, `FreeBSD`, `Windows` support - :zap: `Linux`, `macOS`, `FreeBSD`, `Windows` support
- :wrench: Configurable source code patching - :wrench: Configurable source code patching
@@ -34,6 +33,8 @@ with popular extensions.
### 1. Download spc binary ### 1. Download spc binary
`spc` binary is StaticPHP CLI tool packaged as a single executable file.
```bash ```bash
# For Linux x86_64 # For Linux x86_64
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-x86_64 curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-x86_64
@@ -53,7 +54,7 @@ For macOS and Linux, add execute permission first:
chmod +x ./spc chmod +x ./spc
``` ```
### 2. Build Static PHP ### 2. Build standalone PHP binaries
First, create a `craft.yml` file and specify which extensions you want to include from [extension list](https://static-php.dev/en/guide/extensions.html) or [command generator](https://static-php.dev/en/guide/cli-generator.html): First, create a `craft.yml` file and specify which extensions you want to include from [extension list](https://static-php.dev/en/guide/extensions.html) or [command generator](https://static-php.dev/en/guide/cli-generator.html):
@@ -79,7 +80,7 @@ Run command:
./spc craft --debug ./spc craft --debug
``` ```
### 3. Static PHP usage ### 3. Using the built binaries
Now you can copy binaries built by static-php-cli to another machine and run with no dependencies: Now you can copy binaries built by static-php-cli to another machine and run with no dependencies:
@@ -105,7 +106,7 @@ see <https://static-php.dev> .
If you don't want to build or want to test first, you can download example pre-compiled artifact from [Actions](https://github.com/static-php/static-php-cli-hosted/actions/workflows/build-php-bulk.yml), or from self-hosted server. If you don't want to build or want to test first, you can download example pre-compiled artifact from [Actions](https://github.com/static-php/static-php-cli-hosted/actions/workflows/build-php-bulk.yml), or from self-hosted server.
Below are several precompiled static-php binaries with different extension combinations, Below are several precompiled statically built php binaries with different extension combinations,
which can be downloaded directly according to your needs. which can be downloaded directly according to your needs.
| Combination | Extension Count | OS | Comment | | Combination | Extension Count | OS | Comment |

View File

@@ -108,7 +108,8 @@ RUN apk update; \
wget \ wget \
xz \ xz \
gettext-dev \ gettext-dev \
binutils-gold binutils-gold \
patchelf
RUN curl -#fSL https://dl.static-php.dev/static-php-cli/bulk/php-8.4.4-cli-linux-\$(uname -m).tar.gz | tar -xz -C /usr/local/bin && \ RUN curl -#fSL https://dl.static-php.dev/static-php-cli/bulk/php-8.4.4-cli-linux-\$(uname -m).tar.gz | tar -xz -C /usr/local/bin && \
chmod +x /usr/local/bin/php chmod +x /usr/local/bin/php

View File

@@ -92,6 +92,11 @@ RUN echo "source scl_source enable devtoolset-10" >> /etc/bashrc
RUN source /etc/bashrc RUN source /etc/bashrc
RUN yum install -y which RUN yum install -y which
RUN curl -fsSL -o patchelf.tgz https://github.com/NixOS/patchelf/releases/download/0.18.0/patchelf-0.18.0-$SPC_USE_ARCH.tar.gz && \
mkdir -p /patchelf && \
tar -xzf patchelf.tgz -C /patchelf --strip-components=1 && \
cp /patchelf/bin/patchelf /usr/bin/
RUN curl -o cmake.tgz -#fSL https://github.com/Kitware/CMake/releases/download/v3.31.4/cmake-3.31.4-linux-$SPC_USE_ARCH.tar.gz && \ RUN curl -o cmake.tgz -#fSL https://github.com/Kitware/CMake/releases/download/v3.31.4/cmake-3.31.4-linux-$SPC_USE_ARCH.tar.gz && \
mkdir /cmake && \ mkdir /cmake && \
tar -xzf cmake.tgz -C /cmake --strip-components 1 tar -xzf cmake.tgz -C /cmake --strip-components 1

428
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -75,11 +75,8 @@ SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime
; - musl-native: used for alpine linux, can build `musl` and `musl -dynamic` target. ; - musl-native: used for alpine linux, can build `musl` and `musl -dynamic` target.
; - gnu-native: used for general linux distros, can build gnu target for the installed glibc version only. ; - gnu-native: used for general linux distros, can build gnu target for the installed glibc version only.
; option to specify the target, superceded by SPC_TARGET if set ; LEGACY option to specify the target
SPC_LIBC=musl SPC_LIBC=musl
; uncomment to link libc dynamically on musl
; 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:
@@ -98,7 +95,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="-Wl,--as-needed" SPC_DEFAULT_LD_FLAGS=""
; 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
@@ -116,11 +113,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="-Wl,--as-needed" SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS=""
; 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
OPENSSLDIR=""
[macos] [macos]
; build target: macho or macho (possibly we could support macho-universal in the future) ; build target: macho or macho (possibly we could support macho-universal in the future)
@@ -149,8 +142,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}"
; minimum compatible macOS version (LLVM vars, availability not guaranteed)
MACOSX_DEPLOYMENT_TARGET=12.0
[freebsd] [freebsd]
; compiler environments ; compiler environments

View File

@@ -43,14 +43,6 @@
"calendar": { "calendar": {
"type": "builtin" "type": "builtin"
}, },
"com_dotnet": {
"support": {
"BSD": "no",
"Linux": "no",
"Darwin": "no"
},
"type": "builtin"
},
"ctype": { "ctype": {
"type": "builtin" "type": "builtin"
}, },
@@ -135,14 +127,6 @@
"sockets" "sockets"
] ]
}, },
"excimer": {
"support": {
"Windows": "wip",
"BSD": "wip"
},
"type": "external",
"source": "ext-excimer"
},
"exif": { "exif": {
"type": "builtin" "type": "builtin"
}, },
@@ -248,13 +232,11 @@
"BSD": "wip" "BSD": "wip"
}, },
"type": "external", "type": "external",
"source": "ext-grpc", "source": "grpc",
"arg-type-unix": "enable-path", "arg-type-unix": "enable-path",
"cpp-extension": true, "cpp-extension": true,
"lib-depends": [ "lib-depends": [
"zlib", "grpc"
"openssl",
"libcares"
] ]
}, },
"iconv": { "iconv": {
@@ -426,7 +408,8 @@
"ext-depends": [ "ext-depends": [
"zlib", "zlib",
"session" "session"
] ],
"build-with-php": true
}, },
"memcached": { "memcached": {
"support": { "support": {
@@ -504,40 +487,6 @@
"zlib" "zlib"
] ]
}, },
"mysqlnd_ed25519": {
"type": "external",
"source": "mysqlnd_ed25519",
"arg-type": "enable",
"target": [
"shared"
],
"ext-depends": [
"mysqlnd"
],
"lib-depends": [
"libsodium"
],
"lib-suggests": [
"openssl"
]
},
"mysqlnd_parsec": {
"type": "external",
"source": "mysqlnd_parsec",
"arg-type": "enable",
"target": [
"shared"
],
"ext-depends": [
"mysqlnd"
],
"lib-depends": [
"libsodium"
],
"lib-suggests": [
"openssl"
]
},
"oci8": { "oci8": {
"type": "wip", "type": "wip",
"support": { "support": {
@@ -618,13 +567,6 @@
"type": "builtin", "type": "builtin",
"unix-only": true "unix-only": true
}, },
"pcov": {
"type": "external",
"source": "pcov",
"target": [
"shared"
]
},
"pdo": { "pdo": {
"type": "builtin" "type": "builtin"
}, },

View File

@@ -303,9 +303,6 @@
}, },
"krb5": { "krb5": {
"source": "krb5", "source": "krb5",
"target": [
"static"
],
"pkg-configs": [ "pkg-configs": [
"krb5-gssapi" "krb5-gssapi"
], ],
@@ -364,9 +361,6 @@
"source": "libargon2", "source": "libargon2",
"static-libs-unix": [ "static-libs-unix": [
"libargon2.a" "libargon2.a"
],
"lib-suggests": [
"libsodium"
] ]
}, },
"libavif": { "libavif": {
@@ -376,15 +370,6 @@
], ],
"static-libs-windows": [ "static-libs-windows": [
"avif.lib" "avif.lib"
],
"lib-depends": [
"libaom"
],
"lib-suggests": [
"libwebp",
"libjpeg",
"libxml2",
"libpng"
] ]
}, },
"libcares": { "libcares": {
@@ -865,9 +850,6 @@
}, },
"openssl": { "openssl": {
"source": "openssl", "source": "openssl",
"pkg-configs": [
"openssl"
],
"static-libs-unix": [ "static-libs-unix": [
"libssl.a", "libssl.a",
"libcrypto.a" "libcrypto.a"
@@ -980,11 +962,6 @@
}, },
"unixodbc": { "unixodbc": {
"source": "unixodbc", "source": "unixodbc",
"pkg-configs": [
"odbc",
"odbccr",
"odbcinst"
],
"static-libs-unix": [ "static-libs-unix": [
"libodbc.a", "libodbc.a",
"libodbccr.a", "libodbccr.a",
@@ -1026,10 +1003,7 @@
}, },
"zlib": { "zlib": {
"source": "zlib", "source": "zlib",
"pkg-configs": [ "static-libs-unix": [
"zlib"
],
"static-libs": [
"libz.a" "libz.a"
], ],
"static-libs-windows": [ "static-libs-windows": [
@@ -1042,15 +1016,14 @@
}, },
"zstd": { "zstd": {
"source": "zstd", "source": "zstd",
"pkg-configs": [
"libzstd"
],
"static-libs-unix": [ "static-libs-unix": [
"libzstd.a" "libzstd.a"
], ],
"static-libs-windows": [ "static-libs-windows": [
"zstd.lib", [
"zstd_static.lib" "zstd.lib",
"zstd_static.lib"
]
], ],
"headers-unix": [ "headers-unix": [
"zdict.h", "zdict.h",

View File

@@ -126,23 +126,13 @@
}, },
"ext-event": { "ext-event": {
"type": "url", "type": "url",
"url": "https://bitbucket.org/osmanov/pecl-event/get/3.1.4.tar.gz", "url": "https://bitbucket.org/osmanov/pecl-event/get/3.0.8.tar.gz",
"path": "php-src/ext/event", "path": "php-src/ext/event",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"ext-excimer": {
"type": "url",
"url": "https://pecl.php.net/get/excimer",
"path": "php-src/ext/excimer",
"filename": "excimer.tgz",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"ext-glfw": { "ext-glfw": {
"type": "git", "type": "git",
"url": "https://github.com/mario-deluna/php-glfw", "url": "https://github.com/mario-deluna/php-glfw",
@@ -161,18 +151,6 @@
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"ext-grpc": {
"type": "url",
"url": "https://pecl.php.net/get/grpc",
"path": "php-src/ext/grpc",
"filename": "grpc.tgz",
"license": {
"type": "file",
"path": [
"LICENSE"
]
}
},
"ext-imagick": { "ext-imagick": {
"type": "url", "type": "url",
"url": "https://pecl.php.net/get/imagick", "url": "https://pecl.php.net/get/imagick",
@@ -361,7 +339,7 @@
}, },
"gmp": { "gmp": {
"type": "filelist", "type": "filelist",
"url": "https://ftp.gnu.org/gnu/gmp/", "url": "https://gmplib.org/download/gmp/",
"regex": "/href=\"(?<file>gmp-(?<version>[^\"]+)\\.tar\\.xz)\"/", "regex": "/href=\"(?<file>gmp-(?<version>[^\"]+)\\.tar\\.xz)\"/",
"provide-pre-built": true, "provide-pre-built": true,
"alt": { "alt": {
@@ -526,7 +504,7 @@
"libavif": { "libavif": {
"type": "ghtar", "type": "ghtar",
"repo": "AOMediaCodec/libavif", "repo": "AOMediaCodec/libavif",
"provide-pre-built": false, "provide-pre-built": true,
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -692,10 +670,9 @@
} }
}, },
"libpng": { "libpng": {
"type": "ghtagtar", "type": "git",
"repo": "pnggroup/libpng", "url": "https://github.com/glennrp/libpng.git",
"match": "v1\\.6\\.\\d+", "rev": "libpng16",
"query": "?per_page=150",
"provide-pre-built": true, "provide-pre-built": true,
"license": { "license": {
"type": "file", "type": "file",
@@ -703,9 +680,9 @@
} }
}, },
"librabbitmq": { "librabbitmq": {
"type": "ghtar", "type": "git",
"repo": "alanxz/rabbitmq-c", "url": "https://github.com/alanxz/rabbitmq-c.git",
"prefer-stable": true, "rev": "master",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -722,7 +699,7 @@
"libsodium": { "libsodium": {
"type": "ghrel", "type": "ghrel",
"repo": "jedisct1/libsodium", "repo": "jedisct1/libsodium",
"match": "libsodium-(?!1\\.0\\.21)\\d+(\\.\\d+)*\\.tar\\.gz", "match": "libsodium-\\d+(\\.\\d+)*\\.tar\\.gz",
"prefer-stable": true, "prefer-stable": true,
"provide-pre-built": true, "provide-pre-built": true,
"license": { "license": {
@@ -794,9 +771,8 @@
] ]
}, },
"libwebp": { "libwebp": {
"type": "ghtagtar", "type": "url",
"repo": "webmproject/libwebp", "url": "https://github.com/webmproject/libwebp/archive/refs/tags/v1.3.2.tar.gz",
"match": "v1\\.\\d+\\.\\d+$",
"provide-pre-built": true, "provide-pre-built": true,
"license": { "license": {
"type": "file", "type": "file",
@@ -804,10 +780,8 @@
} }
}, },
"libxml2": { "libxml2": {
"type": "ghtagtar", "type": "url",
"repo": "GNOME/libxml2", "url": "https://github.com/GNOME/libxml2/archive/refs/tags/v2.12.5.tar.gz",
"match": "v2\\.\\d+\\.\\d+$",
"provide-pre-built": false,
"license": { "license": {
"type": "file", "type": "file",
"path": "Copyright" "path": "Copyright"
@@ -894,24 +868,6 @@
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"mysqlnd_ed25519": {
"type": "pie",
"repo": "mariadb/mysqlnd_ed25519",
"path": "php-src/ext/mysqlnd_ed25519",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"mysqlnd_parsec": {
"type": "pie",
"repo": "mariadb/mysqlnd_parsec",
"path": "php-src/ext/mysqlnd_parsec",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"ncurses": { "ncurses": {
"type": "filelist", "type": "filelist",
"url": "https://ftp.gnu.org/pub/gnu/ncurses/", "url": "https://ftp.gnu.org/pub/gnu/ncurses/",
@@ -1007,15 +963,6 @@
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"pcov": {
"type": "url",
"url": "https://pecl.php.net/get/pcov",
"filename": "pcov.tgz",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"pdo_sqlsrv": { "pdo_sqlsrv": {
"type": "url", "type": "url",
"url": "https://pecl.php.net/get/pdo_sqlsrv", "url": "https://pecl.php.net/get/pdo_sqlsrv",
@@ -1213,8 +1160,9 @@
} }
}, },
"xdebug": { "xdebug": {
"type": "pie", "type": "url",
"repo": "xdebug/xdebug", "url": "https://pecl.php.net/get/xdebug",
"filename": "xdebug.tgz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"

View File

@@ -4,7 +4,7 @@ import sidebarZh from "./sidebar.zh";
// https://vitepress.dev/reference/site-config // https://vitepress.dev/reference/site-config
export default { export default {
title: "Static PHP", title: "StaticPHP",
description: "Build single static PHP binary, with PHP project together, with popular extensions included.", description: "Build single static PHP binary, with PHP project together, with popular extensions included.",
locales: { locales: {
en: { en: {

View File

@@ -1,6 +1,6 @@
# Guide # Guide
Static php cli is a tool used to build statically compiled PHP binaries, StaticPHP is a tool used to build statically compiled PHP binaries,
currently supporting Linux and macOS systems. currently supporting Linux and macOS systems.
In the guide section, you will learn how to use static php cli to build standalone PHP programs. In the guide section, you will learn how to use static php cli to build standalone PHP programs.
@@ -14,12 +14,14 @@ In the guide section, you will learn how to use static php cli to build standalo
The following is the architecture support situation, where :gear: represents support for GitHub Action build, The following is the architecture support situation, where :gear: represents support for GitHub Action build,
:computer: represents support for local manual build, and empty represents temporarily not supported. :computer: represents support for local manual build, and empty represents temporarily not supported.
| | x86_64 | aarch64 | | | x86_64 | aarch64 |
|---------|-------------------|-------------------| |---------|------------------------|------------------------|
| macOS | :gear: :computer: | :gear: :computer: | | macOS | :gear: :computer: | :gear: :computer: |
| Linux | :gear: :computer: | :gear: :computer: | | Linux | :gear: :computer: | :gear: :computer: |
| Windows | :gear: :computer: | | | Windows | :gear: :computer: | |
| FreeBSD | :computer: | :computer: | | FreeBSD | :computer: (:warning:) | :computer: (:warning:) |
> Due to lack of users and testing, FreeBSD is no longer supported in latest StaticPHP project.
Current supported PHP versions for compilation: Current supported PHP versions for compilation:
@@ -29,17 +31,17 @@ Current supported PHP versions for compilation:
> >
> :x: Not supported > :x: Not supported
| PHP Version | Status | Comment | | PHP Version | Status | Comment |
|-------------|--------------------|-------------------------------------------------------------------------------------------------------------------------| |-------------|--------------------|--------------------------------------------------------------------------------------------|
| 7.2 | :x: | | | 7.2 | :x: | |
| 7.3 | :x: | phpmicro and many extensions do not support 7.3, 7.4 versions | | 7.3 | :x: | phpmicro and many extensions do not support 7.3, 7.4 versions |
| 7.4 | :x: | phpmicro and many extensions do not support 7.3, 7.4 versions | | 7.4 | :x: | phpmicro and many extensions do not support 7.3, 7.4 versions |
| 8.0 | :warning: | PHP official has stopped maintaining 8.0, we no longer handle 8.0 related backport support | | 8.0 | :warning: | PHP official has stopped maintaining 8.0, we no longer handle 8.0 related backport support |
| 8.1 | :warning: | PHP official only provides security updates for 8.1, we no longer handle 8.1 related backport support after 8.5 release | | 8.1 | :warning: | PHP official only provides security updates for 8.1 |
| 8.2 | :heavy_check_mark: | | | 8.2 | :heavy_check_mark: | |
| 8.3 | :heavy_check_mark: | | | 8.3 | :heavy_check_mark: | |
| 8.4 | :heavy_check_mark: | | | 8.4 | :heavy_check_mark: | |
| 8.5 (beta) | :warning: | PHP 8.5 is currently in beta stage | | 8.5 | :heavy_check_mark: | |
> This table shows the support status of static-php-cli for building corresponding versions, not the PHP official support status for that version. > This table shows the support status of static-php-cli for building corresponding versions, not the PHP official support status for that version.

View File

@@ -549,24 +549,22 @@ otherwise it will be executed repeatedly in other events.
The following are the supported `patch_point` event names and corresponding locations: The following are the supported `patch_point` event names and corresponding locations:
| Event name | Event description | | Event name | Event description |
|---------------------------------|----------------------------------------------------------------------------------------------------| |------------------------------|----------------------------------------------------------------------------------------------------|
| before-libs-extract | Triggered before the dependent libraries extracted | | before-libs-extract | Triggered before the dependent libraries extracted |
| after-libs-extract | Triggered after the compiled dependent libraries extracted | | after-libs-extract | Triggered after the compiled dependent libraries extracted |
| before-php-extract | Triggered before PHP source code extracted | | before-php-extract | Triggered before PHP source code extracted |
| after-php-extract | Triggered after PHP source code extracted | | after-php-extract | Triggered after PHP source code extracted |
| before-micro-extract | Triggered before phpmicro extract | | before-micro-extract | Triggered before phpmicro extract |
| after-micro-extract | Triggered after phpmicro extracted | | after-micro-extract | Triggered after phpmicro extracted |
| before-exts-extract | Triggered before the extension (to be compiled) extracted to the PHP source directory | | before-exts-extract | Triggered before the extension (to be compiled) extracted to the PHP source directory |
| after-exts-extract | Triggered after the extension extracted to the PHP source directory | | after-exts-extract | Triggered after the extension extracted to the PHP source directory |
| before-library[*name*]-build | Triggered before the library named `name` is compiled (such as `before-library[postgresql]-build`) | | before-library[*name*]-build | Triggered before the library named `name` is compiled (such as `before-library[postgresql]-build`) |
| after-library[*name*]-build | Triggered after the library named `name` is compiled | | after-library[*name*]-build | Triggered after the library named `name` is compiled |
| after-shared-ext[*name*]-build | Triggered after the shared extension named `name` is compiled | | before-php-buildconf | Triggered before compiling PHP command `./buildconf` |
| before-shared-ext[*name*]-build | Triggered before the shared extension named `name` is compiled | | before-php-configure | Triggered before compiling PHP command `./configure` |
| before-php-buildconf | Triggered before compiling PHP command `./buildconf` | | before-php-make | Triggered before compiling PHP command `make` |
| before-php-configure | Triggered before compiling PHP command `./configure` | | before-sanity-check | Triggered after compiling PHP but before running extended checks |
| before-php-make | Triggered before compiling PHP command `make` |
| before-sanity-check | Triggered after compiling PHP but before running extended checks |
The following is a simple example of temporarily modifying the PHP source code. The following is a simple example of temporarily modifying the PHP source code.
Enable the CLI function to search for the `php.ini` configuration in the current working directory: Enable the CLI function to search for the `php.ini` configuration in the current working directory:

View File

@@ -3,7 +3,7 @@
layout: home layout: home
hero: hero:
name: "Static PHP" name: "StaticPHP"
tagline: "Build standalone PHP binary on Linux, macOS, FreeBSD, Windows, with PHP project together, with popular extensions included." tagline: "Build standalone PHP binary on Linux, macOS, FreeBSD, Windows, with PHP project together, with popular extensions included."
image: image:
src: /images/static-php_nobg.png src: /images/static-php_nobg.png
@@ -14,9 +14,9 @@ hero:
link: ./guide/ link: ./guide/
features: features:
- title: Static CLI Binary - title: Static PHP Binary
details: You can easily compile a standalone php binary for general use. Including CLI, FPM sapi. details: You can easily compile a standalone php binary for general use. Including CLI, FPM sapi.
- title: Micro Self-Extracted Executable - title: PHP micro Self-Extracted Executable
details: You can compile a self-extracted executable and build with your php source code. details: You can compile a self-extracted executable and build with your php source code.
- title: Dependency Management - title: Dependency Management
details: static-php-cli comes with dependency management and supports installation of different types of PHP extensions. details: static-php-cli comes with dependency management and supports installation of different types of PHP extensions.

View File

@@ -3,7 +3,7 @@
layout: home layout: home
hero: hero:
name: "Static PHP" name: "StaticPHP"
tagline: "Build standalone PHP binary on Linux, macOS, FreeBSD, Windows, with PHP project together, with popular extensions included." tagline: "Build standalone PHP binary on Linux, macOS, FreeBSD, Windows, with PHP project together, with popular extensions included."
image: image:
src: /images/static-php_nobg.png src: /images/static-php_nobg.png

View File

@@ -12,12 +12,14 @@ static-php-cli 是一个用于构建静态编译的 PHP 二进制的工具,目
下面是架构支持情况,:gear: 代表支持 GitHub Action 构建,:computer: 代表支持本地构建,空 代表暂不支持。 下面是架构支持情况,:gear: 代表支持 GitHub Action 构建,:computer: 代表支持本地构建,空 代表暂不支持。
| | x86_64 | aarch64 | | | x86_64 | aarch64 |
|---------|-------------------|-------------------| |---------|------------------------|------------------------|
| macOS | :gear: :computer: | :gear: :computer: | | macOS | :gear: :computer: | :gear: :computer: |
| Linux | :gear: :computer: | :gear: :computer: | | Linux | :gear: :computer: | :gear: :computer: |
| Windows | :gear: :computer: | | | Windows | :gear: :computer: | |
| FreeBSD | :computer: | :computer: | | FreeBSD | :computer: (:warning:) | :computer: (:warning:) |
> 由于缺乏用户和测试FreeBSD 在最新的 StaticPHP 项目中不再受支持。
当前支持编译的 PHP 版本: 当前支持编译的 PHP 版本:
@@ -27,17 +29,17 @@ static-php-cli 是一个用于构建静态编译的 PHP 二进制的工具,目
> >
> :x: 不支持 > :x: 不支持
| PHP Version | Status | Comment | | PHP Version | Status | Comment |
|-------------|--------------------|---------------------------------------------------------| |-------------|--------------------|----------------------------------------------|
| 7.2 | :x: | | | 7.2 | :x: | |
| 7.3 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 | | 7.3 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
| 7.4 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 | | 7.4 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
| 8.0 | :warning: | PHP 官方已停止 8.0 的维护,我们不再处理 8.0 相关的 backport 支持 | | 8.0 | :warning: | PHP 官方已停止 8.0 的维护,我们不再处理 8.0 相关的 backport 支持 |
| 8.1 | :warning: | PHP 官方仅对 8.1 提供安全更新,在 8.5 发布后我们不再处理 8.1 相关的 backport 支持 | | 8.1 | :warning: | PHP 官方仅对 8.1 提供安全更新 |
| 8.2 | :heavy_check_mark: | | | 8.2 | :heavy_check_mark: | |
| 8.3 | :heavy_check_mark: | | | 8.3 | :heavy_check_mark: | |
| 8.4 | :heavy_check_mark: | | | 8.4 | :heavy_check_mark: | |
| 8.5 (beta) | :warning: | PHP 8.5 目前处于 beta 阶段 | | 8.5 | :heavy_check_mark: | |
> 这个表格的支持状态是 static-php-cli 对构建对应版本的支持情况,不是 PHP 官方对该版本的支持情况。 > 这个表格的支持状态是 static-php-cli 对构建对应版本的支持情况,不是 PHP 官方对该版本的支持情况。

View File

@@ -500,8 +500,6 @@ bin/spc dev:sort-config ext
| after-exts-extract | 在要编译的扩展解压到 PHP 源码目录后触发 | | after-exts-extract | 在要编译的扩展解压到 PHP 源码目录后触发 |
| before-library[*name*]-build | 在名称为 `name` 的库编译前触发(如 `before-library[postgresql]-build` | | before-library[*name*]-build | 在名称为 `name` 的库编译前触发(如 `before-library[postgresql]-build` |
| after-library[*name*]-build | 在名称为 `name` 的库编译后触发 | | after-library[*name*]-build | 在名称为 `name` 的库编译后触发 |
| after-shared-ext[*name*]-build | 在名称为 `name` 的共享扩展编译后触发(如 `after-shared-ext[redis]-build` |
| before-shared-ext[*name*]-build | 在名称为 `name` 的共享扩展编译前触发 |
| before-php-buildconf | 在编译 PHP 命令 `./buildconf` 前触发 | | before-php-buildconf | 在编译 PHP 命令 `./buildconf` 前触发 |
| before-php-configure | 在编译 PHP 命令 `./configure` 前触发 | | before-php-configure | 在编译 PHP 命令 `./configure` 前触发 |
| before-php-make | 在编译 PHP 命令 `make` 前触发 | | before-php-make | 在编译 PHP 命令 `make` 前触发 |

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.3'; public const string VERSION = '2.7.8';
public function __construct() public function __construct()
{ {

View File

@@ -96,8 +96,7 @@ class Extension
fn ($x) => $x->getStaticLibFiles(), fn ($x) => $x->getStaticLibFiles(),
$this->getLibraryDependencies(recursive: true) $this->getLibraryDependencies(recursive: true)
); );
$libs = implode(' ', $ret); return implode(' ', $ret);
return deduplicate_flags($libs);
} }
/** /**
@@ -386,9 +385,6 @@ class Extension
logger()->info('Shared extension [' . $this->getName() . '] was already built, skipping (' . $this->getName() . '.so)'); logger()->info('Shared extension [' . $this->getName() . '] was already built, skipping (' . $this->getName() . '.so)');
return; return;
} }
if ((string) Config::getExt($this->getName(), 'type') === 'addon') {
return;
}
logger()->info('Building extension [' . $this->getName() . '] as shared extension (' . $this->getName() . '.so)'); logger()->info('Building extension [' . $this->getName() . '] as shared extension (' . $this->getName() . '.so)');
foreach ($this->dependencies as $dependency) { foreach ($this->dependencies as $dependency) {
if (!$dependency instanceof Extension) { if (!$dependency instanceof Extension) {
@@ -399,12 +395,13 @@ class Extension
$dependency->buildShared([...$visited, $this->getName()]); $dependency->buildShared([...$visited, $this->getName()]);
} }
} }
$this->builder->emitPatchPoint('before-shared-ext[' . $this->getName() . ']-build'); if (Config::getExt($this->getName(), 'type') === 'addon') {
return;
}
match (PHP_OS_FAMILY) { match (PHP_OS_FAMILY) {
'Darwin', 'Linux' => $this->buildUnixShared(), 'Darwin', 'Linux' => $this->buildUnixShared(),
default => throw new WrongUsageException(PHP_OS_FAMILY . ' build shared extensions is not supported yet'), default => throw new WrongUsageException(PHP_OS_FAMILY . ' build shared extensions is not supported yet'),
}; };
$this->builder->emitPatchPoint('after-shared-ext[' . $this->getName() . ']-build');
} catch (SPCException $e) { } catch (SPCException $e) {
$e->bindExtensionInfo(['extension_name' => $this->getName()]); $e->bindExtensionInfo(['extension_name' => $this->getName()]);
throw $e; throw $e;
@@ -455,17 +452,12 @@ class Extension
// process *.so file // process *.so file
$soFile = BUILD_MODULES_PATH . '/' . $this->getName() . '.so'; $soFile = BUILD_MODULES_PATH . '/' . $this->getName() . '.so';
$soDest = $soFile;
preg_match('/-release\s+(\S*)/', getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'), $matches);
if (!empty($matches[1])) {
$soDest = str_replace('.so', '-' . $matches[1] . '.so', $soFile);
}
if (!file_exists($soFile)) { if (!file_exists($soFile)) {
throw new ValidationException("extension {$this->getName()} build failed: {$soFile} not found", validation_module: "Extension {$this->getName()} build"); throw new ValidationException("extension {$this->getName()} build failed: {$soFile} not found", validation_module: "Extension {$this->getName()} build");
} }
/** @var UnixBuilderBase $builder */ /** @var UnixBuilderBase $builder */
$builder = $this->builder; $builder = $this->builder;
$builder->deployBinary($soFile, $soDest, false); $builder->deployBinary($soFile, $soFile, false);
} }
/** /**
@@ -543,7 +535,7 @@ class Extension
*/ */
protected function getSharedExtensionEnv(): array protected function getSharedExtensionEnv(): array
{ {
$config = (new SPCConfigUtil($this->builder, ['no_php' => true]))->getExtensionConfig($this); $config = (new SPCConfigUtil($this->builder))->getExtensionConfig($this);
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']); [$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
$preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group '; $preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group ';
$postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group '; $postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group ';
@@ -551,7 +543,6 @@ class Extension
'CFLAGS' => $config['cflags'], 'CFLAGS' => $config['cflags'],
'CXXFLAGS' => $config['cflags'], 'CXXFLAGS' => $config['cflags'],
'LDFLAGS' => $config['ldflags'], 'LDFLAGS' => $config['ldflags'],
'EXTRA_LDFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'),
'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"), 'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"),
'LD_LIBRARY_PATH' => BUILD_LIB_PATH, 'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
]; ];

View File

@@ -184,18 +184,18 @@ abstract class LibraryBase
// extract first if not exists // extract first if not exists
if (!is_dir($this->source_dir)) { if (!is_dir($this->source_dir)) {
$this->getBuilder()->emitPatchPoint('before-library[' . static::NAME . ']-extract'); $this->getBuilder()->emitPatchPoint('before-library[ ' . static::NAME . ']-extract');
SourceManager::initSource(libs: [static::NAME], source_only: true); SourceManager::initSource(libs: [static::NAME], source_only: true);
$this->getBuilder()->emitPatchPoint('after-library[' . static::NAME . ']-extract'); $this->getBuilder()->emitPatchPoint('after-library[ ' . static::NAME . ']-extract');
} }
if (!$this->patched && $this->patchBeforeBuild()) { if (!$this->patched && $this->patchBeforeBuild()) {
file_put_contents($this->source_dir . '/.spc.patched', 'PATCHED!!!'); file_put_contents($this->source_dir . '/.spc.patched', 'PATCHED!!!');
} }
$this->getBuilder()->emitPatchPoint('before-library[' . static::NAME . ']-build'); $this->getBuilder()->emitPatchPoint('before-library[ ' . static::NAME . ']-build');
$this->build(); $this->build();
$this->installLicense(); $this->installLicense();
$this->getBuilder()->emitPatchPoint('after-library[' . static::NAME . ']-build'); $this->getBuilder()->emitPatchPoint('after-library[ ' . static::NAME . ']-build');
return LIB_STATUS_OK; return LIB_STATUS_OK;
} }
@@ -346,50 +346,27 @@ abstract class LibraryBase
*/ */
protected function installLicense(): void protected function installLicense(): void
{ {
FileSystem::createDir(BUILD_ROOT_PATH . '/source-licenses/' . $this->getName());
$source = Config::getLib($this->getName(), 'source'); $source = Config::getLib($this->getName(), 'source');
FileSystem::createDir(BUILD_ROOT_PATH . "/source-licenses/{$source}");
$license_files = Config::getSource($source)['license'] ?? []; $license_files = Config::getSource($source)['license'] ?? [];
if (is_assoc_array($license_files)) { if (is_assoc_array($license_files)) {
$license_files = [$license_files]; $license_files = [$license_files];
} }
foreach ($license_files as $index => $license) { foreach ($license_files as $index => $license) {
if ($license['type'] === 'text') { if ($license['type'] === 'text') {
FileSystem::writeFile(BUILD_ROOT_PATH . "/source-licenses/{$source}/{$index}.txt", $license['text']); FileSystem::writeFile(BUILD_ROOT_PATH . '/source-licenses/' . $this->getName() . "/{$index}.txt", $license['text']);
continue; continue;
} }
if ($license['type'] === 'file') { if ($license['type'] === 'file') {
copy($this->source_dir . '/' . $license['path'], BUILD_ROOT_PATH . "/source-licenses/{$source}/{$index}.txt"); copy($this->source_dir . '/' . $license['path'], BUILD_ROOT_PATH . '/source-licenses/' . $this->getName() . "/{$index}.txt");
} }
} }
} }
protected function isLibraryInstalled(): bool protected function isLibraryInstalled(): bool
{ {
$pkg_configs = Config::getLib(static::NAME, 'pkg-configs', []);
if (count($pkg_configs) !== 0) {
$pkg_config_path = getenv('PKG_CONFIG_PATH') ?: '';
$search_paths = array_unique(array_filter(explode(is_unix() ? ':' : ';', $pkg_config_path)));
foreach ($pkg_configs as $name) {
$found = false;
foreach ($search_paths as $path) {
if (file_exists($path . "/{$name}.pc")) {
$found = true;
break;
}
}
if (!$found) {
return false;
}
}
return true; // allow using system dependencies if pkg_config_path is explicitly defined
}
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;
} }
} }
@@ -398,6 +375,11 @@ abstract class LibraryBase
return false; return false;
} }
} }
foreach (Config::getLib(static::NAME, 'pkg-configs', []) as $name) {
if (!file_exists(BUILD_LIB_PATH . "/pkgconfig/{$name}.pc")) {
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

@@ -1,17 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\util\CustomExt;
#[CustomExt('com_dotnet')]
class com_dotnet extends Extension
{
public function getWindowsConfigureArg(bool $shared = false): string
{
return '--enable-com-dotnet=yes';
}
}

View File

@@ -5,21 +5,11 @@ declare(strict_types=1);
namespace SPC\builder\extension; namespace SPC\builder\extension;
use SPC\builder\Extension; use SPC\builder\Extension;
use SPC\builder\linux\SystemUtil;
use SPC\store\SourcePatcher;
use SPC\util\CustomExt; use SPC\util\CustomExt;
#[CustomExt('ffi')] #[CustomExt('ffi')]
class ffi extends Extension class ffi extends Extension
{ {
public function patchBeforeBuildconf(): bool
{
if (PHP_OS_FAMILY === 'Linux' && SystemUtil::getOSRelease()['dist'] === 'centos') {
return SourcePatcher::patchFfiCentos7FixO3strncmp();
}
return false;
}
public function getUnixConfigureArg(bool $shared = false): string public function getUnixConfigureArg(bool $shared = false): string
{ {
return '--with-ffi' . ($shared ? '=shared' : '') . ' --enable-zend-signals'; return '--with-ffi' . ($shared ? '=shared' : '') . ' --enable-zend-signals';

View File

@@ -21,14 +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');
} }
FileSystem::replaceFileStr( if (file_exists(SOURCE_PATH . '/php-src/ext/grpc')) {
$this->source_dir . '/src/php/ext/grpc/call.c', return false;
'zend_exception_get_default(TSRMLS_C),', }
'zend_ce_exception,', // soft link to the grpc source code
); if (is_dir($this->source_dir . '/src/php/ext/grpc')) {
shell()->exec('ln -s ' . $this->source_dir . '/src/php/ext/grpc ' . SOURCE_PATH . '/php-src/ext/grpc');
} else {
throw new ValidationException('Cannot find grpc source code in ' . $this->source_dir . '/src/php/ext/grpc');
}
if (SPCTarget::getTargetOS() === 'Darwin') { if (SPCTarget::getTargetOS() === 'Darwin') {
FileSystem::replaceFileRegex( FileSystem::replaceFileRegex(
$this->source_dir . '/config.m4', SOURCE_PATH . '/php-src/ext/grpc/config.m4',
'/GRPC_LIBDIR=.*$/m', '/GRPC_LIBDIR=.*$/m',
'GRPC_LIBDIR=' . BUILD_LIB_PATH . "\n" . 'LDFLAGS="$LDFLAGS -framework CoreFoundation"' 'GRPC_LIBDIR=' . BUILD_LIB_PATH . "\n" . 'LDFLAGS="$LDFLAGS -framework CoreFoundation"'
); );

View File

@@ -5,8 +5,6 @@ declare(strict_types=1);
namespace SPC\builder\extension; namespace SPC\builder\extension;
use SPC\builder\Extension; use SPC\builder\Extension;
use SPC\toolchain\ToolchainManager;
use SPC\toolchain\ZigToolchain;
use SPC\util\CustomExt; use SPC\util\CustomExt;
#[CustomExt('imagick')] #[CustomExt('imagick')]
@@ -21,9 +19,7 @@ class imagick extends Extension
protected function splitLibsIntoStaticAndShared(string $allLibs): array protected function splitLibsIntoStaticAndShared(string $allLibs): array
{ {
[$static, $shared] = parent::splitLibsIntoStaticAndShared($allLibs); [$static, $shared] = parent::splitLibsIntoStaticAndShared($allLibs);
if (ToolchainManager::getToolchainClass() !== ZigToolchain::class && if (str_contains(getenv('PATH'), 'rh/devtoolset') || str_contains(getenv('PATH'), 'rh/gcc-toolset')) {
(str_contains(getenv('PATH'), 'rh/devtoolset') || str_contains(getenv('PATH'), 'rh/gcc-toolset'))
) {
$static .= ' -l:libstdc++.a'; $static .= ' -l:libstdc++.a';
$shared = str_replace('-lstdc++', '', $shared); $shared = str_replace('-lstdc++', '', $shared);
} }

View File

@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace SPC\builder\extension; namespace SPC\builder\extension;
use SPC\builder\Extension; use SPC\builder\Extension;
use SPC\store\FileSystem;
use SPC\util\CustomExt; use SPC\util\CustomExt;
#[CustomExt('maxminddb')] #[CustomExt('maxminddb')]
@@ -13,13 +12,15 @@ class maxminddb extends Extension
{ {
public function patchBeforeBuildconf(): bool public function patchBeforeBuildconf(): bool
{ {
if (!is_dir(SOURCE_PATH . '/php-src/ext/maxminddb')) { if (!is_link(SOURCE_PATH . '/php-src/ext/maxminddb')) {
$original = $this->source_dir; $original = $this->source_dir;
FileSystem::copyDir($original . '/ext', SOURCE_PATH . '/php-src/ext/maxminddb'); if (PHP_OS_FAMILY === 'Windows') {
$this->source_dir = SOURCE_PATH . '/php-src/ext/maxminddb'; f_passthru('cd ' . SOURCE_PATH . '/php-src/ext && mklink /D maxminddb ' . $original . '\ext');
} else {
f_passthru('cd ' . SOURCE_PATH . '/php-src/ext && ln -s ' . $original . '/ext maxminddb');
}
return true; return true;
} }
$this->source_dir = SOURCE_PATH . '/php-src/ext/maxminddb';
return false; return false;
} }
} }

View File

@@ -18,9 +18,6 @@ class memcache extends Extension
public function patchBeforeBuildconf(): bool public function patchBeforeBuildconf(): bool
{ {
if (!$this->isBuildStatic()) {
return false;
}
FileSystem::replaceFileStr( FileSystem::replaceFileStr(
SOURCE_PATH . '/php-src/ext/memcache/config9.m4', SOURCE_PATH . '/php-src/ext/memcache/config9.m4',
'if test -d $abs_srcdir/src ; then', 'if test -d $abs_srcdir/src ; then',
@@ -46,27 +43,4 @@ EOF
); );
return true; return true;
} }
public function patchBeforeSharedConfigure(): bool
{
if (!$this->isBuildShared()) {
return false;
}
FileSystem::replaceFileStr(
SOURCE_PATH . '/php-src/ext/memcache/config9.m4',
'if test -d $abs_srcdir/main ; then',
'if test -d $abs_srcdir/src ; then',
);
FileSystem::replaceFileStr(
SOURCE_PATH . '/php-src/ext/memcache/config9.m4',
'export CPPFLAGS="$CPPFLAGS $INCLUDES -I$abs_srcdir/main"',
'export CPPFLAGS="$CPPFLAGS $INCLUDES"',
);
return true;
}
protected function getExtraEnv(): array
{
return ['CFLAGS' => '-std=c17'];
}
} }

View File

@@ -24,9 +24,4 @@ class mongodb extends Extension
$arg .= $this->builder->getLib('zlib') ? ' --with-mongodb-zlib=yes ' : ' --with-mongodb-zlib=bundled '; $arg .= $this->builder->getLib('zlib') ? ' --with-mongodb-zlib=yes ' : ' --with-mongodb-zlib=bundled ';
return clean_spaces($arg); return clean_spaces($arg);
} }
public function getExtraEnv(): array
{
return ['CFLAGS' => '-std=c17'];
}
} }

View File

@@ -1,22 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\util\CustomExt;
#[CustomExt('mysqlnd_ed25519')]
class mysqlnd_ed25519 extends Extension
{
public function getConfigureArg(bool $shared = false): string
{
return '--with-mysqlnd_ed25519' . ($shared ? '=shared' : '');
}
public function getUnixConfigureArg(bool $shared = false): string
{
return $this->getConfigureArg();
}
}

View File

@@ -1,22 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\util\CustomExt;
#[CustomExt('mysqlnd_parsec')]
class mysqlnd_parsec extends Extension
{
public function getConfigureArg(bool $shared = false): string
{
return '--enable-mysqlnd_parsec' . ($shared ? '=shared' : '');
}
public function getUnixConfigureArg(bool $shared = false): string
{
return $this->getConfigureArg();
}
}

View File

@@ -24,6 +24,25 @@ class password_argon2 extends Extension
} }
} }
public function patchBeforeMake(): bool
{
$patched = parent::patchBeforeMake();
if ($this->builder->getLib('libsodium') !== null) {
$extraLibs = getenv('SPC_EXTRA_LIBS');
if ($extraLibs !== false) {
$extraLibs = str_replace(
[BUILD_LIB_PATH . '/libargon2.a', BUILD_LIB_PATH . '/libsodium.a'],
['', BUILD_LIB_PATH . '/libargon2.a ' . BUILD_LIB_PATH . '/libsodium.a'],
$extraLibs,
);
$extraLibs = trim(preg_replace('/\s+/', ' ', $extraLibs)); // normalize spacing
f_putenv('SPC_EXTRA_LIBS=' . $extraLibs);
return true;
}
}
return $patched;
}
public function getConfigureArg(bool $shared = false): string public function getConfigureArg(bool $shared = false): string
{ {
if ($this->builder->getLib('openssl') !== null) { if ($this->builder->getLib('openssl') !== null) {

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 = deduplicate_flags($libfiles); $libfiles = str_replace(BUILD_LIB_PATH . '/lib', '-l', $libfiles);
$libfiles = clean_spaces($libfiles); $libfiles = str_replace('.a', '', $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 . '"';
@@ -45,7 +45,7 @@ class pgsql extends Extension
protected function getExtraEnv(): array protected function getExtraEnv(): array
{ {
return [ return [
'CFLAGS' => '-std=c17 -Wno-int-conversion', 'CFLAGS' => '-Wno-int-conversion',
]; ];
} }
} }

View File

@@ -45,11 +45,4 @@ class spx extends Extension
FileSystem::copy($this->source_dir . '/src/php_spx.h', $this->source_dir . '/php_spx.h'); FileSystem::copy($this->source_dir . '/src/php_spx.h', $this->source_dir . '/php_spx.h');
return true; return true;
} }
public function getSharedExtensionEnv(): array
{
$env = parent::getSharedExtensionEnv();
$env['SPX_SHARED_LIBADD'] = $env['LIBS'];
return $env;
}
} }

View File

@@ -17,7 +17,6 @@ class swoole extends Extension
public function patchBeforeMake(): bool public function patchBeforeMake(): bool
{ {
$patched = parent::patchBeforeMake(); $patched = parent::patchBeforeMake();
FileSystem::replaceFileStr($this->source_dir . '/ext-src/php_swoole_private.h', 'PHP_VERSION_ID > 80500', 'PHP_VERSION_ID >= 80600');
if ($this->builder instanceof MacOSBuilder) { if ($this->builder instanceof MacOSBuilder) {
// Fix swoole with event extension <util.h> conflict bug // Fix swoole with event extension <util.h> conflict bug
$util_path = shell()->execWithResult('xcrun --show-sdk-path', false)[1][0] . '/usr/include/util.h'; $util_path = shell()->execWithResult('xcrun --show-sdk-path', false)[1][0] . '/usr/include/util.h';

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 {$extra} " . "./Configure no-shared {$extra} " .
'--prefix=/ ' . // use prefix=/ '--prefix=/ ' . // use prefix=/
"--libdir={$lib} " . "--libdir={$lib} " .
'--openssldir=/etc/ssl ' . '--openssldir=/etc/ssl ' .

View File

@@ -94,7 +94,6 @@ 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!
]); ]);
@@ -284,14 +283,11 @@ class LinuxBuilder extends UnixBuilderBase
// process libphp.so for shared embed // process libphp.so for shared embed
$libphpSo = BUILD_LIB_PATH . '/libphp.so'; $libphpSo = BUILD_LIB_PATH . '/libphp.so';
$libphpSoDest = BUILD_LIB_PATH . '/libphp.so';
if (file_exists($libphpSo)) { if (file_exists($libphpSo)) {
// post actions: rename libphp.so to libphp-<release>.so if -release is set in LDFLAGS
$this->processLibphpSoFile($libphpSo);
// deploy libphp.so // deploy libphp.so
preg_match('/-release\s+(\S*)/', getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'), $matches); $this->deployBinary($libphpSo, $libphpSo, false);
if (!empty($matches[1])) {
$libphpSoDest = str_replace('.so', '-' . $matches[1] . '.so', $libphpSo);
}
$this->deployBinary($libphpSo, $libphpSoDest, false);
} }
// process shared extensions build-with-php // process shared extensions build-with-php
@@ -317,7 +313,7 @@ class LinuxBuilder extends UnixBuilderBase
*/ */
private function getMakeExtraVars(): array private function getMakeExtraVars(): array
{ {
$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')); $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'));
$static = SPCTarget::isStatic() ? '-all-static' : ''; $static = SPCTarget::isStatic() ? '-all-static' : '';
$lib = BUILD_LIB_PATH; $lib = BUILD_LIB_PATH;
return array_filter([ return array_filter([
@@ -328,6 +324,74 @@ class LinuxBuilder extends UnixBuilderBase
]); ]);
} }
private function processLibphpSoFile(string $libphpSo): void
{
$ldflags = getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS') ?: '';
$libDir = BUILD_LIB_PATH;
$modulesDir = BUILD_MODULES_PATH;
$realLibName = 'libphp.so';
$cwd = getcwd();
if (preg_match('/-release\s+(\S+)/', $ldflags, $matches)) {
$release = $matches[1];
$realLibName = "libphp-{$release}.so";
$libphpRelease = "{$libDir}/{$realLibName}";
if (!file_exists($libphpRelease) && file_exists($libphpSo)) {
rename($libphpSo, $libphpRelease);
}
if (file_exists($libphpRelease)) {
chdir($libDir);
if (file_exists($libphpSo)) {
unlink($libphpSo);
}
symlink($realLibName, 'libphp.so');
shell()->exec(sprintf(
'patchelf --set-soname %s %s',
escapeshellarg($realLibName),
escapeshellarg($libphpRelease)
));
}
if (is_dir($modulesDir)) {
chdir($modulesDir);
foreach ($this->getExts() as $ext) {
if (!$ext->isBuildShared()) {
continue;
}
$name = $ext->getName();
$versioned = "{$name}-{$release}.so";
$unversioned = "{$name}.so";
$src = "{$modulesDir}/{$versioned}";
$dst = "{$modulesDir}/{$unversioned}";
if (is_file($src)) {
rename($src, $dst);
shell()->exec(sprintf(
'patchelf --set-soname %s %s',
escapeshellarg($unversioned),
escapeshellarg($dst)
));
}
}
}
chdir($cwd);
}
$target = "{$libDir}/{$realLibName}";
if (file_exists($target)) {
[, $output] = shell()->execWithResult('readelf -d ' . escapeshellarg($target));
$output = implode("\n", $output);
if (preg_match('/SONAME.*\[(.+)]/', $output, $sonameMatch)) {
$currentSoname = $sonameMatch[1];
if ($currentSoname !== basename($target)) {
shell()->exec(sprintf(
'patchelf --set-soname %s %s',
escapeshellarg(basename($target)),
escapeshellarg($target)
));
}
}
}
}
/** /**
* Patch micro.sfx after UPX compression. * Patch micro.sfx after UPX compression.
* micro needs special section handling in LinuxBuilder. * micro needs special section handling in LinuxBuilder.

View File

@@ -6,8 +6,6 @@ namespace SPC\builder\linux\library;
use SPC\builder\linux\SystemUtil; use SPC\builder\linux\SystemUtil;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\toolchain\GccNativeToolchain;
use SPC\toolchain\ToolchainManager;
use SPC\util\executor\UnixAutoconfExecutor; use SPC\util\executor\UnixAutoconfExecutor;
use SPC\util\SPCTarget; use SPC\util\SPCTarget;
@@ -17,31 +15,35 @@ class liburing extends LinuxLibraryBase
public function patchBeforeBuild(): bool public function patchBeforeBuild(): bool
{ {
if (SystemUtil::isMuslDist()) { if (!SystemUtil::isMuslDist()) {
FileSystem::replaceFileStr($this->source_dir . '/configure', 'realpath -s', 'realpath'); return false;
return true;
} }
return false; FileSystem::replaceFileStr($this->source_dir . '/configure', 'realpath -s', 'realpath');
return true;
} }
protected function build(): void protected function build(): void
{ {
$use_libc = ToolchainManager::getToolchainClass() !== GccNativeToolchain::class || version_compare(SPCTarget::getLibcVersion(), '2.30', '>='); $use_libc = SPCTarget::getLibc() !== 'glibc' || version_compare(SPCTarget::getLibcVersion(), '2.30', '>=');
$make = UnixAutoconfExecutor::create($this); $make = UnixAutoconfExecutor::create($this);
if ($use_libc) { if (!$use_libc) {
$make->appendEnv([
'CC' => 'gcc', // libc-less version fails to compile with clang or zig
'CXX' => 'g++',
'AR' => 'ar',
'LD' => 'ld',
]);
} else {
$make->appendEnv([ $make->appendEnv([
'CFLAGS' => '-D_GNU_SOURCE', 'CFLAGS' => '-D_GNU_SOURCE',
]); ]);
} }
$shared = getenv('SPC_LINK_STATIC') ? 'ENABLE_SHARED=0' : 'ENABLE_SHARED=1';
$make $make
->removeConfigureArgs( ->removeConfigureArgs(
'--enable-static',
'--disable-static',
'--enable-shared',
'--disable-shared', '--disable-shared',
'--enable-static',
'--with-pic', '--with-pic',
'--enable-pic', '--enable-pic',
) )
@@ -49,7 +51,7 @@ class liburing extends LinuxLibraryBase
$use_libc ? '--use-libc' : '', $use_libc ? '--use-libc' : '',
) )
->configure() ->configure()
->make("library {$shared}", "install {$shared}", with_clean: false); ->make('library', 'install ENABLE_SHARED=0', with_clean: false);
$this->patchPkgconfPrefix(); $this->patchPkgconfPrefix();
} }

View File

@@ -21,7 +21,6 @@ declare(strict_types=1);
namespace SPC\builder\linux\library; namespace SPC\builder\linux\library;
use SPC\builder\linux\SystemUtil;
use SPC\store\FileSystem; use SPC\store\FileSystem;
class openssl extends LinuxLibraryBase class openssl extends LinuxLibraryBase
@@ -52,22 +51,17 @@ class openssl extends LinuxLibraryBase
$zlib_extra = ''; $zlib_extra = '';
} }
$openssl_dir = getenv('OPENSSLDIR') ?: null;
// TODO: in v3 use the following: $openssl_dir ??= SystemUtil::getOSRelease()['dist'] === 'redhat' ? '/etc/pki/tls' : '/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(
"./Configure {$noShared} {$extra} " . "{$env} ./Configure no-shared {$extra} " .
'--prefix=' . BUILD_ROOT_PATH . ' ' . '--prefix=' . BUILD_ROOT_PATH . ' ' .
'--libdir=' . BUILD_LIB_PATH . ' ' . '--libdir=' . BUILD_LIB_PATH . ' ' .
"--openssldir={$openssl_dir} " . '--openssldir=/etc/ssl ' .
"{$zlib_extra}" . "{$zlib_extra}" .
'enable-pie ' . 'enable-pie ' .
'no-legacy ' . 'no-legacy ' .
'no-tests ' .
"linux-{$arch}" "linux-{$arch}"
) )
->exec('make clean') ->exec('make clean')

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 {$extra} " . "./Configure no-shared {$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]); $config = new SPCConfigUtil($this->builder, options: ['libs_only_deps' => true, 'absolute_libs' => 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'];
} }
@@ -34,7 +34,7 @@ trait UnixLibraryTrait
$files = array_map(fn ($x) => "{$x}.pc", $conf_pc); $files = array_map(fn ($x) => "{$x}.pc", $conf_pc);
} }
foreach ($files as $name) { foreach ($files as $name) {
$realpath = realpath(BUILD_LIB_PATH . '/pkgconfig/' . $name); $realpath = realpath(BUILD_ROOT_PATH . '/lib/pkgconfig/' . $name);
if ($realpath === false) { if ($realpath === false) {
throw new PatchException('pkg-config prefix patcher', 'Cannot find library [' . static::NAME . '] pkgconfig file [' . $name . '] in ' . BUILD_LIB_PATH . '/pkgconfig/ !'); throw new PatchException('pkg-config prefix patcher', 'Cannot find library [' . static::NAME . '] pkgconfig file [' . $name . '] in ' . BUILD_LIB_PATH . '/pkgconfig/ !');
} }

View File

@@ -7,7 +7,6 @@ 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;
@@ -73,12 +72,12 @@ 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';
} }
if (SPCTarget::getTargetOS() !== 'Linux' || ToolchainManager::getToolchainClass() === ZigToolchain::class) { // macOS
if (SPCTarget::getTargetOS() !== 'Linux') {
return "-Wl,-exported_symbols_list,{$symbol_file}"; return "-Wl,-exported_symbols_list,{$symbol_file}";
} }
return "-Wl,--dynamic-list={$symbol_file}"; return "-Wl,--dynamic-list={$symbol_file}";

View File

@@ -145,10 +145,11 @@ abstract class UnixBuilderBase extends BuilderBase
throw new SPCInternalException("Deploy failed. Cannot find file after copy: {$dst}"); throw new SPCInternalException("Deploy failed. Cannot find file after copy: {$dst}");
} }
// extract debug info
$this->extractDebugInfo($dst);
// strip
if (!$this->getOption('no-strip')) { if (!$this->getOption('no-strip')) {
// extract debug info
$this->extractDebugInfo($dst);
// extra strip
$this->stripBinary($dst); $this->stripBinary($dst);
} }
@@ -235,10 +236,8 @@ abstract class UnixBuilderBase extends BuilderBase
$lens .= ' -static'; $lens .= ' -static';
} }
$dynamic_exports = ''; $dynamic_exports = '';
$embedType = 'static';
// if someone changed to EMBED_TYPE=shared, we need to add LD_LIBRARY_PATH // if someone changed to EMBED_TYPE=shared, we need to add LD_LIBRARY_PATH
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') { if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') {
$embedType = 'shared';
if (PHP_OS_FAMILY === 'Darwin') { if (PHP_OS_FAMILY === 'Darwin') {
$ext_path = 'DYLD_LIBRARY_PATH=' . BUILD_LIB_PATH . ':$DYLD_LIBRARY_PATH '; $ext_path = 'DYLD_LIBRARY_PATH=' . BUILD_LIB_PATH . ':$DYLD_LIBRARY_PATH ';
} else { } else {
@@ -257,19 +256,18 @@ abstract class UnixBuilderBase extends BuilderBase
} }
} }
$cc = getenv('CC'); $cc = getenv('CC');
[$ret, $out] = shell()->cd($sample_file_path)->execWithResult("{$cc} -o embed embed.c {$lens} {$dynamic_exports}"); [$ret, $out] = shell()->cd($sample_file_path)->execWithResult("{$cc} -o embed embed.c {$lens} {$dynamic_exports}");
if ($ret !== 0) { if ($ret !== 0) {
throw new ValidationException( throw new ValidationException(
'embed failed to build. Error message: ' . implode("\n", $out), 'embed failed sanity check: build failed. Error message: ' . implode("\n", $out),
validation_module: $embedType . ' libphp embed build sanity check' validation_module: 'static libphp.a sanity check'
); );
} }
[$ret, $output] = shell()->cd($sample_file_path)->execWithResult($ext_path . './embed'); [$ret, $output] = shell()->cd($sample_file_path)->execWithResult($ext_path . './embed');
if ($ret !== 0 || trim(implode('', $output)) !== 'hello') { if ($ret !== 0 || trim(implode('', $output)) !== 'hello') {
throw new ValidationException( throw new ValidationException(
'embed failed to run. Error message: ' . implode("\n", $output), 'embed failed sanity check: run failed. Error message: ' . implode("\n", $output),
validation_module: $embedType . ' libphp embed run sanity check' validation_module: 'static libphp.a sanity check'
); );
} }
} }
@@ -365,7 +363,6 @@ abstract class UnixBuilderBase extends BuilderBase
$frankenphpAppPath = $this->getOption('with-frankenphp-app'); $frankenphpAppPath = $this->getOption('with-frankenphp-app');
if ($frankenphpAppPath) { if ($frankenphpAppPath) {
$frankenphpAppPath = trim($frankenphpAppPath, "\"'");
if (!is_dir($frankenphpAppPath)) { if (!is_dir($frankenphpAppPath)) {
throw new WrongUsageException("The path provided to --with-frankenphp-app is not a valid directory: {$frankenphpAppPath}"); throw new WrongUsageException("The path provided to --with-frankenphp-app is not a valid directory: {$frankenphpAppPath}");
} }
@@ -456,7 +453,6 @@ abstract class UnixBuilderBase extends BuilderBase
'CGO_LDFLAGS' => "{$this->arch_ld_flags} {$staticFlags} {$config['ldflags']} {$libs}", 'CGO_LDFLAGS' => "{$this->arch_ld_flags} {$staticFlags} {$config['ldflags']} {$libs}",
'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.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,6 +20,11 @@ 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,7 +5,6 @@ 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
{ {
@@ -13,13 +12,6 @@ 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'))
@@ -37,7 +29,6 @@ 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

@@ -16,11 +16,7 @@ trait gettext
->addConfigureArgs( ->addConfigureArgs(
'--disable-java', '--disable-java',
'--disable-c++', '--disable-c++',
'--disable-d', '--with-included-gettext',
'--disable-rpath',
'--disable-modula2',
'--disable-libasprintf',
'--with-included-libintl',
"--with-iconv-prefix={$this->getBuildRootPath()}", "--with-iconv-prefix={$this->getBuildRootPath()}",
); );

View File

@@ -10,14 +10,7 @@ trait gmp
{ {
protected function build(): void protected function build(): void
{ {
UnixAutoconfExecutor::create($this) UnixAutoconfExecutor::create($this)->configure()->make();
->appendEnv([
'CFLAGS' => '-std=c17',
])
->configure(
'--enable-fat'
)
->make();
$this->patchPkgconfPrefix(['gmp.pc']); $this->patchPkgconfPrefix(['gmp.pc']);
} }
} }

View File

@@ -40,16 +40,6 @@ 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,6 +4,8 @@ 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()
@@ -15,6 +17,12 @@ 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,11 +11,6 @@ trait libavif
protected function build(): void protected function build(): void
{ {
UnixCMakeExecutor::create($this) UnixCMakeExecutor::create($this)
->optionalLib('libaom', '-DAVIF_CODEC_AOM=SYSTEM', '-DAVIF_CODEC_AOM=OFF')
->optionalLib('libsharpyuv', '-DAVIF_LIBSHARPYUV=SYSTEM', '-DAVIF_LIBSHARPYUV=OFF')
->optionalLib('libjpeg', '-DAVIF_JPEG=SYSTEM', '-DAVIF_JPEG=OFF')
->optionalLib('libxml2', '-DAVIF_LIBXML2=SYSTEM', '-DAVIF_LIBXML2=OFF')
->optionalLib('libpng', '-DAVIF_LIBPNG=SYSTEM', '-DAVIF_LIBPNG=OFF')
->addConfigureArgs('-DAVIF_LIBYUV=OFF') ->addConfigureArgs('-DAVIF_LIBYUV=OFF')
->build(); ->build();
// patch pkgconfig // patch pkgconfig

View File

@@ -29,17 +29,13 @@ trait libjxl
); );
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) { if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
$cflags = getenv('SPC_DEFAULT_C_FLAGS') ?: getenv('CFLAGS') ?: ''; $cmake->addConfigureArgs(
$has_avx512 = str_contains($cflags, '-mavx512') || str_contains($cflags, '-march=x86-64-v4'); '-DCXX_MAVX512F_SUPPORTED:BOOL=FALSE',
if (!$has_avx512) { '-DCXX_MAVX512DQ_SUPPORTED:BOOL=FALSE',
$cmake->addConfigureArgs( '-DCXX_MAVX512CD_SUPPORTED:BOOL=FALSE',
'-DCXX_MAVX512F_SUPPORTED:BOOL=FALSE', '-DCXX_MAVX512BW_SUPPORTED:BOOL=FALSE',
'-DCXX_MAVX512DQ_SUPPORTED:BOOL=FALSE', '-DCXX_MAVX512VL_SUPPORTED:BOOL=FALSE'
'-DCXX_MAVX512CD_SUPPORTED:BOOL=FALSE', );
'-DCXX_MAVX512BW_SUPPORTED:BOOL=FALSE',
'-DCXX_MAVX512VL_SUPPORTED:BOOL=FALSE'
);
}
} }
$cmake->build(); $cmake->build();

View File

@@ -27,5 +27,11 @@ 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,7 +13,6 @@ 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=' . (getenv('SPC_LINK_STATIC') ? 'OFF' : 'ON')) ->addConfigureArgs('-DLIBUV_BUILD_SHARED=OFF')
->build(); ->build();
// patch pkgconfig // patch pkgconfig
$this->patchPkgconfPrefix(['libuv-static.pc']); $this->patchPkgconfPrefix(['libuv-static.pc']);

View File

@@ -10,26 +10,8 @@ trait libwebp
{ {
protected function build(): void protected function build(): void
{ {
$code = '#include <immintrin.h>
int main() { return _mm256_cvtsi256_si32(_mm256_setzero_si256()); }';
$cc = getenv('CC') ?: 'gcc';
[$ret] = shell()->execWithResult("printf '%s' '{$code}' | {$cc} -x c -mavx2 -o /dev/null - 2>&1");
$disableAvx2 = $ret !== 0 && GNU_ARCH === 'x86_64' && PHP_OS_FAMILY === 'Linux';
UnixCMakeExecutor::create($this) UnixCMakeExecutor::create($this)
->addConfigureArgs( ->addConfigureArgs('-DWEBP_BUILD_EXTRAS=ON')
'-DWEBP_BUILD_EXTRAS=OFF',
'-DWEBP_BUILD_ANIM_UTILS=OFF',
'-DWEBP_BUILD_CWEBP=OFF',
'-DWEBP_BUILD_DWEBP=OFF',
'-DWEBP_BUILD_GIF2WEBP=OFF',
'-DWEBP_BUILD_IMG2WEBP=OFF',
'-DWEBP_BUILD_VWEBP=OFF',
'-DWEBP_BUILD_WEBPINFO=OFF',
'-DWEBP_BUILD_WEBPMUX=OFF',
'-DWEBP_BUILD_FUZZTEST=OFF',
$disableAvx2 ? '-DWEBP_ENABLE_SIMD=OFF' : ''
)
->build(); ->build();
// patch pkgconfig // patch pkgconfig
$this->patchPkgconfPrefix(patch_option: PKGCONF_PATCH_PREFIX | PKGCONF_PATCH_LIBDIR); $this->patchPkgconfPrefix(patch_option: PKGCONF_PATCH_PREFIX | PKGCONF_PATCH_LIBDIR);

View File

@@ -6,29 +6,10 @@ 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)
@@ -39,6 +20,7 @@ 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=' . (getenv('SPC_LINK_STATIC') ? 'OFF' : 'ON'), '-DMI_BUILD_SHARED=OFF',
'-DMI_BUILD_OBJECT=OFF', '-DMI_BUILD_OBJECT=OFF',
'-DMI_INSTALL_TOPLEVEL=ON', '-DMI_INSTALL_TOPLEVEL=ON',
); );

View File

@@ -16,7 +16,6 @@ trait ncurses
UnixAutoconfExecutor::create($this) UnixAutoconfExecutor::create($this)
->appendEnv([ ->appendEnv([
'CFLAGS' => '-std=c17',
'LDFLAGS' => SPCTarget::isStatic() ? '-static' : '', 'LDFLAGS' => SPCTarget::isStatic() ? '-static' : '',
]) ])
->configure( ->configure(
@@ -30,7 +29,7 @@ trait ncurses
'--without-tests', '--without-tests',
'--without-dlsym', '--without-dlsym',
'--without-debug', '--without-debug',
'--enable-symlinks', '-enable-symlinks',
"--bindir={$this->getBinDir()}", "--bindir={$this->getBinDir()}",
"--includedir={$this->getIncludeDir()}", "--includedir={$this->getIncludeDir()}",
"--libdir={$this->getLibDir()}", "--libdir={$this->getLibDir()}",

View File

@@ -4,16 +4,28 @@ declare(strict_types=1);
namespace SPC\builder\unix\library; namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\util\PkgConfigUtil; use SPC\util\PkgConfigUtil;
use SPC\util\SPCConfigUtil; use SPC\util\SPCConfigUtil;
use SPC\util\SPCTarget;
trait postgresql trait postgresql
{ {
public function patchBeforeBuild(): bool public function patchBeforeBuild(): bool
{ {
if (!getenv('SPC_LINK_STATIC')) { // fix aarch64 build on glibc 2.17 (e.g. CentOS 7)
return false; if (SPCTarget::getLibcVersion() === '2.17' && GNU_ARCH === 'aarch64') {
try {
FileSystem::replaceFileStr("{$this->source_dir}/src/port/pg_popcount_aarch64.c", 'HWCAP_SVE', '0');
FileSystem::replaceFileStr(
"{$this->source_dir}/src/port/pg_crc32c_armv8_choose.c",
'#if defined(__linux__) && !defined(__aarch64__) && !defined(HWCAP2_CRC32)',
'#if defined(__linux__) && !defined(HWCAP_CRC32)'
);
} catch (FileSystemException) {
// allow file not-existence to make it compatible with old and new version
}
} }
// 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\';');
@@ -38,7 +50,7 @@ trait postgresql
$config = $spc->config(libraries: $libs, include_suggest_lib: $this->builder->getOption('with-suggested-libs', false)); $config = $spc->config(libraries: $libs, include_suggest_lib: $this->builder->getOption('with-suggested-libs', false));
$env_vars = [ $env_vars = [
'CFLAGS' => $config['cflags'] . ' -std=c17', 'CFLAGS' => $config['cflags'],
'CPPFLAGS' => '-DPIC', 'CPPFLAGS' => '-DPIC',
'LDFLAGS' => $config['ldflags'], 'LDFLAGS' => $config['ldflags'],
'LIBS' => $config['libs'], 'LIBS' => $config['libs'],
@@ -95,11 +107,11 @@ trait postgresql
->exec('make -C src/interfaces/libpq install'); ->exec('make -C src/interfaces/libpq install');
// remove dynamic libs // remove dynamic libs
if (getenv('SPC_LINK_STATIC')) { shell()->cd($this->source_dir . '/build')
shell()->cd($this->source_dir . '/build') ->exec("rm -rf {$this->getBuildRootPath()}/lib/*.so.*")
->exec("rm -rf {$this->getBuildRootPath()}/lib/*.so*") ->exec("rm -rf {$this->getBuildRootPath()}/lib/*.so")
->exec("rm -rf {$this->getBuildRootPath()}/lib/*.dylib"); ->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=' . (getenv('SPC_LINK_STATIC') ? 'OFF' : 'ON') '-DBUILD_SHARED_LIB=OFF'
); );
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

@@ -10,14 +10,7 @@ trait xz
{ {
public function build(): void public function build(): void
{ {
$make = UnixAutoconfExecutor::create($this); 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,8 +10,7 @@ trait zlib
{ {
protected function build(): void protected function build(): void
{ {
$static = getenv('SPC_LINK_STATIC') ? '--static' : ''; UnixAutoconfExecutor::create($this)->exec("./configure --static --prefix={$this->getBuildRootPath()}")->make();
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=' . (getenv('SPC_LINK_STATIC') ? 'OFF' : 'ON'), '-DZSTD_BUILD_SHARED=OFF',
) )
->build(); ->build();
$this->patchPkgconfPrefix(); $this->patchPkgconfPrefix(['libzstd.pc']);
} }
} }

View File

@@ -30,6 +30,7 @@ class curl extends WindowsLibraryBase
'-DCMAKE_BUILD_TYPE=Release ' . '-DCMAKE_BUILD_TYPE=Release ' .
'-DBUILD_SHARED_LIBS=OFF ' . '-DBUILD_SHARED_LIBS=OFF ' .
'-DBUILD_STATIC_LIBS=ON ' . '-DBUILD_STATIC_LIBS=ON ' .
'-DCURL_STATICLIB=ON ' .
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' . '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' .
'-DBUILD_CURL_EXE=OFF ' . // disable curl.exe '-DBUILD_CURL_EXE=OFF ' . // disable curl.exe
'-DBUILD_TESTING=OFF ' . // disable tests '-DBUILD_TESTING=OFF ' . // disable tests
@@ -41,9 +42,9 @@ class curl extends WindowsLibraryBase
'-DCURL_USE_OPENSSL=OFF ' . // disable openssl due to certificate issue '-DCURL_USE_OPENSSL=OFF ' . // disable openssl due to certificate issue
'-DCURL_ENABLE_SSL=ON ' . '-DCURL_ENABLE_SSL=ON ' .
'-DUSE_NGHTTP2=ON ' . // enable nghttp2 '-DUSE_NGHTTP2=ON ' . // enable nghttp2
'-DSHARE_LIB_OBJECT=OFF ' . // disable shared lib object
'-DCURL_USE_LIBSSH2=ON ' . // enable libssh2 '-DCURL_USE_LIBSSH2=ON ' . // enable libssh2
'-DENABLE_IPV6=ON ' . // enable ipv6 '-DENABLE_IPV6=ON ' . // enable ipv6
'-DNGHTTP2_CFLAGS="/DNGHTTP2_STATICLIB" ' .
$alt $alt
) )
->execWithWrapper( ->execWithWrapper(
@@ -52,7 +53,5 @@ class curl extends WindowsLibraryBase
); );
// move libcurl.lib to libcurl_a.lib // move libcurl.lib to libcurl_a.lib
rename(BUILD_LIB_PATH . '\libcurl.lib', BUILD_LIB_PATH . '\libcurl_a.lib'); rename(BUILD_LIB_PATH . '\libcurl.lib', BUILD_LIB_PATH . '\libcurl_a.lib');
FileSystem::replaceFileStr(BUILD_INCLUDE_PATH . '\curl\curl.h', '#ifdef CURL_STATICLIB', '#if 1');
} }
} }

View File

@@ -29,16 +29,11 @@ class nghttp2 extends WindowsLibraryBase
'-DBUILD_SHARED_LIBS=OFF ' . '-DBUILD_SHARED_LIBS=OFF ' .
'-DENABLE_STATIC_CRT=ON ' . '-DENABLE_STATIC_CRT=ON ' .
'-DENABLE_LIB_ONLY=ON ' . '-DENABLE_LIB_ONLY=ON ' .
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' . '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' '
'-DENABLE_STATIC_CRT=ON ' .
'-DENABLE_DOC=OFF ' .
'-DBUILD_TESTING=OFF '
) )
->execWithWrapper( ->execWithWrapper(
$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}"
); );
FileSystem::replaceFileStr(BUILD_INCLUDE_PATH . '\nghttp2\nghttp2.h', '#ifdef NGHTTP2_STATICLIB', '#if 1');
} }
} }

View File

@@ -33,6 +33,7 @@ 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

@@ -39,6 +39,7 @@ 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

@@ -20,9 +20,9 @@ class SwitchPhpVersionCommand extends BaseCommand
$this->addArgument( $this->addArgument(
'php-major-version', 'php-major-version',
InputArgument::REQUIRED, InputArgument::REQUIRED,
'PHP major version (supported: 7.4, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5)', 'PHP major version (supported: 7.4, 8.0, 8.1, 8.2, 8.3, 8.4)',
null, null,
fn () => ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5'] fn () => ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
); );
$this->no_motd = true; $this->no_motd = true;
@@ -32,7 +32,7 @@ class SwitchPhpVersionCommand extends BaseCommand
public function handle(): int public function handle(): int
{ {
$php_ver = $this->input->getArgument('php-major-version'); $php_ver = $this->input->getArgument('php-major-version');
if (!in_array($php_ver, ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5'])) { if (!in_array($php_ver, ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4'])) {
// match x.y.z // match x.y.z
preg_match('/^\d+\.\d+\.\d+$/', $php_ver, $matches); preg_match('/^\d+\.\d+\.\d+$/', $php_ver, $matches);
if (!$matches) { if (!$matches) {

View File

@@ -22,6 +22,7 @@ class LinuxToolCheckList
'bzip2', 'cmake', 'gcc', 'bzip2', 'cmake', 'gcc',
'g++', 'patch', 'binutils-gold', 'g++', 'patch', 'binutils-gold',
'libtoolize', 'which', 'libtoolize', 'which',
'patchelf',
]; ];
public const TOOLS_DEBIAN = [ public const TOOLS_DEBIAN = [
@@ -30,6 +31,7 @@ class LinuxToolCheckList
'tar', 'unzip', 'gzip', 'gcc', 'g++', 'tar', 'unzip', 'gzip', 'gcc', 'g++',
'bzip2', 'cmake', 'patch', 'bzip2', 'cmake', 'patch',
'xz', 'libtoolize', 'which', 'xz', 'libtoolize', 'which',
'patchelf',
]; ];
public const TOOLS_RHEL = [ public const TOOLS_RHEL = [
@@ -37,7 +39,8 @@ class LinuxToolCheckList
'git', 'autoconf', 'automake', 'git', 'autoconf', 'automake',
'tar', 'unzip', 'gzip', 'gcc', 'g++', 'tar', 'unzip', 'gzip', 'gcc', 'g++',
'bzip2', 'cmake', 'patch', 'which', 'bzip2', 'cmake', 'patch', 'which',
'xz', 'libtool', 'gettext-devel', 'file', 'xz', 'libtool', 'gettext-devel',
'patchelf', 'file',
]; ];
public const TOOLS_ARCH = [ public const TOOLS_ARCH = [

View File

@@ -97,9 +97,8 @@ class Downloader
public static function getLatestGithubTarball(string $name, array $source, string $type = 'releases'): array public static function getLatestGithubTarball(string $name, array $source, string $type = 'releases'): array
{ {
logger()->debug("finding {$name} source from github {$type} tarball"); logger()->debug("finding {$name} source from github {$type} tarball");
$source['query'] ??= '';
$data = json_decode(self::curlExec( $data = json_decode(self::curlExec(
url: "https://api.github.com/repos/{$source['repo']}/{$type}{$source['query']}", url: "https://api.github.com/repos/{$source['repo']}/{$type}",
hooks: [[CurlHook::class, 'setupGithubToken']], hooks: [[CurlHook::class, 'setupGithubToken']],
retries: self::getRetryAttempts() retries: self::getRetryAttempts()
), true, 512, JSON_THROW_ON_ERROR); ), true, 512, JSON_THROW_ON_ERROR);
@@ -109,9 +108,6 @@ class Downloader
if (($rel['prerelease'] ?? false) === true && ($source['prefer-stable'] ?? false)) { if (($rel['prerelease'] ?? false) === true && ($source['prefer-stable'] ?? false)) {
continue; continue;
} }
if (($rel['draft'] ?? false) === true && (($source['prefer-stable'] ?? false) || !$rel['tarball_url'])) {
continue;
}
if (!($source['match'] ?? null)) { if (!($source['match'] ?? null)) {
$url = $rel['tarball_url'] ?? null; $url = $rel['tarball_url'] ?? null;
break; break;

View File

@@ -408,15 +408,15 @@ class FileSystem
continue; continue;
} }
$sub_file = self::convertPath($dir . '/' . $v); $sub_file = self::convertPath($dir . '/' . $v);
if (is_link($sub_file) || is_file($sub_file)) { if (is_dir($sub_file)) {
if (!unlink($sub_file)) {
return false;
}
} elseif (is_dir($sub_file)) {
# 如果是 目录 且 递推 , 则递推添加下级文件 # 如果是 目录 且 递推 , 则递推添加下级文件
if (!self::removeDir($sub_file)) { if (!self::removeDir($sub_file)) {
return false; return false;
} }
} elseif (is_link($sub_file) || is_file($sub_file)) {
if (!unlink($sub_file)) {
return false;
}
} }
} }
if (is_link($dir)) { if (is_link($dir)) {
@@ -572,44 +572,6 @@ class FileSystem
return file_put_contents($file, implode('', $lines)); return file_put_contents($file, implode('', $lines));
} }
/**
* Move file or directory, handling cross-device scenarios
* Uses rename() if possible, falls back to copy+delete for cross-device moves
*
* @param string $source Source path
* @param string $dest Destination path
*/
public static function moveFileOrDir(string $source, string $dest): void
{
$source = self::convertPath($source);
$dest = self::convertPath($dest);
// Check if source and dest are on the same device to avoid cross-device rename errors
$source_stat = @stat($source);
$dest_parent = dirname($dest);
$dest_stat = @stat($dest_parent);
// Only use rename if on same device
if ($source_stat !== false && $dest_stat !== false && $source_stat['dev'] === $dest_stat['dev']) {
if (@rename($source, $dest)) {
return;
}
}
// Fall back to copy + delete for cross-device moves or if rename failed
if (is_dir($source)) {
self::copyDir($source, $dest);
self::removeDir($source);
} else {
if (!copy($source, $dest)) {
throw new FileSystemException("Failed to copy file from {$source} to {$dest}");
}
if (!unlink($source)) {
throw new FileSystemException("Failed to remove source file: {$source}");
}
}
}
private static function extractArchive(string $filename, string $target): void private static function extractArchive(string $filename, string $target): void
{ {
// Create base dir // Create base dir
@@ -686,6 +648,36 @@ class FileSystem
}; };
} }
/**
* Move file or directory, handling cross-device scenarios
* Uses rename() if possible, falls back to copy+delete for cross-device moves
*
* @param string $source Source path
* @param string $dest Destination path
*/
private static function moveFileOrDir(string $source, string $dest): void
{
$source = self::convertPath($source);
$dest = self::convertPath($dest);
// Try rename first (fast, atomic)
if (@rename($source, $dest)) {
return;
}
if (is_dir($source)) {
self::copyDir($source, $dest);
self::removeDir($source);
} else {
if (!copy($source, $dest)) {
throw new FileSystemException("Failed to copy file from {$source} to {$dest}");
}
if (!unlink($source)) {
throw new FileSystemException("Failed to remove source file: {$source}");
}
}
}
/** /**
* Unzip file with stripping top-level directory * Unzip file with stripping top-level directory
*/ */

View File

@@ -22,10 +22,9 @@ class SourcePatcher
FileSystem::addSourceExtractHook('swoole', [__CLASS__, 'patchSwoole']); FileSystem::addSourceExtractHook('swoole', [__CLASS__, 'patchSwoole']);
FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchPhpLibxml212']); FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchPhpLibxml212']);
FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchGDWin32']); FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchGDWin32']);
// FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchFfiCentos7FixO3strncmp']); FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchFfiCentos7FixO3strncmp']);
FileSystem::addSourceExtractHook('sqlsrv', [__CLASS__, 'patchSQLSRVWin32']); FileSystem::addSourceExtractHook('sqlsrv', [__CLASS__, 'patchSQLSRVWin32']);
FileSystem::addSourceExtractHook('pdo_sqlsrv', [__CLASS__, 'patchSQLSRVWin32']); FileSystem::addSourceExtractHook('pdo_sqlsrv', [__CLASS__, 'patchSQLSRVWin32']);
FileSystem::addSourceExtractHook('pdo_sqlsrv', [__CLASS__, 'patchSQLSRVPhp85']);
FileSystem::addSourceExtractHook('yaml', [__CLASS__, 'patchYamlWin32']); FileSystem::addSourceExtractHook('yaml', [__CLASS__, 'patchYamlWin32']);
FileSystem::addSourceExtractHook('libyaml', [__CLASS__, 'patchLibYaml']); FileSystem::addSourceExtractHook('libyaml', [__CLASS__, 'patchLibYaml']);
FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchImapLicense']); FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchImapLicense']);
@@ -433,23 +432,6 @@ class SourcePatcher
return false; return false;
} }
/**
* Fix the compilation issue of pdo_sqlsrv with php 8.5
*/
public static function patchSQLSRVPhp85(): bool
{
$source_dir = SOURCE_PATH . '/php-src/ext/pdo_sqlsrv';
if (!file_exists($source_dir . '/config.m4') && is_dir($source_dir . '/source/pdo_sqlsrv')) {
FileSystem::moveFileOrDir($source_dir . '/LICENSE', $source_dir . '/source/pdo_sqlsrv/LICENSE');
FileSystem::moveFileOrDir($source_dir . '/source/shared', $source_dir . '/source/pdo_sqlsrv/shared');
FileSystem::moveFileOrDir($source_dir . '/source/pdo_sqlsrv', SOURCE_PATH . '/pdo_sqlsrv');
FileSystem::removeDir($source_dir);
FileSystem::moveFileOrDir(SOURCE_PATH . '/pdo_sqlsrv', $source_dir);
return true;
}
return false;
}
public static function patchYamlWin32(): bool public static function patchYamlWin32(): bool
{ {
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/yaml/config.w32', "lib.substr(lib.length - 6, 6) == '_a.lib'", "lib.substr(lib.length - 6, 6) == '_a.lib' || 'yes' == 'yes'"); FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/yaml/config.w32', "lib.substr(lib.length - 6, 6) == '_a.lib'", "lib.substr(lib.length - 6, 6) == '_a.lib' || 'yes' == 'yes'");

View File

@@ -30,8 +30,8 @@ class GoXcaddy extends CustomPackage
public function fetch(string $name, bool $force = false, ?array $config = null): void public function fetch(string $name, bool $force = false, ?array $config = null): void
{ {
$pkgroot = PKG_ROOT_PATH; $pkgroot = PKG_ROOT_PATH;
$go_exec = "{$pkgroot}/go-xcaddy/bin/go"; $go_exec = "{$pkgroot}/{$name}/bin/go";
$xcaddy_exec = "{$pkgroot}/go-xcaddy/bin/xcaddy"; $xcaddy_exec = "{$pkgroot}/{$name}/bin/xcaddy";
if ($force) { if ($force) {
FileSystem::removeDir("{$pkgroot}/{$name}"); FileSystem::removeDir("{$pkgroot}/{$name}");
} }
@@ -48,10 +48,10 @@ class GoXcaddy extends CustomPackage
'macos' => 'darwin', 'macos' => 'darwin',
default => throw new \InvalidArgumentException('Unsupported OS: ' . $name), default => throw new \InvalidArgumentException('Unsupported OS: ' . $name),
}; };
[$go_version] = explode("\n", Downloader::curlExec('https://go.dev/VERSION?m=text')); $go_version = '1.25.0';
$config = [ $config = [
'type' => 'url', 'type' => 'url',
'url' => "https://go.dev/dl/{$go_version}.{$os}-{$arch}.tar.gz", 'url' => "https://go.dev/dl/go{$go_version}.{$os}-{$arch}.tar.gz",
]; ];
Downloader::downloadPackage($name, $config, $force); Downloader::downloadPackage($name, $config, $force);
} }

View File

@@ -72,11 +72,8 @@ class Zig extends CustomPackage
$latest_version = null; $latest_version = null;
foreach ($index_json as $version => $data) { foreach ($index_json as $version => $data) {
// Skip the master branch, get the latest stable release $latest_version = $version;
if ($version !== 'master') { break;
$latest_version = $version;
break;
}
} }
if (!$latest_version) { if (!$latest_version) {

View File

@@ -6,17 +6,11 @@ namespace SPC\store\source;
use JetBrains\PhpStorm\ArrayShape; use JetBrains\PhpStorm\ArrayShape;
use SPC\exception\DownloaderException; use SPC\exception\DownloaderException;
use SPC\exception\SPCException;
use SPC\store\Downloader; use SPC\store\Downloader;
class PhpSource extends CustomSourceBase class PhpSource extends CustomSourceBase
{ {
public const string NAME = 'php-src'; public const NAME = 'php-src';
public const array WEB_PHP_DOMAINS = [
'https://www.php.net',
'https://phpmirror.static-php.dev',
];
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
{ {
@@ -34,26 +28,21 @@ class PhpSource extends CustomSourceBase
#[ArrayShape(['type' => 'string', 'path' => 'string', 'rev' => 'string', 'url' => 'string'])] #[ArrayShape(['type' => 'string', 'path' => 'string', 'rev' => 'string', 'url' => 'string'])]
public function getLatestPHPInfo(string $major_version): array public function getLatestPHPInfo(string $major_version): array
{ {
foreach (self::WEB_PHP_DOMAINS as $domain) { // 查找最新的小版本号
try { $info = json_decode(Downloader::curlExec(
$info = json_decode(Downloader::curlExec( url: "https://www.php.net/releases/index.php?json&version={$major_version}",
url: "{$domain}/releases/index.php?json&version={$major_version}", retries: (int) getenv('SPC_DOWNLOAD_RETRIES') ?: 0
retries: (int) getenv('SPC_DOWNLOAD_RETRIES') ?: 0 ), true);
), true); if (!isset($info['version'])) {
if (!isset($info['version'])) { throw new DownloaderException("Version {$major_version} not found.");
throw new DownloaderException("Version {$major_version} not found.");
}
$version = $info['version'];
return [
'type' => 'url',
'url' => "{$domain}/distributions/php-{$version}.tar.xz",
];
} catch (SPCException) {
logger()->warning('Failed to fetch latest PHP version for major version {$major_version} from {$domain}, trying next mirror if available.');
continue;
}
} }
// exception if all mirrors failed
throw new DownloaderException("Failed to fetch latest PHP version for major version {$major_version} from all tried mirrors."); $version = $info['version'];
// 从官网直接下载
return [
'type' => 'url',
'url' => "https://www.php.net/distributions/php-{$version}.tar.xz",
];
} }
} }

View File

@@ -58,10 +58,6 @@ 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
@@ -71,8 +67,7 @@ class ZigToolchain implements ToolchainInterface
$cflags = getenv('SPC_DEFAULT_C_FLAGS') ?: getenv('CFLAGS') ?: ''; $cflags = getenv('SPC_DEFAULT_C_FLAGS') ?: getenv('CFLAGS') ?: '';
$has_avx512 = str_contains($cflags, '-mavx512') || str_contains($cflags, '-march=x86-64-v4'); $has_avx512 = str_contains($cflags, '-mavx512') || str_contains($cflags, '-march=x86-64-v4');
if (!$has_avx512) { if (!$has_avx512) {
$extra_vars = getenv('SPC_EXTRA_PHP_VARS') ?: ''; GlobalEnvManager::putenv('SPC_EXTRA_PHP_VARS=php_cv_have_avx512=no php_cv_have_avx512vbmi=no');
GlobalEnvManager::putenv("SPC_EXTRA_PHP_VARS=php_cv_have_avx512=no php_cv_have_avx512vbmi=no {$extra_vars}");
} }
} }

View File

@@ -38,13 +38,6 @@ 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 $extra = '--static'): string public static function getCflags(string $pkg_config_str): string
{ {
// get other things // get other things
$result = self::execWithResult("pkg-config {$extra} --cflags-only-other {$pkg_config_str}"); $result = self::execWithResult("pkg-config --static --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, string $extra = '--static'): array public static function getLibsArray(string $pkg_config_str): array
{ {
// Use this instead of shell() to avoid unnecessary outputs // Use this instead of shell() to avoid unnecessary outputs
$result = self::execWithResult("pkg-config {$extra} --libs-only-l {$pkg_config_str}"); $result = self::execWithResult("pkg-config --static --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 {$extra} --libs-only-other {$pkg_config_str}"); $result = self::execWithResult("pkg-config --static --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,10 +20,13 @@ 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 = [])
@@ -33,6 +36,7 @@ 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;
} }
/** /**
@@ -73,9 +77,10 @@ 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); $libs = $this->getLibsString($libraries, !$this->absolute_libs);
// additional OS-specific libraries (e.g. macOS -lresolv) // additional OS-specific libraries (e.g. macOS -lresolv)
// embed
if ($extra_libs = SPCTarget::getRuntimeLibs()) { if ($extra_libs = SPCTarget::getRuntimeLibs()) {
$libs .= " {$extra_libs}"; $libs .= " {$extra_libs}";
} }
@@ -221,22 +226,13 @@ class SPCConfigUtil
// parse pkg-configs // parse pkg-configs
foreach ($libraries as $library) { foreach ($libraries as $library) {
$pc = Config::getLib($library, 'pkg-configs', []); $pc = Config::getLib($library, 'pkg-configs', []);
$pkg_config_path = getenv('PKG_CONFIG_PATH') ?: '';
$search_paths = array_filter(explode(is_unix() ? ':' : ';', $pkg_config_path));
foreach ($pc as $file) { foreach ($pc as $file) {
$found = false; if (!file_exists(BUILD_LIB_PATH . "/pkgconfig/{$file}.pc")) {
foreach ($search_paths as $path) { throw new WrongUsageException("pkg-config file '{$file}.pc' for lib [{$library}] does not exist in '" . BUILD_LIB_PATH . "/pkgconfig'. Please build it first.");
if (file_exists($path . "/{$file}.pc")) {
$found = true;
}
}
if (!$found) {
throw new WrongUsageException("pkg-config file '{$file}.pc' for lib [{$library}] does not exist. Please build it first.");
} }
} }
$pc_cflags = implode(' ', $pc); $pc_cflags = implode(' ', $pc);
$static = getenv('SPC_LINK_STATIC') ? '--static' : ''; if ($pc_cflags !== '' && ($pc_cflags = PkgConfigUtil::getCflags($pc_cflags)) !== '') {
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_'));
@@ -253,7 +249,7 @@ class SPCConfigUtil
return '-L' . BUILD_LIB_PATH; return '-L' . BUILD_LIB_PATH;
} }
private function getLibsString(array $libraries): string private function getLibsString(array $libraries, bool $use_short_libs = true): string
{ {
$lib_names = []; $lib_names = [];
$frameworks = []; $frameworks = [];
@@ -261,35 +257,22 @@ 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; foreach ($pkg_configs as $pkg_config) {
if (!$static) { if (!file_exists(BUILD_LIB_PATH . "/pkgconfig/{$pkg_config}.pc")) {
$target = Config::getLib($library, 'target'); throw new WrongUsageException("pkg-config file '{$pkg_config}.pc' for lib [{$library}] does not exist in '" . BUILD_LIB_PATH . "/pkgconfig'. Please build it first.");
$static = $target && !in_array('shared', $target) ? '--static' : '';
}
$pkg_config_path = getenv('PKG_CONFIG_PATH') ?: '';
$search_paths = array_filter(explode(is_unix() ? ':' : ';', $pkg_config_path));
foreach ($pkg_configs as $file) {
$found = false;
foreach ($search_paths as $path) {
if (file_exists($path . "/{$file}.pc")) {
$found = true;
}
}
if (!$found) {
throw new WrongUsageException("pkg-config file '{$file}.pc' for lib [{$library}] does not exist. Please build it first.");
} }
} }
$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($static, $pkg_configs)); $pc_libs = array_reverse(PkgConfigUtil::getLibsArray($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}") && getenv('SPC_LINK_STATIC')) { if (!file_exists(BUILD_LIB_PATH . "/{$lib}")) {
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);
@@ -318,8 +301,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 (getenv('SPC_LINK_STATIC')) { if (!$use_short_libs) {
$lib_names = array_map(fn ($l) => $this->getStaticLibname($l), $lib_names); $lib_names = array_map(fn ($l) => $this->getFullLibName($l), $lib_names);
} }
return implode(' ', $lib_names); return implode(' ', $lib_names);
} }
@@ -333,7 +316,7 @@ class SPCConfigUtil
return '-l' . substr($lib, 3, -2); return '-l' . substr($lib, 3, -2);
} }
private function getStaticLibname(string $lib) private function getFullLibName(string $lib)
{ {
if (!str_starts_with($lib, '-l')) { if (!str_starts_with($lib, '-l')) {
return $lib; return $lib;
@@ -341,7 +324,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 "-l:lib{$libname}.a"; return $staticLib;
} }
return $lib; return $lib;
} }

View File

@@ -27,10 +27,10 @@ class SPCTarget
return true; return true;
} }
if (ToolchainManager::getToolchainClass() === GccNativeToolchain::class) { if (ToolchainManager::getToolchainClass() === GccNativeToolchain::class) {
return PHP_OS_FAMILY === 'Linux' && SystemUtil::isMuslDist() && !getenv('SPC_MUSL_DYNAMIC'); return PHP_OS_FAMILY === 'Linux' && SystemUtil::isMuslDist();
} }
if (ToolchainManager::getToolchainClass() === ClangNativeToolchain::class) { if (ToolchainManager::getToolchainClass() === ClangNativeToolchain::class) {
return PHP_OS_FAMILY === 'Linux' && SystemUtil::isMuslDist() && !getenv('SPC_MUSL_DYNAMIC'); return PHP_OS_FAMILY === 'Linux' && SystemUtil::isMuslDist();
} }
// if SPC_LIBC is set, it means the target is static, remove it when 3.0 is released // if SPC_LIBC is set, it means the target is static, remove it when 3.0 is released
if ($target = getenv('SPC_TARGET')) { if ($target = getenv('SPC_TARGET')) {

View File

@@ -16,11 +16,12 @@ class UnixAutoconfExecutor extends Executor
protected array $configure_args = []; protected array $configure_args = [];
protected array $ignore_args = [];
public function __construct(protected BSDLibraryBase|LinuxLibraryBase|MacOSLibraryBase $library) public function __construct(protected BSDLibraryBase|LinuxLibraryBase|MacOSLibraryBase $library)
{ {
parent::__construct($library); parent::__construct($library);
$this->initShell(); $this->initShell();
$this->configure_args = $this->getDefaultConfigureArgs();
} }
/** /**
@@ -28,12 +29,19 @@ class UnixAutoconfExecutor extends Executor
*/ */
public function configure(...$args): static public function configure(...$args): static
{ {
$args = array_merge($args, $this->configure_args); // remove all the ignored args
$args = array_merge($args, $this->getDefaultConfigureArgs(), $this->configure_args);
$args = array_diff($args, $this->ignore_args);
$configure_args = implode(' ', $args); $configure_args = implode(' ', $args);
return $this->seekLogFileOnException(fn () => $this->shell->exec("./configure {$configure_args}")); return $this->seekLogFileOnException(fn () => $this->shell->exec("./configure {$configure_args}"));
} }
public function getConfigureArgsString(): string
{
return implode(' ', array_merge($this->getDefaultConfigureArgs(), $this->configure_args));
}
/** /**
* Run make * Run make
* *
@@ -103,7 +111,7 @@ class UnixAutoconfExecutor extends Executor
*/ */
public function removeConfigureArgs(...$args): static public function removeConfigureArgs(...$args): static
{ {
$this->configure_args = array_diff($this->configure_args, $args); $this->ignore_args = [...$this->ignore_args, ...$args];
return $this; return $this;
} }
@@ -125,8 +133,8 @@ class UnixAutoconfExecutor extends Executor
private function getDefaultConfigureArgs(): array private function getDefaultConfigureArgs(): array
{ {
return [ return [
'--disable-shared',
'--enable-static', '--enable-static',
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=' . (getenv('SPC_LINK_STATIC') ? 'OFF' : 'ON'), '-DBUILD_SHARED_LIBS=OFF',
"-DCMAKE_TOOLCHAIN_FILE={$this->makeCmakeToolchainFile()}", "-DCMAKE_TOOLCHAIN_FILE={$this->makeCmakeToolchainFile()}",
]); ]);
} }

View File

@@ -13,19 +13,19 @@ 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',
]; ];
// test os (macos-15-intel, macos-15, ubuntu-latest, windows-latest are available) // test os (macos-15-intel, macos-15, ubuntu-latest, windows-latest are available)
$test_os = [ $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
@@ -35,7 +35,7 @@ $test_os = [
]; ];
// whether enable thread safe // whether enable thread safe
$zts = true; $zts = false;
$no_strip = false; $no_strip = false;
@@ -50,8 +50,8 @@ $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' => 'maxminddb',
'Windows' => 'com_dotnet', 'Windows' => 'bcmath',
}; };
// 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`).