Compare commits

..

1 Commits

Author SHA1 Message Date
crazywhalecc
1a6c044ee9 Add google analytics for docs 2025-11-04 09:45:25 +08:00
50 changed files with 472 additions and 1291 deletions

View File

@@ -1,24 +1,24 @@
# StaticPHP # static-php-cli
[![Chinese readme](https://img.shields.io/badge/README-%E4%B8%AD%E6%96%87%20%F0%9F%87%A8%F0%9F%87%B3-moccasin?style=flat-square)](README-zh.md)
[![English readme](https://img.shields.io/badge/README-English%20%F0%9F%87%AC%F0%9F%87%A7-moccasin?style=flat-square)](README.md) [![English readme](https://img.shields.io/badge/README-English%20%F0%9F%87%AC%F0%9F%87%A7-moccasin?style=flat-square)](README.md)
[![Chinese readme](https://img.shields.io/badge/README-%E4%B8%AD%E6%96%87%20%F0%9F%87%A8%F0%9F%87%B3-moccasin?style=flat-square)](README-zh.md)
[![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)
**StaticPHP**(原名 **static-php-cli**是一个用于构建静态、独立 PHP 运行时的强大工具,支持众多流行扩展。 **static-php-cli** 是一个用于构建静态、独立 PHP 运行时的强大工具,支持众多流行扩展。
## 特性 ## 特性
- :elephant: **支持多 PHP 版本** - 支持 PHP 8.1, 8.2, 8.3, 8.4, 8.5 - :elephant: **支持多 PHP 版本** - 支持 PHP 8.1, 8.2, 8.3, 8.4, 8.5
- :handbag: **单文件 PHP 可执行文件** - 构建零依赖的独立 PHP - :handbag: **单文件 PHP 可执行文件** - 构建零依赖的独立 PHP
- :hamburger: **phpmicro 集成** - 构建 **[phpmicro](https://github.com/static-php/phpmicro)** 自解压可执行文件(将 PHP 二进制文件和源代码合并为一个文件) - :hamburger: **phpmicro 集成** - 构建 **[phpmicro](https://github.com/dixyes/phpmicro)** 自解压可执行文件(将 PHP 二进制文件和源代码合并为一个文件)
- :pill: **智能环境检查器** - 自动构建环境检查器,具备自动修复功能 - :pill: **智能环境检查器** - 自动构建环境检查器,具备自动修复功能
- :zap: **跨平台支持** - 支持 Linux、macOS、FreeBSD 和 Windows - :zap: **跨平台支持** - 支持 Linux、macOS、FreeBSD 和 Windows
- :wrench: **可配置补丁** - 可自定义的源代码补丁系统 - :wrench: **可配置补丁** - 可自定义的源代码补丁系统
- :books: **智能依赖管理** - 自动处理构建依赖 - :books: **智能依赖管理** - 自动处理构建依赖
- 📦 **自包含工具** - 提供使用 [box](https://github.com/box-project/box) 构建的 `spc` 可执行文件 - 📦 **自包含工具** - 提供使用 [box](https://github.com/box-project/box) 构建的 `spc` 可执行文件
- :fire: **广泛的扩展支持** - 支持 100+ 流行 [扩展](https://static-php.dev/zh/guide/extensions.html) - :fire: **广泛的扩展支持** - 支持 75+ 流行 [扩展](https://static-php.dev/zh/guide/extensions.html)
- :floppy_disk: **UPX 压缩** - 减小二进制文件大小 30-50%(仅 Linux/Windows - :floppy_disk: **UPX 压缩** - 减小二进制文件大小 30-50%(仅 Linux/Windows
**单文件独立 php-cli** **单文件独立 php-cli**
@@ -33,8 +33,6 @@
### 1. 下载 spc 二进制文件 ### 1. 下载 spc 二进制文件
`spc` 二进制文件是 StaticPHP 项目的 CLI 工具,打包为单个可执行文件。
```bash ```bash
# Linux x86_64 # Linux x86_64
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-x86_64 curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-x86_64

View File

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

View File

@@ -162,47 +162,6 @@ if [ ! -z "$GITHUB_TOKEN" ]; then
ENV_LIST="$ENV_LIST -e GITHUB_TOKEN=$GITHUB_TOKEN" ENV_LIST="$ENV_LIST -e GITHUB_TOKEN=$GITHUB_TOKEN"
fi fi
# Intercept and rewrite --with-frankenphp-app option, and mount host path to /app/app
FRANKENPHP_APP_PATH=""
NEW_ARGS=()
while [ $# -gt 0 ]; do
case "$1" in
--with-frankenphp-app=*)
FRANKENPHP_APP_PATH="${1#*=}"
NEW_ARGS+=("--with-frankenphp-app=/app/app")
shift
;;
--with-frankenphp-app)
if [ -n "${2:-}" ]; then
FRANKENPHP_APP_PATH="$2"
NEW_ARGS+=("--with-frankenphp-app=/app/app")
shift 2
else
NEW_ARGS+=("$1")
shift
fi
;;
*)
NEW_ARGS+=("$1")
shift
;;
esac
done
# Normalize the path and add mount if provided
if [ -n "$FRANKENPHP_APP_PATH" ]; then
# expand ~ to $HOME
if [ "${FRANKENPHP_APP_PATH#~}" != "$FRANKENPHP_APP_PATH" ]; then
FRANKENPHP_APP_PATH="$HOME${FRANKENPHP_APP_PATH#~}"
fi
# make absolute if relative
case "$FRANKENPHP_APP_PATH" in
/*) ABS_APP_PATH="$FRANKENPHP_APP_PATH" ;;
*) ABS_APP_PATH="$(pwd)/$FRANKENPHP_APP_PATH" ;;
esac
MOUNT_LIST="$MOUNT_LIST -v $ABS_APP_PATH:/app/app"
fi
# Run docker # Run docker
# shellcheck disable=SC2068 # shellcheck disable=SC2068
# shellcheck disable=SC2086 # shellcheck disable=SC2086
@@ -224,5 +183,5 @@ if [ "$SPC_DOCKER_DEBUG" = "yes" ]; then
set -ex set -ex
$DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST $MOUNT_LIST cwcc-spc-$SPC_USE_ARCH-$SPC_DOCKER_VERSION /bin/bash $DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST $MOUNT_LIST cwcc-spc-$SPC_USE_ARCH-$SPC_DOCKER_VERSION /bin/bash
else else
$DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST $MOUNT_LIST cwcc-spc-$SPC_USE_ARCH-$SPC_DOCKER_VERSION bin/spc "${NEW_ARGS[@]}" $DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST $MOUNT_LIST cwcc-spc-$SPC_USE_ARCH-$SPC_DOCKER_VERSION bin/spc $@
fi fi

View File

@@ -174,47 +174,6 @@ if [ ! -z "$GITHUB_TOKEN" ]; then
ENV_LIST="$ENV_LIST -e GITHUB_TOKEN=$GITHUB_TOKEN" ENV_LIST="$ENV_LIST -e GITHUB_TOKEN=$GITHUB_TOKEN"
fi fi
# Intercept and rewrite --with-frankenphp-app option, and mount host path to /app/app
FRANKENPHP_APP_PATH=""
NEW_ARGS=()
while [ $# -gt 0 ]; do
case "$1" in
--with-frankenphp-app=*)
FRANKENPHP_APP_PATH="${1#*=}"
NEW_ARGS+=("--with-frankenphp-app=/app/app")
shift
;;
--with-frankenphp-app)
if [ -n "${2:-}" ]; then
FRANKENPHP_APP_PATH="$2"
NEW_ARGS+=("--with-frankenphp-app=/app/app")
shift 2
else
NEW_ARGS+=("$1")
shift
fi
;;
*)
NEW_ARGS+=("$1")
shift
;;
esac
done
# Normalize the path and add mount if provided
if [ -n "$FRANKENPHP_APP_PATH" ]; then
# expand ~ to $HOME
if [ "${FRANKENPHP_APP_PATH#~}" != "$FRANKENPHP_APP_PATH" ]; then
FRANKENPHP_APP_PATH="$HOME${FRANKENPHP_APP_PATH#~}"
fi
# make absolute if relative
case "$FRANKENPHP_APP_PATH" in
/*) ABS_APP_PATH="$FRANKENPHP_APP_PATH" ;;
*) ABS_APP_PATH="$(pwd)/$FRANKENPHP_APP_PATH" ;;
esac
MOUNT_LIST="$MOUNT_LIST -v $ABS_APP_PATH:/app/app"
fi
# Run docker # Run docker
# shellcheck disable=SC2068 # shellcheck disable=SC2068
# shellcheck disable=SC2086 # shellcheck disable=SC2086
@@ -237,5 +196,5 @@ if [ "$SPC_DOCKER_DEBUG" = "yes" ]; then
set -ex set -ex
$DOCKER_EXECUTABLE run $PLATFORM_ARG --privileged --rm -it $INTERACT $ENV_LIST --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION /bin/bash $DOCKER_EXECUTABLE run $PLATFORM_ARG --privileged --rm -it $INTERACT $ENV_LIST --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION /bin/bash
else else
$DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION bin/spc "${NEW_ARGS[@]}" $DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION bin/spc $@
fi fi

176
composer.lock generated
View File

@@ -416,16 +416,16 @@
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v7.3.6", "version": "v7.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a" "reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/c28ad91448f86c5f6d9d2c70f0cf68bf135f252a", "url": "https://api.github.com/repos/symfony/console/zipball/2b9c5fafbac0399a20a2e82429e2bd735dcfb7db",
"reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a", "reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -490,7 +490,7 @@
"terminal" "terminal"
], ],
"support": { "support": {
"source": "https://github.com/symfony/console/tree/v7.3.6" "source": "https://github.com/symfony/console/tree/v7.3.4"
}, },
"funding": [ "funding": [
{ {
@@ -510,7 +510,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-11-04T01:21:42+00:00" "time": "2025-09-22T15:31:00+00:00"
}, },
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
@@ -981,16 +981,16 @@
}, },
{ {
"name": "symfony/service-contracts", "name": "symfony/service-contracts",
"version": "v3.6.1", "version": "v3.6.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/service-contracts.git", "url": "https://github.com/symfony/service-contracts.git",
"reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
"reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1044,7 +1044,7 @@
"standards" "standards"
], ],
"support": { "support": {
"source": "https://github.com/symfony/service-contracts/tree/v3.6.1" "source": "https://github.com/symfony/service-contracts/tree/v3.6.0"
}, },
"funding": [ "funding": [
{ {
@@ -1055,16 +1055,12 @@
"url": "https://github.com/fabpot", "url": "https://github.com/fabpot",
"type": "github" "type": "github"
}, },
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{ {
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-07-15T11:30:57+00:00" "time": "2025-04-25T09:37:31+00:00"
}, },
{ {
"name": "symfony/string", "name": "symfony/string",
@@ -1158,16 +1154,16 @@
}, },
{ {
"name": "symfony/yaml", "name": "symfony/yaml",
"version": "v7.3.5", "version": "v7.3.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/yaml.git", "url": "https://github.com/symfony/yaml.git",
"reference": "90208e2fc6f68f613eae7ca25a2458a931b1bacc" "reference": "d4f4a66866fe2451f61296924767280ab5732d9d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/90208e2fc6f68f613eae7ca25a2458a931b1bacc", "url": "https://api.github.com/repos/symfony/yaml/zipball/d4f4a66866fe2451f61296924767280ab5732d9d",
"reference": "90208e2fc6f68f613eae7ca25a2458a931b1bacc", "reference": "d4f4a66866fe2451f61296924767280ab5732d9d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1210,7 +1206,7 @@
"description": "Loads and dumps YAML files", "description": "Loads and dumps YAML files",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/yaml/tree/v7.3.5" "source": "https://github.com/symfony/yaml/tree/v7.3.3"
}, },
"funding": [ "funding": [
{ {
@@ -1230,20 +1226,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-09-27T09:00:46+00:00" "time": "2025-08-27T11:34:33+00:00"
}, },
{ {
"name": "zhamao/logger", "name": "zhamao/logger",
"version": "1.1.4", "version": "1.1.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/zhamao-robot/zhamao-logger.git", "url": "https://github.com/zhamao-robot/zhamao-logger.git",
"reference": "b28c0c26d59d58f153c764f224c21c5901213e25" "reference": "2551b3e1dbbb1db81794d5c3a666c66804a9dca9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/zhamao-robot/zhamao-logger/zipball/b28c0c26d59d58f153c764f224c21c5901213e25", "url": "https://api.github.com/repos/zhamao-robot/zhamao-logger/zipball/2551b3e1dbbb1db81794d5c3a666c66804a9dca9",
"reference": "b28c0c26d59d58f153c764f224c21c5901213e25", "reference": "2551b3e1dbbb1db81794d5c3a666c66804a9dca9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1297,9 +1293,9 @@
"description": "Another Console Logger for CLI Applications", "description": "Another Console Logger for CLI Applications",
"support": { "support": {
"issues": "https://github.com/zhamao-robot/zhamao-logger/issues", "issues": "https://github.com/zhamao-robot/zhamao-logger/issues",
"source": "https://github.com/zhamao-robot/zhamao-logger/tree/1.1.4" "source": "https://github.com/zhamao-robot/zhamao-logger/tree/1.1.3"
}, },
"time": "2025-11-08T15:38:01+00:00" "time": "2025-08-02T13:44:27+00:00"
} }
], ],
"packages-dev": [ "packages-dev": [
@@ -2864,16 +2860,16 @@
}, },
{ {
"name": "friendsofphp/php-cs-fixer", "name": "friendsofphp/php-cs-fixer",
"version": "v3.89.2", "version": "v3.89.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "7569658f91e475ec93b99bd5964b059ad1336dcf" "reference": "4dd6768cb7558440d27d18f54909eee417317ce9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/7569658f91e475ec93b99bd5964b059ad1336dcf", "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/4dd6768cb7558440d27d18f54909eee417317ce9",
"reference": "7569658f91e475ec93b99bd5964b059ad1336dcf", "reference": "4dd6768cb7558440d27d18f54909eee417317ce9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2909,7 +2905,7 @@
"justinrainbow/json-schema": "^6.5", "justinrainbow/json-schema": "^6.5",
"keradus/cli-executor": "^2.2", "keradus/cli-executor": "^2.2",
"mikey179/vfsstream": "^1.6.12", "mikey179/vfsstream": "^1.6.12",
"php-coveralls/php-coveralls": "^2.9", "php-coveralls/php-coveralls": "^2.8",
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6",
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6",
"phpunit/phpunit": "^9.6.25 || ^10.5.53 || ^11.5.34", "phpunit/phpunit": "^9.6.25 || ^10.5.53 || ^11.5.34",
@@ -2955,7 +2951,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.89.2" "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.89.0"
}, },
"funding": [ "funding": [
{ {
@@ -2963,20 +2959,20 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-11-06T21:12:50+00:00" "time": "2025-10-18T19:30:16+00:00"
}, },
{ {
"name": "humbug/box", "name": "humbug/box",
"version": "4.6.10", "version": "4.6.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/box-project/box.git", "url": "https://github.com/box-project/box.git",
"reference": "6dc6a1314d63e9d75c8195c996e1081e68514c36" "reference": "05d205d99ddb72f3729658a0115db02cfc08912e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/box-project/box/zipball/6dc6a1314d63e9d75c8195c996e1081e68514c36", "url": "https://api.github.com/repos/box-project/box/zipball/05d205d99ddb72f3729658a0115db02cfc08912e",
"reference": "6dc6a1314d63e9d75c8195c996e1081e68514c36", "reference": "05d205d99ddb72f3729658a0115db02cfc08912e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3005,7 +3001,7 @@
"symfony/process": "^6.4.0 || ^7.0.0", "symfony/process": "^6.4.0 || ^7.0.0",
"symfony/var-dumper": "^6.4.0 || ^7.0.0", "symfony/var-dumper": "^6.4.0 || ^7.0.0",
"thecodingmachine/safe": "^2.5 || ^3.0", "thecodingmachine/safe": "^2.5 || ^3.0",
"webmozart/assert": "^1.12" "webmozart/assert": "^1.11"
}, },
"conflict": { "conflict": {
"marc-mabe/php-enum": "<4.4" "marc-mabe/php-enum": "<4.4"
@@ -3075,9 +3071,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/box-project/box/issues", "issues": "https://github.com/box-project/box/issues",
"source": "https://github.com/box-project/box/tree/4.6.10" "source": "https://github.com/box-project/box/tree/4.6.8"
}, },
"time": "2025-10-31T18:38:02+00:00" "time": "2025-10-13T17:13:17+00:00"
}, },
{ {
"name": "humbug/php-scoper", "name": "humbug/php-scoper",
@@ -3212,16 +3208,16 @@
}, },
{ {
"name": "justinrainbow/json-schema", "name": "justinrainbow/json-schema",
"version": "6.6.1", "version": "6.6.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/jsonrainbow/json-schema.git", "url": "https://github.com/jsonrainbow/json-schema.git",
"reference": "fd8e5c6b1badb998844ad34ce0abcd71a0aeb396" "reference": "68ba7677532803cc0c5900dd5a4d730537f2b2f3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/fd8e5c6b1badb998844ad34ce0abcd71a0aeb396", "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/68ba7677532803cc0c5900dd5a4d730537f2b2f3",
"reference": "fd8e5c6b1badb998844ad34ce0abcd71a0aeb396", "reference": "68ba7677532803cc0c5900dd5a4d730537f2b2f3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3281,9 +3277,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/jsonrainbow/json-schema/issues", "issues": "https://github.com/jsonrainbow/json-schema/issues",
"source": "https://github.com/jsonrainbow/json-schema/tree/6.6.1" "source": "https://github.com/jsonrainbow/json-schema/tree/6.6.0"
}, },
"time": "2025-11-07T18:30:29+00:00" "time": "2025-10-10T11:34:09+00:00"
}, },
{ {
"name": "kelunik/certificate", "name": "kelunik/certificate",
@@ -3704,16 +3700,16 @@
}, },
{ {
"name": "nikic/php-parser", "name": "nikic/php-parser",
"version": "v5.6.2", "version": "v5.6.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nikic/PHP-Parser.git", "url": "https://github.com/nikic/PHP-Parser.git",
"reference": "3a454ca033b9e06b63282ce19562e892747449bb" "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3a454ca033b9e06b63282ce19562e892747449bb", "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
"reference": "3a454ca033b9e06b63282ce19562e892747449bb", "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3756,9 +3752,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/nikic/PHP-Parser/issues", "issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v5.6.2" "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1"
}, },
"time": "2025-10-21T19:32:17+00:00" "time": "2025-08-13T20:13:15+00:00"
}, },
{ {
"name": "phar-io/composer-distributor", "name": "phar-io/composer-distributor",
@@ -6780,16 +6776,16 @@
}, },
{ {
"name": "symfony/filesystem", "name": "symfony/filesystem",
"version": "v7.3.6", "version": "v7.3.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/filesystem.git", "url": "https://github.com/symfony/filesystem.git",
"reference": "e9bcfd7837928ab656276fe00464092cc9e1826a" "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/e9bcfd7837928ab656276fe00464092cc9e1826a", "url": "https://api.github.com/repos/symfony/filesystem/zipball/edcbb768a186b5c3f25d0643159a787d3e63b7fd",
"reference": "e9bcfd7837928ab656276fe00464092cc9e1826a", "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6826,7 +6822,7 @@
"description": "Provides basic utilities for the filesystem", "description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/filesystem/tree/v7.3.6" "source": "https://github.com/symfony/filesystem/tree/v7.3.2"
}, },
"funding": [ "funding": [
{ {
@@ -6846,20 +6842,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-11-05T09:52:27+00:00" "time": "2025-07-07T08:17:47+00:00"
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",
"version": "v7.3.5", "version": "v7.3.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/finder.git", "url": "https://github.com/symfony/finder.git",
"reference": "9f696d2f1e340484b4683f7853b273abff94421f" "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/9f696d2f1e340484b4683f7853b273abff94421f", "url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe",
"reference": "9f696d2f1e340484b4683f7853b273abff94421f", "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6894,7 +6890,7 @@
"description": "Finds files and directories via an intuitive fluent interface", "description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/finder/tree/v7.3.5" "source": "https://github.com/symfony/finder/tree/v7.3.2"
}, },
"funding": [ "funding": [
{ {
@@ -6914,7 +6910,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-10-15T18:45:57+00:00" "time": "2025-07-15T13:41:35+00:00"
}, },
{ {
"name": "symfony/options-resolver", "name": "symfony/options-resolver",
@@ -7215,16 +7211,16 @@
}, },
{ {
"name": "symfony/var-dumper", "name": "symfony/var-dumper",
"version": "v7.3.5", "version": "v7.3.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/var-dumper.git", "url": "https://github.com/symfony/var-dumper.git",
"reference": "476c4ae17f43a9a36650c69879dcf5b1e6ae724d" "reference": "b8abe7daf2730d07dfd4b2ee1cecbf0dd2fbdabb"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/476c4ae17f43a9a36650c69879dcf5b1e6ae724d", "url": "https://api.github.com/repos/symfony/var-dumper/zipball/b8abe7daf2730d07dfd4b2ee1cecbf0dd2fbdabb",
"reference": "476c4ae17f43a9a36650c69879dcf5b1e6ae724d", "reference": "b8abe7daf2730d07dfd4b2ee1cecbf0dd2fbdabb",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -7278,7 +7274,7 @@
"dump" "dump"
], ],
"support": { "support": {
"source": "https://github.com/symfony/var-dumper/tree/v7.3.5" "source": "https://github.com/symfony/var-dumper/tree/v7.3.4"
}, },
"funding": [ "funding": [
{ {
@@ -7298,7 +7294,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-09-27T09:00:46+00:00" "time": "2025-09-11T10:12:26+00:00"
}, },
{ {
"name": "thecodingmachine/safe", "name": "thecodingmachine/safe",
@@ -7441,16 +7437,16 @@
}, },
{ {
"name": "theseer/tokenizer", "name": "theseer/tokenizer",
"version": "1.3.0", "version": "1.2.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/theseer/tokenizer.git", "url": "https://github.com/theseer/tokenizer.git",
"reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb" "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/d74205c497bfbca49f34d4bc4c19c17e22db4ebb", "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
"reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb", "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -7479,7 +7475,7 @@
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": { "support": {
"issues": "https://github.com/theseer/tokenizer/issues", "issues": "https://github.com/theseer/tokenizer/issues",
"source": "https://github.com/theseer/tokenizer/tree/1.3.0" "source": "https://github.com/theseer/tokenizer/tree/1.2.3"
}, },
"funding": [ "funding": [
{ {
@@ -7487,32 +7483,32 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-11-13T13:44:09+00:00" "time": "2024-03-03T12:36:25+00:00"
}, },
{ {
"name": "webmozart/assert", "name": "webmozart/assert",
"version": "1.12.1", "version": "1.11.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/webmozarts/assert.git", "url": "https://github.com/webmozarts/assert.git",
"reference": "9be6926d8b485f55b9229203f962b51ed377ba68" "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/9be6926d8b485f55b9229203f962b51ed377ba68", "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
"reference": "9be6926d8b485f55b9229203f962b51ed377ba68", "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-ctype": "*", "ext-ctype": "*",
"ext-date": "*",
"ext-filter": "*",
"php": "^7.2 || ^8.0" "php": "^7.2 || ^8.0"
}, },
"suggest": { "conflict": {
"ext-intl": "", "phpstan/phpstan": "<0.12.20",
"ext-simplexml": "", "vimeo/psalm": "<4.6.1 || 4.6.2"
"ext-spl": "" },
"require-dev": {
"phpunit/phpunit": "^8.5.13"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@@ -7543,9 +7539,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/webmozarts/assert/issues", "issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.12.1" "source": "https://github.com/webmozarts/assert/tree/1.11.0"
}, },
"time": "2025-10-29T15:56:20+00:00" "time": "2022-06-03T18:03:27+00:00"
} }
], ],
"aliases": [], "aliases": [],

View File

@@ -1,41 +1,40 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; static-php-cli (spc) env configuration ; static-php-cli (spc) env configuration
; ;
; This file is used to set default env vars for static-php-cli build. ; This file is used to set default env vars for static-php-cli build.
; As dynamic build process, some of these vars can be overwritten by CLI options. ; As dynamic build process, some of these vars can be overwritten by CLI options.
; And you can also overwrite these vars by setting them in your shell environment. ; And you can also overwrite these vars by setting them in your shell environment.
; The value should be changed only if you know what you are doing. Otherwise, please leave them as default.
; ;
; We need to use some pre-defined internal env vars, like `BUILD_ROOT_PATH`, `DOWNLOAD_PATH`, etc. ; We need to use some pre-defined internal env vars, like `BUILD_ROOT_PATH`, `DOWNLOAD_PATH`, etc.
; Please note that these vars cannot be defined in this file, they should only be defined before static-php-cli running. ; Please note that these vars cannot be defined in this file, they are only be defined before static-php-cli running.
; ;
; Here's a list of env vars, these variables will be defined if not defined: ; Here's a list of env vars, these value cannot be changed anywhere:
;
; BUILD_ROOT_PATH: the root path of the build process. (default: `$(pwd)/buildroot`)
; BUILD_INCLUDE_PATH: the path of the include files. (default: `$BUILD_ROOT_PATH/include`)
; BUILD_LIB_PATH: the path of the lib files. (default: `$BUILD_ROOT_PATH/lib`)
; BUILD_BIN_PATH: the path of the bin files. (default: `$BUILD_ROOT_PATH/bin`)
; BUILD_MODULES_PATH: the path of the php modules (shared extensions) files. (default: `$BUILD_ROOT_PATH/modules`)
; PKG_ROOT_PATH: the root path of the package files. (default: `$(pwd)/pkgroot/$GNU_ARCH-{darwin|linux|windows}`)
; SOURCE_PATH: the path of the source files. (default: `$(pwd)/source`)
; DOWNLOAD_PATH: the path of the download files. (default: `$(pwd)/downloads`)
; PATH: (*nix only) static-php-cli will add `$BUILD_BIN_PATH` to PATH.
; PKG_CONFIG_PATH: (*nix only) static-php-cli will set `$BUILD_LIB_PATH/pkgconfig` to PKG_CONFIG_PATH.
;
; Here's a list of env vars, these variables is defined in SPC and cannot be changed anywhere:
; ;
; SPC_VERSION: the version of static-php-cli. ; SPC_VERSION: the version of static-php-cli.
; WORKING_DIR: the working directory of the build process. (default: `$(pwd)`) ; WORKING_DIR: the working directory of the build process. (default: `$(pwd)`)
; ROOT_DIR: the root directory of static-php-cli. (default: `/path/to/static-php-cli`, when running in phar or micro mode: `phar://path/to/spc.phar`) ; ROOT_DIR: the root directory of static-php-cli. (default: `/path/to/static-php-cli`, when running in phar or micro mode: `phar://path/to/spc.phar`)
; BUILD_ROOT_PATH: the root path of the build process. (default: `$(pwd)/buildroot`)
; BUILD_INCLUDE_PATH: the path of the include files. (default: `$BUILD_ROOT_PATH/include`)
; BUILD_LIB_PATH: the path of the lib files. (default: `$BUILD_ROOT_PATH/lib`)
; BUILD_BIN_PATH: the path of the bin files. (default: `$BUILD_ROOT_PATH/bin`)
; PKG_ROOT_PATH: the root path of the package files. (default: `$(pwd)/pkgroot`)
; SOURCE_PATH: the path of the source files. (default: `$(pwd)/source`)
; DOWNLOAD_PATH: the path of the download files. (default: `$(pwd)/downloads`)
; CPU_COUNT: the count of the CPU cores. (default: `$(nproc)`) ; CPU_COUNT: the count of the CPU cores. (default: `$(nproc)`)
; SPC_ARCH: the arch of the current system, for some libraries needed `--host=XXX` args. (default: `$(uname -m)`, e.g. `x86_64`, `aarch64`, `arm64`) ; SPC_ARCH: the arch of the current system, for some libraries needed `--host=XXX` args. (default: `$(uname -m)`, e.g. `x86_64`, `aarch64`, `arm64`)
; GNU_ARCH: the GNU arch of the current system. (default: `$(uname -m)`, e.g. `x86_64`, `aarch64`) ; GNU_ARCH: the GNU arch of the current system. (default: `$(uname -m)`, e.g. `x86_64`, `aarch64`)
; MAC_ARCH: the MAC arch of the current system. (default: `$(uname -m)`, e.g. `x86_64`, `arm64`) ; MAC_ARCH: the MAC arch of the current system. (default: `$(uname -m)`, e.g. `x86_64`, `arm64`)
; PKG_CONFIG: (*nix only) static-php-cli will set `$BUILD_BIN_PATH/pkg-config` to PKG_CONFIG. ;
; SPC_LINUX_DEFAULT_CC: (linux only) the default compiler for linux. (For alpine linux: `gcc`, default: `$GNU_ARCH-linux-musl-gcc`) ; * These vars are only be defined in Unix (macOS, Linux, FreeBSD)Builder and cannot be changed anywhere:
; SPC_LINUX_DEFAULT_CXX: (linux only) the default c++ compiler for linux. (For alpine linux: `g++`, default: `$GNU_ARCH-linux-musl-g++`) ; PATH: static-php-cli will add `$BUILD_BIN_PATH` to PATH.
; SPC_LINUX_DEFAULT_AR: (linux only) the default archiver for linux. (For alpine linux: `ar`, default: `$GNU_ARCH-linux-musl-ar`) ; PKG_CONFIG: static-php-cli will set `$BUILD_BIN_PATH/pkg-config` to PKG_CONFIG.
; SPC_EXTRA_PHP_VARS: (linux only) the extra vars for building php, used in `configure` and `make` command. ; PKG_CONFIG_PATH: static-php-cli will set `$BUILD_LIB_PATH/pkgconfig` to PKG_CONFIG_PATH.
;
; * These vars are only be defined in LinuxBuilder and cannot be changed anywhere:
; 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_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.
@@ -45,7 +44,7 @@ SPC_SKIP_PHP_VERSION_CHECK="no"
; Ignore some check item for bin/spc doctor command, comma separated (e.g. SPC_SKIP_DOCTOR_CHECK_ITEMS="if homebrew has installed") ; Ignore some check item for bin/spc doctor command, comma separated (e.g. SPC_SKIP_DOCTOR_CHECK_ITEMS="if homebrew has installed")
SPC_SKIP_DOCTOR_CHECK_ITEMS="" SPC_SKIP_DOCTOR_CHECK_ITEMS=""
; extra modules that xcaddy will include in the FrankenPHP build ; extra modules that xcaddy will include in the FrankenPHP build
SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES="--with github.com/dunglas/mercure/caddy --with github.com/dunglas/vulcain/caddy --with github.com/dunglas/caddy-cbrotli" SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES="--with github.com/dunglas/frankenphp/caddy --with github.com/dunglas/mercure/caddy --with github.com/dunglas/vulcain/caddy --with github.com/dunglas/caddy-cbrotli"
; The display message for php version output (PHP >= 8.4 available) ; The display message for php version output (PHP >= 8.4 available)
PHP_BUILD_PROVIDER="static-php-cli ${SPC_VERSION}" PHP_BUILD_PROVIDER="static-php-cli ${SPC_VERSION}"
@@ -110,7 +109,9 @@ SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --disable
; *** default build vars for building php *** ; *** default build vars for building php ***
; embed type for php, static (libphp.a) or shared (libphp.so) ; embed type for php, static (libphp.a) or shared (libphp.so)
SPC_CMD_VAR_PHP_EMBED_TYPE="static" SPC_CMD_VAR_PHP_EMBED_TYPE="static"
; EXTRA_CFLAGS for `configure` and `make` php ; CFLAGS for configuring php
SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS="${SPC_DEFAULT_C_FLAGS} -fPIE"
; EXTRA_CFLAGS for `make` php
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fno-ident -fPIE ${SPC_DEFAULT_C_FLAGS}" SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fno-ident -fPIE ${SPC_DEFAULT_C_FLAGS}"
; EXTRA_LDFLAGS for `make` php, can use -release to set a soname for libphp.so ; EXTRA_LDFLAGS for `make` php, can use -release to set a soname for libphp.so
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS="" SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS=""
@@ -140,8 +141,10 @@ SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --enable-
; *** default build vars for building php *** ; *** default build vars for building php ***
; embed type for php, static (libphp.a) or shared (libphp.dylib) ; embed type for php, static (libphp.a) or shared (libphp.dylib)
SPC_CMD_VAR_PHP_EMBED_TYPE="static" SPC_CMD_VAR_PHP_EMBED_TYPE="static"
; EXTRA_CFLAGS for `configure` and `make` php ; CFLAGS for configuring php
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fpic -fpie -Werror=unknown-warning-option ${SPC_DEFAULT_C_FLAGS}" SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS="${SPC_DEFAULT_C_FLAGS} -Werror=unknown-warning-option"
; EXTRA_CFLAGS for `make` php
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fpic -fpie ${SPC_DEFAULT_C_FLAGS}"
[freebsd] [freebsd]
; compiler environments ; compiler environments

View File

@@ -358,18 +358,6 @@
"liblz4" "liblz4"
] ]
}, },
"maxminddb": {
"support": {
"BSD": "wip",
"Windows": "wip"
},
"type": "external",
"source": "ext-maxminddb",
"arg-type": "with",
"lib-depends": [
"libmaxminddb"
]
},
"mbregex": { "mbregex": {
"type": "builtin", "type": "builtin",
"arg-type": "custom", "arg-type": "custom",

View File

@@ -7,14 +7,12 @@
"source": "php-src", "source": "php-src",
"lib-depends": [ "lib-depends": [
"lib-base", "lib-base",
"micro", "micro"
"frankenphp"
], ],
"lib-depends-macos": [ "lib-depends-macos": [
"lib-base", "lib-base",
"micro", "micro",
"libxml2", "libxml2"
"frankenphp"
], ],
"lib-suggests-linux": [ "lib-suggests-linux": [
"libacl", "libacl",
@@ -26,10 +24,6 @@
"watcher" "watcher"
] ]
}, },
"frankenphp": {
"source": "frankenphp",
"type": "target"
},
"micro": { "micro": {
"type": "target", "type": "target",
"source": "micro" "source": "micro"
@@ -104,9 +98,7 @@
"ngtcp2", "ngtcp2",
"zstd", "zstd",
"libcares", "libcares",
"ldap", "ldap"
"idn2",
"krb5"
], ],
"lib-suggests-windows": [ "lib-suggests-windows": [
"brotli", "brotli",
@@ -236,24 +228,6 @@
"unicode" "unicode"
] ]
}, },
"idn2": {
"source": "libidn2",
"pkg-configs": [
"libidn2"
],
"headers": [
"idn2.h"
],
"lib-suggests-unix": [
"libiconv",
"gettext",
"libunistring"
],
"lib-depends-macos": [
"libiconv",
"gettext"
]
},
"imagemagick": { "imagemagick": {
"source": "imagemagick", "source": "imagemagick",
"cpp-library": true, "cpp-library": true,
@@ -301,26 +275,6 @@
"jbig_ar.h" "jbig_ar.h"
] ]
}, },
"krb5": {
"source": "krb5",
"pkg-configs": [
"krb5-gssapi"
],
"headers": [
"krb5.h",
"gssapi/gssapi.h"
],
"lib-depends": [
"openssl"
],
"lib-suggests": [
"ldap",
"libedit"
],
"frameworks": [
"Kerberos"
]
},
"ldap": { "ldap": {
"source": "ldap", "source": "ldap",
"pkg-configs": [ "pkg-configs": [
@@ -506,16 +460,6 @@
"liblz4.a" "liblz4.a"
] ]
}, },
"libmaxminddb": {
"source": "libmaxminddb",
"static-libs-unix": [
"libmaxminddb.a"
],
"headers": [
"maxminddb.h",
"maxminddb_config.h"
]
},
"libmemcached": { "libmemcached": {
"source": "libmemcached", "source": "libmemcached",
"cpp-library": true, "cpp-library": true,
@@ -562,16 +506,13 @@
}, },
"librdkafka": { "librdkafka": {
"source": "librdkafka", "source": "librdkafka",
"pkg-configs": [ "static-libs-unix": [
"rdkafka++-static", "librdkafka.a",
"rdkafka-static" "librdkafka++.a",
"librdkafka-static.a"
], ],
"cpp-library": true, "cpp-library": true,
"lib-suggests": [ "lib-suggests": [
"curl",
"liblz4",
"openssl",
"zlib",
"zstd" "zstd"
] ]
}, },
@@ -618,16 +559,6 @@
"zstd" "zstd"
] ]
}, },
"libunistring": {
"source": "libunistring",
"static-libs-unix": [
"libunistring.a"
],
"headers": [
"unistr.h",
"unistring/"
]
},
"liburing": { "liburing": {
"source": "liburing", "source": "liburing",
"pkg-configs": [ "pkg-configs": [

View File

@@ -184,15 +184,6 @@
] ]
} }
}, },
"ext-maxminddb": {
"type": "url",
"url": "https://pecl.php.net/get/maxminddb",
"filename": "ext-maxminddb.tgz",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"ext-memcache": { "ext-memcache": {
"type": "url", "type": "url",
"url": "https://pecl.php.net/get/memcache", "url": "https://pecl.php.net/get/memcache",
@@ -310,19 +301,10 @@
"path": "LICENSE.MIT" "path": "LICENSE.MIT"
} }
}, },
"frankenphp": {
"type": "ghtar",
"repo": "php/frankenphp",
"prefer-stable": true,
"license": {
"type": "file",
"path": "LICENSE"
}
},
"freetype": { "freetype": {
"type": "ghtagtar", "type": "git",
"repo": "freetype/freetype", "rev": "VER-2-13-2",
"match": "VER-2-\\d+-\\d+", "url": "https://github.com/freetype/freetype",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE.TXT" "path": "LICENSE.TXT"
@@ -439,16 +421,6 @@
"path": "COPYING" "path": "COPYING"
} }
}, },
"krb5": {
"type": "ghtagtar",
"repo": "krb5/krb5",
"match": "krb5.+-final",
"prefer-stable": true,
"license": {
"type": "file",
"path": "NOTICE"
}
},
"ldap": { "ldap": {
"type": "filelist", "type": "filelist",
"url": "https://www.openldap.org/software/download/OpenLDAP/openldap-release/", "url": "https://www.openldap.org/software/download/OpenLDAP/openldap-release/",
@@ -607,15 +579,6 @@
"path": "source/COPYING" "path": "source/COPYING"
} }
}, },
"libidn2": {
"type": "filelist",
"url": "https://ftp.gnu.org/gnu/libidn/",
"regex": "/href=\"(?<file>libidn2-(?<version>[^\"]+)\\.tar\\.gz)\"/",
"license": {
"type": "file",
"path": "COPYING.LESSERv3"
}
},
"libjpeg": { "libjpeg": {
"type": "ghtar", "type": "ghtar",
"repo": "libjpeg-turbo/libjpeg-turbo", "repo": "libjpeg-turbo/libjpeg-turbo",
@@ -650,16 +613,6 @@
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"libmaxminddb": {
"type": "ghrel",
"repo": "maxmind/libmaxminddb",
"match": "libmaxminddb-.+\\.tar\\.gz",
"prefer-stable": true,
"license": {
"type": "file",
"path": "LICENSE"
}
},
"libmemcached": { "libmemcached": {
"type": "ghtagtar", "type": "ghtagtar",
"repo": "awesomized/libmemcached", "repo": "awesomized/libmemcached",
@@ -727,16 +680,6 @@
"path": "LICENSE.md" "path": "LICENSE.md"
} }
}, },
"libunistring": {
"type": "filelist",
"url": "https://ftp.gnu.org/gnu/libunistring/",
"regex": "/href=\"(?<file>libunistring-(?<version>[^\"]+)\\.tar\\.gz)\"/",
"provide-pre-built": true,
"license": {
"type": "file",
"path": "COPYING.LIB"
}
},
"liburing": { "liburing": {
"type": "ghtar", "type": "ghtar",
"repo": "axboe/liburing", "repo": "axboe/liburing",
@@ -750,7 +693,6 @@
"type": "git", "type": "git",
"url": "https://github.com/static-php/libuuid.git", "url": "https://github.com/static-php/libuuid.git",
"rev": "master", "rev": "master",
"provide-pre-built": true,
"license": { "license": {
"type": "file", "type": "file",
"path": "COPYING" "path": "COPYING"

View File

@@ -1,10 +1,11 @@
import sidebarEn from "./sidebar.en"; import sidebarEn from "./sidebar.en";
import sidebarZh from "./sidebar.zh"; import sidebarZh from "./sidebar.zh";
import sidebarJa from "./sidebar.ja";
// https://vitepress.dev/reference/site-config // https://vitepress.dev/reference/site-config
export default { export default {
title: "StaticPHP", title: "Static PHP",
description: "Build single static PHP binary, with PHP project together, with popular extensions included.", description: "Build single static PHP binary, with PHP project together, with popular extensions included.",
locales: { locales: {
en: { en: {
@@ -61,5 +62,19 @@ export default {
indexName: 'static-php docs', indexName: 'static-php docs',
}, },
}, },
} },
head: [
[
'script',
{ async: '', src: 'https://www.googletagmanager.com/gtag/js?id=G-0MBJ29BD7F' }
],
[
'script',
{},
`window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-0MBJ29BD7F');`
]
]
} }

View File

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

View File

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

View File

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

BIN
docs/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

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

View File

@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace SPC\builder; namespace SPC\builder;
use SPC\builder\unix\UnixBuilderBase;
use SPC\exception\EnvironmentException; use SPC\exception\EnvironmentException;
use SPC\exception\SPCException; use SPC\exception\SPCException;
use SPC\exception\ValidationException; use SPC\exception\ValidationException;
@@ -221,7 +220,7 @@ class Extension
*/ */
public function patchBeforeSharedMake(): bool public function patchBeforeSharedMake(): bool
{ {
$config = (new SPCConfigUtil($this->builder))->getExtensionConfig($this); $config = (new SPCConfigUtil($this->builder))->config([$this->getName()], array_map(fn ($l) => $l->getName(), $this->builder->getLibs()));
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']); [$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
$lstdcpp = str_contains($sharedLibs, '-l:libstdc++.a') ? '-l:libstdc++.a' : null; $lstdcpp = str_contains($sharedLibs, '-l:libstdc++.a') ? '-l:libstdc++.a' : null;
$lstdcpp ??= str_contains($sharedLibs, '-lstdc++') ? '-lstdc++' : ''; $lstdcpp ??= str_contains($sharedLibs, '-lstdc++') ? '-lstdc++' : '';
@@ -449,15 +448,6 @@ class Extension
->exec('make clean') ->exec('make clean')
->exec('make -j' . $this->builder->concurrency) ->exec('make -j' . $this->builder->concurrency)
->exec('make install'); ->exec('make install');
// process *.so file
$soFile = BUILD_MODULES_PATH . '/' . $this->getName() . '.so';
if (!file_exists($soFile)) {
throw new ValidationException("extension {$this->getName()} build failed: {$soFile} not found", validation_module: "Extension {$this->getName()} build");
}
/** @var UnixBuilderBase $builder */
$builder = $this->builder;
$builder->deployBinary($soFile, $soFile, false);
} }
/** /**
@@ -496,46 +486,18 @@ class Extension
return $this->build_static; return $this->build_static;
} }
/**
* Get the library dependencies that current extension depends on.
*
* @param bool $recursive Whether it includes dependencies recursively
*/
public function getLibraryDependencies(bool $recursive = false): array
{
$ret = array_filter($this->dependencies, fn ($x) => $x instanceof LibraryBase);
if (!$recursive) {
return $ret;
}
$deps = [];
$added = 1;
while ($added !== 0) {
$added = 0;
foreach ($ret as $depName => $dep) {
foreach ($dep->getDependencies(true) as $depdepName => $depdep) {
if (!array_key_exists($depdepName, $deps)) {
$deps[$depdepName] = $depdep;
++$added;
}
}
if (!array_key_exists($depName, $deps)) {
$deps[$depName] = $dep;
}
}
}
return $deps;
}
/** /**
* Returns the environment variables a shared extension needs to be built. * Returns the environment variables a shared extension needs to be built.
* CFLAGS, CXXFLAGS, LDFLAGS and so on. * CFLAGS, CXXFLAGS, LDFLAGS and so on.
*/ */
protected function getSharedExtensionEnv(): array protected function getSharedExtensionEnv(): array
{ {
$config = (new SPCConfigUtil($this->builder))->getExtensionConfig($this); $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']); [$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
$preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group '; $preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group ';
$postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group '; $postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group ';
@@ -557,7 +519,7 @@ class Extension
} }
logger()->info("enabling {$this->name} without library {$name}"); logger()->info("enabling {$this->name} without library {$name}");
} else { } else {
$this->dependencies[$name] = $depLib; $this->dependencies[] = $depLib;
} }
} }
@@ -570,7 +532,7 @@ class Extension
} }
logger()->info("enabling {$this->name} without extension {$name}"); logger()->info("enabling {$this->name} without extension {$name}");
} else { } else {
$this->dependencies[$name] = $depExt; $this->dependencies[] = $depExt;
} }
} }
@@ -605,4 +567,37 @@ class Extension
} }
return [trim($staticLibString), trim($sharedLibString)]; return [trim($staticLibString), trim($sharedLibString)];
} }
private function getLibraryDependencies(bool $recursive = false): array
{
$ret = array_filter($this->dependencies, fn ($x) => $x instanceof LibraryBase);
if (!$recursive) {
return $ret;
}
$deps = [];
$added = 1;
while ($added !== 0) {
$added = 0;
foreach ($ret as $depName => $dep) {
foreach ($dep->getDependencies(true) as $depdepName => $depdep) {
if (!array_key_exists($depdepName, $deps)) {
$deps[$depdepName] = $depdep;
++$added;
}
}
if (!array_key_exists($depName, $deps)) {
$deps[$depName] = $dep;
}
}
}
if (array_key_exists(0, $deps)) {
$zero = [0 => $deps[0]];
unset($deps[0]);
return $zero + $deps;
}
return $deps;
}
} }

View File

@@ -43,7 +43,7 @@ class grpc extends Extension
public function patchBeforeConfigure(): bool public function patchBeforeConfigure(): bool
{ {
$util = new SPCConfigUtil($this->builder, ['libs_only_deps' => true]); $util = new SPCConfigUtil($this->builder, ['libs_only_deps' => true]);
$config = $util->getExtensionConfig($this); $config = $util->config(['grpc']);
$libs = $config['libs']; $libs = $config['libs'];
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/configure', '-lgrpc', $libs); FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/configure', '-lgrpc', $libs);
return true; return true;

View File

@@ -1,25 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('maxminddb')]
class maxminddb extends Extension
{
public function patchBeforeBuildconf(): bool
{
if (!is_dir(SOURCE_PATH . '/php-src/ext/maxminddb')) {
$original = $this->source_dir;
FileSystem::copyDir($original . '/ext', SOURCE_PATH . '/php-src/ext/maxminddb');
$this->source_dir = SOURCE_PATH . '/php-src/ext/maxminddb';
return true;
}
$this->source_dir = SOURCE_PATH . '/php-src/ext/maxminddb';
return false;
}
}

View File

@@ -7,7 +7,6 @@ namespace SPC\builder\extension;
use SPC\builder\Extension; use SPC\builder\Extension;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\util\CustomExt; use SPC\util\CustomExt;
use SPC\util\SPCConfigUtil;
#[CustomExt('rdkafka')] #[CustomExt('rdkafka')]
class rdkafka extends Extension class rdkafka extends Extension
@@ -16,7 +15,6 @@ class rdkafka extends Extension
{ {
FileSystem::replaceFileStr("{$this->source_dir}/config.m4", "-L\$RDKAFKA_DIR/\$PHP_LIBDIR -lm\n", "-L\$RDKAFKA_DIR/\$PHP_LIBDIR -lm \$RDKAFKA_LIBS\n"); FileSystem::replaceFileStr("{$this->source_dir}/config.m4", "-L\$RDKAFKA_DIR/\$PHP_LIBDIR -lm\n", "-L\$RDKAFKA_DIR/\$PHP_LIBDIR -lm \$RDKAFKA_LIBS\n");
FileSystem::replaceFileStr("{$this->source_dir}/config.m4", "-L\$RDKAFKA_DIR/\$PHP_LIBDIR -lm\"\n", '-L$RDKAFKA_DIR/$PHP_LIBDIR -lm $RDKAFKA_LIBS"'); FileSystem::replaceFileStr("{$this->source_dir}/config.m4", "-L\$RDKAFKA_DIR/\$PHP_LIBDIR -lm\"\n", '-L$RDKAFKA_DIR/$PHP_LIBDIR -lm $RDKAFKA_LIBS"');
FileSystem::replaceFileStr("{$this->source_dir}/config.m4", 'PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,', 'AC_CHECK_LIB([$LIBNAME], [$LIBSYMBOL],');
return true; return true;
} }
@@ -39,7 +37,8 @@ class rdkafka extends Extension
public function getUnixConfigureArg(bool $shared = false): string public function getUnixConfigureArg(bool $shared = false): string
{ {
$pkgconf_libs = (new SPCConfigUtil($this->builder, ['no_php' => true, 'libs_only_deps' => true]))->getExtensionConfig($this); $pkgconf_libs = shell()->execWithResult('pkg-config --libs --static rdkafka')[1];
return '--with-rdkafka=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH . " RDKAFKA_LIBS=\"{$pkgconf_libs['libs']}\""; $pkgconf_libs = trim(implode('', $pkgconf_libs));
return '--with-rdkafka=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH . ' RDKAFKA_LIBS="' . $pkgconf_libs . '"';
} }
} }

View File

@@ -70,7 +70,7 @@ class swoole extends Extension
$arg .= $this->builder->getExt('swoole-hook-mysql') ? ' --enable-mysqlnd' : ' --disable-mysqlnd'; $arg .= $this->builder->getExt('swoole-hook-mysql') ? ' --enable-mysqlnd' : ' --disable-mysqlnd';
$arg .= $this->builder->getExt('swoole-hook-sqlite') ? ' --enable-swoole-sqlite' : ' --disable-swoole-sqlite'; $arg .= $this->builder->getExt('swoole-hook-sqlite') ? ' --enable-swoole-sqlite' : ' --disable-swoole-sqlite';
if ($this->builder->getExt('swoole-hook-odbc')) { if ($this->builder->getExt('swoole-hook-odbc')) {
$config = (new SPCConfigUtil($this->builder))->getLibraryConfig($this->builder->getLib('unixodbc')); $config = (new SPCConfigUtil($this->builder, ['libs_only_deps' => true]))->config([], ['unixodbc']);
$arg .= ' --with-swoole-odbc=unixODBC,' . BUILD_ROOT_PATH . ' SWOOLE_ODBC_LIBS="' . $config['libs'] . '"'; $arg .= ' --with-swoole-odbc=unixODBC,' . BUILD_ROOT_PATH . ' SWOOLE_ODBC_LIBS="' . $config['libs'] . '"';
} }

View File

@@ -1,19 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('trader')]
class trader extends Extension
{
public function patchBeforeBuildconf(): bool
{
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/trader/config.m4', 'PHP_TA', 'PHP_TRADER');
return true;
}
}

View File

@@ -153,7 +153,7 @@ class BSDBuilder extends UnixBuilderBase
if (!$this->getOption('no-strip', false)) { if (!$this->getOption('no-strip', false)) {
$shell->exec('strip sapi/cli/php'); $shell->exec('strip sapi/cli/php');
} }
$this->deploySAPIBinary(BUILD_TARGET_CLI); $this->deployBinary(BUILD_TARGET_CLI);
} }
/** /**
@@ -184,7 +184,7 @@ class BSDBuilder extends UnixBuilderBase
if (!$this->getOption('no-strip', false)) { if (!$this->getOption('no-strip', false)) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/micro')->exec('strip --strip-unneeded micro.sfx'); shell()->cd(SOURCE_PATH . '/php-src/sapi/micro')->exec('strip --strip-unneeded micro.sfx');
} }
$this->deploySAPIBinary(BUILD_TARGET_MICRO); $this->deployBinary(BUILD_TARGET_MICRO);
if ($this->phar_patched) { if ($this->phar_patched) {
SourcePatcher::unpatchMicroPhar(); SourcePatcher::unpatchMicroPhar();
@@ -206,7 +206,7 @@ class BSDBuilder extends UnixBuilderBase
if (!$this->getOption('no-strip', false)) { if (!$this->getOption('no-strip', false)) {
$shell->exec('strip sapi/fpm/php-fpm'); $shell->exec('strip sapi/fpm/php-fpm');
} }
$this->deploySAPIBinary(BUILD_TARGET_FPM); $this->deployBinary(BUILD_TARGET_FPM);
} }
/** /**

View File

@@ -8,7 +8,6 @@ use SPC\builder\unix\UnixBuilderBase;
use SPC\exception\PatchException; use SPC\exception\PatchException;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
use SPC\store\Config; use SPC\store\Config;
use SPC\store\DirDiff;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\store\SourcePatcher; use SPC\store\SourcePatcher;
use SPC\util\GlobalEnvManager; use SPC\util\GlobalEnvManager;
@@ -91,7 +90,7 @@ class LinuxBuilder extends UnixBuilderBase
// prepare build php envs // prepare build php envs
// $musl_flag = SPCTarget::getLibc() === 'musl' ? ' -D__MUSL__' : ' -U__MUSL__'; // $musl_flag = SPCTarget::getLibc() === 'musl' ? ' -D__MUSL__' : ' -U__MUSL__';
$php_configure_env = SystemUtil::makeEnvVarString([ $php_configure_env = SystemUtil::makeEnvVarString([
'CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), 'CFLAGS' => getenv('SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS'),
'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH, // . ' -Dsomethinghere', // . $musl_flag, 'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH, // . ' -Dsomethinghere', // . $musl_flag,
'LDFLAGS' => '-L' . BUILD_LIB_PATH, 'LDFLAGS' => '-L' . BUILD_LIB_PATH,
// '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!
@@ -195,7 +194,15 @@ class LinuxBuilder extends UnixBuilderBase
SourcePatcher::patchFile('musl_static_readline.patch', SOURCE_PATH . '/php-src', true); SourcePatcher::patchFile('musl_static_readline.patch', SOURCE_PATH . '/php-src', true);
} }
$this->deploySAPIBinary(BUILD_TARGET_CLI); if (!$this->getOption('no-strip', false)) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/cli')->exec('strip --strip-unneeded php');
}
if ($this->getOption('with-upx-pack')) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/cli')
->exec(getenv('UPX_EXEC') . ' --best php');
}
$this->deployBinary(BUILD_TARGET_CLI);
} }
protected function buildCgi(): void protected function buildCgi(): void
@@ -206,7 +213,15 @@ class LinuxBuilder extends UnixBuilderBase
->exec('sed -i "s|//lib|/lib|g" Makefile') ->exec('sed -i "s|//lib|/lib|g" Makefile')
->exec("make {$concurrency} {$vars} cgi"); ->exec("make {$concurrency} {$vars} cgi");
$this->deploySAPIBinary(BUILD_TARGET_CGI); if (!$this->getOption('no-strip', false)) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/cgi')->exec('strip --strip-unneeded php-cgi');
}
if ($this->getOption('with-upx-pack')) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/cgi')
->exec(getenv('UPX_EXEC') . ' --best php-cgi');
}
$this->deployBinary(BUILD_TARGET_CGI);
} }
/** /**
@@ -217,7 +232,6 @@ class LinuxBuilder extends UnixBuilderBase
if ($this->getPHPVersionID() < 80000) { if ($this->getPHPVersionID() < 80000) {
throw new WrongUsageException('phpmicro only support PHP >= 8.0!'); throw new WrongUsageException('phpmicro only support PHP >= 8.0!');
} }
try {
if ($this->getExt('phar')) { if ($this->getExt('phar')) {
$this->phar_patched = true; $this->phar_patched = true;
SourcePatcher::patchMicroPhar($this->getPHPVersionID()); SourcePatcher::patchMicroPhar($this->getPHPVersionID());
@@ -235,17 +249,14 @@ class LinuxBuilder extends UnixBuilderBase
->exec('sed -i "s|//lib|/lib|g" Makefile') ->exec('sed -i "s|//lib|/lib|g" Makefile')
->exec("make {$concurrency} {$vars} micro"); ->exec("make {$concurrency} {$vars} micro");
// deploy micro.sfx $this->processMicroUPX();
$dst = $this->deploySAPIBinary(BUILD_TARGET_MICRO);
$this->deployBinary(BUILD_TARGET_MICRO);
// patch after UPX-ed micro.sfx
$this->processUpxedMicroSfx($dst);
} finally {
if ($this->phar_patched) { if ($this->phar_patched) {
SourcePatcher::unpatchMicroPhar(); SourcePatcher::unpatchMicroPhar();
} }
} }
}
/** /**
* Build fpm sapi * Build fpm sapi
@@ -258,7 +269,14 @@ class LinuxBuilder extends UnixBuilderBase
->exec('sed -i "s|//lib|/lib|g" Makefile') ->exec('sed -i "s|//lib|/lib|g" Makefile')
->exec("make {$concurrency} {$vars} fpm"); ->exec("make {$concurrency} {$vars} fpm");
$this->deploySAPIBinary(BUILD_TARGET_FPM); if (!$this->getOption('no-strip', false)) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/fpm')->exec('strip --strip-unneeded php-fpm');
}
if ($this->getOption('with-upx-pack')) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/fpm')
->exec(getenv('UPX_EXEC') . ' --best php-fpm');
}
$this->deployBinary(BUILD_TARGET_FPM);
} }
/** /**
@@ -271,9 +289,6 @@ class LinuxBuilder extends UnixBuilderBase
return Config::getExt($ext->getName(), 'build-with-php') === true; return Config::getExt($ext->getName(), 'build-with-php') === true;
}); });
$install_modules = $sharedExts ? 'install-modules' : ''; $install_modules = $sharedExts ? 'install-modules' : '';
// detect changes in module path
$diff = new DirDiff(BUILD_MODULES_PATH, true);
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars()); $vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
shell()->cd(SOURCE_PATH . '/php-src') shell()->cd(SOURCE_PATH . '/php-src')
@@ -281,54 +296,10 @@ class LinuxBuilder extends UnixBuilderBase
->exec('sed -i "s|^EXTENSION_DIR = .*|EXTENSION_DIR = /' . basename(BUILD_MODULES_PATH) . '|" Makefile') ->exec('sed -i "s|^EXTENSION_DIR = .*|EXTENSION_DIR = /' . basename(BUILD_MODULES_PATH) . '|" Makefile')
->exec("make {$concurrency} INSTALL_ROOT=" . BUILD_ROOT_PATH . " {$vars} install-sapi {$install_modules} install-build install-headers install-programs"); ->exec("make {$concurrency} INSTALL_ROOT=" . BUILD_ROOT_PATH . " {$vars} install-sapi {$install_modules} install-build install-headers install-programs");
// process libphp.so for shared embed
$libphpSo = BUILD_LIB_PATH . '/libphp.so';
if (file_exists($libphpSo)) {
// post actions: rename libphp.so to libphp-<release>.so if -release is set in LDFLAGS
$this->processLibphpSoFile($libphpSo);
// deploy libphp.so
$this->deployBinary($libphpSo, $libphpSo, false);
}
// process shared extensions build-with-php
$increment_files = $diff->getChangedFiles();
foreach ($increment_files as $increment_file) {
$this->deployBinary($increment_file, $increment_file, false);
}
// process libphp.a for static embed
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'static') {
$AR = getenv('AR') ?: 'ar';
f_passthru("{$AR} -t " . BUILD_LIB_PATH . "/libphp.a | grep '\\.a$' | xargs -n1 {$AR} d " . BUILD_LIB_PATH . '/libphp.a');
// export dynamic symbols
SystemUtil::exportDynamicSymbols(BUILD_LIB_PATH . '/libphp.a');
}
// patch embed php scripts
$this->patchPhpScripts();
}
/**
* Return extra variables for php make command.
*/
private function getMakeExtraVars(): array
{
$config = (new SPCConfigUtil($this, ['libs_only_deps' => true, 'absolute_libs' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs'));
$static = SPCTarget::isStatic() ? '-all-static' : '';
$lib = BUILD_LIB_PATH;
return array_filter([
'EXTRA_CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'),
'EXTRA_LIBS' => $config['libs'],
'EXTRA_LDFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'),
'EXTRA_LDFLAGS_PROGRAM' => "-L{$lib} {$static} -pie",
]);
}
private function processLibphpSoFile(string $libphpSo): void
{
$ldflags = getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS') ?: ''; $ldflags = getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS') ?: '';
$libDir = BUILD_LIB_PATH; $libDir = BUILD_LIB_PATH;
$modulesDir = BUILD_MODULES_PATH; $modulesDir = BUILD_MODULES_PATH;
$libphpSo = "{$libDir}/libphp.so";
$realLibName = 'libphp.so'; $realLibName = 'libphp.so';
$cwd = getcwd(); $cwd = getcwd();
@@ -390,21 +361,51 @@ class LinuxBuilder extends UnixBuilderBase
} }
} }
} }
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'static') {
$AR = getenv('AR') ?: 'ar';
f_passthru("{$AR} -t " . BUILD_LIB_PATH . "/libphp.a | grep '\\.a$' | xargs -n1 {$AR} d " . BUILD_LIB_PATH . '/libphp.a');
// export dynamic symbols
SystemUtil::exportDynamicSymbols(BUILD_LIB_PATH . '/libphp.a');
}
if (!$this->getOption('no-strip', false) && file_exists(BUILD_LIB_PATH . '/' . $realLibName)) {
shell()->cd(BUILD_LIB_PATH)->exec("strip --strip-unneeded {$realLibName}");
}
$this->patchPhpScripts();
} }
/** /**
* Patch micro.sfx after UPX compression. * Return extra variables for php make command.
* micro needs special section handling in LinuxBuilder.
* The micro.sfx does not support UPX directly, but we can remove UPX
* info segment to adapt.
* This will also make micro.sfx with upx-packed more like a malware fore antivirus
*/ */
private function processUpxedMicroSfx(string $dst): void private function getMakeExtraVars(): array
{ {
if ($this->getOption('with-upx-pack') && version_compare($this->getMicroVersion(), '0.2.0') >= 0) { $config = (new SPCConfigUtil($this, ['libs_only_deps' => true, 'absolute_libs' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs'));
$static = SPCTarget::isStatic() ? '-all-static' : '';
$lib = BUILD_LIB_PATH;
return array_filter([
'EXTRA_CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'),
'EXTRA_LIBS' => $config['libs'],
'EXTRA_LDFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'),
'EXTRA_LDFLAGS_PROGRAM' => "-L{$lib} {$static} -pie",
]);
}
/**
* Strip micro.sfx for Linux.
* The micro.sfx does not support UPX directly, but we can remove UPX-info segment to adapt.
* This will also make micro.sfx with upx-packed more like a malware fore antivirus :(
*/
private function processMicroUPX(): void
{
if (version_compare($this->getMicroVersion(), '0.2.0') >= 0 && !$this->getOption('no-strip', false)) {
shell()->exec('strip --strip-unneeded ' . SOURCE_PATH . '/php-src/sapi/micro/micro.sfx');
if ($this->getOption('with-upx-pack')) {
// strip first // strip first
shell()->exec(getenv('UPX_EXEC') . ' --best ' . SOURCE_PATH . '/php-src/sapi/micro/micro.sfx');
// cut binary with readelf // cut binary with readelf
[$ret, $out] = shell()->execWithResult("readelf -l {$dst} | awk '/LOAD|GNU_STACK/ {getline; print \$1, \$2, \$3, \$4, \$6, \$7}'"); [$ret, $out] = shell()->execWithResult('readelf -l ' . SOURCE_PATH . '/php-src/sapi/micro/micro.sfx | awk \'/LOAD|GNU_STACK/ {getline; print $1, $2, $3, $4, $6, $7}\'');
$out[1] = explode(' ', $out[1]); $out[1] = explode(' ', $out[1]);
$offset = $out[1][0]; $offset = $out[1][0];
if ($ret !== 0 || !str_starts_with($offset, '0x')) { if ($ret !== 0 || !str_starts_with($offset, '0x')) {
@@ -412,7 +413,8 @@ class LinuxBuilder extends UnixBuilderBase
} }
$offset = hexdec($offset); $offset = hexdec($offset);
// remove upx extra wastes // remove upx extra wastes
file_put_contents($dst, substr(file_get_contents($dst), 0, $offset)); file_put_contents(SOURCE_PATH . '/php-src/sapi/micro/micro.sfx', substr(file_get_contents(SOURCE_PATH . '/php-src/sapi/micro/micro.sfx'), 0, $offset));
}
} }
} }
} }

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux\library;
class idn2 extends LinuxLibraryBase
{
use \SPC\builder\unix\library\idn2;
public const NAME = 'idn2';
}

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux\library;
class krb5 extends LinuxLibraryBase
{
use \SPC\builder\unix\library\krb5;
public const NAME = 'krb5';
}

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux\library;
class libmaxminddb extends LinuxLibraryBase
{
use \SPC\builder\unix\library\libmaxminddb;
public const NAME = 'libmaxminddb';
}

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux\library;
class libunistring extends LinuxLibraryBase
{
use \SPC\builder\unix\library\libunistring;
public const NAME = 'libunistring';
}

View File

@@ -8,7 +8,6 @@ use SPC\builder\macos\library\MacOSLibraryBase;
use SPC\builder\unix\UnixBuilderBase; use SPC\builder\unix\UnixBuilderBase;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
use SPC\store\Config; use SPC\store\Config;
use SPC\store\DirDiff;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\store\SourcePatcher; use SPC\store\SourcePatcher;
use SPC\util\GlobalEnvManager; use SPC\util\GlobalEnvManager;
@@ -106,7 +105,7 @@ class MacOSBuilder extends UnixBuilderBase
// prepare build php envs // prepare build php envs
$envs_build_php = SystemUtil::makeEnvVarString([ $envs_build_php = SystemUtil::makeEnvVarString([
'CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), 'CFLAGS' => getenv('SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS'),
'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH, 'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH,
'LDFLAGS' => '-L' . BUILD_LIB_PATH, 'LDFLAGS' => '-L' . BUILD_LIB_PATH,
]); ]);
@@ -190,7 +189,10 @@ class MacOSBuilder extends UnixBuilderBase
$shell = shell()->cd(SOURCE_PATH . '/php-src'); $shell = shell()->cd(SOURCE_PATH . '/php-src');
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
$shell->exec("make {$concurrency} {$vars} cli"); $shell->exec("make {$concurrency} {$vars} cli");
$this->deploySAPIBinary(BUILD_TARGET_CLI); if (!$this->getOption('no-strip', false)) {
$shell->exec('dsymutil -f sapi/cli/php')->exec('strip -S sapi/cli/php');
}
$this->deployBinary(BUILD_TARGET_CLI);
} }
protected function buildCgi(): void protected function buildCgi(): void
@@ -200,7 +202,10 @@ class MacOSBuilder extends UnixBuilderBase
$shell = shell()->cd(SOURCE_PATH . '/php-src'); $shell = shell()->cd(SOURCE_PATH . '/php-src');
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
$shell->exec("make {$concurrency} {$vars} cgi"); $shell->exec("make {$concurrency} {$vars} cgi");
$this->deploySAPIBinary(BUILD_TARGET_CGI); if (!$this->getOption('no-strip', false)) {
$shell->exec('dsymutil -f sapi/cgi/php-cgi')->exec('strip -S sapi/cgi/php-cgi');
}
$this->deployBinary(BUILD_TARGET_CGI);
} }
/** /**
@@ -211,8 +216,6 @@ class MacOSBuilder extends UnixBuilderBase
if ($this->getPHPVersionID() < 80000) { if ($this->getPHPVersionID() < 80000) {
throw new WrongUsageException('phpmicro only support PHP >= 8.0!'); throw new WrongUsageException('phpmicro only support PHP >= 8.0!');
} }
try {
if ($this->getExt('phar')) { if ($this->getExt('phar')) {
$this->phar_patched = true; $this->phar_patched = true;
SourcePatcher::patchMicroPhar($this->getPHPVersionID()); SourcePatcher::patchMicroPhar($this->getPHPVersionID());
@@ -229,14 +232,17 @@ class MacOSBuilder extends UnixBuilderBase
// build // build
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
$shell->exec("make {$concurrency} {$vars} micro"); $shell->exec("make {$concurrency} {$vars} micro");
// strip
if (!$this->getOption('no-strip', false)) {
$shell->exec('dsymutil -f sapi/micro/micro.sfx')->exec('strip -S sapi/micro/micro.sfx');
}
$this->deployBinary(BUILD_TARGET_MICRO);
$this->deploySAPIBinary(BUILD_TARGET_MICRO);
} finally {
if ($this->phar_patched) { if ($this->phar_patched) {
SourcePatcher::unpatchMicroPhar(); SourcePatcher::unpatchMicroPhar();
} }
} }
}
/** /**
* Build fpm sapi * Build fpm sapi
@@ -248,7 +254,10 @@ class MacOSBuilder extends UnixBuilderBase
$shell = shell()->cd(SOURCE_PATH . '/php-src'); $shell = shell()->cd(SOURCE_PATH . '/php-src');
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
$shell->exec("make {$concurrency} {$vars} fpm"); $shell->exec("make {$concurrency} {$vars} fpm");
$this->deploySAPIBinary(BUILD_TARGET_FPM); if (!$this->getOption('no-strip', false)) {
$shell->exec('dsymutil -f sapi/fpm/php-fpm')->exec('strip -S sapi/fpm/php-fpm');
}
$this->deployBinary(BUILD_TARGET_FPM);
} }
/** /**
@@ -263,25 +272,9 @@ class MacOSBuilder extends UnixBuilderBase
$install_modules = $sharedExts ? 'install-modules' : ''; $install_modules = $sharedExts ? 'install-modules' : '';
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars()); $vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
$diff = new DirDiff(BUILD_MODULES_PATH, true);
shell()->cd(SOURCE_PATH . '/php-src') shell()->cd(SOURCE_PATH . '/php-src')
->exec('sed -i "" "s|^EXTENSION_DIR = .*|EXTENSION_DIR = /' . basename(BUILD_MODULES_PATH) . '|" Makefile')
->exec("make {$concurrency} INSTALL_ROOT=" . BUILD_ROOT_PATH . " {$vars} install-sapi {$install_modules} install-build install-headers install-programs"); ->exec("make {$concurrency} INSTALL_ROOT=" . BUILD_ROOT_PATH . " {$vars} install-sapi {$install_modules} install-build install-headers install-programs");
$libphp = BUILD_LIB_PATH . '/libphp.dylib';
if (file_exists($libphp)) {
$this->deployBinary($libphp, $libphp, false);
// macOS currently have no -release option for dylib, so we just rename it here
}
// process shared extensions build-with-php
$increment_files = $diff->getChangedFiles();
foreach ($increment_files as $increment_file) {
$this->deployBinary($increment_file, $increment_file, false);
}
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'static') { if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'static') {
$AR = getenv('AR') ?: 'ar'; $AR = getenv('AR') ?: 'ar';
f_passthru("{$AR} -t " . BUILD_LIB_PATH . "/libphp.a | grep '\\.a$' | xargs -n1 {$AR} d " . BUILD_LIB_PATH . '/libphp.a'); f_passthru("{$AR} -t " . BUILD_LIB_PATH . "/libphp.a | grep '\\.a$' | xargs -n1 {$AR} d " . BUILD_LIB_PATH . '/libphp.a');

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\macos\library;
class idn2 extends MacOSLibraryBase
{
use \SPC\builder\unix\library\idn2;
public const NAME = 'idn2';
}

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\macos\library;
class krb5 extends MacOSLibraryBase
{
use \SPC\builder\unix\library\krb5;
public const NAME = 'krb5';
}

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\macos\library;
class libmaxminddb extends MacOSLibraryBase
{
use \SPC\builder\unix\library\libmaxminddb;
public const NAME = 'libmaxminddb';
}

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\macos\library;
class libunistring extends MacOSLibraryBase
{
use \SPC\builder\unix\library\libunistring;
public const NAME = 'libunistring';
}

View File

@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace SPC\builder\unix; namespace SPC\builder\unix;
use SPC\builder\BuilderBase; use SPC\builder\BuilderBase;
use SPC\builder\linux\SystemUtil;
use SPC\builder\linux\SystemUtil as LinuxSystemUtil; use SPC\builder\linux\SystemUtil as LinuxSystemUtil;
use SPC\exception\SPCException; use SPC\exception\SPCException;
use SPC\exception\SPCInternalException; use SPC\exception\SPCInternalException;
@@ -14,7 +13,6 @@ use SPC\exception\WrongUsageException;
use SPC\store\Config; use SPC\store\Config;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\store\pkg\GoXcaddy; use SPC\store\pkg\GoXcaddy;
use SPC\store\SourceManager;
use SPC\toolchain\GccNativeToolchain; use SPC\toolchain\GccNativeToolchain;
use SPC\toolchain\ToolchainManager; use SPC\toolchain\ToolchainManager;
use SPC\util\DependencyUtil; use SPC\util\DependencyUtil;
@@ -80,92 +78,6 @@ abstract class UnixBuilderBase extends BuilderBase
$this->lib_list = $sorted_libraries; $this->lib_list = $sorted_libraries;
} }
/**
* Strip unneeded symbols from binary file.
*/
public function stripBinary(string $binary_path): void
{
shell()->exec(match (PHP_OS_FAMILY) {
'Darwin' => "strip -S {$binary_path}",
'Linux' => "strip --strip-unneeded {$binary_path}",
default => throw new SPCInternalException('stripBinary is only supported on Linux and macOS'),
});
}
/**
* Extract debug information from binary file.
*
* @param string $binary_path the path to the binary file, including executables, shared libraries, etc
*/
public function extractDebugInfo(string $binary_path): string
{
$target_dir = BUILD_ROOT_PATH . '/debug';
FileSystem::createDir($target_dir);
$basename = basename($binary_path);
$debug_file = "{$target_dir}/{$basename}" . (PHP_OS_FAMILY === 'Darwin' ? '.dwarf' : '.debug');
if (PHP_OS_FAMILY === 'Darwin') {
shell()->exec("dsymutil -f {$binary_path} -o {$debug_file}");
} elseif (PHP_OS_FAMILY === 'Linux') {
if ($eu_strip = SystemUtil::findCommand('eu-strip')) {
shell()
->exec("{$eu_strip} -f {$debug_file} {$binary_path}")
->exec("objcopy --add-gnu-debuglink={$debug_file} {$binary_path}");
} else {
shell()
->exec("objcopy --only-keep-debug {$binary_path} {$debug_file}")
->exec("objcopy --add-gnu-debuglink={$debug_file} {$binary_path}");
}
} else {
throw new SPCInternalException('extractDebugInfo is only supported on Linux and macOS');
}
return $debug_file;
}
/**
* Deploy the binary file from src to dst.
*/
public function deployBinary(string $src, string $dst, bool $executable = true): string
{
logger()->debug('Deploying binary from ' . $src . ' to ' . $dst);
// file must exists
if (!file_exists($src)) {
throw new SPCInternalException("Deploy failed. Cannot find file: {$src}");
}
// dst dir must exists
FileSystem::createDir(dirname($dst));
// ignore copy to self
if (realpath($src) !== realpath($dst)) {
shell()->exec('cp ' . escapeshellarg($src) . ' ' . escapeshellarg($dst));
}
// file exist
if (!file_exists($dst)) {
throw new SPCInternalException("Deploy failed. Cannot find file after copy: {$dst}");
}
// extract debug info
$this->extractDebugInfo($dst);
// strip
if (!$this->getOption('no-strip')) {
$this->stripBinary($dst);
}
// UPX for linux
$upx_option = $this->getOption('with-upx-pack');
if ($upx_option && PHP_OS_FAMILY === 'Linux' && $executable) {
if ($this->getOption('no-strip')) {
logger()->warning('UPX compression is not recommended when --no-strip is enabled.');
}
logger()->info("Compressing {$dst} with UPX");
shell()->exec(getenv('UPX_EXEC') . " --best {$dst}");
}
return $dst;
}
/** /**
* Sanity check after build complete. * Sanity check after build complete.
*/ */
@@ -296,20 +208,23 @@ abstract class UnixBuilderBase extends BuilderBase
} }
/** /**
* Deploy binaries that produces executable SAPI * Deploy the binary file to the build bin path.
*
* @param int $type Type integer, one of BUILD_TARGET_CLI, BUILD_TARGET_MICRO, BUILD_TARGET_FPM
*/ */
protected function deploySAPIBinary(int $type): string protected function deployBinary(int $type): bool
{ {
$src = match ($type) { $src = match ($type) {
BUILD_TARGET_CLI => SOURCE_PATH . '/php-src/sapi/cli/php', BUILD_TARGET_CLI => SOURCE_PATH . '/php-src/sapi/cli/php',
BUILD_TARGET_MICRO => SOURCE_PATH . '/php-src/sapi/micro/micro.sfx', BUILD_TARGET_MICRO => SOURCE_PATH . '/php-src/sapi/micro/micro.sfx',
BUILD_TARGET_FPM => SOURCE_PATH . '/php-src/sapi/fpm/php-fpm', BUILD_TARGET_FPM => SOURCE_PATH . '/php-src/sapi/fpm/php-fpm',
BUILD_TARGET_CGI => SOURCE_PATH . '/php-src/sapi/cgi/php-cgi', BUILD_TARGET_CGI => SOURCE_PATH . '/php-src/sapi/cgi/php-cgi',
BUILD_TARGET_FRANKENPHP => BUILD_BIN_PATH . '/frankenphp',
default => throw new SPCInternalException("Deployment does not accept type {$type}"), default => throw new SPCInternalException("Deployment does not accept type {$type}"),
}; };
$dst = BUILD_BIN_PATH . '/' . basename($src); logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file');
return $this->deployBinary($src, $dst); FileSystem::createDir(BUILD_BIN_PATH);
shell()->exec('cp ' . escapeshellarg($src) . ' ' . escapeshellarg(BUILD_BIN_PATH));
return true;
} }
/** /**
@@ -350,75 +265,22 @@ abstract class UnixBuilderBase extends BuilderBase
} }
} }
/**
* Process the --with-frankenphp-app option
* Creates app.tar and app.checksum in source/frankenphp directory
*/
protected function processFrankenphpApp(): void
{
$frankenphpSourceDir = getenv('FRANKENPHP_SOURCE_PATH') ?: SOURCE_PATH . '/frankenphp';
if (!is_dir($frankenphpSourceDir)) {
SourceManager::initSource(['frankenphp'], ['frankenphp']);
}
$frankenphpAppPath = $this->getOption('with-frankenphp-app');
if ($frankenphpAppPath) {
if (!is_dir($frankenphpAppPath)) {
throw new WrongUsageException("The path provided to --with-frankenphp-app is not a valid directory: {$frankenphpAppPath}");
}
$appTarPath = $frankenphpSourceDir . '/app.tar';
logger()->info("Creating app.tar from {$frankenphpAppPath}");
shell()->exec('tar -cf ' . escapeshellarg($appTarPath) . ' -C ' . escapeshellarg($frankenphpAppPath) . ' .');
$checksum = hash_file('md5', $appTarPath);
file_put_contents($frankenphpSourceDir . '/app_checksum.txt', $checksum);
} else {
FileSystem::removeFileIfExists($frankenphpSourceDir . '/app.tar');
FileSystem::removeFileIfExists($frankenphpSourceDir . '/app_checksum.txt');
file_put_contents($frankenphpSourceDir . '/app.tar', '');
file_put_contents($frankenphpSourceDir . '/app_checksum.txt', '');
}
}
protected function getFrankenPHPVersion(): string
{
if ($version = getenv('FRANKENPHP_VERSION')) {
return $version;
}
$frankenphpSourceDir = getenv('FRANKENPHP_SOURCE_PATH') ?: SOURCE_PATH . '/frankenphp';
$goModPath = $frankenphpSourceDir . '/caddy/go.mod';
if (!file_exists($goModPath)) {
throw new SPCInternalException("FrankenPHP caddy/go.mod file not found at {$goModPath}, why did we not download FrankenPHP?");
}
$content = file_get_contents($goModPath);
if (preg_match('/github\.com\/dunglas\/frankenphp\s+v?(\d+\.\d+\.\d+)/', $content, $matches)) {
return $matches[1];
}
throw new SPCInternalException('Could not find FrankenPHP version in caddy/go.mod');
}
protected function buildFrankenphp(): void protected function buildFrankenphp(): void
{ {
GlobalEnvManager::addPathIfNotExists(GoXcaddy::getPath()); GlobalEnvManager::addPathIfNotExists(GoXcaddy::getPath());
$this->processFrankenphpApp();
$nobrotli = $this->getLib('brotli') === null ? ',nobrotli' : ''; $nobrotli = $this->getLib('brotli') === null ? ',nobrotli' : '';
$nowatcher = $this->getLib('watcher') === null ? ',nowatcher' : ''; $nowatcher = $this->getLib('watcher') === null ? ',nowatcher' : '';
$xcaddyModules = getenv('SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES'); $xcaddyModules = getenv('SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES');
$frankenphpSourceDir = getenv('FRANKENPHP_SOURCE_PATH') ?: SOURCE_PATH . '/frankenphp'; // make it possible to build from a different frankenphp directory!
if (!str_contains($xcaddyModules, '--with github.com/dunglas/frankenphp')) {
$xcaddyModules = preg_replace('#--with github.com/dunglas/frankenphp\S*#', '', $xcaddyModules); $xcaddyModules = '--with github.com/dunglas/frankenphp ' . $xcaddyModules;
$xcaddyModules = "--with github.com/dunglas/frankenphp={$frankenphpSourceDir} " . }
"--with github.com/dunglas/frankenphp/caddy={$frankenphpSourceDir}/caddy {$xcaddyModules}";
if ($this->getLib('brotli') === null && str_contains($xcaddyModules, '--with github.com/dunglas/caddy-cbrotli')) { if ($this->getLib('brotli') === null && str_contains($xcaddyModules, '--with github.com/dunglas/caddy-cbrotli')) {
logger()->warning('caddy-cbrotli module is enabled, but brotli library is not built. Disabling caddy-cbrotli.'); logger()->warning('caddy-cbrotli module is enabled, but brotli library is not built. Disabling caddy-cbrotli.');
$xcaddyModules = str_replace('--with github.com/dunglas/caddy-cbrotli', '', $xcaddyModules); $xcaddyModules = str_replace('--with github.com/dunglas/caddy-cbrotli', '', $xcaddyModules);
} }
[, $out] = shell()->execWithResult('go list -m github.com/dunglas/frankenphp@latest');
$frankenPhpVersion = $this->getFrankenPHPVersion(); $frankenPhpVersion = str_replace('github.com/dunglas/frankenphp v', '', $out[0]);
$libphpVersion = $this->getPHPVersion(); $libphpVersion = $this->getPHPVersion();
$dynamic_exports = ''; $dynamic_exports = '';
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') { if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') {
@@ -428,6 +290,7 @@ abstract class UnixBuilderBase extends BuilderBase
$dynamic_exports = ' ' . $dynamicSymbolsArgument; $dynamic_exports = ' ' . $dynamicSymbolsArgument;
} }
} }
$debugFlags = $this->getOption('no-strip') ? '-w -s ' : '';
$extLdFlags = "-extldflags '-pie{$dynamic_exports} {$this->arch_ld_flags}'"; $extLdFlags = "-extldflags '-pie{$dynamic_exports} {$this->arch_ld_flags}'";
$muslTags = ''; $muslTags = '';
$staticFlags = ''; $staticFlags = '';
@@ -438,7 +301,7 @@ 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') . ' -DFRANKENPHP_VERSION=' . $frankenPhpVersion; $cflags = "{$this->arch_c_flags} {$config['cflags']} " . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS');
$libs = $config['libs']; $libs = $config['libs'];
// 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') ||
@@ -452,7 +315,7 @@ abstract class UnixBuilderBase extends BuilderBase
'CGO_CFLAGS' => clean_spaces($cflags), 'CGO_CFLAGS' => clean_spaces($cflags),
'CGO_LDFLAGS' => "{$this->arch_ld_flags} {$staticFlags} {$config['ldflags']} {$libs}", 'CGO_LDFLAGS' => "{$this->arch_ld_flags} {$staticFlags} {$config['ldflags']} {$libs}",
'XCADDY_GO_BUILD_FLAGS' => '-buildmode=pie ' . 'XCADDY_GO_BUILD_FLAGS' => '-buildmode=pie ' .
'-ldflags \"-linkmode=external ' . $extLdFlags . ' ' . '-ldflags \"-linkmode=external ' . $extLdFlags . ' ' . $debugFlags .
'-X \'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ' . '-X \'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ' .
"v{$frankenPhpVersion} PHP {$libphpVersion} Caddy'\\\" " . "v{$frankenPhpVersion} PHP {$libphpVersion} Caddy'\\\" " .
"-tags={$muslTags}nobadger,nomysql,nopgx{$nobrotli}{$nowatcher}", "-tags={$muslTags}nobadger,nomysql,nopgx{$nobrotli}{$nowatcher}",
@@ -462,7 +325,13 @@ abstract class UnixBuilderBase extends BuilderBase
->setEnv($env) ->setEnv($env)
->exec("xcaddy build --output frankenphp {$xcaddyModules}"); ->exec("xcaddy build --output frankenphp {$xcaddyModules}");
$this->deploySAPIBinary(BUILD_TARGET_FRANKENPHP); if (!$this->getOption('no-strip', false) && file_exists(BUILD_BIN_PATH . '/frankenphp')) {
if (PHP_OS_FAMILY === 'Linux') {
shell()->cd(BUILD_BIN_PATH)->exec('strip --strip-unneeded frankenphp');
} else { // macOS doesn't understand strip-unneeded
shell()->cd(BUILD_BIN_PATH)->exec('strip -S frankenphp');
}
}
} }
/** /**

View File

@@ -23,8 +23,6 @@ trait curl
->optionalLib('zstd', ...cmake_boolean_args('CURL_ZSTD')) ->optionalLib('zstd', ...cmake_boolean_args('CURL_ZSTD'))
->optionalLib('idn2', ...cmake_boolean_args('USE_LIBIDN2')) ->optionalLib('idn2', ...cmake_boolean_args('USE_LIBIDN2'))
->optionalLib('psl', ...cmake_boolean_args('CURL_USE_LIBPSL')) ->optionalLib('psl', ...cmake_boolean_args('CURL_USE_LIBPSL'))
->optionalLib('krb5', ...cmake_boolean_args('CURL_USE_GSSAPI'))
->optionalLib('idn2', ...cmake_boolean_args('CURL_USE_IDN2'))
->optionalLib('libcares', '-DENABLE_ARES=ON') ->optionalLib('libcares', '-DENABLE_ARES=ON')
->addConfigureArgs( ->addConfigureArgs(
'-DBUILD_CURL_EXE=OFF', '-DBUILD_CURL_EXE=OFF',

View File

@@ -1,27 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\util\executor\UnixAutoconfExecutor;
trait idn2
{
protected function build(): void
{
UnixAutoconfExecutor::create($this)
->configure(
'--disable-nls',
'--disable-doc',
'--enable-year2038',
'--disable-rpath'
)
->optionalLib('libiconv', "--with-libiconv-prefix={$this->getBuildRootPath()}")
->optionalLib('libunistring', "--with-libunistring-prefix={$this->getBuildRootPath()}")
->optionalLib('gettext', "--with-libnintl-prefix={$this->getBuildRootPath()}")
->make();
$this->patchPkgconfPrefix(['libidn2.pc']);
$this->patchLaDependencyPrefix();
}
}

View File

@@ -1,57 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\util\executor\UnixAutoconfExecutor;
use SPC\util\SPCConfigUtil;
trait krb5
{
protected function build(): void
{
$origin_source_dir = $this->source_dir;
$this->source_dir .= '/src';
shell()->cd($this->source_dir)->exec('autoreconf -if');
$libs = array_map(fn ($x) => $x->getName(), $this->getDependencies(true));
$spc = new SPCConfigUtil($this->builder, ['no_php' => true, 'libs_only_deps' => true]);
$config = $spc->config(libraries: $libs, include_suggest_lib: $this->builder->getOption('with-suggested-libs', false));
$extraEnv = [
'CFLAGS' => '-fcommon',
'LIBS' => $config['libs'],
];
if (getenv('SPC_LD_LIBRARY_PATH') && getenv('SPC_LIBRARY_PATH')) {
$extraEnv = [...$extraEnv, ...[
'LD_LIBRARY_PATH' => getenv('SPC_LD_LIBRARY_PATH'),
'LIBRARY_PATH' => getenv('SPC_LIBRARY_PATH'),
]];
}
$args = [
'--disable-nls',
'--disable-rpath',
'--without-system-verto',
];
if (PHP_OS_FAMILY === 'Darwin') {
$extraEnv['LDFLAGS'] = '-framework Kerberos';
$args[] = 'ac_cv_func_secure_getenv=no';
}
UnixAutoconfExecutor::create($this)
->appendEnv($extraEnv)
->optionalLib('ldap', '--with-ldap', '--without-ldap')
->optionalLib('libedit', '--with-libedit', '--without-libedit')
->configure(...$args)
->make();
$this->patchPkgconfPrefix([
'krb5-gssapi.pc',
'krb5.pc',
'kadm-server.pc',
'kadm-client.pc',
'kdb.pc',
'mit-krb5-gssapi.pc',
'mit-krb5.pc',
'gssrpc.pc',
]);
$this->source_dir = $origin_source_dir;
}
}

View File

@@ -1,20 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\util\executor\UnixCMakeExecutor;
trait libmaxminddb
{
protected function build(): void
{
UnixCMakeExecutor::create($this)
->addConfigureArgs(
'-DBUILD_TESTING=OFF',
'-DMAXMINDDB_BUILD_BINARIES=OFF',
)
->build();
}
}

View File

@@ -5,7 +5,7 @@ declare(strict_types=1);
namespace SPC\builder\unix\library; namespace SPC\builder\unix\library;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\util\executor\UnixCMakeExecutor; use SPC\util\executor\UnixAutoconfExecutor;
trait librdkafka trait librdkafka
{ {
@@ -26,18 +26,34 @@ trait librdkafka
protected function build(): void protected function build(): void
{ {
UnixCMakeExecutor::create($this) UnixAutoconfExecutor::create($this)
->optionalLib('zstd', ...cmake_boolean_args('WITH_ZSTD')) ->appendEnv(['CFLAGS' => '-Wno-int-conversion -Wno-unused-but-set-variable -Wno-unused-variable'])
->optionalLib('curl', ...cmake_boolean_args('WITH_CURL')) ->optionalLib(
->optionalLib('openssl', ...cmake_boolean_args('WITH_SSL')) 'zstd',
->optionalLib('zlib', ...cmake_boolean_args('WITH_ZLIB')) function ($lib) {
->optionalLib('liblz4', ...cmake_boolean_args('ENABLE_LZ4_EXT')) putenv("STATIC_LIB_libzstd={$lib->getLibDir()}/libzstd.a");
->addConfigureArgs( return '';
'-DWITH_SASL=OFF', },
'-DRDKAFKA_BUILD_STATIC=ON', '--disable-zstd'
'-DRDKAFKA_BUILD_EXAMPLES=OFF',
'-DRDKAFKA_BUILD_TESTS=OFF',
) )
->build(); ->removeConfigureArgs(
'--with-pic',
'--enable-pic',
)
->configure(
'--disable-curl',
'--disable-sasl',
'--disable-valgrind',
'--disable-zlib',
'--disable-ssl',
)
->make();
$this->patchPkgconfPrefix(['rdkafka.pc', 'rdkafka-static.pc', 'rdkafka++.pc', 'rdkafka++-static.pc']);
// remove dynamic libs
shell()
->exec("rm -rf {$this->getLibDir()}/*.so.*")
->exec("rm -rf {$this->getLibDir()}/*.so")
->exec("rm -rf {$this->getLibDir()}/*.dylib");
} }
} }

View File

@@ -1,18 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\util\executor\UnixAutoconfExecutor;
trait libunistring
{
protected function build(): void
{
UnixAutoconfExecutor::create($this)
->configure('--disable-nls')
->make();
$this->patchLaDependencyPrefix();
}
}

View File

@@ -47,7 +47,7 @@ trait postgresql
{ {
$libs = array_map(fn ($x) => $x->getName(), $this->getDependencies(true)); $libs = array_map(fn ($x) => $x->getName(), $this->getDependencies(true));
$spc = new SPCConfigUtil($this->builder, ['no_php' => true, 'libs_only_deps' => true]); $spc = new SPCConfigUtil($this->builder, ['no_php' => true, 'libs_only_deps' => true]);
$config = $spc->config(libraries: $libs, include_suggest_lib: $this->builder->getOption('with-suggested-libs', false)); $config = $spc->config(libraries: $libs, include_suggest_lib: $this->builder->getOption('with-suggested-libs'));
$env_vars = [ $env_vars = [
'CFLAGS' => $config['cflags'], 'CFLAGS' => $config['cflags'],

View File

@@ -67,6 +67,21 @@ class WindowsBuilder extends BuilderBase
$zts = $this->zts ? '--enable-zts=yes ' : '--enable-zts=no '; $zts = $this->zts ? '--enable-zts=yes ' : '--enable-zts=no ';
// with-upx-pack for phpmicro
if ($enableMicro && version_compare($this->getMicroVersion(), '0.2.0') < 0) {
$makefile = FileSystem::convertPath(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.w32');
if ($this->getOption('with-upx-pack', false)) {
if (!file_exists($makefile . '.originfile')) {
copy($makefile, $makefile . '.originfile');
FileSystem::replaceFileStr($makefile, '$(MICRO_SFX):', '_MICRO_UPX = ' . getenv('UPX_EXEC') . " --best $(MICRO_SFX)\n$(MICRO_SFX):");
FileSystem::replaceFileStr($makefile, '@$(_MICRO_MT)', "@$(_MICRO_MT)\n\t@$(_MICRO_UPX)");
}
} elseif (file_exists($makefile . '.originfile')) {
copy($makefile . '.originfile', $makefile);
unlink($makefile . '.originfile');
}
}
$opcache_jit = !$this->getOption('disable-opcache-jit', false); $opcache_jit = !$this->getOption('disable-opcache-jit', false);
$opcache_jit_arg = $opcache_jit ? '--enable-opcache-jit=yes ' : '--enable-opcache-jit=no '; $opcache_jit_arg = $opcache_jit ? '--enable-opcache-jit=yes ' : '--enable-opcache-jit=no ';
@@ -130,7 +145,7 @@ class WindowsBuilder extends BuilderBase
} }
} }
public function testPHP(int $build_target = BUILD_TARGET_NONE): void public function testPHP(int $build_target = BUILD_TARGET_NONE)
{ {
$this->sanityCheck($build_target); $this->sanityCheck($build_target);
} }
@@ -141,27 +156,12 @@ class WindowsBuilder extends BuilderBase
$extra_libs = getenv('SPC_EXTRA_LIBS') ?: ''; $extra_libs = getenv('SPC_EXTRA_LIBS') ?: '';
// Add debug symbols for release build if --no-strip is specified
// We need to modify CFLAGS to replace /Ox with /Zi and add /DEBUG to LDFLAGS
$debug_overrides = '';
if ($this->getOption('no-strip', false)) {
// Read current CFLAGS from Makefile and replace optimization flags
$makefile_content = file_get_contents(SOURCE_PATH . '\php-src\Makefile');
if (preg_match('/^CFLAGS=(.+?)$/m', $makefile_content, $matches)) {
$cflags = $matches[1];
// Replace /Ox (full optimization) with /Zi (debug info) and /Od (disable optimization)
// Keep optimization for speed: /O2 /Zi instead of /Od /Zi
$cflags = str_replace('/Ox ', '/O2 /Zi ', $cflags);
$debug_overrides = '"CFLAGS=' . $cflags . '" "LDFLAGS=/DEBUG /LTCG /INCREMENTAL:NO" "LDFLAGS_CLI=/DEBUG" ';
}
}
// add nmake wrapper // add nmake wrapper
FileSystem::writeFile(SOURCE_PATH . '\php-src\nmake_cli_wrapper.bat', "nmake /nologo {$debug_overrides}LIBS_CLI=\"ws2_32.lib shell32.lib {$extra_libs}\" EXTRA_LD_FLAGS_PROGRAM= %*"); FileSystem::writeFile(SOURCE_PATH . '\php-src\nmake_cli_wrapper.bat', "nmake /nologo LIBS_CLI=\"ws2_32.lib shell32.lib {$extra_libs}\" EXTRA_LD_FLAGS_PROGRAM= %*");
cmd()->cd(SOURCE_PATH . '\php-src')->exec("{$this->sdk_prefix} nmake_cli_wrapper.bat --task-args php.exe"); cmd()->cd(SOURCE_PATH . '\php-src')->exec("{$this->sdk_prefix} nmake_cli_wrapper.bat --task-args php.exe");
$this->deploySAPIBinary(BUILD_TARGET_CLI); $this->deployBinary(BUILD_TARGET_CLI);
} }
public function buildCgi(): void public function buildCgi(): void
@@ -170,23 +170,12 @@ class WindowsBuilder extends BuilderBase
$extra_libs = getenv('SPC_EXTRA_LIBS') ?: ''; $extra_libs = getenv('SPC_EXTRA_LIBS') ?: '';
// Add debug symbols for release build if --no-strip is specified
$debug_overrides = '';
if ($this->getOption('no-strip', false)) {
$makefile_content = file_get_contents(SOURCE_PATH . '\php-src\Makefile');
if (preg_match('/^CFLAGS=(.+?)$/m', $makefile_content, $matches)) {
$cflags = $matches[1];
$cflags = str_replace('/Ox ', '/O2 /Zi ', $cflags);
$debug_overrides = '"CFLAGS=' . $cflags . '" "LDFLAGS=/DEBUG /LTCG /INCREMENTAL:NO" "LDFLAGS_CGI=/DEBUG" ';
}
}
// add nmake wrapper // add nmake wrapper
FileSystem::writeFile(SOURCE_PATH . '\php-src\nmake_cgi_wrapper.bat', "nmake /nologo {$debug_overrides}LIBS_CGI=\"ws2_32.lib kernel32.lib advapi32.lib {$extra_libs}\" EXTRA_LD_FLAGS_PROGRAM= %*"); FileSystem::writeFile(SOURCE_PATH . '\php-src\nmake_cgi_wrapper.bat', "nmake /nologo LIBS_CGI=\"ws2_32.lib kernel32.lib advapi32.lib {$extra_libs}\" EXTRA_LD_FLAGS_PROGRAM= %*");
cmd()->cd(SOURCE_PATH . '\php-src')->exec("{$this->sdk_prefix} nmake_cgi_wrapper.bat --task-args php-cgi.exe"); cmd()->cd(SOURCE_PATH . '\php-src')->exec("{$this->sdk_prefix} nmake_cgi_wrapper.bat --task-args php-cgi.exe");
$this->deploySAPIBinary(BUILD_TARGET_CGI); $this->deployBinary(BUILD_TARGET_CGI);
} }
public function buildEmbed(): void public function buildEmbed(): void
@@ -213,20 +202,9 @@ class WindowsBuilder extends BuilderBase
$extra_libs = getenv('SPC_EXTRA_LIBS') ?: ''; $extra_libs = getenv('SPC_EXTRA_LIBS') ?: '';
// Add debug symbols for release build if --no-strip is specified
$debug_overrides = '';
if ($this->getOption('no-strip', false) && !$this->getOption('debug', false)) {
$makefile_content = file_get_contents(SOURCE_PATH . '\php-src\Makefile');
if (preg_match('/^CFLAGS=(.+?)$/m', $makefile_content, $matches)) {
$cflags = $matches[1];
$cflags = str_replace('/Ox ', '/O2 /Zi ', $cflags);
$debug_overrides = '"CFLAGS=' . $cflags . '" "LDFLAGS=/DEBUG /LTCG /INCREMENTAL:NO" "LDFLAGS_MICRO=/DEBUG" ';
}
}
// add nmake wrapper // add nmake wrapper
$fake_cli = $this->getOption('with-micro-fake-cli', false) ? ' /DPHP_MICRO_FAKE_CLI" ' : ''; $fake_cli = $this->getOption('with-micro-fake-cli', false) ? ' /DPHP_MICRO_FAKE_CLI" ' : '';
$wrapper = "nmake /nologo {$debug_overrides}LIBS_MICRO=\"ws2_32.lib shell32.lib {$extra_libs}\" CFLAGS_MICRO=\"/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1{$fake_cli}\" %*"; $wrapper = "nmake /nologo LIBS_MICRO=\"ws2_32.lib shell32.lib {$extra_libs}\" CFLAGS_MICRO=\"/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1{$fake_cli}\" %*";
FileSystem::writeFile(SOURCE_PATH . '\php-src\nmake_micro_wrapper.bat', $wrapper); FileSystem::writeFile(SOURCE_PATH . '\php-src\nmake_micro_wrapper.bat', $wrapper);
// phar patch for micro // phar patch for micro
@@ -243,7 +221,7 @@ class WindowsBuilder extends BuilderBase
} }
} }
$this->deploySAPIBinary(BUILD_TARGET_MICRO); $this->deployBinary(BUILD_TARGET_MICRO);
} }
public function proveLibs(array $sorted_libraries): void public function proveLibs(array $sorted_libraries): void
@@ -357,53 +335,28 @@ class WindowsBuilder extends BuilderBase
* *
* @param int $type Deploy type * @param int $type Deploy type
*/ */
public function deploySAPIBinary(int $type): void public function deployBinary(int $type): bool
{ {
logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file');
$debug_dir = BUILD_ROOT_PATH . '\debug';
$bin_path = BUILD_BIN_PATH;
// create dirs
FileSystem::createDir($debug_dir);
FileSystem::createDir($bin_path);
// determine source path for different SAPI
$rel_type = 'Release'; // TODO: Debug build support
$ts = $this->zts ? '_TS' : ''; $ts = $this->zts ? '_TS' : '';
$src = match ($type) { $src = match ($type) {
BUILD_TARGET_CLI => [SOURCE_PATH . "\\php-src\\x64\\{$rel_type}{$ts}", 'php.exe', 'php.pdb'], BUILD_TARGET_CLI => SOURCE_PATH . "\\php-src\\x64\\Release{$ts}\\php.exe",
BUILD_TARGET_MICRO => [SOURCE_PATH . "\\php-src\\x64\\{$rel_type}{$ts}", 'micro.sfx', 'micro.pdb'], BUILD_TARGET_MICRO => SOURCE_PATH . "\\php-src\\x64\\Release{$ts}\\micro.sfx",
BUILD_TARGET_CGI => [SOURCE_PATH . "\\php-src\\x64\\{$rel_type}{$ts}", 'php-cgi.exe', 'php-cgi.pdb'], BUILD_TARGET_CGI => SOURCE_PATH . "\\php-src\\x64\\Release{$ts}\\php-cgi.exe",
default => throw new SPCInternalException("Deployment does not accept type {$type}"), default => throw new SPCInternalException("Deployment does not accept type {$type}"),
}; };
$src = "{$src[0]}\\{$src[1]}";
$dst = BUILD_BIN_PATH . '\\' . basename($src);
// file must exists
if (!file_exists($src)) {
throw new SPCInternalException("Deploy failed. Cannot find file: {$src}");
}
// dst dir must exists
FileSystem::createDir(dirname($dst));
// copy file
if (realpath($src) !== realpath($dst)) {
cmd()->exec('copy ' . escapeshellarg($src) . ' ' . escapeshellarg($dst));
}
// extract debug info in buildroot/debug
if ($this->getOption('no-strip', false) && file_exists("{$src[0]}\\{$src[2]}")) {
cmd()->exec('copy ' . escapeshellarg("{$src[0]}\\{$src[2]}") . ' ' . escapeshellarg($debug_dir));
}
// with-upx-pack for cli and micro // with-upx-pack for cli and micro
if ($this->getOption('with-upx-pack', false)) { if ($this->getOption('with-upx-pack', false)) {
if ($type === BUILD_TARGET_CLI || $type === BUILD_TARGET_CGI || ($type === BUILD_TARGET_MICRO && version_compare($this->getMicroVersion(), '0.2.0') >= 0)) { if ($type === BUILD_TARGET_CLI || $type === BUILD_TARGET_CGI || ($type === BUILD_TARGET_MICRO && version_compare($this->getMicroVersion(), '0.2.0') >= 0)) {
cmd()->exec(getenv('UPX_EXEC') . ' --best ' . escapeshellarg($dst)); cmd()->exec(getenv('UPX_EXEC') . ' --best ' . escapeshellarg($src));
} }
} }
logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file');
FileSystem::createDir(BUILD_BIN_PATH);
cmd()->exec('copy ' . escapeshellarg($src) . ' ' . escapeshellarg(BUILD_BIN_PATH . '\\'));
return true;
} }
/** /**

View File

@@ -48,7 +48,6 @@ class BuildPHPCommand extends BuildCommand
$this->addOption('with-upx-pack', null, null, 'Compress / pack binary using UPX tool (linux/windows only)'); $this->addOption('with-upx-pack', null, null, 'Compress / pack binary using UPX tool (linux/windows only)');
$this->addOption('with-micro-logo', null, InputOption::VALUE_REQUIRED, 'Use custom .ico for micro.sfx (windows only)'); $this->addOption('with-micro-logo', null, InputOption::VALUE_REQUIRED, 'Use custom .ico for micro.sfx (windows only)');
$this->addOption('enable-micro-win32', null, null, 'Enable win32 mode for phpmicro (Windows only)'); $this->addOption('enable-micro-win32', null, null, 'Enable win32 mode for phpmicro (Windows only)');
$this->addOption('with-frankenphp-app', null, InputOption::VALUE_REQUIRED, 'Path to a folder to be embedded in FrankenPHP');
} }
public function handle(): int public function handle(): int

View File

@@ -22,7 +22,7 @@ class LinuxMuslCheck
public static function optionalCheck(): bool public static function optionalCheck(): bool
{ {
return getenv('SPC_TOOLCHAIN') === MuslToolchain::class || return getenv('SPC_TOOLCHAIN') === MuslToolchain::class ||
(getenv('SPC_TOOLCHAIN') === ZigToolchain::class && !SystemUtil::isMuslDist() && !str_contains((string) getenv('SPC_TARGET'), 'gnu')); (getenv('SPC_TOOLCHAIN') === ZigToolchain::class && !SystemUtil::isMuslDist());
} }
/** @noinspection PhpUnused */ /** @noinspection PhpUnused */

View File

@@ -159,9 +159,7 @@ class ExceptionHandler
public static function handleDefaultException(\Throwable $e): void public static function handleDefaultException(\Throwable $e): void
{ {
$class = get_class($e); $class = get_class($e);
$file = $e->getFile(); self::logError("✗ Unhandled exception {$class}:\n\t{$e->getMessage()}\n");
$line = $e->getLine();
self::logError("✗ Unhandled exception {$class} on {$file} line {$line}:\n\t{$e->getMessage()}\n");
self::logError('Stack trace:'); self::logError('Stack trace:');
self::logError(ConsoleColor::gray($e->getTraceAsString()) . PHP_EOL, 4); self::logError(ConsoleColor::gray($e->getTraceAsString()) . PHP_EOL, 4);
self::logError('⚠ Please report this exception to: https://github.com/crazywhalecc/static-php-cli/issues'); self::logError('⚠ Please report this exception to: https://github.com/crazywhalecc/static-php-cli/issues');

View File

@@ -1,95 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\store;
/**
* A util class to diff directory file increments.
*/
class DirDiff
{
protected array $before = [];
protected array $before_file_hashes = [];
public function __construct(protected string $dir, protected bool $track_content_changes = false)
{
$this->reset();
}
/**
* Reset the baseline to current state.
*/
public function reset(): void
{
$this->before = FileSystem::scanDirFiles($this->dir, relative: true) ?: [];
if ($this->track_content_changes) {
$this->before_file_hashes = [];
foreach ($this->before as $file) {
$this->before_file_hashes[$file] = md5_file($this->dir . DIRECTORY_SEPARATOR . $file);
}
}
}
/**
* Get the list of incremented files.
*
* @param bool $relative Return relative paths or absolute paths
* @return array<string> List of incremented files
*/
public function getIncrementFiles(bool $relative = false): array
{
$after = FileSystem::scanDirFiles($this->dir, relative: true) ?: [];
$diff = array_diff($after, $this->before);
if ($relative) {
return $diff;
}
return array_map(fn ($f) => $this->dir . DIRECTORY_SEPARATOR . $f, $diff);
}
/**
* Get the list of changed files (including new files).
*
* @param bool $relative Return relative paths or absolute paths
* @param bool $include_new_files Include new files as changed files
* @return array<string> List of changed files
*/
public function getChangedFiles(bool $relative = false, bool $include_new_files = true): array
{
$after = FileSystem::scanDirFiles($this->dir, relative: true) ?: [];
$changed = [];
foreach ($after as $file) {
if (isset($this->before_file_hashes[$file])) {
$after_hash = md5_file($this->dir . DIRECTORY_SEPARATOR . $file);
if ($after_hash !== $this->before_file_hashes[$file]) {
$changed[] = $file;
}
} elseif ($include_new_files) {
// New file, consider as changed
$changed[] = $file;
}
}
if ($relative) {
return $changed;
}
return array_map(fn ($f) => $this->dir . DIRECTORY_SEPARATOR . $f, $changed);
}
/**
* Get the list of removed files.
*
* @param bool $relative Return relative paths or absolute paths
* @return array<string> List of removed files
*/
public function getRemovedFiles(bool $relative = false): array
{
$after = FileSystem::scanDirFiles($this->dir, relative: true) ?: [];
$removed = array_diff($this->before, $after);
if ($relative) {
return $removed;
}
return array_map(fn ($f) => $this->dir . DIRECTORY_SEPARATOR . $f, $removed);
}
}

View File

@@ -174,9 +174,6 @@ class FileSystem
logger()->debug("Copying file from {$from} to {$to}"); logger()->debug("Copying file from {$from} to {$to}");
$dst_path = FileSystem::convertPath($to); $dst_path = FileSystem::convertPath($to);
$src_path = FileSystem::convertPath($from); $src_path = FileSystem::convertPath($from);
if ($src_path === $dst_path) {
return;
}
if (!copy($src_path, $dst_path)) { if (!copy($src_path, $dst_path)) {
throw new FileSystemException('Cannot copy file from ' . $src_path . ' to ' . $dst_path); throw new FileSystemException('Cannot copy file from ' . $src_path . ' to ' . $dst_path);
} }
@@ -660,19 +657,11 @@ class FileSystem
$source = self::convertPath($source); $source = self::convertPath($source);
$dest = self::convertPath($dest); $dest = self::convertPath($dest);
// Check if source and dest are on the same device to avoid cross-device rename errors // Try rename first (fast, atomic)
$source_stat = @stat($source);
$dest_parent = dirname($dest);
$dest_stat = @stat($dest_parent);
// Only use rename if on same device
if ($source_stat !== false && $dest_stat !== false && $source_stat['dev'] === $dest_stat['dev']) {
if (@rename($source, $dest)) { if (@rename($source, $dest)) {
return; return;
} }
}
// Fall back to copy + delete for cross-device moves or if rename failed
if (is_dir($source)) { if (is_dir($source)) {
self::copyDir($source, $dest); self::copyDir($source, $dest);
self::removeDir($source); self::removeDir($source);

View File

@@ -15,7 +15,9 @@ class PhpSource extends CustomSourceBase
public function fetch(bool $force = false, ?array $config = null, int $lock_as = SPC_DOWNLOAD_SOURCE): void public function fetch(bool $force = false, ?array $config = null, int $lock_as = SPC_DOWNLOAD_SOURCE): void
{ {
$major = defined('SPC_BUILD_PHP_VERSION') ? SPC_BUILD_PHP_VERSION : '8.4'; $major = defined('SPC_BUILD_PHP_VERSION') ? SPC_BUILD_PHP_VERSION : '8.4';
if ($major === 'git') { if ($major === '8.5') {
Downloader::downloadSource('php-src', ['type' => 'url', 'url' => 'https://downloads.php.net/~daniels/php-8.5.0RC3.tar.xz'], $force);
} 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', $this->getLatestPHPInfo($major), $force); Downloader::downloadSource('php-src', $this->getLatestPHPInfo($major), $force);

View File

@@ -7,7 +7,6 @@ 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\builder\Extension;
use SPC\builder\LibraryBase;
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;
@@ -54,9 +53,6 @@ class SPCConfigUtil
*/ */
public function config(array $extensions = [], array $libraries = [], bool $include_suggest_ext = false, bool $include_suggest_lib = false): array public function config(array $extensions = [], array $libraries = [], bool $include_suggest_ext = false, bool $include_suggest_lib = false): array
{ {
logger()->debug('config extensions: ' . implode(',', $extensions));
logger()->debug('config libs: ' . implode(',', $libraries));
logger()->debug('config suggest for [ext, lib]: ' . ($include_suggest_ext ? 'true' : 'false') . ',' . ($include_suggest_lib ? 'true' : 'false'));
$extra_exts = []; $extra_exts = [];
foreach ($extensions as $ext) { foreach ($extensions as $ext) {
$extra_exts = array_merge($extra_exts, Config::getExt($ext, 'ext-suggests', [])); $extra_exts = array_merge($extra_exts, Config::getExt($ext, 'ext-suggests', []));
@@ -128,63 +124,6 @@ class SPCConfigUtil
]; ];
} }
/**
* [Helper function]
* Get configuration for a specific extension(s) dependencies.
*
* @param Extension|Extension[] $extension Extension instance or list
* @param bool $include_suggest_ext Whether to include suggested extensions
* @param bool $include_suggest_lib Whether to include suggested libraries
* @return array{
* cflags: string,
* ldflags: string,
* libs: string
* }
*/
public function getExtensionConfig(array|Extension $extension, bool $include_suggest_ext = false, bool $include_suggest_lib = false): array
{
if (!is_array($extension)) {
$extension = [$extension];
}
$libs = array_map(fn ($y) => $y->getName(), array_merge(...array_map(fn ($x) => $x->getLibraryDependencies(true), $extension)));
return $this->config(
extensions: array_map(fn ($x) => $x->getName(), $extension),
libraries: $libs,
include_suggest_ext: $include_suggest_ext ?: $this->builder?->getOption('with-suggested-exts') ?? false,
include_suggest_lib: $include_suggest_lib ?: $this->builder?->getOption('with-suggested-libs') ?? false,
);
}
/**
* [Helper function]
* Get configuration for a specific library(s) dependencies.
*
* @param LibraryBase|LibraryBase[] $lib Library instance or list
* @param bool $include_suggest_lib Whether to include suggested libraries
* @return array{
* cflags: string,
* ldflags: string,
* libs: string
* }
*/
public function getLibraryConfig(array|LibraryBase $lib, bool $include_suggest_lib = false): array
{
if (!is_array($lib)) {
$lib = [$lib];
}
$save_no_php = $this->no_php;
$this->no_php = true;
$save_libs_only_deps = $this->libs_only_deps;
$this->libs_only_deps = true;
$ret = $this->config(
libraries: array_map(fn ($x) => $x->getName(), $lib),
include_suggest_lib: $include_suggest_lib ?: $this->builder?->getOption('with-suggested-libs') ?? false,
);
$this->no_php = $save_no_php;
$this->libs_only_deps = $save_libs_only_deps;
return $ret;
}
private function hasCpp(array $extensions, array $libraries): bool private function hasCpp(array $extensions, array $libraries): bool
{ {
// judge cpp-extension // judge cpp-extension

View File

@@ -35,7 +35,7 @@ $test_os = [
]; ];
// whether enable thread safe // whether enable thread safe
$zts = false; $zts = true;
$no_strip = false; $no_strip = false;
@@ -50,8 +50,8 @@ $prefer_pre_built = false;
// If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`). // If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`).
$extensions = match (PHP_OS_FAMILY) { $extensions = match (PHP_OS_FAMILY) {
'Linux', 'Darwin' => 'maxminddb', 'Linux', 'Darwin' => 'trader',
'Windows' => 'bcmath', 'Windows' => 'bcmath,bz2,calendar,ctype,curl,dba,dom,exif,ffi,fileinfo,filter,ftp,iconv,libxml,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pdo,pdo_mysql,pdo_sqlite,pdo_sqlsrv,phar,session,shmop,simdjson,simplexml,soap,sockets,sqlite3,sqlsrv,ssh2,sysvshm,tokenizer,xml,xmlreader,xmlwriter,yaml,zip,zlib',
}; };
// 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`).
@@ -74,7 +74,7 @@ $with_libs = match (PHP_OS_FAMILY) {
// You can use `common`, `bulk`, `minimal` or `none`. // You can use `common`, `bulk`, `minimal` or `none`.
// note: combination is only available for *nix platform. Windows must use `none` combination // note: combination is only available for *nix platform. Windows must use `none` combination
$base_combination = match (PHP_OS_FAMILY) { $base_combination = match (PHP_OS_FAMILY) {
'Linux', 'Darwin' => 'minimal', 'Linux', 'Darwin' => 'none',
'Windows' => 'none', 'Windows' => 'none',
}; };