Compare commits

...

91 Commits
2.7.4 ... 2.7.5

Author SHA1 Message Date
Jerry Ma
c5ae719b9c Update src/SPC/builder/unix/library/postgresql.php
Co-authored-by: Marc <m@pyc.ac>
2025-10-14 00:08:40 +08:00
crazywhalecc
7b6e707e24 Remove unnecessary macOS 15 bug CFLAGS from PostgreSQL build configuration 2025-10-14 00:08:40 +08:00
crazywhalecc
0114700dad Fix PostgreSQL build compatibility for aarch64 on glibc 2.17 and update test configurations 2025-10-14 00:08:40 +08:00
Marc
ec9364db69 use latest zip version for building shared (#917) 2025-10-13 11:28:16 +02:00
Marc
033e29985e Merge branch 'main' into feature/shared-exts 2025-10-13 11:20:54 +02:00
Marc
61cba2342d Drop macos-13 from actions runner (#922) 2025-10-13 11:20:37 +02:00
Marc
a3acad4ef3 Update config/source.json 2025-10-13 10:59:31 +02:00
Marc
1e13eb4abe Merge branch 'main' into ci/macos-15-intel 2025-10-13 10:38:48 +02:00
Jerry Ma
1bac06fe3c Remove more macOS 14 case from shared extensions switch
Yeah. Copied by tab.
2025-10-13 08:27:40 +08:00
Marc
762a768969 Merge branch 'main' into feature/shared-exts 2025-10-12 23:23:25 +02:00
Marc
d0a6e3a860 update pgsql version to 18.0, php 8.5 to RC2 (#916) 2025-10-12 22:59:09 +02:00
henderkes
995187d258 extra information for steps 2025-10-12 22:32:27 +02:00
henderkes
5333a04e1c clarification 2025-10-12 22:27:38 +02:00
henderkes
19be5263b5 add error 2025-10-12 22:26:06 +02:00
crazywhalecc
6e79401ab5 Add missing libs for suggested option defined 2025-10-13 00:21:13 +08:00
crazywhalecc
903036f1c0 Bump version 2025-10-13 00:00:31 +08:00
crazywhalecc
6bd3eea0fe Use SPCConfigUtil for postgresql build, refactor patches 2025-10-12 23:54:59 +08:00
crazywhalecc
f28a3cf5a3 Drop macos-13 from actions runner 2025-10-12 22:33:22 +08:00
Marc
c828c2c6e4 Merge branch 'main' into feature/shared-exts 2025-10-12 11:35:57 +02:00
Marc
ae1193ab16 Merge branch 'main' into pgsql-18 2025-10-12 11:28:49 +02:00
Marc
6d6a29368e fix building of shared extensions (grpc, simdjson, soap) (#905) 2025-10-12 11:24:32 +02:00
crazywhalecc
897cb00351 Use failsafe for SPC_EXTRA_PHP_VARS 2025-10-12 16:42:38 +08:00
henderkes
8a1689b79d don't fail build without ldap 2025-10-11 13:20:20 +02:00
henderkes
018dfae15e suggestions 2025-10-11 10:38:51 +02:00
Marc
c83e803c85 Merge branch 'main' into pgsql-18 2025-10-10 18:47:48 +02:00
henderkes
fa4d33671d update to RC2 2025-10-10 18:35:15 +02:00
Marc
e6408b4693 Fix static linux cli -a not working issue (#893) 2025-10-08 11:37:27 +02:00
henderkes
3467c9d291 patch correct file 2025-10-06 22:53:41 +02:00
henderkes
15cd8543f1 arm64 fix 2025-10-06 22:50:37 +02:00
henderkes
864db0ebc5 fix macos finally I hope 2025-10-06 22:49:28 +02:00
henderkes
9ee623112d attempt to fix macOS? 2025-10-06 22:43:03 +02:00
henderkes
d789b1a472 fix musl toolchain (needs LD_LIBRARY_PATH) 2025-10-06 22:31:23 +02:00
henderkes
17a25b44e2 attempt fix for aarch64 #2 2025-10-06 22:26:00 +02:00
henderkes
781260f3fc attempt fix for aarch64 2025-10-06 22:11:17 +02:00
henderkes
6c43fa55b1 don't use -static, shared libraries cannot link against static musl libc and linking isn't done for static libraries yet 2025-10-06 21:37:36 +02:00
henderkes
c4440668bb make sure -DFRONTEND is used 2025-10-06 21:28:57 +02:00
henderkes
e437bf2ffe don't test macos 13 2025-10-06 21:05:05 +02:00
henderkes
0f2d2d5734 test pgsql without macos 13 2025-10-06 21:03:57 +02:00
henderkes
a49ae05599 use latest zip version for building shared 2025-10-06 21:00:45 +02:00
henderkes
8ae2755dbe update php 8.5 to rc1 2025-10-06 20:14:52 +02:00
henderkes
3966bd5f0a update pgsql version to 18.0 2025-10-06 20:06:37 +02:00
Marc
384ba54c79 update extension count (#914) 2025-10-04 08:56:30 +02:00
Marc
26dbc922eb update extension count
we now sit at 101 🎉
2025-10-04 08:39:45 +02:00
henderkes
31a4498056 bring back simdjson tests, extension headers do not properly guard for avx512 symbols 2025-09-30 15:07:22 +02:00
henderkes
044275d909 typo 2025-09-30 14:22:38 +02:00
henderkes
c5316f9231 -v3 doesn't have avx512 yet 2025-09-30 14:21:31 +02:00
henderkes
2d1a61d184 explicitly disable avx512 if zig and march not high enough 2025-09-30 14:00:13 +02:00
henderkes
f7744188f4 fix configutil 2025-09-30 00:34:30 +02:00
henderkes
5b6c923eef snappy is a c++ lib 2025-09-30 00:31:20 +02:00
henderkes
b0b031afb2 add docstring 2025-09-30 00:18:32 +02:00
henderkes
fe09d8c03e add docstring 2025-09-30 00:17:53 +02:00
henderkes
c2813d5736 move hasCpp to SPCConfigUtil 2025-09-30 00:12:59 +02:00
Marc
8b2b658ced Merge branch 'main' into fix/grpc-shared 2025-09-29 23:27:58 +02:00
henderkes
e862bacc8a php 8.5 has beta 3 2025-09-29 21:15:56 +02:00
henderkes
cac57dbf79 php 8.5 has beta 3 2025-09-29 21:15:18 +02:00
crazywhalecc
345fe783cc Add version table in docs 2025-09-24 15:46:54 +08:00
crazywhalecc
55efe6d65b Add gnu-bulk 2025-09-24 15:46:54 +08:00
crazywhalecc
dccbc30972 update README 2025-09-24 15:46:54 +08:00
crazywhalecc
f914a82379 Add PHP version, remove duplicate desc 2025-09-24 15:46:54 +08:00
crazywhalecc
18979d8fb6 Simplify README 2025-09-24 15:46:54 +08:00
henderkes
21149f6807 simdjson needs patch 2025-09-23 12:42:29 +02:00
henderkes
93e6dcab1d cflags and cxxflags separately 2025-09-23 12:01:09 +02:00
henderkes
59dedbea2c simdjson requires +evex512 (for zig-cc) 2025-09-23 12:00:15 +02:00
henderkes
8bda4fd31e simdjson requires +evex512 2025-09-23 11:59:30 +02:00
henderkes
8039ea49f9 soap requires libxml and session 2025-09-23 11:56:12 +02:00
henderkes
fc90b4ae23 allow appending pkg_config_path #910 2025-09-22 13:10:48 +02:00
henderkes
e02be69e40 update grpc from 1.68.x to 1.75.x 2025-09-21 21:01:07 +02:00
henderkes
35a90f2769 skip -mcpu or -march=armv8-... flags because zig doesn't support them (stupid grpc build thirdparty hardcode) 2025-09-21 20:32:47 +02:00
henderkes
fa87149631 shallow submodules as well (grpc download goes from 2.9 gb to 900mb) 2025-09-21 19:59:24 +02:00
Marc
8dfe722e14 Merge branch 'main' into fix/grpc-shared 2025-09-19 15:31:25 +02:00
henderkes
dcbfe1e0ab e-dant/watcher is a c++ library too 2025-09-19 15:29:49 +02:00
Marc
e11946fd10 also install g++ with doctor (not preinstalled on ubuntu, not include… (#904) 2025-09-19 15:22:17 +02:00
henderkes
44399cd185 remove -Wl,--as-needed for imagemagick build 2025-09-19 09:21:17 +02:00
henderkes
927d7f55ba make sure -ldl is not taken as needed, problem on EL8 2025-09-18 22:47:01 +02:00
henderkes
e323d7b155 revert to private 2025-09-18 21:41:35 +02:00
henderkes
d0b253c346 not required 2025-09-18 21:36:38 +02:00
henderkes
81430e6853 also use libstdc++.a for grpc? 2025-09-18 21:29:46 +02:00
henderkes
83696e92b7 remove whitespace 2025-09-18 20:12:41 +02:00
henderkes
b0538c09bf deduplicate those to make it more readable 2025-09-18 20:09:17 +02:00
henderkes
40f89d1dca is shared_libadd enough? 2025-09-18 19:44:48 +02:00
henderkes
fa2e041cc9 test shared grpc, imagick 2025-09-18 19:01:10 +02:00
Marc
3c614663a3 Merge branch 'main' into fix/grpc-shared 2025-09-18 18:22:42 +02:00
henderkes
b5c7185374 add comment for new method 2025-09-18 18:20:26 +02:00
henderkes
d0a9a3a594 fix return of array 2025-09-18 18:17:48 +02:00
henderkes
2e6329bb86 add cpp-library for imagemagick too 2025-09-18 18:16:42 +02:00
henderkes
d3ba04fc5b fix grpc shared build (ignores CXXFLAGS, needs CPPFLAGS) 2025-09-18 18:16:41 +02:00
Marc
7a78ea0185 Merge branch 'main' into fix/g++ 2025-09-18 17:35:44 +02:00
henderkes
36b04f9eba also install g++ with doctor (not preinstalled on ubuntu, not included in gcc package) 2025-09-18 17:24:08 +02:00
crazywhalecc
be7c002869 Patch only when building cli 2025-09-07 16:10:50 +08:00
crazywhalecc
e621e4a5a1 test 2025-09-07 15:38:38 +08:00
crazywhalecc
bd815d4ea2 Fix static linux cli -a not working issue 2025-09-07 14:10:28 +08:00
34 changed files with 558 additions and 736 deletions

View File

@@ -136,12 +136,12 @@ jobs:
macos-x86_64) macos-x86_64)
DOWN_CMD="composer update --no-dev --classmap-authoritative && ./bin/spc doctor --auto-fix && ./bin/spc download" DOWN_CMD="composer update --no-dev --classmap-authoritative && ./bin/spc doctor --auto-fix && ./bin/spc download"
BUILD_CMD="./bin/spc build" BUILD_CMD="./bin/spc build"
RUNS_ON="macos-13" RUNS_ON="macos-15-intel"
;; ;;
macos-aarch64) macos-aarch64)
DOWN_CMD="composer update --no-dev --classmap-authoritative && ./bin/spc doctor --auto-fix && ./bin/spc download" DOWN_CMD="composer update --no-dev --classmap-authoritative && ./bin/spc doctor --auto-fix && ./bin/spc download"
BUILD_CMD="./bin/spc build" BUILD_CMD="./bin/spc build"
RUNS_ON="macos-14" RUNS_ON="macos-15"
;; ;;
esac esac
DOWN_CMD="$DOWN_CMD --with-php=${{ inputs.php-version }} --for-extensions=${{ inputs.extensions }} --ignore-cache-sources=php-src" DOWN_CMD="$DOWN_CMD --with-php=${{ inputs.php-version }} --for-extensions=${{ inputs.extensions }} --ignore-cache-sources=php-src"

View File

@@ -85,9 +85,9 @@ jobs:
- "8.4" - "8.4"
operating-system: operating-system:
- "ubuntu-latest" - "ubuntu-latest"
#- "macos-13" #- "macos-15-intel"
#- "debian-arm64-self-hosted" #- "debian-arm64-self-hosted"
- "macos-14" - "macos-15"
steps: steps:
- name: "Checkout" - name: "Checkout"
@@ -99,11 +99,11 @@ jobs:
OS="" OS=""
if [ "${{ matrix.operating-system }}" = "ubuntu-latest" ]; then if [ "${{ matrix.operating-system }}" = "ubuntu-latest" ]; then
OS="linux-x86_64" OS="linux-x86_64"
elif [ "${{ matrix.operating-system }}" = "macos-13" ]; then elif [ "${{ matrix.operating-system }}" = "macos-15-intel" ]; then
OS="macos-x86_64" OS="macos-x86_64"
elif [ "${{ matrix.operating-system }}" = "debian-arm64-self-hosted" ]; then elif [ "${{ matrix.operating-system }}" = "debian-arm64-self-hosted" ]; then
OS="linux-aarch64" OS="linux-aarch64"
elif [ "${{ matrix.operating-system }}" = "macos-14" ]; then elif [ "${{ matrix.operating-system }}" = "macos-15" ]; then
OS="macos-aarch64" OS="macos-aarch64"
fi fi
echo "OS=$OS" >> $GITHUB_ENV echo "OS=$OS" >> $GITHUB_ENV

View File

@@ -27,7 +27,7 @@ jobs:
os: "ubuntu-latest" os: "ubuntu-latest"
filename: "spc-linux-x86_64.tar.gz" filename: "spc-linux-x86_64.tar.gz"
- name: "macos-x86_64" - name: "macos-x86_64"
os: "macos-13" os: "macos-15-intel"
filename: "spc-macos-x86_64.tar.gz" filename: "spc-macos-x86_64.tar.gz"
- name: "linux-aarch64" - name: "linux-aarch64"
os: "ubuntu-latest" os: "ubuntu-latest"
@@ -147,11 +147,11 @@ jobs:
- name: "linux-x86_64" - name: "linux-x86_64"
os: "ubuntu-latest" os: "ubuntu-latest"
- name: "macos-x86_64" - name: "macos-x86_64"
os: "macos-13" os: "macos-15-intel"
- name: "linux-aarch64" - name: "linux-aarch64"
os: "ubuntu-24.04-arm" os: "ubuntu-24.04-arm"
- name: "macos-aarch64" - name: "macos-aarch64"
os: "macos-latest" os: "macos-15"
- name: "windows-x64" - name: "windows-x64"
os: "windows-latest" os: "windows-latest"
steps: steps:

View File

@@ -5,310 +5,168 @@
[![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)
[![Extensions](https://img.shields.io/badge/Extension%20Counter-75+-yellow.svg?style=flat-square)](https://static-php.dev/zh/guide/extensions.html)
**static-php-cli**是一个用于静态编译、构建 PHP 解释器的工具,支持众多流行扩展。 **static-php-cli** 是一个用于构建静态、独立 PHP 运行时的强大工具,支持众多流行扩展。
目前 static-php-cli 支持 `cli``fpm``embed``micro``frankenphp` SAPI。
**static-php-cli**也支持将 PHP 代码和 PHP 运行时打包为一个文件并运行。
## 特性 ## 特性
static-php-cli简称 `spc`)有许多特性: - :elephant: **支持多 PHP 版本** - 支持 PHP 8.1, 8.2, 8.3, 8.4, 8.5
- :handbag: **单文件 PHP 可执行文件** - 构建零依赖的独立 PHP
- :hamburger: **phpmicro 集成** - 构建 **[phpmicro](https://github.com/dixyes/phpmicro)** 自解压可执行文件(将 PHP 二进制文件和源代码合并为一个文件)
- :pill: **智能环境检查器** - 自动构建环境检查器,具备自动修复功能
- :zap: **跨平台支持** - 支持 Linux、macOS、FreeBSD 和 Windows
- :wrench: **可配置补丁** - 可自定义的源代码补丁系统
- :books: **智能依赖管理** - 自动处理构建依赖
- 📦 **自包含工具** - 提供使用 [box](https://github.com/box-project/box) 构建的 `spc` 可执行文件
- :fire: **广泛的扩展支持** - 支持 75+ 流行 [扩展](https://static-php.dev/zh/guide/extensions.html)
- :floppy_disk: **UPX 压缩** - 减小二进制文件大小 30-50%(仅 Linux/Windows
- :handbag: 构建独立的单文件 PHP 解释器,无需任何依赖 **单文件独立 php-cli**
- :hamburger: 构建 **[phpmicro](https://github.com/dixyes/phpmicro)** 自执行二进制(将 PHP 代码和 PHP 解释器打包为一个文件)
- :pill: 提供一键检查和修复编译环境的 Doctor 模块
- :zap: 支持多个系统:`Linux``macOS``FreeBSD``Windows`
- :wrench: 高度自定义的代码 patch 功能
- :books: 自带编译依赖管理
- 📦 提供由自身编译的独立 `spc` 二进制(使用 spc 和 [box](https://github.com/box-project/box) 构建)
- :fire: 支持大量 [扩展](https://static-php.dev/zh/guide/extensions.html)
- :floppy_disk: 整合 UPX 工具(减小二进制文件体积)
**静态 php-cli:**
<img width="700" alt="out1" src="https://github.com/crazywhalecc/static-php-cli/assets/20330940/01a2e60f-13b0-4242-a645-f7afa4936396"> <img width="700" alt="out1" src="https://github.com/crazywhalecc/static-php-cli/assets/20330940/01a2e60f-13b0-4242-a645-f7afa4936396">
**使用 phpmicro 打包 PHP 代码:** **使用 phpmicro PHP 代码与 PHP 解释器结合:**
<img width="700" alt="out2" src="https://github.com/crazywhalecc/static-php-cli/assets/20330940/46b7128d-fb72-4169-957e-48564c3ff3e2"> <img width="700" alt="out2" src="https://github.com/crazywhalecc/static-php-cli/assets/20330940/46b7128d-fb72-4169-957e-48564c3ff3e2">
## 文档 ## 快速开始
目前 README 编写了基本用法。有关 static-php-cli 所有的功能,请点击这里查看文档:<https://static-php.dev>。 ### 1. 下载 spc 二进制文件
## 直接下载
如果你不想自行编译 PHP可以从本项目现有的示例 Action 下载 Artifact也可以从自托管的服务器下载。
| 组合名称 | 组合扩展数 | 系统 | 备注 |
|---------------------------------------------------------------------|----------------------------------------------------------------------------|-------------|--------------|
| [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 左右 |
| [minimal](https://dl.static-php.dev/static-php-cli/minimal/) | [5](https://dl.static-php.dev/static-php-cli/minimal/README.txt) | Linux/macOS | 体积为 3MB 左右 |
| [spc-min](https://dl.static-php.dev/static-php-cli/windows/spc-min) | [5](https://dl.static-php.dev/static-php-cli/windows/spc-min/README.txt) | Windows | 体积为 3MB 左右 |
| [spc-max](https://dl.static-php.dev/static-php-cli/windows/spc-max) | [40+](https://dl.static-php.dev/static-php-cli/windows/spc-max/README.txt) | Windows | 体积为 8.5MB 左右 |
> Linux 和 Windows 默认启用了 UPX 压缩,可减小 30~50% 的 PHP 二进制体积。
> macOS 当前不支持 UPX所以上述预编译的 macOS 版本体积可能较大。
## 使用 static-php-cli 构建 PHP
### 编译环境需求
- PHP >= 8.4(这是 spc 自身需要的版本,不是支持的构建版本)
- 扩展:`mbstring,tokenizer,phar`
- 系统安装了 `curl``git`
是的,本项目采用 PHP 编写,编译前需要一个 PHP 环境,比较滑稽。
但本项目默认可通过自身构建的 micro 和 static-php 二进制运行,其他只需要包含上面提到的扩展和 PHP 版本大于等于 8.1 即可。
下面是架构支持情况,:octocat: 代表支持 GitHub Action 构建,:computer: 代表支持本地构建,空 代表暂不支持。
| | x86_64 | aarch64 |
|---------|----------------------|----------------------|
| macOS | :octocat: :computer: | :octocat: :computer: |
| Linux | :octocat: :computer: | :octocat: :computer: |
| Windows | :octocat: :computer: | |
| FreeBSD | :computer: | :computer: |
当前支持编译的 PHP 版本:
> :warning: 部分支持,对于新的测试版和旧版本可能存在问题。
>
> :heavy_check_mark: 支持
>
> :x: 不支持
| PHP Version | Status | Comment |
|-------------|--------------------|---------------------------------------------------------|
| 7.2 | :x: | |
| 7.3 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
| 7.4 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
| 8.0 | :warning: | PHP 官方已停止 8.0 的维护,我们不再处理 8.0 相关的 backport 支持 |
| 8.1 | :heavy_check_mark: | PHP 官方仅对 8.1 提供安全更新,在 8.5 发布后我们不再处理 8.1 相关的 backport 支持 |
| 8.2 | :heavy_check_mark: | |
| 8.3 | :heavy_check_mark: | |
| 8.4 | :heavy_check_mark: | |
| 8.5 (alpha) | :warning: | PHP 8.5 目前处于 alpha 阶段 |
> 这个表格的支持状态是 static-php-cli 对构建对应版本的支持情况,不是 PHP 官方对该版本的支持情况。
### 支持的扩展
请先根据下方扩展列表选择你要编译的扩展。
- [扩展支持列表](https://static-php.dev/zh/guide/extensions.html)
- [编译命令生成器](https://static-php.dev/zh/guide/cli-generator.html)
> 如果这里没有你需要的扩展,可以提交 Issue。
### 在线构建(使用 GitHub Actions
使用 GitHub Action 可以方便地构建一个静态编译的 PHP同时可以自行定义要编译的扩展。
1. Fork 本项目。
2. 进入项目的 Actions选择 CI。
3. 选择 `Run workflow`,填入你要编译的 PHP 版本、目标类型、扩展列表。(扩展列表使用英文逗号分割,例如 `bcmath,curl,mbstring`
4. 等待大约一段时间后,进入对应的任务中,获取 `Artifacts`
如果你选择了 `debug`,则会在构建时输出所有日志,包括编译的日志,以供排查错误。
### 本地构建(使用 spc 二进制,推荐)
该项目提供了 static-php-cli 的二进制文件:`spc`
您可以使用 `spc` 二进制文件,无需安装任何运行时(用起来就像 golang 程序)。
目前,`spc` 二进制文件提供的平台有 Linux 和 macOS。
使用以下命令从自托管服务器下载:
```bash ```bash
# Download from self-hosted nightly builds (sync with main branch) # 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
# For Linux aarch64 # Linux aarch64
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-aarch64 curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-aarch64
# macOS x86_64 (Intel) # macOS x86_64 (Intel)
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-x86_64 curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-x86_64
# macOS aarch64 (Apple) # macOS aarch64 (Apple)
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-aarch64 curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-aarch64
# Windows (x86_64, win10 build 17063 or later) # Windows (x86_64, win10 build 17063 或更高版本,请先安装 VS2022)
curl.exe -fsSL -o spc.exe https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe curl.exe -fsSL -o spc.exe https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe
```
# Add execute perm (Linux and macOS only) 对于 macOS 和 Linux请先添加执行权限
```bash
chmod +x ./spc chmod +x ./spc
# Run (Linux and macOS)
./spc --version
# Run (Windows powershell)
.\spc.exe --version
``` ```
自托管 `spc` 由 GitHub Actions 构建,你也可以从 Actions 直接下载:[此处](https://github.com/crazywhalecc/static-php-cli/actions/workflows/release-build.yml)。 ### 2. 构建静态 PHP
### 本地构建(使用 git 源码) 首先,创建一个 `craft.yml` 文件,并从 [扩展列表](https://static-php.dev/zh/guide/extensions.html) 或 [命令生成器](https://static-php.dev/zh/guide/cli-generator.html) 中指定要包含的扩展:
如果你需要修改 static-php-cli 源码,或者使用 spc 二进制构建有问题,你可以使用 git 源码下载 static-php-cli。 ```yml
# PHP 版本支持8.1, 8.2, 8.3, 8.4, 8.5
php-version: 8.4
# 在此处放置您的扩展列表
extensions: "apcu,bcmath,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,gd,iconv,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,readline,redis,session,simplexml,sockets,sodium,sqlite3,tokenizer,xml,xmlreader,xmlwriter,xsl,zip,zlib"
sapi:
- cli
- micro
- fpm
download-options:
prefer-pre-built: true
```
运行命令:
```bash ```bash
# clone 仓库即可 ./spc craft
git clone https://github.com/crazywhalecc/static-php-cli.git
# 输出完整控制台日志
./spc craft --debug
``` ```
如果您的系统上尚未安装 php我们建议你使用内置的 setup-runtime 自动安装 PHP 和 Composer。 ### 3. 静态 PHP 使用
```bash 现在您可以将 static-php-cli 构建的二进制文件复制到另一台机器上,无需依赖即可运行:
cd static-php-cli
chmod +x bin/setup-runtime ```
# it will download static php (from self-hosted server) and composer (from getcomposer) # php-cli
bin/setup-runtime buildroot/bin/php -v
# initialize composer deps
bin/composer install # phpmicro
# chmod echo '<?php echo "Hello world!\n";' > a.php
chmod +x bin/spc ./spc micro:combine a.php -O my-app
bin/spc --version ./my-app
# php-fpm
buildroot/bin/php-fpm -v
``` ```
### 开始构建 PHP ## 文档
下面是使用 static-php-cli 的基础用法: 当前 README 包含基本用法。有关 static-php-cli 的所有功能,
请访问 <https://static-php.dev>。
> 如果你使用的是打包好的 `spc` 二进制,你需要将下列命令的 `./bin/spc` 替换为 `./spc`。 ## 直接下载
```bash 如果您不想构建或想先测试,可以从 [Actions](https://github.com/static-php/static-php-cli-hosted/actions/workflows/build-php-bulk.yml) 下载示例预编译工件,或从自托管服务器下载。
# 检查环境依赖,并根据尝试自动安装缺失的编译工具
./bin/spc doctor --auto-fix
# 输出目标项目依赖的扩展列表 以下是几个具有不同扩展组合的预编译静态 PHP 二进制文件,
./bin/spc dump-extensions /path/to/your/project --format=text 您可以根据需要直接下载。
# 拉取所有依赖库 | 组合名称 | 扩展数量 | 系统 | 备注 |
./bin/spc download --all |----------------------------------------------------------------------|----------------------------------------------------------------------------|--------------|--------------------|
# 只拉取编译指定扩展需要的所有依赖(推荐) | [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 |
./bin/spc download --for-extensions="openssl,pcntl,mbstring,pdo_sqlite" | [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 |
# 下载依赖时,优先下载有预编译的库(节省编译依赖的时间) | [gnu-bulk](https://dl.static-php.dev/static-php-cli/gnu-bulk/) | [50+](https://dl.static-php.dev/static-php-cli/bulk/README.txt) | Linux, macOS | 使用 glibc 的 bulk 组合 |
./bin/spc download --for-extensions="openssl,curl,mbstring,mbregex" --prefer-pre-built | [minimal](https://dl.static-php.dev/static-php-cli/minimal/) | [5](https://dl.static-php.dev/static-php-cli/minimal/README.txt) | Linux, macOS | 二进制文件大小约为 3MB |
# 下载编译不同版本的 PHP (--with-php=x.y 或 --with-php=x.y.z推荐 8.1 ~ 8.3) | [spc-min](https://dl.static-php.dev/static-php-cli/windows/spc-min/) | [5](https://dl.static-php.dev/static-php-cli/windows/spc-min/README.txt) | Windows | 二进制文件大小约为 3MB |
./bin/spc download --for-extensions="openssl,curl,mbstring" --with-php=8.1 | [spc-max](https://dl.static-php.dev/static-php-cli/windows/spc-max/) | [40+](https://dl.static-php.dev/static-php-cli/windows/spc-max/README.txt) | Windows | 二进制文件大小约为 8.5MB |
# 构建包含 bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl 扩展的 php-cli 和 micro.sfx > Linux 和 Windows 支持对二进制文件进行 UPX 压缩,可以将二进制文件大小减少 30% 到 50%。
./bin/spc build "bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl" --build-cli --build-micro > macOS 不支持 UPX 压缩,因此 mac 的预构建二进制文件大小较大。
# 编译线程安全版本 (--enable-zts)
./bin/spc build "curl,phar" --enable-zts --build-cli
# 编译后使用 UPX 减小可执行文件体积 (仅 Linux、Windows 可用) (至少压缩至原来的 30~50%)
./bin/spc build "curl,phar" --enable-zts --build-cli --with-upx-pack
```
其中,目前支持构建 climicrofpm 和 embed使用以下参数的一个或多个来指定编译的 SAPI ### 在线构建(使用 GitHub Actions
- `--build-cli`:构建 cli 二进制 上方直接下载的二进制不能满足需求时,可使用 GitHub Action 可以轻松构建静态编译的 PHP
- `--build-micro`:构建 phpmicro 自执行二进制 同时自行定义要编译的扩展。
- `--build-fpm`:构建 fpm
- `--build-embed`:构建 embedlibphp
- `--build-cgi`: 构建 cgi不推荐
- `--build-all`:构建所有
如果出现了任何错误,可以使用 `--debug` 参数来展示完整的输出日志,以供排查错误: 1. Fork 本项目。
2. 进入项目的 Actions 并选择 `CI`
3. 选择 `Run workflow`,填入您要编译的 PHP 版本、目标类型和扩展列表。(扩展用逗号分隔,例如 `bcmath,curl,mbstring`
4. 等待一段时间后,进入相应的任务并获取 `Artifacts`
```bash 如果您启用 `debug`,构建时将输出所有日志,包括编译日志,以便故障排除。
./bin/spc build "openssl,pcntl,mbstring" --debug --build-all
./bin/spc download --all --debug
```
## 不同 SAPI 的使用
### 使用 cli
> php-cli 是一个静态的二进制文件,类似 Go、Rust 语言编译后的单个可移植的二进制文件。
采用参数 `--build-cli``--build-all` 参数时,最后编译结果会输出一个 `./php` 的二进制文件,此文件可分发、可直接使用。
该文件编译后会存放在 `buildroot/bin/` 目录中,名称为 `php`,拷贝出来即可。
```bash
cd buildroot/bin/
./php -v # 检查版本
./php -m # 检查编译的扩展
./php your_code.php # 运行代码
./php your_project.phar # 运行打包为 phar 单文件的项目
```
### 使用 micro
> phpmicro 是一个提供自执行二进制 PHP 的项目,本项目依赖 phpmicro 进行编译自执行二进制。详见 [dixyes/phpmicro](https://github.com/dixyes/phpmicro)。
采用项目参数 `--build-micro``--build-all` 时,最后编译结果会输出一个 `./micro.sfx` 的文件,此文件需要配合你的 PHP 源码使用。
该文件编译后会存放在 `buildroot/bin/` 目录中,拷贝出来即可。
使用时应准备好你的项目源码文件,可以是单个 PHP 文件,也可以是 Phar 文件。
```bash
echo "<?php echo 'Hello world' . PHP_EOL;" > code.php
cat micro.sfx code.php > single-app && chmod +x single-app
./single-app
```
如果打包 PHAR 文件,仅需把 code.php 更换为 phar 文件路径即可。
你可以使用 [box-project/box](https://github.com/box-project/box) 将你的 CLI 项目打包为 Phar
然后将它与 phpmicro 结合,生成独立可执行的二进制文件。
```bash
# 使用 static-php-cli 生成的 micro.sfx 结合,也可以直接使用 cat 命令结合它们
bin/spc micro:combine my-app.phar
cat buildroot/bin/micro.sfx my-app.phar > my-app && chmod +x my-app
# 使用 micro:combine 结合可以将 INI 选项注入到二进制中
bin/spc micro:combine my-app.phar -I "memory_limit=4G" -I "disable_functions=system" --output my-app-2
```
> 有些情况下的 phar 文件或 PHP 项目可能无法在 micro 环境下运行。
### 使用 fpm
采用项目参数 `--build-fpm``--build-all` 时,最后编译结果会输出一个 `./php-fpm` 的文件。
该文件存放在 `buildroot/bin/` 目录,拷贝出来即可使用。
在正常的 Linux 发行版和 macOS 系统中,安装 php-fpm 后包管理会自动生成默认的 fpm 配置文件。
因为 php-fpm 必须指定配置文件才可启动,本项目编译的 php-fpm 不会带任何配置文件,所以需自行编写 `php-fpm.conf``pool.conf` 配置文件。
指定 `php-fpm.conf` 可以使用命令参数 `-y`,例如:`./php-fpm -y php-fpm.conf`
### 使用 embed
采用项目参数 `--build-embed``--build-all` 时,最后编译结果会输出一个 `libphp.a``php-config` 以及一系列头文件,存放在 `buildroot/`,你可以在你的其他代码中引入它们。
如果你知道 [embed SAPI](https://github.com/php/php-src/tree/master/sapi/embed),你应该知道如何使用它。对于有可能编译用到引入其他库的问题,你可以使用 `buildroot/bin/php-config` 来获取编译时的配置。
另外,有关如何使用此功能的高级示例,请查看[如何使用它构建 FrankenPHP 的静态版本](https://github.com/php/frankenphp/blob/main/docs/static.md)。
## 贡献 ## 贡献
如果缺少你需要的扩展,可发起 Issue。如果你对本项目较熟悉也欢迎为本项目发起 Pull Request 如果需要的扩展缺失,可以创建 issue
如果您熟悉本项目,也欢迎发起 pull request。
另外,添加新扩展的贡献方式,可以参考下方 `进阶` 如果您想贡献文档,请直接编辑 `docs/` 目录
如果你想贡献文档内容,请直接修改 `docs/` 目录 现在有一个 [static-php](https://github.com/static-php) 组织,用于存储与项目相关的仓库
## 赞助本项目 ## 赞助本项目
可以 [我的个人赞助页](https://github.com/crazywhalecc/crazywhalecc/blob/master/FUNDING.md) 支持我和我的项目。捐赠的一部分将会被用于维护 **static-php.dev** 服务器。 可以 [GitHub Sponsor](https://github.com/crazywhalecc) 赞助我或我的项目。捐赠的一部分将用于维护 **static-php.dev** 服务器。
**特别赞助商**: **特别感谢以下赞助商**
<a href="https://beyondco.de/"><img src="/docs/public/images/beyondcode-seeklogo.png" width="300" alt="Beyond Code Logo" /></a> <a href="https://beyondco.de/"><img src="/docs/public/images/beyondcode-seeklogo.png" width="300" alt="Beyond Code Logo" /></a>
<a href="https://nativephp.com/"><img src="/docs/public/images/nativephp-logo.svg" width="300" alt="NativePHP Logo" /></a> <a href="https://nativephp.com/"><img src="/docs/public/images/nativephp-logo.svg" width="300" alt="NativePHP Logo" /></a>
## 开源协议 ## 开源许可证
本项目采用 MIT License 许可开源,下面是类似的项目: 本项目本身基于 MIT 许可证,
一些新添加的扩展和依赖可能来自其他项目,
这些代码文件的头部也会给出额外的许可证和作者说明。
这些是类似的项目:
- [dixyes/lwmbs](https://github.com/dixyes/lwmbs) - [dixyes/lwmbs](https://github.com/dixyes/lwmbs)
- [swoole/swoole-cli](https://github.com/swoole/swoole-cli) - [swoole/swoole-cli](https://github.com/swoole/swoole-cli)
项目使用了 [dixyes/lwmbs](https://github.com/dixyes/lwmbs) 的一些代码,例如 Windows 静态构建目标和 libiconv 支持。 项目使用了 [dixyes/lwmbs](https://github.com/dixyes/lwmbs) 的一些代码,例如 Windows 静态构建目标和 libiconv 支持。
lwmbs 使用 [Mulan PSL 2](http://license.coscl.org.cn/MulanPSL2) 许可进行分发。对应文件有关于作者和许可的特殊说明,除此之外,均使用 MIT 授权许可 lwmbs 基于 [Mulan PSL 2](http://license.coscl.org.cn/MulanPSL2) 许可
本项目的特殊性,使用项目编译过程中会使用很多其他开源项目,例如 curl、protobuf 等,它们都有各自的开源协议。 由于本项目的特殊性,
请在编译完成后,使用命令 `bin/spc dump-license` 导出项目使用项目的开源协议,并遵守对应项目的 LICENSE。 项目编译过程中会使用许多其他开源项目,如 curl 和 protobuf
它们都有自己的开源许可证。
请在编译后使用 `bin/spc dump-license` 命令导出项目中使用的开源许可证,
并遵守相应项目的 LICENSE。

329
README.md
View File

@@ -5,29 +5,22 @@
[![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)
[![Extensions](https://img.shields.io/badge/Extension%20Counter-75+-yellow.svg?style=flat-square)](https://static-php.dev/en/guide/extensions.html)
**static-php-cli** is a powerful tool designed for building static, standalone PHP runtime **static-php-cli** is a powerful tool designed for building static, standalone PHP runtime
with popular extensions. with popular extensions.
Static PHP built by **static-php-cli** supports `cli`, `fpm`, `embed`, `micro` and `frankenphp` SAPI.
**static-php-cli** also has the ability to package PHP projects
along with the PHP interpreter into one single executable file.
## Features ## Features
static-php-cli (you can call it `spc`) has a lot of features: - :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, without any 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/dixyes/phpmicro)** self-extracted executable (glue php binary and php source code into one file) - :pill: Automatic build environment checker with auto-fix capabilities
- :pill: Automatic build environment checker (Doctor module)
- :zap: `Linux`, `macOS`, `FreeBSD`, `Windows` support - :zap: `Linux`, `macOS`, `FreeBSD`, `Windows` support
- :wrench: Configurable source code patches - :wrench: Configurable source code patching
- :books: Build dependency management - :books: Intelligent dependency management
- 📦 Provide `spc` own standalone executable (built by spc and [box](https://github.com/box-project/box)) - 📦 Self-contained `spc` executable (built with [box](https://github.com/box-project/box))
- :fire: Support many popular [extensions](https://static-php.dev/en/guide/extensions.html) - :fire: Support 100+ popular [extensions](https://static-php.dev/en/guide/extensions.html)
- :floppy_disk: UPX integration (significantly reduces binary size) - :floppy_disk: UPX compression support (reduces binary size by 30-50%)
**Single-file standalone php-cli:** **Single-file standalone php-cli:**
@@ -37,6 +30,72 @@ static-php-cli (you can call it `spc`) has a lot of features:
<img width="700" alt="out2" src="https://github.com/crazywhalecc/static-php-cli/assets/20330940/46b7128d-fb72-4169-957e-48564c3ff3e2"> <img width="700" alt="out2" src="https://github.com/crazywhalecc/static-php-cli/assets/20330940/46b7128d-fb72-4169-957e-48564c3ff3e2">
## Quickstart
### 1. Download spc binary
```bash
# For Linux x86_64
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-x86_64
# For Linux aarch64
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-aarch64
# macOS x86_64 (Intel)
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-x86_64
# macOS aarch64 (Apple)
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-aarch64
# Windows (x86_64, win10 build 17063 or later, please install VS2022 first)
curl.exe -fsSL -o spc.exe https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe
```
For macOS and Linux, add execute permission first:
```bash
chmod +x ./spc
```
### 2. Build Static PHP
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):
```yml
# PHP version support: 8.1, 8.2, 8.3, 8.4, 8.5
php-version: 8.4
# Put your extension list here
extensions: "apcu,bcmath,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,gd,iconv,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,readline,redis,session,simplexml,sockets,sodium,sqlite3,tokenizer,xml,xmlreader,xmlwriter,xsl,zip,zlib"
sapi:
- cli
- micro
- fpm
download-options:
prefer-pre-built: true
```
Run command:
```bash
./spc craft
# Output full console log
./spc craft --debug
```
### 3. Static PHP usage
Now you can copy binaries built by static-php-cli to another machine and run with no dependencies:
```
# php-cli
buildroot/bin/php -v
# phpmicro
echo '<?php echo "Hello world!\n";' > a.php
./spc micro:combine a.php -O my-app
./my-app
# php-fpm
buildroot/bin/php-fpm -v
```
## Documentation ## Documentation
The current README contains basic usage. For all the features of static-php-cli, The current README contains basic usage. For all the features of static-php-cli,
@@ -53,6 +112,7 @@ which can be downloaded directly according to your needs.
|----------------------------------------------------------------------|----------------------------------------------------------------------------|--------------|--------------------------------| |----------------------------------------------------------------------|----------------------------------------------------------------------------|--------------|--------------------------------|
| [common](https://dl.static-php.dev/static-php-cli/common/) | [30+](https://dl.static-php.dev/static-php-cli/common/README.txt) | Linux, macOS | The binary size is about 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 | The binary size is about 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 | The binary size is about 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 | The binary size is about 25MB |
| [gnu-bulk](https://dl.static-php.dev/static-php-cli/gnu-bulk/) | [50+](https://dl.static-php.dev/static-php-cli/bulk/README.txt) | Linux, macOS | Using shared glibc |
| [minimal](https://dl.static-php.dev/static-php-cli/minimal/) | [5](https://dl.static-php.dev/static-php-cli/minimal/README.txt) | Linux, macOS | The binary size is about 3MB | | [minimal](https://dl.static-php.dev/static-php-cli/minimal/) | [5](https://dl.static-php.dev/static-php-cli/minimal/README.txt) | Linux, macOS | The binary size is about 3MB |
| [spc-min](https://dl.static-php.dev/static-php-cli/windows/spc-min/) | [5](https://dl.static-php.dev/static-php-cli/windows/spc-min/README.txt) | Windows | The binary size is about 3MB | | [spc-min](https://dl.static-php.dev/static-php-cli/windows/spc-min/) | [5](https://dl.static-php.dev/static-php-cli/windows/spc-min/README.txt) | Windows | The binary size is about 3MB |
| [spc-max](https://dl.static-php.dev/static-php-cli/windows/spc-max/) | [40+](https://dl.static-php.dev/static-php-cli/windows/spc-max/README.txt) | Windows | The binary size is about 8.5MB | | [spc-max](https://dl.static-php.dev/static-php-cli/windows/spc-max/) | [40+](https://dl.static-php.dev/static-php-cli/windows/spc-max/README.txt) | Windows | The binary size is about 8.5MB |
@@ -60,64 +120,10 @@ which can be downloaded directly according to your needs.
> Linux and Windows supports UPX compression for binaries, which can reduce the size of the binary by 30% to 50%. > Linux and Windows supports UPX compression for binaries, which can reduce the size of the binary by 30% to 50%.
> macOS does not support UPX compression, so the size of the pre-built binaries for mac is larger. > macOS does not support UPX compression, so the size of the pre-built binaries for mac is larger.
## Build
### Compilation Requirements
You can say I made a PHP builder written in PHP, pretty funny.
But static-php-cli runtime only requires an environment above PHP 8.1 and extensions mentioned below.
- PHP >= 8.4 (This is the version required by spc itself, not the build version)
- Extension: `mbstring,tokenizer,phar`
- Supported OS with `curl` and `git` installed
Here is the supported OS and arch, where :octocat: represents support for GitHub Action builds,
:computer: represents support for local manual builds, and blank represents not currently supported.
| | x86_64 | aarch64 |
|---------|----------------------|----------------------|
| macOS | :octocat: :computer: | :octocat: :computer: |
| Linux | :octocat: :computer: | :octocat: :computer: |
| Windows | :octocat: :computer: | |
| FreeBSD | :computer: | :computer: |
Currently supported PHP versions for compilation:
> :warning: Partial support, there may be issues with newer test versions or older versions.
>
> :heavy_check_mark: supported
>
> :x: not supported
| PHP Version | Status | Comment |
|-------------|--------------------|----------------------------------------------------------------------------------------------------|
| 7.2 | :x: | |
| 7.3 | :x: | phpmicro and some extensions not supported on 7.x |
| 7.4 | :x: | phpmicro and some extensions not supported on 7.x |
| 8.0 | :warning: | PHP official has stopped maintenance of 8.0, we no longer provide backport support for version 8.0 |
| 8.1 | :heavy_check_mark: | PHP official has security fixes only, we no longer provide backport support when 8.5 released |
| 8.2 | :heavy_check_mark: | |
| 8.3 | :heavy_check_mark: | |
| 8.4 | :heavy_check_mark: | |
| 8.5 (alpha) | :warning: | PHP 8.5 is in alpha |
> This table shows the support status for static-php-cli in building the corresponding version,
> not the official PHP support status for that version.
### Supported Extensions
Please first select the extension you want to compile based on the extension list below.
- [Supported Extension List](https://static-php.dev/en/guide/extensions.html)
- [Command Generator](https://static-php.dev/en/guide/cli-generator.html)
> If an extension you need is missing, you can submit an issue.
Here is the current planned roadmap for extension support: [#152](https://github.com/crazywhalecc/static-php-cli/issues/152) .
### Build Online (using GitHub Actions) ### Build Online (using GitHub Actions)
Use GitHub Action to easily build a statically compiled PHP, When the above direct download binaries cannot meet your needs,
you can use GitHub Action to easily build a statically compiled PHP,
and at the same time define the extensions to be compiled by yourself. and at the same time define the extensions to be compiled by yourself.
1. Fork me. 1. Fork me.
@@ -127,185 +133,6 @@ and at the same time define the extensions to be compiled by yourself.
If you enable `debug`, all logs will be output at build time, including compiled logs, for troubleshooting. If you enable `debug`, all logs will be output at build time, including compiled logs, for troubleshooting.
### Build Locally (using SPC binary, recommended)
This project provides a binary file of static-php-cli: `spc`.
You can use `spc` binary instead of installing any runtime like golang app.
Currently, the platforms supported by `spc` binary are Linux and macOS.
Download from self-hosted nightly builds using commands below:
```bash
# Download from self-hosted nightly builds (sync with main branch)
# For Linux x86_64
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-x86_64
# For Linux aarch64
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-aarch64
# macOS x86_64 (Intel)
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-x86_64
# macOS aarch64 (Apple)
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-aarch64
# Windows (x86_64, win10 build 17063 or later)
curl.exe -fsSL -o spc.exe https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe
# Add execute perm (Linux and macOS only)
chmod +x ./spc
# Run (Linux and macOS)
./spc --version
# Run (Windows powershell)
.\spc.exe --version
```
Self-hosted `spc` is built by GitHub Actions, you can also download from Actions artifacts [here](https://github.com/crazywhalecc/static-php-cli/actions/workflows/release-build.yml).
### Build Locally (using git source)
If you need to modify the static-php-cli source code, or have problems using the spc binary build,
you can download static-php-cli using the git source code.
```bash
# just clone me!
git clone https://github.com/crazywhalecc/static-php-cli.git
```
If you have not installed php on your system, we recommend that you use the built-in setup-runtime to install PHP and Composer automatically.
```bash
cd static-php-cli
chmod +x bin/setup-runtime
# it will download static php (from self-hosted server) and composer (from getcomposer)
bin/setup-runtime
# initialize composer deps
bin/composer install
# chmod
chmod +x bin/spc
bin/spc --version
```
### Start Building PHP
Basic usage for building php with some extensions:
> If you are using the packaged standalone `spc` binary, you need to replace `bin/spc` with `./spc` or `.\spc.exe` in the following commands.
```bash
# Check system tool dependencies, auto-fix them if possible
./bin/spc doctor --auto-fix
# fetch all libraries
./bin/spc download --all
# dump a list of extensions required by your project
./bin/spc dump-extensions /path/to/your/project --format=text
# only fetch necessary sources by needed extensions (recommended)
./bin/spc download --for-extensions="openssl,pcntl,mbstring,pdo_sqlite"
# download pre-built libraries first (save time for compiling dependencies)
./bin/spc download --for-extensions="openssl,curl,mbstring,mbregex" --prefer-pre-built
# download different PHP version (--with-php=x.y or --with-php=x.y.z, recommend 8.3 ~ 8.4)
./bin/spc download --for-extensions="openssl,curl,mbstring" --with-php=8.1
# with bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl extension, build both CLI and phpmicro SAPI
./bin/spc build "bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl" --build-cli --build-micro
# build thread-safe (ZTS) version (--enable-zts)
./bin/spc build "curl,phar" --enable-zts --build-cli
# build, pack executable with UPX (linux and windows only) (reduce binary size for 30~50%)
./bin/spc build "curl,phar" --enable-zts --build-cli --with-upx-pack
```
Now we support `cli`, `micro`, `fpm` and `embed` SAPI. You can use one or more of the following parameters to specify the compiled SAPI:
- `--build-cli`: build static cli executable
- `--build-micro`: build static phpmicro self-extracted executable
- `--build-fpm`: build static fpm binary
- `--build-embed`: build embed (libphp)
- `--build-cgi`: build cgi binary (not recommended)
- `--build-all`: build all
If anything goes wrong, use `--debug` option to display full terminal output:
```bash
./bin/spc build "openssl,pcntl,mbstring" --debug --build-all
./bin/spc download --all --debug
```
## Different SAPI Usage
### Use cli
> php-cli is a single static binary, you can use it like normal php installed on your system.
When using the parameter `--build-cli` or `--build-all`,
the final compilation result will output a binary file named `./php`,
which can be distributed and used directly.
This file will be located in the directory `buildroot/bin/`, copy it out for use.
```bash
cd buildroot/bin/
./php -v # check version
./php -m # check extensions
./php your_code.php # run your php code
./php your_project.phar # run your phar (project archive)
```
### Use micro
> phpmicro is a SelF-extracted eXecutable SAPI module,
> provided by [phpmicro](https://github.com/dixyes/phpmicro) project.
> But this project is using a [fork](https://github.com/static-php/phpmicro) of phpmicro, because we need to add some features to it.
> It can put php runtime and your source code together.
When using the parameter `--build-all` or `--build-micro`,
the final compilation result will output a file named `./micro.sfx`,
which needs to be used with your PHP source code like `code.php`.
This file will be located in the path `buildroot/bin/micro.sfx`, simply copy it out for use.
Prepare your project source code, which can be a single PHP file or a Phar file, for use.
```bash
echo "<?php echo 'Hello world' . PHP_EOL;" > code.php
cat micro.sfx code.php > single-app && chmod +x single-app
./single-app
```
If you package a PHAR file, just replace `code.php` with the phar file path.
You can use [box-project/box](https://github.com/box-project/box) to package your CLI project as Phar,
It is then combined with phpmicro to produce a standalone executable binary.
```bash
# Use the micro.sfx generated by static-php-cli to combine,
bin/spc micro:combine my-app.phar
# or you can directly use the cat command to combine them.
cat buildroot/bin/micro.sfx my-app.phar > my-app && chmod +x my-app
# Use micro:combine combination to inject INI options into the binary.
bin/spc micro:combine my-app.phar -I "memory_limit=4G" -I "disable_functions=system" --output my-app-2
```
> In some cases, PHAR files may not run in a micro environment. Overall, micro is not production ready.
### Use fpm
When using the parameter `--build-all` or `--build-fpm`,
the final compilation result will output a file named `./php-fpm`,
This file will be located in the path `buildroot/bin/`, simply copy it out for use.
In common Linux distributions and macOS systems, the package manager will automatically generate a default fpm configuration file after installing php-fpm.
Because php-fpm must specify a configuration file before running, the php-fpm compiled by this project will not have any configuration files, so you need to write `php-fpm.conf` and `pool.conf` configuration files yourself.
Specifying `php-fpm.conf` can use the command parameter `-y`, for example: `./php-fpm -y php-fpm.conf`.
### Use embed
When using the project parameters `--build-embed` or `--build-all`,
the final compilation result will output a `libphp.a`, `php-config` and a series of header files,
stored in `buildroot/`. You can introduce them in your other projects.
If you know [embed SAPI](https://github.com/php/php-src/tree/master/sapi/embed), you should know how to use it.
You may require the introduction of other libraries during compilation,
you can use `buildroot/bin/php-config` to obtain the compile-time configuration.
For an advanced example of how to use this feature, take a look at [how to use it to build a static version of FrankenPHP](https://github.com/php/frankenphp/blob/main/docs/static.md).
## Contribution ## Contribution
If the extension you need is missing, you can create an issue. If the extension you need is missing, you can create an issue.

View File

@@ -34,6 +34,7 @@
; SPC_LINUX_DEFAULT_CC: the default compiler for linux. (For alpine linux: `gcc`, default: `$GNU_ARCH-linux-musl-gcc`) ; SPC_LINUX_DEFAULT_CC: the default compiler for linux. (For alpine linux: `gcc`, default: `$GNU_ARCH-linux-musl-gcc`)
; SPC_LINUX_DEFAULT_CXX: the default c++ compiler for linux. (For alpine linux: `g++`, default: `$GNU_ARCH-linux-musl-g++`) ; SPC_LINUX_DEFAULT_CXX: the default c++ compiler for linux. (For alpine linux: `g++`, default: `$GNU_ARCH-linux-musl-g++`)
; SPC_LINUX_DEFAULT_AR: the default archiver for linux. (For alpine linux: `ar`, default: `$GNU_ARCH-linux-musl-ar`) ; SPC_LINUX_DEFAULT_AR: the default archiver for linux. (For alpine linux: `ar`, default: `$GNU_ARCH-linux-musl-ar`)
; SPC_EXTRA_PHP_VARS: the extra vars for building php, used in `configure` and `make` command.
[global] [global]
; Build concurrency for make -jN, default is CPU_COUNT, this value are used in every libs. ; Build concurrency for make -jN, default is CPU_COUNT, this value are used in every libs.

View File

@@ -759,11 +759,9 @@
}, },
"type": "builtin", "type": "builtin",
"arg-type": "custom", "arg-type": "custom",
"lib-depends": [ "ext-depends": [
"libxml2" "libxml",
], "session"
"ext-depends-windows": [
"xml"
] ]
}, },
"sockets": { "sockets": {
@@ -1154,8 +1152,9 @@
"support": { "support": {
"BSD": "wip" "BSD": "wip"
}, },
"type": "builtin", "type": "external",
"arg-type": "with-path", "source": "ext-zip",
"arg-type": "custom",
"arg-type-windows": "enable", "arg-type-windows": "enable",
"lib-depends-unix": [ "lib-depends-unix": [
"libzip" "libzip"

View File

@@ -202,6 +202,7 @@
"openssl", "openssl",
"libcares" "libcares"
], ],
"cpp-library": true,
"provide-pre-built": true, "provide-pre-built": true,
"frameworks": [ "frameworks": [
"CoreFoundation" "CoreFoundation"
@@ -230,6 +231,7 @@
}, },
"imagemagick": { "imagemagick": {
"source": "imagemagick", "source": "imagemagick",
"cpp-library": true,
"pkg-configs": [ "pkg-configs": [
"Magick++-7.Q16HDRI", "Magick++-7.Q16HDRI",
"MagickCore-7.Q16HDRI", "MagickCore-7.Q16HDRI",
@@ -822,6 +824,7 @@
}, },
"snappy": { "snappy": {
"source": "snappy", "source": "snappy",
"cpp-library": true,
"static-libs-unix": [ "static-libs-unix": [
"libsnappy.a" "libsnappy.a"
], ],
@@ -867,6 +870,7 @@
}, },
"watcher": { "watcher": {
"source": "watcher", "source": "watcher",
"cpp-library": true,
"static-libs-unix": [ "static-libs-unix": [
"libwatcher-c.a" "libwatcher-c.a"
], ],

View File

@@ -263,6 +263,15 @@
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"ext-zip": {
"type": "url",
"url": "https://pecl.php.net/get/zip",
"filename": "ext-zip.tgz",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"ext-zstd": { "ext-zstd": {
"type": "git", "type": "git",
"path": "php-src/ext/zstd", "path": "php-src/ext/zstd",
@@ -324,7 +333,7 @@
}, },
"grpc": { "grpc": {
"type": "git", "type": "git",
"rev": "v1.68.x", "rev": "v1.75.x",
"url": "https://github.com/grpc/grpc.git", "url": "https://github.com/grpc/grpc.git",
"provide-pre-built": true, "provide-pre-built": true,
"license": { "license": {
@@ -880,7 +889,7 @@
"postgresql": { "postgresql": {
"type": "ghtagtar", "type": "ghtagtar",
"repo": "postgres/postgres", "repo": "postgres/postgres",
"match": "REL_16_\\d+", "match": "REL_18_\\d+",
"license": { "license": {
"type": "file", "type": "file",
"path": "COPYRIGHT" "path": "COPYRIGHT"

View File

@@ -21,19 +21,30 @@ The following is the architecture support situation, where :gear: represents sup
| Windows | :gear: :computer: | | | Windows | :gear: :computer: | |
| FreeBSD | :computer: | :computer: | | FreeBSD | :computer: | :computer: |
Among them, Linux is currently only tested on Ubuntu, Debian, and Alpine distributions, Current supported PHP versions for compilation:
and other distributions have not been tested, which cannot guarantee successful compilation.
For untested distributions, local compilation can be done using methods such as Docker to avoid environmental issues.
There are two architectures for macOS: `x86_64` and `Arm`, but binaries compiled on one architecture cannot be directly used on the other architecture. > :warning: Partial support, there may be issues with new beta versions and old versions.
Rosetta 2 cannot guarantee that programs compiled with `Arm` architecture can fully run on `x86_64` environment. >
> :heavy_check_mark: Supported
>
> :x: Not supported
Windows currently only supports the x86_64 architecture, and does not support 32-bit x86 or arm64 architecture. | PHP Version | Status | Comment |
|-------------|--------------------|-------------------------------------------------------------------------------------------------------------------------|
| 7.2 | :x: | |
| 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 |
| 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.2 | :heavy_check_mark: | |
| 8.3 | :heavy_check_mark: | |
| 8.4 | :heavy_check_mark: | |
| 8.5 (beta) | :warning: | PHP 8.5 is currently in beta stage |
## Supported PHP Version > This table shows the support status of static-php-cli for building corresponding versions, not the PHP official support status for that version.
Currently, static php cli supports PHP versions 8.1 to 8.5, and theoretically supports PHP 8.0 and earlier versions. ## PHP Support Versions
Simply select the earlier version when downloading.
However, due to some extensions and special components that have stopped supporting earlier versions of PHP, Currently, static-php-cli supports PHP versions 8.2 ~ 8.5, and theoretically supports PHP 8.1 and earlier versions, just select the earlier version when downloading.
static-php-cli will not explicitly support earlier versions. However, due to some extensions and special components that have stopped supporting earlier versions of PHP, static-php-cli will not explicitly support earlier versions.
We recommend that you compile the latest PHP version possible for a better experience. We recommend that you compile the latest PHP version possible for a better experience.

View File

@@ -19,16 +19,30 @@ static-php-cli 是一个用于构建静态编译的 PHP 二进制的工具,目
| Windows | :gear: :computer: | | | Windows | :gear: :computer: | |
| FreeBSD | :computer: | :computer: | | FreeBSD | :computer: | :computer: |
其中Linux 目前仅在 Ubuntu、Debian、Alpine 发行版测试通过,其他发行版未进行测试,不能保证编译成功。 当前支持编译的 PHP 版本:
对于未经过测试的发行版,可以使用 Docker 等方式本地编译,避免环境导致的问题。
macOS 下支持 x86_64 和 Arm 两种架构,但在其中一个架构上编译的二进制无法直接在另一个架构上使用 > :warning: 部分支持,对于新的测试版和旧版本可能存在问题
Rosetta 2 不能保证 Arm 架构编译的程序可以完全运行在 x86_64 环境下。 >
> :heavy_check_mark: 支持
>
> :x: 不支持
Windows 目前只支持 x86_64 架构,不支持 32 位 x86、不支持 arm64 架构。 | PHP Version | Status | Comment |
|-------------|--------------------|---------------------------------------------------------|
| 7.2 | :x: | |
| 7.3 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
| 7.4 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
| 8.0 | :warning: | PHP 官方已停止 8.0 的维护,我们不再处理 8.0 相关的 backport 支持 |
| 8.1 | :warning: | PHP 官方仅对 8.1 提供安全更新,在 8.5 发布后我们不再处理 8.1 相关的 backport 支持 |
| 8.2 | :heavy_check_mark: | |
| 8.3 | :heavy_check_mark: | |
| 8.4 | :heavy_check_mark: | |
| 8.5 (beta) | :warning: | PHP 8.5 目前处于 beta 阶段 |
> 这个表格的支持状态是 static-php-cli 对构建对应版本的支持情况,不是 PHP 官方对该版本的支持情况。
## PHP 支持版本 ## PHP 支持版本
目前static-php-cli 对 PHP 8.1 ~ 8.5 版本是支持的,对于 PHP 8.0 及更早版本理论上支持,只需下载时选择早期版本即可。 目前static-php-cli 对 PHP 8.2 ~ 8.5 版本是支持的,对于 PHP 8.1 及更早版本理论上支持,只需下载时选择早期版本即可。
但由于部分扩展和特殊组件已对早期版本的 PHP 停止了支持,所以 static-php-cli 不会明确支持早期版本。 但由于部分扩展和特殊组件已对早期版本的 PHP 停止了支持,所以 static-php-cli 不会明确支持早期版本。
我们推荐你编译尽可能新的 PHP 版本,以获得更好的体验。 我们推荐你编译尽可能新的 PHP 版本,以获得更好的体验。

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

View File

@@ -128,27 +128,6 @@ abstract class BuilderBase
return array_filter($this->exts, fn ($ext) => $ext->isBuildStatic()); return array_filter($this->exts, fn ($ext) => $ext->isBuildStatic());
} }
/**
* Check if there is a cpp extensions or libraries.
*/
public function hasCpp(): bool
{
// judge cpp-extension
$exts = array_keys($this->getExts(false));
foreach ($exts as $ext) {
if (Config::getExt($ext, 'cpp-extension', false) === true) {
return true;
}
}
$libs = array_keys($this->getLibs());
foreach ($libs as $lib) {
if (Config::getLib($lib, 'cpp-library', false) === true) {
return true;
}
}
return false;
}
/** /**
* Set libs only mode. * Set libs only mode.
* *

View File

@@ -5,16 +5,11 @@ declare(strict_types=1);
namespace SPC\builder; namespace SPC\builder;
use SPC\exception\EnvironmentException; use SPC\exception\EnvironmentException;
use SPC\exception\FileSystemException;
use SPC\exception\SPCException; use SPC\exception\SPCException;
use SPC\exception\ValidationException; use SPC\exception\ValidationException;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
use SPC\store\Config; use SPC\store\Config;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\toolchain\ClangNativeToolchain;
use SPC\toolchain\GccNativeToolchain;
use SPC\toolchain\ToolchainManager;
use SPC\toolchain\ZigToolchain;
use SPC\util\SPCConfigUtil; use SPC\util\SPCConfigUtil;
use SPC\util\SPCTarget; use SPC\util\SPCTarget;
@@ -226,12 +221,24 @@ class Extension
public function patchBeforeSharedMake(): bool public function patchBeforeSharedMake(): bool
{ {
$config = (new SPCConfigUtil($this->builder))->config([$this->getName()], array_map(fn ($l) => $l->getName(), $this->builder->getLibs())); $config = (new SPCConfigUtil($this->builder))->config([$this->getName()], array_map(fn ($l) => $l->getName(), $this->builder->getLibs()));
[$staticLibs] = $this->splitLibsIntoStaticAndShared($config['libs']); [$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
FileSystem::replaceFileRegex( $lstdcpp = str_contains($sharedLibs, '-l:libstdc++.a') ? '-l:libstdc++.a' : null;
$this->source_dir . '/Makefile', $lstdcpp ??= str_contains($sharedLibs, '-lstdc++') ? '-lstdc++' : '';
'/^(.*_SHARED_LIBADD\s*=.*)$/m',
'$1 ' . trim($staticLibs) $makefileContent = file_get_contents($this->source_dir . '/Makefile');
); if (preg_match('/^(.*_SHARED_LIBADD\s*=\s*)(.*)$/m', $makefileContent, $matches)) {
$prefix = $matches[1];
$currentLibs = trim($matches[2]);
$newLibs = trim("{$currentLibs} {$staticLibs} {$lstdcpp}");
$deduplicatedLibs = deduplicate_flags($newLibs);
FileSystem::replaceFileRegex(
$this->source_dir . '/Makefile',
'/^(.*_SHARED_LIBADD\s*=.*)$/m',
$prefix . $deduplicatedLibs
);
}
if ($objs = getenv('SPC_EXTRA_RUNTIME_OBJECTS')) { if ($objs = getenv('SPC_EXTRA_RUNTIME_OBJECTS')) {
FileSystem::replaceFileRegex( FileSystem::replaceFileRegex(
$this->source_dir . '/Makefile', $this->source_dir . '/Makefile',
@@ -405,42 +412,7 @@ class Extension
*/ */
public function buildUnixShared(): void public function buildUnixShared(): void
{ {
$config = (new SPCConfigUtil($this->builder))->config( $env = $this->getSharedExtensionEnv();
[$this->getName()],
array_map(fn ($l) => $l->getName(), $this->getLibraryDependencies(recursive: true)),
$this->builder->getOption('with-suggested-exts'),
$this->builder->getOption('with-suggested-libs'),
);
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
$preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group ';
$postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group ';
$env = [
'CFLAGS' => $config['cflags'],
'CXXFLAGS' => $config['cflags'],
'LDFLAGS' => $config['ldflags'],
'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"),
'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
];
if (str_contains($env['LIBS'], '-lstdc++') && SPCTarget::getTargetOS() === 'Linux') {
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
$env['SPC_COMPILER_EXTRA'] = '-lstdc++';
} elseif (ToolchainManager::getToolchainClass() === GccNativeToolchain::class || ToolchainManager::getToolchainClass() === ClangNativeToolchain::class) {
try {
$content = FileSystem::readFile($this->source_dir . '/config.m4');
if ($content && !str_contains($content, 'PHP_ADD_LIBRARY(stdc++')) {
$pattern = '/(PHP_NEW_EXTENSION\(' . $this->name . ',.*\))/m';
$replacement = "$1\nPHP_ADD_LIBRARY(stdc++, 1, " . strtoupper($this->name) . '_SHARED_LIBADD)';
FileSystem::replaceFileRegex(
$this->source_dir . '/config.m4',
$pattern,
$replacement
);
}
} catch (FileSystemException) {
}
}
}
if ($this->patchBeforeSharedPhpize()) { if ($this->patchBeforeSharedPhpize()) {
logger()->info("Extension [{$this->getName()}] patched before shared phpize"); logger()->info("Extension [{$this->getName()}] patched before shared phpize");
} }
@@ -455,13 +427,15 @@ class Extension
logger()->info("Extension [{$this->getName()}] patched before shared configure"); logger()->info("Extension [{$this->getName()}] patched before shared configure");
} }
$phpvars = getenv('SPC_EXTRA_PHP_VARS') ?: '';
shell()->cd($this->source_dir) shell()->cd($this->source_dir)
->setEnv($env) ->setEnv($env)
->appendEnv($this->getExtraEnv()) ->appendEnv($this->getExtraEnv())
->exec( ->exec(
'./configure ' . $this->getUnixConfigureArg(true) . './configure ' . $this->getUnixConfigureArg(true) .
' --with-php-config=' . BUILD_BIN_PATH . '/php-config ' . ' --with-php-config=' . BUILD_BIN_PATH . '/php-config ' .
'--enable-shared --disable-static' "--enable-shared --disable-static {$phpvars}"
); );
if ($this->patchBeforeSharedMake()) { if ($this->patchBeforeSharedMake()) {
@@ -512,6 +486,30 @@ class Extension
return $this->build_static; return $this->build_static;
} }
/**
* Returns the environment variables a shared extension needs to be built.
* CFLAGS, CXXFLAGS, LDFLAGS and so on.
*/
protected function getSharedExtensionEnv(): array
{
$config = (new SPCConfigUtil($this->builder))->config(
[$this->getName()],
array_map(fn ($l) => $l->getName(), $this->getLibraryDependencies(recursive: true)),
$this->builder->getOption('with-suggested-exts'),
$this->builder->getOption('with-suggested-libs'),
);
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
$preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group ';
$postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group ';
return [
'CFLAGS' => $config['cflags'],
'CXXFLAGS' => $config['cflags'],
'LDFLAGS' => $config['ldflags'],
'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"),
'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
];
}
protected function addLibraryDependency(string $name, bool $optional = false): void protected function addLibraryDependency(string $name, bool $optional = false): void
{ {
$depLib = $this->builder->getLib($name); $depLib = $this->builder->getLib($name);
@@ -584,12 +582,12 @@ class Extension
$added = 0; $added = 0;
foreach ($ret as $depName => $dep) { foreach ($ret as $depName => $dep) {
foreach ($dep->getDependencies(true) as $depdepName => $depdep) { foreach ($dep->getDependencies(true) as $depdepName => $depdep) {
if (!in_array($depdepName, array_keys($deps), true)) { if (!array_key_exists($depdepName, $deps)) {
$deps[$depdepName] = $depdep; $deps[$depdepName] = $depdep;
++$added; ++$added;
} }
} }
if (!in_array($depName, array_keys($deps), true)) { if (!array_key_exists($depName, $deps)) {
$deps[$depName] = $dep; $deps[$depName] = $dep;
} }
} }

View File

@@ -56,4 +56,11 @@ class grpc extends Extension
GlobalEnvManager::putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -Wno-strict-prototypes'); GlobalEnvManager::putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -Wno-strict-prototypes');
return true; return true;
} }
protected function getSharedExtensionEnv(): array
{
$env = parent::getSharedExtensionEnv();
$env['CPPFLAGS'] = $env['CXXFLAGS'] . ' -Wno-attributes';
return $env;
}
} }

View File

@@ -6,6 +6,8 @@ namespace SPC\builder\extension;
use SPC\builder\Extension; use SPC\builder\Extension;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\toolchain\ToolchainManager;
use SPC\toolchain\ZigToolchain;
use SPC\util\CustomExt; use SPC\util\CustomExt;
#[CustomExt('simdjson')] #[CustomExt('simdjson')]
@@ -17,7 +19,7 @@ class simdjson extends Extension
FileSystem::replaceFileRegex( FileSystem::replaceFileRegex(
SOURCE_PATH . '/php-src/ext/simdjson/config.m4', SOURCE_PATH . '/php-src/ext/simdjson/config.m4',
'/php_version=(`.*`)$/m', '/php_version=(`.*`)$/m',
'php_version=' . strval($php_ver) 'php_version=' . $php_ver
); );
FileSystem::replaceFileStr( FileSystem::replaceFileStr(
SOURCE_PATH . '/php-src/ext/simdjson/config.m4', SOURCE_PATH . '/php-src/ext/simdjson/config.m4',
@@ -31,4 +33,18 @@ class simdjson extends Extension
); );
return true; return true;
} }
public function getSharedExtensionEnv(): array
{
$env = parent::getSharedExtensionEnv();
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
$extra = getenv('SPC_COMPILER_EXTRA');
if (!str_contains((string) $extra, '-lstdc++')) {
f_putenv('SPC_COMPILER_EXTRA=' . clean_spaces($extra . ' -lstdc++'));
}
$env['CFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512';
$env['CXXFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512';
}
return $env;
}
} }

View File

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

View File

@@ -95,6 +95,8 @@ class LinuxBuilder extends UnixBuilderBase
// '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!
]); ]);
$phpvars = getenv('SPC_EXTRA_PHP_VARS') ?: '';
$embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static'; $embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static';
if ($embed_type !== 'static' && SPCTarget::isStatic()) { if ($embed_type !== 'static' && SPCTarget::isStatic()) {
throw new WrongUsageException( throw new WrongUsageException(
@@ -116,6 +118,7 @@ class LinuxBuilder extends UnixBuilderBase
$json_74 . $json_74 .
$zts . $zts .
$maxExecutionTimers . $maxExecutionTimers .
"{$phpvars} " .
$this->makeStaticExtensionArgs() . ' ' $this->makeStaticExtensionArgs() . ' '
)); ));
@@ -153,7 +156,14 @@ class LinuxBuilder extends UnixBuilderBase
} }
$shared_extensions = array_map('trim', array_filter(explode(',', $this->getOption('build-shared')))); $shared_extensions = array_map('trim', array_filter(explode(',', $this->getOption('build-shared'))));
if (!empty($shared_extensions)) { if (!empty($shared_extensions)) {
logger()->info('Building shared extensions ...'); if (SPCTarget::isStatic()) {
throw new WrongUsageException(
"You're building against musl libc statically (the default on Linux), but you're trying to build shared extensions.\n" .
'Static musl libc does not implement `dlopen`, so your php binary is not able to load shared extensions.' . "\n" .
'Either use SPC_LIBC=glibc to link against glibc on a glibc OS, or use SPC_TARGET="native-native-musl -dynamic" to link against musl libc dynamically using `zig cc`.'
);
}
logger()->info('Building shared extensions...');
$this->buildSharedExts(); $this->buildSharedExts();
} }
} }
@@ -169,12 +179,19 @@ class LinuxBuilder extends UnixBuilderBase
*/ */
protected function buildCli(): void protected function buildCli(): void
{ {
if ($this->getExt('readline')) {
SourcePatcher::patchFile('musl_static_readline.patch', SOURCE_PATH . '/php-src');
}
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars()); $vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make'; $SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
shell()->cd(SOURCE_PATH . '/php-src') shell()->cd(SOURCE_PATH . '/php-src')
->exec('sed -i "s|//lib|/lib|g" Makefile') ->exec('sed -i "s|//lib|/lib|g" Makefile')
->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} cli"); ->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} cli");
if ($this->getExt('readline')) {
SourcePatcher::patchFile('musl_static_readline.patch', SOURCE_PATH . '/php-src', true);
}
if (!$this->getOption('no-strip', false)) { if (!$this->getOption('no-strip', false)) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/cli')->exec('strip --strip-unneeded php'); shell()->cd(SOURCE_PATH . '/php-src/sapi/cli')->exec('strip --strip-unneeded php');
} }

View File

@@ -291,11 +291,11 @@ abstract class UnixBuilderBase extends BuilderBase
} }
} }
$debugFlags = $this->getOption('no-strip') ? '-w -s ' : ''; $debugFlags = $this->getOption('no-strip') ? '-w -s ' : '';
$extLdFlags = "-extldflags '-pie{$dynamic_exports}'"; $extLdFlags = "-extldflags '-pie{$dynamic_exports} {$this->arch_ld_flags}'";
$muslTags = ''; $muslTags = '';
$staticFlags = ''; $staticFlags = '';
if (SPCTarget::isStatic()) { if (SPCTarget::isStatic()) {
$extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000{$dynamic_exports}'"; $extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000{$dynamic_exports} {$this->arch_ld_flags}'";
$muslTags = 'static_build,'; $muslTags = 'static_build,';
$staticFlags = '-static-pie'; $staticFlags = '-static-pie';
} }
@@ -303,7 +303,6 @@ abstract class UnixBuilderBase extends BuilderBase
$config = (new SPCConfigUtil($this))->config($this->ext_list, $this->lib_list); $config = (new SPCConfigUtil($this))->config($this->ext_list, $this->lib_list);
$cflags = "{$this->arch_c_flags} {$config['cflags']} " . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'); $cflags = "{$this->arch_c_flags} {$config['cflags']} " . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS');
$libs = $config['libs']; $libs = $config['libs'];
$libs .= PHP_OS_FAMILY === 'Linux' ? ' -lrt' : '';
// Go's gcc driver doesn't automatically link against -lgcov or -lrt. Ugly, but necessary fix. // Go's gcc driver doesn't automatically link against -lgcov or -lrt. Ugly, but necessary fix.
if ((str_contains((string) getenv('SPC_DEFAULT_C_FLAGS'), '-fprofile') || if ((str_contains((string) getenv('SPC_DEFAULT_C_FLAGS'), '-fprofile') ||
str_contains((string) getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), '-fprofile')) && str_contains((string) getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), '-fprofile')) &&

View File

@@ -12,6 +12,11 @@ trait imagemagick
{ {
protected function build(): void protected function build(): void
{ {
$original_ldflags = $this->builder->arch_ld_flags;
if (str_contains($this->builder->arch_ld_flags, '-Wl,--as-needed')) {
$this->builder->arch_ld_flags = str_replace('-Wl,--as-needed', '', $original_ldflags);
}
$ac = UnixAutoconfExecutor::create($this) $ac = UnixAutoconfExecutor::create($this)
->optionalLib('libzip', ...ac_with_args('zip')) ->optionalLib('libzip', ...ac_with_args('zip'))
->optionalLib('libjpeg', ...ac_with_args('jpeg')) ->optionalLib('libjpeg', ...ac_with_args('jpeg'))
@@ -32,7 +37,7 @@ trait imagemagick
); );
// special: linux-static target needs `-static` // special: linux-static target needs `-static`
$ldflags = SPCTarget::isStatic() ? ('-static -ldl') : '-ldl'; $ldflags = SPCTarget::isStatic() ? '-static -ldl' : '-ldl';
// special: macOS needs -iconv // special: macOS needs -iconv
$libs = SPCTarget::getTargetOS() === 'Darwin' ? '-liconv' : ''; $libs = SPCTarget::getTargetOS() === 'Darwin' ? '-liconv' : '';
@@ -45,6 +50,8 @@ trait imagemagick
$ac->configure()->make(); $ac->configure()->make();
$this->builder->arch_ld_flags = $original_ldflags;
$filelist = [ $filelist = [
'ImageMagick.pc', 'ImageMagick.pc',
'ImageMagick-7.Q16HDRI.pc', 'ImageMagick-7.Q16HDRI.pc',

View File

@@ -38,7 +38,7 @@ trait ncurses
->make(); ->make();
$final = FileSystem::scanDirFiles(BUILD_BIN_PATH, relative: true); $final = FileSystem::scanDirFiles(BUILD_BIN_PATH, relative: true);
// Remove the new files // Remove the new files
$new_files = array_diff($final, $filelist); $new_files = array_diff($final, $filelist ?: []);
foreach ($new_files as $file) { foreach ($new_files as $file) {
@unlink(BUILD_BIN_PATH . '/' . $file); @unlink(BUILD_BIN_PATH . '/' . $file);
} }

View File

@@ -4,93 +4,83 @@ declare(strict_types=1);
namespace SPC\builder\unix\library; namespace SPC\builder\unix\library;
use SPC\builder\linux\library\LinuxLibraryBase;
use SPC\exception\BuildFailureException;
use SPC\exception\FileSystemException; use SPC\exception\FileSystemException;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\util\PkgConfigUtil;
use SPC\util\SPCConfigUtil;
use SPC\util\SPCTarget; use SPC\util\SPCTarget;
trait postgresql trait postgresql
{ {
public function patchBeforeBuild(): bool
{
// fix aarch64 build on glibc 2.17 (e.g. CentOS 7)
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
FileSystem::replaceFileStr("{$this->source_dir}/src/interfaces/libpq/Makefile", 'invokes exit\'; exit 1;', 'invokes exit\';');
// disable shared libs build
FileSystem::replaceFileStr(
"{$this->source_dir}/src/Makefile.shlib",
[
'$(LINK.shared) -o $@ $(OBJS) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK)',
'$(INSTALL_SHLIB) $< \'$(DESTDIR)$(pkglibdir)/$(shlib)\'',
'$(INSTALL_SHLIB) $< \'$(DESTDIR)$(libdir)/$(shlib)\'',
'$(INSTALL_SHLIB) $< \'$(DESTDIR)$(bindir)/$(shlib)\'',
],
''
);
return true;
}
protected function build(): void protected function build(): void
{ {
$builddir = BUILD_ROOT_PATH; $libs = array_map(fn ($x) => $x->getName(), $this->getDependencies());
$envs = ''; $spc = new SPCConfigUtil($this->getBuilder(), ['no_php' => true, 'libs_only_deps' => true]);
$packages = 'zlib openssl readline libxml-2.0'; $config = $spc->config(libraries: $libs, include_suggest_lib: $this->builder->getOption('with-suggested-libs'));
$optional_packages = [
'zstd' => 'libzstd', $env_vars = [
'ldap' => 'ldap', 'CFLAGS' => $config['cflags'],
'libxslt' => 'libxslt', 'CPPFLAGS' => '-DPIC',
'icu' => 'icu-i18n', 'LDFLAGS' => $config['ldflags'],
'LIBS' => $config['libs'],
]; ];
$error_exec_cnt = 0;
foreach ($optional_packages as $lib => $pkg) { if ($ldLibraryPath = getenv('SPC_LD_LIBRARY_PATH')) {
if ($this->getBuilder()->getLib($lib)) { $env_vars['LD_LIBRARY_PATH'] = $ldLibraryPath;
$packages .= ' ' . $pkg;
$output = shell()->execWithResult("pkg-config --static {$pkg}");
$error_exec_cnt += $output[0] === 0 ? 0 : 1;
logger()->info(var_export($output[1], true));
}
}
$output = shell()->execWithResult("pkg-config --cflags-only-I --static {$packages}");
$error_exec_cnt += $output[0] === 0 ? 0 : 1;
$macos_15_bug_cflags = PHP_OS_FAMILY === 'Darwin' ? ' -Wno-unguarded-availability-new' : '';
$cflags = '';
if (!empty($output[1][0])) {
$cflags = $output[1][0];
$envs .= ' CPPFLAGS="-DPIC"';
$cflags = "{$cflags} -fno-ident{$macos_15_bug_cflags}";
}
$output = shell()->execWithResult("pkg-config --libs-only-L --static {$packages}");
$error_exec_cnt += $output[0] === 0 ? 0 : 1;
if (!empty($output[1][0])) {
$ldflags = $output[1][0];
$envs .= SPCTarget::isStatic() ? " LDFLAGS=\"{$ldflags} -static\" " : " LDFLAGS=\"{$ldflags}\" ";
}
$output = shell()->execWithResult("pkg-config --libs-only-l --static {$packages}");
$error_exec_cnt += $output[0] === 0 ? 0 : 1;
if (!empty($output[1][0])) {
$libs = $output[1][0];
$libcpp = '';
if ($this->builder->getLib('icu')) {
$libcpp = $this instanceof LinuxLibraryBase ? ' -lstdc++' : ' -lc++';
}
$envs .= " LIBS=\"{$libs}{$libcpp}\" ";
}
if ($error_exec_cnt > 0) {
throw new BuildFailureException('Failed to get pkg-config information!');
} }
FileSystem::resetDir($this->source_dir . '/build'); FileSystem::resetDir($this->source_dir . '/build');
$version = $this->getVersion(); // php source relies on the non-private encoding functions in libpgcommon.a
// 16.1 workaround FileSystem::replaceFileStr(
if (version_compare($version, '16.1') >= 0) { "{$this->source_dir}/src/common/Makefile",
# 有静态链接配置 参考文件: src/interfaces/libpq/Makefile '$(OBJS_FRONTEND): CPPFLAGS += -DUSE_PRIVATE_ENCODING_FUNCS',
shell()->cd($this->source_dir . '/build') '$(OBJS_FRONTEND): CPPFLAGS += -UUSE_PRIVATE_ENCODING_FUNCS -DFRONTEND',
->exec('sed -i.backup "s/invokes exit\'; exit 1;/invokes exit\';/" ../src/interfaces/libpq/Makefile') );
->exec('sed -i.backup "278 s/^/# /" ../src/Makefile.shlib')
->exec('sed -i.backup "402 s/^/# /" ../src/Makefile.shlib');
} else {
throw new BuildFailureException('Unsupported version for postgresql: ' . $version . ' !');
}
// configure // configure
shell()->cd($this->source_dir . '/build')->initializeEnv($this) $shell = shell()->cd("{$this->source_dir}/build")->initializeEnv($this)
->appendEnv(['CFLAGS' => $cflags]) ->appendEnv($env_vars)
->exec( ->exec(
"{$envs} ../configure " . '../configure ' .
"--prefix={$builddir} " . "--prefix={$this->getBuildRootPath()} " .
($this->builder->getOption('enable-zts') ? '--enable-thread-safety ' : '--disable-thread-safety ') .
'--enable-coverage=no ' . '--enable-coverage=no ' .
'--with-ssl=openssl ' . '--with-ssl=openssl ' .
'--with-readline ' . '--with-readline ' .
'--with-libxml ' . '--with-libxml ' .
($this->builder->getLib('icu') ? '--with-icu ' : '--without-icu ') . ($this->builder->getLib('icu') ? '--with-icu ' : '--without-icu ') .
($this->builder->getLib('ldap') ? '--with-ldap ' : '--without-ldap ') . ($this->builder->getLib('ldap') ? '--with-ldap ' : '--without-ldap ') .
// '--without-ldap ' .
($this->builder->getLib('libxslt') ? '--with-libxslt ' : '--without-libxslt ') . ($this->builder->getLib('libxslt') ? '--with-libxslt ' : '--without-libxslt ') .
($this->builder->getLib('zstd') ? '--with-zstd ' : '--without-zstd ') . ($this->builder->getLib('zstd') ? '--with-zstd ' : '--without-zstd ') .
'--without-lz4 ' . '--without-lz4 ' .
@@ -99,32 +89,29 @@ trait postgresql
'--without-pam ' . '--without-pam ' .
'--without-bonjour ' . '--without-bonjour ' .
'--without-tcl ' '--without-tcl '
) );
->exec($envs . ' make -C src/bin/pg_config install')
->exec($envs . ' make -C src/include install') // patch ldap lib
->exec($envs . ' make -C src/common install') if ($this->builder->getLib('ldap')) {
->exec($envs . ' make -C src/port install') $libs = PkgConfigUtil::getLibsArray('ldap');
->exec($envs . ' make -C src/interfaces/libpq install'); $libs = clean_spaces(implode(' ', $libs));
FileSystem::replaceFileStr($this->source_dir . '/build/config.status', '-lldap', $libs);
FileSystem::replaceFileStr($this->source_dir . '/build/src/Makefile.global', '-lldap', $libs);
}
$shell
->exec('make -C src/bin/pg_config install')
->exec('make -C src/include install')
->exec('make -C src/common install')
->exec('make -C src/port install')
->exec('make -C src/interfaces/libpq install');
// remove dynamic libs // remove dynamic libs
shell()->cd($this->source_dir . '/build') shell()->cd($this->source_dir . '/build')
->exec("rm -rf {$builddir}/lib/*.so.*") ->exec("rm -rf {$this->getBuildRootPath()}/lib/*.so.*")
->exec("rm -rf {$builddir}/lib/*.so") ->exec("rm -rf {$this->getBuildRootPath()}/lib/*.so")
->exec("rm -rf {$builddir}/lib/*.dylib"); ->exec("rm -rf {$this->getBuildRootPath()}/lib/*.dylib");
FileSystem::replaceFileStr(BUILD_LIB_PATH . '/pkgconfig/libpq.pc', '-lldap', '-lldap -llber'); FileSystem::replaceFileStr("{$this->getLibDir()}/pkgconfig/libpq.pc", '-lldap', '-lldap -llber');
}
private function getVersion(): string
{
try {
$file = FileSystem::readFile($this->source_dir . '/meson.build');
if (preg_match("/^\\s+version:\\s?'(.*)'/m", $file, $match)) {
return $match[1];
}
return 'unknown';
} catch (FileSystemException) {
return 'unknown';
}
} }
} }

View File

@@ -106,7 +106,7 @@ class DownloadCommand extends BaseCommand
} }
// retry // retry
$retry = intval($this->getOption('retry')); $retry = (int) $this->getOption('retry');
f_putenv('SPC_DOWNLOAD_RETRIES=' . $retry); f_putenv('SPC_DOWNLOAD_RETRIES=' . $retry);
// Use shallow-clone can reduce git resource download // Use shallow-clone can reduce git resource download
@@ -265,7 +265,7 @@ class DownloadCommand extends BaseCommand
f_passthru((PHP_OS_FAMILY === 'Windows' ? 'rmdir /s /q ' : 'rm -rf ') . DOWNLOAD_PATH); f_passthru((PHP_OS_FAMILY === 'Windows' ? 'rmdir /s /q ' : 'rm -rf ') . DOWNLOAD_PATH);
} }
// unzip command check // unzip command check
if (PHP_OS_FAMILY !== 'Windows' && !$this->findCommand('unzip')) { if (PHP_OS_FAMILY !== 'Windows' && !self::findCommand('unzip')) {
$this->output->writeln('Missing unzip command, you need to install it first !'); $this->output->writeln('Missing unzip command, you need to install it first !');
$this->output->writeln('You can use "bin/spc doctor" command to check and install required tools'); $this->output->writeln('You can use "bin/spc doctor" command to check and install required tools');
return static::FAILURE; return static::FAILURE;

View File

@@ -28,7 +28,7 @@ class LinuxToolCheckList
public const TOOLS_DEBIAN = [ public const TOOLS_DEBIAN = [
'make', 'bison', 're2c', 'flex', 'make', 'bison', 're2c', 'flex',
'git', 'autoconf', 'automake', 'autopoint', 'git', 'autoconf', 'automake', 'autopoint',
'tar', 'unzip', 'gzip', 'tar', 'unzip', 'gzip', 'gcc', 'g++',
'bzip2', 'cmake', 'patch', 'bzip2', 'cmake', 'patch',
'xz', 'libtoolize', 'which', 'xz', 'libtoolize', 'which',
'patchelf', 'patchelf',
@@ -37,7 +37,7 @@ class LinuxToolCheckList
public const TOOLS_RHEL = [ public const TOOLS_RHEL = [
'perl', 'make', 'bison', 're2c', 'flex', 'perl', 'make', 'bison', 're2c', 'flex',
'git', 'autoconf', 'automake', 'git', 'autoconf', 'automake',
'tar', 'unzip', 'gzip', 'gcc', 'tar', 'unzip', 'gzip', 'gcc', 'g++',
'bzip2', 'cmake', 'patch', 'which', 'bzip2', 'cmake', 'patch', 'which',
'xz', 'libtool', 'gettext-devel', 'xz', 'libtool', 'gettext-devel',
'patchelf', 'patchelf',

View File

@@ -65,19 +65,19 @@ class Downloader
url: "https://api.github.com/repos/{$source['repo']}/{$type}", url: "https://api.github.com/repos/{$source['repo']}/{$type}",
hooks: [[CurlHook::class, 'setupGithubToken']], hooks: [[CurlHook::class, 'setupGithubToken']],
retries: self::getRetryAttempts() retries: self::getRetryAttempts()
), true); ), true, 512, JSON_THROW_ON_ERROR);
$url = null; $url = null;
for ($i = 0; $i < count($data); ++$i) { foreach ($data as $rel) {
if (($data[$i]['prerelease'] ?? false) === true && ($source['prefer-stable'] ?? false)) { if (($rel['prerelease'] ?? false) === true && ($source['prefer-stable'] ?? false)) {
continue; continue;
} }
if (!($source['match'] ?? null)) { if (!($source['match'] ?? null)) {
$url = $data[$i]['tarball_url'] ?? null; $url = $rel['tarball_url'] ?? null;
break; break;
} }
if (preg_match('|' . $source['match'] . '|', $data[$i]['tarball_url'])) { if (preg_match('|' . $source['match'] . '|', $rel['tarball_url'])) {
$url = $data[$i]['tarball_url']; $url = $rel['tarball_url'];
break; break;
} }
} }
@@ -232,7 +232,8 @@ class Downloader
$quiet = !defined('DEBUG_MODE') ? '-q --quiet' : ''; $quiet = !defined('DEBUG_MODE') ? '-q --quiet' : '';
$git = SPC_GIT_EXEC; $git = SPC_GIT_EXEC;
$shallow = defined('GIT_SHALLOW_CLONE') ? '--depth 1 --single-branch' : ''; $shallow = defined('GIT_SHALLOW_CLONE') ? '--depth 1 --single-branch' : '';
$recursive = ($submodules === null) ? '--recursive' : ''; $recursive = ($submodules === null && defined('GIT_SHALLOW_CLONE')) ? '--recursive --shallow-submodules' : null;
$recursive ??= $submodules === null ? '--recursive' : '';
try { try {
self::registerCancelEvent(function () use ($download_path) { self::registerCancelEvent(function () use ($download_path) {
@@ -243,8 +244,9 @@ class Downloader
}); });
f_passthru("{$git} clone {$quiet} --config core.autocrlf=false --branch \"{$branch}\" {$shallow} {$recursive} \"{$url}\" \"{$download_path}\""); f_passthru("{$git} clone {$quiet} --config core.autocrlf=false --branch \"{$branch}\" {$shallow} {$recursive} \"{$url}\" \"{$download_path}\"");
if ($submodules !== null) { if ($submodules !== null) {
$depth_flag = defined('GIT_SHALLOW_CLONE') ? '--depth 1' : '';
foreach ($submodules as $submodule) { foreach ($submodules as $submodule) {
f_passthru("cd \"{$download_path}\" && {$git} submodule update --init " . escapeshellarg($submodule)); f_passthru("cd \"{$download_path}\" && {$git} submodule update --init {$depth_flag} " . escapeshellarg($submodule));
} }
} }
} catch (SPCException $e) { } catch (SPCException $e) {
@@ -399,7 +401,7 @@ class Downloader
* Download source * Download source
* *
* @param string $name source name * @param string $name source name
* @param null|array{ * @param null|array{
* type: string, * type: string,
* repo: ?string, * repo: ?string,
* url: ?string, * url: ?string,
@@ -414,7 +416,7 @@ class Downloader
* path: ?string, * path: ?string,
* text: ?string * text: ?string
* } * }
* } $source source meta info: [type, path, rev, url, filename, regex, license] * } $source source meta info: [type, path, rev, url, filename, regex, license]
* @param bool $force Whether to force download (default: false) * @param bool $force Whether to force download (default: false)
* @param int $download_as Lock source type (default: SPC_LOCK_SOURCE) * @param int $download_as Lock source type (default: SPC_LOCK_SOURCE)
*/ */

View File

@@ -19,9 +19,15 @@ while [[ $# -gt 0 ]]; do
ARG_ABS="$(realpath "$ARG" 2>/dev/null || true)" ARG_ABS="$(realpath "$ARG" 2>/dev/null || true)"
[[ "$ARG_ABS" == "$BUILDROOT_ABS" ]] && PARSED_ARGS+=("-I$ARG") || PARSED_ARGS+=("-isystem$ARG") [[ "$ARG_ABS" == "$BUILDROOT_ABS" ]] && PARSED_ARGS+=("-I$ARG") || PARSED_ARGS+=("-isystem$ARG")
;; ;;
-march=*|-mcpu=*) # replace -march=x86-64 with -march=x86_64 -march=*|-mcpu=*)
OPT_NAME="${1%%=*}" OPT_NAME="${1%%=*}"
OPT_VALUE="${1#*=}" OPT_VALUE="${1#*=}"
# Skip armv8- flags entirely as Zig doesn't support them
if [[ "$OPT_VALUE" == armv8-* ]]; then
shift
continue
fi
# replace -march=x86-64 with -march=x86_64
OPT_VALUE="${OPT_VALUE//-/_}" OPT_VALUE="${OPT_VALUE//-/_}"
PARSED_ARGS+=("${OPT_NAME}=${OPT_VALUE}") PARSED_ARGS+=("${OPT_NAME}=${OPT_VALUE}")
shift shift

View File

@@ -16,11 +16,11 @@ class PhpSource extends CustomSourceBase
{ {
$major = defined('SPC_BUILD_PHP_VERSION') ? SPC_BUILD_PHP_VERSION : '8.4'; $major = defined('SPC_BUILD_PHP_VERSION') ? SPC_BUILD_PHP_VERSION : '8.4';
if ($major === '8.5') { if ($major === '8.5') {
Downloader::downloadSource('php-src', ['type' => 'url', 'url' => 'https://downloads.php.net/~edorian/php-8.5.0beta1.tar.xz'], $force); Downloader::downloadSource('php-src', ['type' => 'url', 'url' => 'https://github.com/php/php-src/archive/refs/tags/php-8.5.0RC2.tar.gz'], $force);
} elseif ($major === 'git') { } elseif ($major === 'git') {
Downloader::downloadSource('php-src', ['type' => 'git', 'url' => 'https://github.com/php/php-src.git', 'rev' => 'master'], $force); Downloader::downloadSource('php-src', ['type' => 'git', 'url' => 'https://github.com/php/php-src.git', 'rev' => 'master'], $force);
} else { } else {
Downloader::downloadSource('php-src', self::getLatestPHPInfo($major), $force); Downloader::downloadSource('php-src', $this->getLatestPHPInfo($major), $force);
} }
} }
@@ -33,7 +33,7 @@ class PhpSource extends CustomSourceBase
// 查找最新的小版本号 // 查找最新的小版本号
$info = json_decode(Downloader::curlExec( $info = json_decode(Downloader::curlExec(
url: "https://www.php.net/releases/index.php?json&version={$major_version}", url: "https://www.php.net/releases/index.php?json&version={$major_version}",
retries: intval(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.");

View File

@@ -64,6 +64,11 @@ class ZigToolchain implements ToolchainInterface
$extra_libs = trim($extra_libs . ' -lunwind'); $extra_libs = trim($extra_libs . ' -lunwind');
GlobalEnvManager::putenv("SPC_EXTRA_LIBS={$extra_libs}"); GlobalEnvManager::putenv("SPC_EXTRA_LIBS={$extra_libs}");
} }
$cflags = getenv('SPC_DEFAULT_C_FLAGS') ?: getenv('CFLAGS') ?: '';
$has_avx512 = str_contains($cflags, '-mavx512') || str_contains($cflags, '-march=x86-64-v4');
if (!$has_avx512) {
GlobalEnvManager::putenv('SPC_EXTRA_PHP_VARS=php_cv_have_avx512=no php_cv_have_avx512vbmi=no');
}
} }
public function getCompilerInfo(): ?string public function getCompilerInfo(): ?string

View File

@@ -40,7 +40,12 @@ class GlobalEnvManager
if (is_unix()) { if (is_unix()) {
self::addPathIfNotExists(BUILD_BIN_PATH); self::addPathIfNotExists(BUILD_BIN_PATH);
self::addPathIfNotExists(PKG_ROOT_PATH . '/bin'); self::addPathIfNotExists(PKG_ROOT_PATH . '/bin');
self::putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig'); $pkgConfigPath = getenv('PKG_CONFIG_PATH');
if ($pkgConfigPath !== false) {
self::putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . "/pkgconfig:{$pkgConfigPath}");
} else {
self::putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig');
}
} }
$ini = self::readIniFile(); $ini = self::readIniFile();

View File

@@ -6,6 +6,7 @@ namespace SPC\util;
use SPC\builder\BuilderBase; use SPC\builder\BuilderBase;
use SPC\builder\BuilderProvider; use SPC\builder\BuilderProvider;
use SPC\builder\Extension;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
use SPC\store\Config; use SPC\store\Config;
use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\ArgvInput;
@@ -87,7 +88,7 @@ class SPCConfigUtil
if (SPCTarget::getTargetOS() === 'Darwin') { if (SPCTarget::getTargetOS() === 'Darwin') {
$libs .= " {$this->getFrameworksString($extensions)}"; $libs .= " {$this->getFrameworksString($extensions)}";
} }
if ($this->builder->hasCpp()) { if ($this->hasCpp($extensions, $libraries)) {
$libcpp = SPCTarget::getTargetOS() === 'Darwin' ? '-lc++' : '-lstdc++'; $libcpp = SPCTarget::getTargetOS() === 'Darwin' ? '-lc++' : '-lstdc++';
$libs = str_replace($libcpp, '', $libs) . " {$libcpp}"; $libs = str_replace($libcpp, '', $libs) . " {$libcpp}";
} }
@@ -123,6 +124,27 @@ class SPCConfigUtil
]; ];
} }
private function hasCpp(array $extensions, array $libraries): bool
{
// judge cpp-extension
$builderExtNames = array_keys($this->builder->getExts(false));
$exts = array_unique([...$builderExtNames, ...$extensions]);
foreach ($exts as $ext) {
if (Config::getExt($ext, 'cpp-extension', false) === true) {
return true;
}
}
$builderLibNames = array_keys($this->builder->getLibs());
$libs = array_unique([...$builderLibNames, ...$libraries]);
foreach ($libs as $lib) {
if (Config::getLib($lib, 'cpp-library', false) === true) {
return true;
}
}
return false;
}
private function getIncludesString(array $libraries): string private function getIncludesString(array $libraries): string
{ {
$base = BUILD_INCLUDE_PATH; $base = BUILD_INCLUDE_PATH;

View File

@@ -245,6 +245,23 @@ function clean_spaces(string $string): string
return trim(preg_replace('/\s+/', ' ', $string)); return trim(preg_replace('/\s+/', ' ', $string));
} }
/**
* Deduplicate flags in a string. Only the last occurence of each flag will be kept.
* E.g. `-lintl -lstdc++ -lphp -lstdc++` becomes `-lintl -lphp -lstdc++`
*
* @param string $flags the string containing flags to deduplicate
* @return string the deduplicated string with no duplicate flags
*/
function deduplicate_flags(string $flags): string
{
$tokens = preg_split('/\s+/', trim($flags));
// Reverse, unique, reverse back - keeps last occurrence of duplicates
$deduplicated = array_reverse(array_unique(array_reverse($tokens)));
return implode(' ', $deduplicated);
}
/** /**
* Register a callback function to handle keyboard interrupts (Ctrl+C). * Register a callback function to handle keyboard interrupts (Ctrl+C).
* *

View File

@@ -0,0 +1,26 @@
diff --git a/ext/readline/readline_cli.c b/ext/readline/readline_cli.c
index 31212999..d80a21c3 100644
--- a/ext/readline/readline_cli.c
+++ b/ext/readline/readline_cli.c
@@ -739,8 +739,8 @@ typedef cli_shell_callbacks_t *(__cdecl *get_cli_shell_callbacks)(void);
} while(0)
#else
-/*
#ifdef COMPILE_DL_READLINE
+/*
This dlsym() is always used as even the CGI SAPI is linked against "CLI"-only
extensions. If that is being changed dlsym() should only be used when building
this extension sharedto offer compatibility.
@@ -754,9 +754,9 @@ this extension sharedto offer compatibility.
(cb) = get_callbacks(); \
} \
} while(0)
-/*#else
+#else
#define GET_SHELL_CB(cb) (cb) = php_cli_get_shell_callbacks()
-#endif*/
+#endif
#endif
PHP_MINIT_FUNCTION(cli_readline)

View File

@@ -21,21 +21,20 @@ $test_php_version = [
// 'git', // 'git',
]; ];
// test os (macos-13, macos-14, 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-13', // bin/spc for x86_64 'macos-15-intel', // bin/spc for x86_64
// 'macos-14', // bin/spc for arm64
'macos-15', // bin/spc for arm64 'macos-15', // bin/spc for arm64
'ubuntu-latest', // bin/spc-alpine-docker for x86_64 // 'ubuntu-latest', // bin/spc-alpine-docker for x86_64
'ubuntu-22.04', // bin/spc-gnu-docker for x86_64 // 'ubuntu-22.04', // bin/spc-gnu-docker for x86_64
// 'ubuntu-24.04', // bin/spc for x86_64 // 'ubuntu-24.04', // bin/spc for x86_64
'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64 // 'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64
// 'ubuntu-24.04-arm', // bin/spc for arm64 // 'ubuntu-24.04-arm', // bin/spc for arm64
// 'windows-latest', // .\bin\spc.ps1 // 'windows-latest', // .\bin\spc.ps1
]; ];
// whether enable thread safe // whether enable thread safe
$zts = true; $zts = false;
$no_strip = false; $no_strip = false;
@@ -50,13 +49,13 @@ $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' => 'bcmath', 'Linux', 'Darwin' => 'pdo_pgsql',
'Windows' => 'bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,iconv,xml,mbstring,mbregex,mysqlnd,openssl,pdo,pdo_mysql,pdo_sqlite,phar,session,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip', 'Windows' => 'bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,iconv,xml,mbstring,mbregex,mysqlnd,openssl,pdo,pdo_mysql,pdo_sqlite,phar,session,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip',
}; };
// 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`).
$shared_extensions = match (PHP_OS_FAMILY) { $shared_extensions = match (PHP_OS_FAMILY) {
'Linux' => 'zip', 'Linux' => '',
'Darwin' => '', 'Darwin' => '',
'Windows' => '', 'Windows' => '',
}; };
@@ -156,17 +155,13 @@ if ($shared_extensions) {
switch ($argv[2] ?? null) { switch ($argv[2] ?? null) {
case 'ubuntu-22.04': case 'ubuntu-22.04':
case 'ubuntu-22.04-arm': case 'ubuntu-22.04-arm':
case 'macos-15':
case 'macos-15-intel':
$shared_cmd = ' --build-shared=' . quote2($shared_extensions) . ' '; $shared_cmd = ' --build-shared=' . quote2($shared_extensions) . ' ';
break; break;
case 'ubuntu-24.04': case 'ubuntu-24.04':
case 'ubuntu-24.04-arm': case 'ubuntu-24.04-arm':
break; break;
case 'macos-13':
case 'macos-14':
case 'macos-15':
$shared_cmd = ' --build-shared=' . quote2($shared_extensions) . ' ';
$no_strip = true;
break;
default: default:
$shared_cmd = ''; $shared_cmd = '';
break; break;

View File

@@ -62,12 +62,6 @@ class BuilderTest extends TestCase
$this->assertInstanceOf(Extension::class, $this->builder->getExt('mbregex')); $this->assertInstanceOf(Extension::class, $this->builder->getExt('mbregex'));
} }
public function testHasCpp()
{
// mbregex doesn't have cpp
$this->assertFalse($this->builder->hasCpp());
}
public function testMakeExtensionArgs() public function testMakeExtensionArgs()
{ {
$this->assertStringContainsString('--enable-mbstring', $this->builder->makeStaticExtensionArgs()); $this->assertStringContainsString('--enable-mbstring', $this->builder->makeStaticExtensionArgs());