mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-11 19:05:35 +08:00
Compare commits
2 Commits
ca8a28a364
...
ttt
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3003d363e | ||
|
|
b5b4e8f622 |
16
.github/workflows/build-unix.yml
vendored
16
.github/workflows/build-unix.yml
vendored
@@ -276,7 +276,7 @@ jobs:
|
||||
# Upload debug logs
|
||||
- if: ${{ inputs.debug && failure() }}
|
||||
name: "Upload build logs on failure"
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: spc-logs-${{ inputs.php-version }}-${{ inputs.os }}
|
||||
path: log/*.log
|
||||
@@ -284,7 +284,7 @@ jobs:
|
||||
# Upload cli executable
|
||||
- if: ${{ inputs.build-cli == true }}
|
||||
name: "Upload PHP cli SAPI"
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: php-cli-${{ inputs.php-version }}-${{ inputs.os }}
|
||||
path: buildroot/bin/php
|
||||
@@ -292,7 +292,7 @@ jobs:
|
||||
# Upload micro self-extracted executable
|
||||
- if: ${{ inputs.build-micro == true }}
|
||||
name: "Upload PHP micro SAPI"
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: php-micro-${{ inputs.php-version }}-${{ inputs.os }}
|
||||
path: buildroot/bin/micro.sfx
|
||||
@@ -300,7 +300,7 @@ jobs:
|
||||
# Upload fpm executable
|
||||
- if: ${{ inputs.build-fpm == true }}
|
||||
name: "Upload PHP fpm SAPI"
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: php-fpm-${{ inputs.php-version }}-${{ inputs.os }}
|
||||
path: buildroot/bin/php-fpm
|
||||
@@ -308,7 +308,7 @@ jobs:
|
||||
# Upload frankenphp executable
|
||||
- if: ${{ inputs['build-frankenphp'] == true }}
|
||||
name: "Upload FrankenPHP SAPI"
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: php-frankenphp-${{ inputs.php-version }}-${{ inputs.os }}
|
||||
path: buildroot/bin/frankenphp
|
||||
@@ -316,17 +316,17 @@ jobs:
|
||||
# Upload extensions metadata
|
||||
- if: ${{ inputs['shared-extensions'] != '' }}
|
||||
name: "Upload shared extensions"
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: php-shared-ext-${{ inputs.php-version }}-${{ inputs.os }}
|
||||
path: |
|
||||
buildroot/modules/*.so
|
||||
- uses: actions/upload-artifact@v7
|
||||
- uses: actions/upload-artifact@v4
|
||||
name: "Upload License Files"
|
||||
with:
|
||||
name: license-files-${{ inputs.php-version }}-${{ inputs.os }}
|
||||
path: buildroot/license/
|
||||
- uses: actions/upload-artifact@v7
|
||||
- uses: actions/upload-artifact@v4
|
||||
name: "Upload Build Metadata"
|
||||
with:
|
||||
name: build-meta-${{ inputs.php-version }}-${{ inputs.os }}
|
||||
|
||||
8
.github/workflows/build-windows-x86_64.yml
vendored
8
.github/workflows/build-windows-x86_64.yml
vendored
@@ -94,24 +94,24 @@ jobs:
|
||||
|
||||
# Upload cli executable
|
||||
- if: ${{ inputs.build-cli == true }}
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: php-${{ inputs.version }}
|
||||
path: buildroot/bin/php.exe
|
||||
|
||||
# Upload micro self-extracted executable
|
||||
- if: ${{ inputs.build-micro == true }}
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: micro-${{ inputs.version }}
|
||||
path: buildroot/bin/micro.sfx
|
||||
|
||||
# Upload extensions metadata
|
||||
- uses: actions/upload-artifact@v7
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: license-files
|
||||
path: buildroot/license/
|
||||
- uses: actions/upload-artifact@v7
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-meta
|
||||
path: |
|
||||
|
||||
50
.github/workflows/release-build.yml
vendored
50
.github/workflows/release-build.yml
vendored
@@ -2,9 +2,9 @@ name: Build SPC Binary
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main", "v3" ]
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main", "v3" ]
|
||||
branches: [ "main" ]
|
||||
paths:
|
||||
- '.github/workflows/release-build.yml'
|
||||
release:
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
filename: "spc-windows-x64.exe"
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
uses: "actions/checkout@v5"
|
||||
uses: "actions/checkout@v4"
|
||||
|
||||
- if: inputs.debug == true
|
||||
run: echo "SPC_BUILD_DEBUG=--debug" >> $GITHUB_ENV
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: "Cache Composer dependencies"
|
||||
uses: "actions/cache@v5"
|
||||
uses: "actions/cache@v4"
|
||||
with:
|
||||
path: "${{ steps.composer-cache.outputs.dir }}"
|
||||
key: "php-${{ env.PHP_VERSION }}-locked-composer-${{ hashFiles('**/composer.lock') }}"
|
||||
@@ -101,7 +101,7 @@ jobs:
|
||||
tar -czf ${{ matrix.operating-system.filename }} spc
|
||||
# validate spc binary
|
||||
if [ "${{ matrix.operating-system.name }}" == "linux-x86_64" ]; then
|
||||
./spc dev:info php
|
||||
./spc dev:extensions
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -120,44 +120,20 @@ jobs:
|
||||
with:
|
||||
files: dist/${{ matrix.operating-system.filename }}
|
||||
|
||||
- name: "Deploy to self-hosted OSS (nightly)"
|
||||
# only run this step if the repository is static-php-cli and is push to v3 branch
|
||||
if: ${{ github.repository == 'crazywhalecc/static-php-cli' && github.ref == 'refs/heads/v3' }}
|
||||
- name: "Deploy to self-hosted OSS"
|
||||
# only run this step if the repository is static-php-cli and the branch is main
|
||||
if: github.repository == 'crazywhalecc/static-php-cli' && github.ref == 'refs/heads/main'
|
||||
uses: static-php/upload-s3-action@v1.0.0
|
||||
with:
|
||||
aws_key_id: ${{ secrets.AWS_KEY_ID }}
|
||||
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws_bucket: ${{ secrets.AWS_BUCKET }}
|
||||
source_dir: "dist/"
|
||||
destination_dir: v3/spc-bin/nightly/
|
||||
endpoint: ${{ secrets.AWS_ENDPOINT }}
|
||||
|
||||
- name: "Deploy to self-hosted OSS (latest)"
|
||||
# only run this step if the repository is static-php-cli and is release tag
|
||||
if: ${{ github.repository == 'crazywhalecc/static-php-cli' && startsWith(github.ref, 'refs/tags/') }}
|
||||
uses: static-php/upload-s3-action@v1.0.0
|
||||
with:
|
||||
aws_key_id: ${{ secrets.AWS_KEY_ID }}
|
||||
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws_bucket: ${{ secrets.AWS_BUCKET }}
|
||||
source_dir: "dist/"
|
||||
destination_dir: v3/spc-bin/latest/
|
||||
endpoint: ${{ secrets.AWS_ENDPOINT }}
|
||||
|
||||
- name: "Deploy to self-hosted OSS (versioned)"
|
||||
# only run this step if the repository is static-php-cli and is release tag
|
||||
if: ${{ github.repository == 'crazywhalecc/static-php-cli' && startsWith(github.ref, 'refs/tags/') }}
|
||||
uses: static-php/upload-s3-action@v1.0.0
|
||||
with:
|
||||
aws_key_id: ${{ secrets.AWS_KEY_ID }}
|
||||
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws_bucket: ${{ secrets.AWS_BUCKET }}
|
||||
source_dir: "dist/"
|
||||
destination_dir: v3/spc-bin/${{ github.ref_name }}/
|
||||
destination_dir: static-php-cli/spc-bin/nightly/
|
||||
endpoint: ${{ secrets.AWS_ENDPOINT }}
|
||||
|
||||
- name: "Upload Artifact"
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: spc${{ env.SUFFIX }}
|
||||
name: spc-${{ matrix.operating-system.name }}${{ env.SUFFIX }}
|
||||
@@ -180,10 +156,10 @@ jobs:
|
||||
os: "windows-latest"
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: "Download Artifact"
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v4
|
||||
env:
|
||||
SUFFIX: ${{ matrix.operating-system.name == 'windows-x64' && '.exe' || '' }}
|
||||
with:
|
||||
@@ -196,4 +172,4 @@ jobs:
|
||||
- name: "Run SPC Tests"
|
||||
env:
|
||||
SUFFIX: ${{ matrix.operating-system.name == 'windows-x64' && '.exe' || '' }}
|
||||
run: ./spc${{ env.SUFFIX }} dev:info php
|
||||
run: ./spc${{ env.SUFFIX }} dev:extensions
|
||||
|
||||
4
.github/workflows/tests.yml
vendored
4
.github/workflows/tests.yml
vendored
@@ -106,7 +106,6 @@ jobs:
|
||||
run: SPC_LIBC=glibc vendor/bin/phpunit tests/ --no-coverage
|
||||
|
||||
define-matrix:
|
||||
if: false # TODO: enable when refactoring workflows
|
||||
name: "Define Matrix"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
@@ -132,7 +131,6 @@ jobs:
|
||||
|
||||
|
||||
build:
|
||||
if: false
|
||||
name: "Build PHP Test (PHP ${{ matrix.php }} ${{ matrix.os }})"
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: [define-matrix, php-cs-fixer, phpstan, phpunit]
|
||||
@@ -206,7 +204,7 @@ jobs:
|
||||
|
||||
- name: "Upload logs"
|
||||
if: ${{ always() && hashFiles('log/**') != '' }}
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-logs-${{ matrix.os }}-${{ matrix.php }}
|
||||
path: log
|
||||
|
||||
139
.github/workflows/vitepress-deploy.yml
vendored
139
.github/workflows/vitepress-deploy.yml
vendored
@@ -1,68 +1,71 @@
|
||||
name: Docs build test and auto deploy
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ "v3" ]
|
||||
types: [ opened, synchronize, reopened ]
|
||||
paths:
|
||||
- 'config/**.yml'
|
||||
- 'docs/**'
|
||||
- 'package.json'
|
||||
- 'yarn.lock'
|
||||
- '.github/workflows/vitepress-deploy.yml'
|
||||
push:
|
||||
branches: [ "v3" ]
|
||||
paths:
|
||||
- 'config/**.yml'
|
||||
- 'docs/**'
|
||||
- 'package.json'
|
||||
- 'yarn.lock'
|
||||
- '.github/workflows/vitepress-deploy.yml'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Deploy docs
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'crazywhalecc/static-php-cli'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
|
||||
- run: npm install
|
||||
|
||||
- name: "Install PHP for official runners"
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
coverage: none
|
||||
tools: composer:v2
|
||||
php-version: 8.4
|
||||
ini-values: memory_limit=-1
|
||||
extensions: curl, openssl, mbstring
|
||||
|
||||
- name: "Get Composer Cache Directory"
|
||||
id: composer-cache
|
||||
run: |
|
||||
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: "Cache Composer dependencies"
|
||||
uses: "actions/cache@v4"
|
||||
with:
|
||||
path: "${{ steps.composer-cache.outputs.dir }}"
|
||||
key: "php-8.2-locked-composer-${{ hashFiles('**/composer.lock') }}"
|
||||
restore-keys: |
|
||||
php-8.2-locked-composer
|
||||
|
||||
- name: "Install Locked Dependencies"
|
||||
run: "composer install --no-interaction --no-progress"
|
||||
|
||||
- name: Build
|
||||
run: npm run docs:build
|
||||
|
||||
# Deploy to GitHub Pages only when the workflow is triggered by a push to the v3 branch
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/v3'
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: docs/.vitepress/dist
|
||||
name: Docs Auto Deploy
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'config/**.json'
|
||||
- 'docs/**'
|
||||
- 'package.json'
|
||||
- 'yarn.lock'
|
||||
- '.github/workflows/vitepress-deploy.yml'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Deploy docs
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'crazywhalecc/static-php-cli'
|
||||
steps:
|
||||
- name: Checkout master
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
cache: yarn
|
||||
|
||||
- run: yarn install --frozen-lockfile
|
||||
|
||||
- name: "Copy Config Files"
|
||||
run: |
|
||||
mkdir -p docs/.vitepress/config
|
||||
cp -r config/* docs/.vitepress/config/
|
||||
|
||||
- name: "Install PHP for official runners"
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
coverage: none
|
||||
tools: composer:v2
|
||||
php-version: 8.4
|
||||
ini-values: memory_limit=-1
|
||||
extensions: curl, openssl, mbstring
|
||||
|
||||
- name: "Get Composer Cache Directory"
|
||||
id: composer-cache
|
||||
run: |
|
||||
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: "Cache Composer dependencies"
|
||||
uses: "actions/cache@v4"
|
||||
with:
|
||||
path: "${{ steps.composer-cache.outputs.dir }}"
|
||||
key: "php-8.2-locked-composer-${{ hashFiles('**/composer.lock') }}"
|
||||
restore-keys: |
|
||||
php-8.2-locked-composer
|
||||
|
||||
- name: "Install Locked Dependencies"
|
||||
run: "composer install --no-interaction --no-progress"
|
||||
|
||||
- name: "Generate Extension Support List"
|
||||
run: |
|
||||
bin/spc dev:gen-ext-docs > docs/extensions.md
|
||||
bin/spc dev:gen-ext-dep-docs > docs/deps-map-ext.md
|
||||
bin/spc dev:gen-lib-dep-docs > docs/deps-map-lib.md
|
||||
|
||||
- name: Build
|
||||
run: yarn docs:build
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: docs/.vitepress/dist
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -52,8 +52,6 @@ packlib_files.txt
|
||||
/node_modules/
|
||||
/docs/.vitepress/dist/
|
||||
/docs/.vitepress/cache/
|
||||
/docs/.vitepress/ext-data.json
|
||||
/docs/.vitepress/deps-data.json
|
||||
package-lock.json
|
||||
pnpm-lock.yaml
|
||||
|
||||
@@ -69,6 +67,3 @@ spc.exe
|
||||
|
||||
# dumped files from StaticPHP v3
|
||||
/dump-*.json
|
||||
|
||||
# config parse cache
|
||||
/.spc.cache.php
|
||||
|
||||
328
README-zh.md
328
README-zh.md
@@ -1,156 +1,172 @@
|
||||
# StaticPHP
|
||||
|
||||
[](README-zh.md)
|
||||
[](README.md)
|
||||
[](https://github.com/crazywhalecc/static-php-cli/releases)
|
||||
[](https://github.com/crazywhalecc/static-php-cli/actions/workflows/tests.yml)
|
||||
[](https://github.com/crazywhalecc/static-php-cli/blob/main/LICENSE)
|
||||
[](https://discord.gg/nrSRbpMJ)
|
||||
|
||||
**StaticPHP** 是一个强大的工具,用于构建可移植的可执行文件,包括 PHP、扩展等。
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 我们正准备发布 **v3** 版本,届时项目名称将从 **static-php-cli** 更改为 **StaticPHP**。
|
||||
> 此分支对应 v3 版本。v2 版本请查看 [v2 分支](https://github.com/crazywhalecc/static-php-cli/tree/main)。
|
||||
> 请更新您的参考资料,并关注正式版发布。
|
||||
|
||||
## 特性
|
||||
|
||||
- :elephant: 支持多个 PHP 版本 - PHP 8.1, 8.2, 8.3, 8.4, 8.5
|
||||
- :handbag: 构建零依赖的单文件 PHP 可执行程序
|
||||
- :hamburger: 构建 **[phpmicro](https://github.com/static-php/phpmicro)** 自解压可执行文件(将 PHP 二进制和源码合并为单个文件)
|
||||
- :pill: 自动构建环境检查器,支持自动修复
|
||||
- :zap: 支持 `Linux`、`macOS`、`Windows`
|
||||
- :wrench: 通过 vendor 模式和自定义注册表实现便捷扩展
|
||||
- :books: 智能依赖管理
|
||||
- 📦 自包含 `spc` 可执行文件,便于自安装
|
||||
- :fire: 支持 100+ 热门 [PHP 扩展](https://static-php.dev/en/guide/extensions.html)
|
||||
- :floppy_disk: 支持 UPX 压缩(二进制体积可缩小 30-50%)
|
||||
|
||||
**单文件独立 php-cli:**
|
||||
|
||||
<img width="700" alt="out1" src="https://github.com/crazywhalecc/static-php-cli/assets/20330940/01a2e60f-13b0-4242-a645-f7afa4936396">
|
||||
|
||||
**使用 phpmicro 将 PHP 代码与 PHP 解释器结合:**
|
||||
|
||||
<img width="700" alt="out2" src="https://github.com/crazywhalecc/static-php-cli/assets/20330940/46b7128d-fb72-4169-957e-48564c3ff3e2">
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 下载 spc 二进制
|
||||
|
||||
```bash
|
||||
# For Linux x86_64
|
||||
curl -fsSL -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-linux-x86_64
|
||||
# For Linux aarch64
|
||||
curl -fsSL -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-linux-aarch64
|
||||
# macOS x86_64 (Intel)
|
||||
curl -fsSL -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-macos-x86_64
|
||||
# macOS aarch64 (Apple)
|
||||
curl -fsSL -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-macos-aarch64
|
||||
# Windows (x86_64, win10 build 17063 or later, please install VS2022 first)
|
||||
curl.exe -fsSL -o spc.exe https://dl.static-php.dev/v3/spc-bin/nightly/spc-windows-x64.exe
|
||||
```
|
||||
|
||||
对于 macOS 和 Linux,请先添加可执行权限:
|
||||
|
||||
```bash
|
||||
chmod +x ./spc
|
||||
```
|
||||
|
||||
### 2. 构建静态 PHP
|
||||
|
||||
首先,创建 `craft.yml` 文件,并从 [扩展列表](https://static-php.dev/en/guide/extensions.html) 或 [命令生成器](https://static-php.dev/en/guide/cli-generator.html) 指定要包含的扩展:
|
||||
|
||||
```yml
|
||||
# PHP version support: 8.1, 8.2, 8.3, 8.4, 8.5
|
||||
php-version: 8.5
|
||||
# Put your extension list here
|
||||
extensions: "apcu,bcmath,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,gd,iconv,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,readline,redis,session,simplexml,sockets,sodium,sqlite3,tokenizer,xml,xmlreader,xmlwriter,xsl,zip,zlib"
|
||||
sapi:
|
||||
- cli
|
||||
- micro
|
||||
download-options:
|
||||
parallel: 10
|
||||
```
|
||||
|
||||
运行命令:
|
||||
|
||||
```bash
|
||||
./spc craft
|
||||
|
||||
# 输出完整控制台日志
|
||||
./spc craft -vvv
|
||||
```
|
||||
|
||||
### 3. 静态 PHP 使用
|
||||
|
||||
现在你可以将 StaticPHP 构建的二进制复制到另一台机器并在无依赖环境下运行:
|
||||
|
||||
```
|
||||
# php-cli
|
||||
buildroot/bin/php -v
|
||||
|
||||
# phpmicro
|
||||
echo '<?php echo "Hello world!\n";' > a.php
|
||||
./spc micro:combine a.php -O my-app
|
||||
./my-app
|
||||
```
|
||||
|
||||
## 文档
|
||||
|
||||
当前 README 包含基础用法。有关 StaticPHP 的完整功能集,
|
||||
请访问 <https://static-php.dev>。
|
||||
|
||||
## 直接下载
|
||||
|
||||
如果你暂时不想构建,或只想先测试,可以从 [Actions](https://github.com/static-php/static-php-cli-hosted/actions/workflows/build-php-bulk.yml) 下载示例预编译产物,或从自托管服务器下载。
|
||||
|
||||
我们为每个 PHP 版本提供 2 种扩展集合:
|
||||
|
||||
- **gigantic**:尽可能包含更多扩展,二进制大小约 100-150MB。
|
||||
- **base**:仅包含 StaticPHP 自身使用的少量扩展,二进制大小约 10MB。
|
||||
|
||||
> WIP
|
||||
|
||||
### 在线构建(使用 GitHub Actions)
|
||||
|
||||
当上方直接下载的二进制无法满足你的需求时,
|
||||
你可以使用 GitHub Actions 轻松构建静态编译的 PHP,
|
||||
并同时自定义要编译的扩展列表。
|
||||
|
||||
1. Fork 此仓库。
|
||||
2. 进入项目的 Actions 并选择 `CI`。
|
||||
3. 选择 `Run workflow`,填写你要编译的 PHP 版本、目标类型和扩展列表。(扩展用逗号分隔,例如 `bcmath,curl,mbstring`)
|
||||
4. 等待工作流执行完成后,进入对应运行记录并下载 `Artifacts`。
|
||||
|
||||
如果你启用 `debug`,构建时将输出所有日志,包括编译日志,便于排查问题。
|
||||
|
||||
> 我们也计划在未来提供可复用的 GitHub Actions 工作流,
|
||||
> 这样你无需 fork 本项目,也能在自己的仓库中轻松构建 static PHP。
|
||||
|
||||
## 贡献
|
||||
|
||||
如果你需要的扩展缺失,可以创建 issue。
|
||||
如果你熟悉本项目,也欢迎发起 pull request。
|
||||
|
||||
如果你想贡献文档,请直接编辑 `docs/`。
|
||||
|
||||
## 赞助本项目
|
||||
|
||||
你可以通过 [GitHub Sponsor](https://github.com/crazywhalecc) 赞助我或我的项目。你捐赠的一部分将用于维护 **static-php.dev** 服务器。
|
||||
|
||||
**特别感谢以下赞助商:**
|
||||
|
||||
<a href="https://beyondco.de/"><img src="/docs/public/images/beyondcode-seeklogo.png" width="300" alt="Beyond Code Logo" /></a>
|
||||
|
||||
<a href="https://nativephp.com/"><img src="/docs/public/images/nativephp-logo.svg" width="300" alt="NativePHP Logo" /></a>
|
||||
|
||||
## 开源许可证
|
||||
|
||||
本项目本身采用 MIT 许可证。
|
||||
一些新添加的扩展和依赖可能来自其他项目。
|
||||
这些源码文件头部也可能包含额外的 LICENSE 和 AUTHOR 信息。
|
||||
|
||||
请在编译后使用 `bin/spc dump-license` 命令导出项目中使用的开源许可证,
|
||||
并遵守对应项目的 LICENSE。
|
||||
# StaticPHP
|
||||
|
||||
[](README.md)
|
||||
[](README-zh.md)
|
||||
[](https://github.com/crazywhalecc/static-php-cli/releases)
|
||||
[](https://github.com/crazywhalecc/static-php-cli/actions/workflows/tests.yml)
|
||||
[](https://github.com/crazywhalecc/static-php-cli/blob/main/LICENSE)
|
||||
|
||||
**StaticPHP** 是一个用于构建静态编译可执行文件(包括 PHP、扩展等)的强大工具。
|
||||
|
||||
## 特性
|
||||
|
||||
- :elephant: **支持多 PHP 版本** - 支持 PHP 8.1, 8.2, 8.3, 8.4, 8.5
|
||||
- :handbag: **单文件 PHP 可执行文件** - 构建零依赖的独立 PHP
|
||||
- :hamburger: **phpmicro 集成** - 构建 **[phpmicro](https://github.com/dixyes/phpmicro)** 自解压可执行文件(将 PHP 二进制文件和源代码合并为一个文件)
|
||||
- :pill: **智能环境检查器** - 自动构建环境检查器,具备自动修复功能
|
||||
- :zap: **跨平台支持** - 支持 Linux、macOS、FreeBSD 和 Windows
|
||||
- :wrench: **可配置补丁** - 可自定义的源代码补丁系统
|
||||
- :books: **智能依赖管理** - 自动处理构建依赖
|
||||
- 📦 **自包含工具** - 提供使用 [box](https://github.com/box-project/box) 构建的 `spc` 可执行文件
|
||||
- :fire: **广泛的扩展支持** - 支持 75+ 流行 [扩展](https://static-php.dev/zh/guide/extensions.html)
|
||||
- :floppy_disk: **UPX 压缩** - 减小二进制文件大小 30-50%(仅 Linux/Windows)
|
||||
|
||||
**单文件独立 php-cli:**
|
||||
|
||||
<img width="700" alt="out1" src="https://github.com/crazywhalecc/static-php-cli/assets/20330940/01a2e60f-13b0-4242-a645-f7afa4936396">
|
||||
|
||||
**使用 phpmicro 将 PHP 代码与 PHP 解释器结合:**
|
||||
|
||||
<img width="700" alt="out2" src="https://github.com/crazywhalecc/static-php-cli/assets/20330940/46b7128d-fb72-4169-957e-48564c3ff3e2">
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 下载 spc 二进制文件
|
||||
|
||||
```bash
|
||||
# Linux x86_64
|
||||
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-x86_64
|
||||
# Linux aarch64
|
||||
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-aarch64
|
||||
# macOS x86_64 (Intel)
|
||||
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-x86_64
|
||||
# macOS aarch64 (Apple)
|
||||
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-aarch64
|
||||
# Windows (x86_64, win10 build 17063 或更高版本,请先安装 VS2022)
|
||||
curl.exe -fsSL -o spc.exe https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe
|
||||
```
|
||||
|
||||
对于 macOS 和 Linux,请先添加执行权限:
|
||||
|
||||
```bash
|
||||
chmod +x ./spc
|
||||
```
|
||||
|
||||
### 2. 构建静态 PHP
|
||||
|
||||
首先,创建一个 `craft.yml` 文件,并从 [扩展列表](https://static-php.dev/zh/guide/extensions.html) 或 [命令生成器](https://static-php.dev/zh/guide/cli-generator.html) 中指定要包含的扩展:
|
||||
|
||||
```yml
|
||||
# PHP 版本支持:8.1, 8.2, 8.3, 8.4, 8.5
|
||||
php-version: 8.4
|
||||
# 在此处放置您的扩展列表
|
||||
extensions: "apcu,bcmath,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,gd,iconv,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,readline,redis,session,simplexml,sockets,sodium,sqlite3,tokenizer,xml,xmlreader,xmlwriter,xsl,zip,zlib"
|
||||
sapi:
|
||||
- cli
|
||||
- micro
|
||||
- fpm
|
||||
download-options:
|
||||
prefer-pre-built: true
|
||||
```
|
||||
|
||||
运行命令:
|
||||
|
||||
```bash
|
||||
./spc craft
|
||||
|
||||
# 输出完整控制台日志
|
||||
./spc craft --debug
|
||||
```
|
||||
|
||||
### 3. 静态 PHP 使用
|
||||
|
||||
现在您可以将 StaticPHP 构建的二进制文件复制到另一台机器上,无需依赖即可运行:
|
||||
|
||||
```
|
||||
# php-cli
|
||||
buildroot/bin/php -v
|
||||
|
||||
# phpmicro
|
||||
echo '<?php echo "Hello world!\n";' > a.php
|
||||
./spc micro:combine a.php -O my-app
|
||||
./my-app
|
||||
|
||||
# php-fpm
|
||||
buildroot/bin/php-fpm -v
|
||||
```
|
||||
|
||||
## 文档
|
||||
|
||||
当前 README 包含基本用法。有关 StaticPHP 的所有功能,
|
||||
请访问 <https://static-php.dev>。
|
||||
|
||||
## 直接下载
|
||||
|
||||
如果您不想构建或想先测试,可以从 [Actions](https://github.com/static-php/static-php-cli-hosted/actions/workflows/build-php-bulk.yml) 下载示例预编译工件,或从自托管服务器下载。
|
||||
|
||||
以下是几个具有不同扩展组合的预编译静态 PHP 二进制文件,
|
||||
您可以根据需要直接下载。
|
||||
|
||||
| 组合名称 | 扩展数量 | 系统 | 备注 |
|
||||
|----------------------------------------------------------------------|----------------------------------------------------------------------------|--------------|--------------------|
|
||||
| [common](https://dl.static-php.dev/static-php-cli/common/) | [30+](https://dl.static-php.dev/static-php-cli/common/README.txt) | Linux, macOS | 二进制文件大小约为 7.5MB |
|
||||
| [bulk](https://dl.static-php.dev/static-php-cli/bulk/) | [50+](https://dl.static-php.dev/static-php-cli/bulk/README.txt) | Linux, macOS | 二进制文件大小约为 25MB |
|
||||
| [gnu-bulk](https://dl.static-php.dev/static-php-cli/gnu-bulk/) | [50+](https://dl.static-php.dev/static-php-cli/bulk/README.txt) | Linux, macOS | 使用 glibc 的 bulk 组合 |
|
||||
| [minimal](https://dl.static-php.dev/static-php-cli/minimal/) | [5](https://dl.static-php.dev/static-php-cli/minimal/README.txt) | Linux, macOS | 二进制文件大小约为 3MB |
|
||||
| [spc-min](https://dl.static-php.dev/static-php-cli/windows/spc-min/) | [5](https://dl.static-php.dev/static-php-cli/windows/spc-min/README.txt) | Windows | 二进制文件大小约为 3MB |
|
||||
| [spc-max](https://dl.static-php.dev/static-php-cli/windows/spc-max/) | [40+](https://dl.static-php.dev/static-php-cli/windows/spc-max/README.txt) | Windows | 二进制文件大小约为 8.5MB |
|
||||
|
||||
> Linux 和 Windows 支持对二进制文件进行 UPX 压缩,可以将二进制文件大小减少 30% 到 50%。
|
||||
> macOS 不支持 UPX 压缩,因此 mac 的预构建二进制文件大小较大。
|
||||
|
||||
### 在线构建(使用 GitHub Actions)
|
||||
|
||||
上方直接下载的二进制不能满足需求时,可使用 GitHub Action 可以轻松构建静态编译的 PHP,
|
||||
同时自行定义要编译的扩展。
|
||||
|
||||
1. Fork 本项目。
|
||||
2. 进入项目的 Actions 并选择 `CI`。
|
||||
3. 选择 `Run workflow`,填入您要编译的 PHP 版本、目标类型和扩展列表。(扩展用逗号分隔,例如 `bcmath,curl,mbstring`)
|
||||
4. 等待一段时间后,进入相应的任务并获取 `Artifacts`。
|
||||
|
||||
如果您启用 `debug`,构建时将输出所有日志,包括编译日志,以便故障排除。
|
||||
|
||||
## 贡献
|
||||
|
||||
如果您需要的扩展缺失,可以创建 issue。
|
||||
如果您熟悉本项目,也欢迎发起 pull request。
|
||||
|
||||
如果您想贡献文档,请直接编辑 `docs/` 目录。
|
||||
|
||||
现在有一个 [static-php](https://github.com/static-php) 组织,用于存储与项目相关的仓库。
|
||||
|
||||
## 赞助本项目
|
||||
|
||||
您可以从 [GitHub Sponsor](https://github.com/crazywhalecc) 赞助我或我的项目。您捐赠的一部分将用于维护 **static-php.dev** 服务器。
|
||||
|
||||
**特别感谢以下赞助商**:
|
||||
|
||||
<a href="https://beyondco.de/"><img src="/docs/public/images/beyondcode-seeklogo.png" width="300" alt="Beyond Code Logo" /></a>
|
||||
|
||||
<a href="https://nativephp.com/"><img src="/docs/public/images/nativephp-logo.svg" width="300" alt="NativePHP Logo" /></a>
|
||||
|
||||
## 开源许可证
|
||||
|
||||
本项目本身基于 MIT 许可证,
|
||||
一些新添加的扩展和依赖可能来自其他项目,
|
||||
这些代码文件的头部也会给出额外的许可证和作者说明。
|
||||
|
||||
这些是类似的项目:
|
||||
|
||||
- [dixyes/lwmbs](https://github.com/dixyes/lwmbs)
|
||||
- [swoole/swoole-cli](https://github.com/swoole/swoole-cli)
|
||||
|
||||
本项目使用了 [dixyes/lwmbs](https://github.com/dixyes/lwmbs) 的一些代码,例如 Windows 静态构建目标和 libiconv 支持。
|
||||
lwmbs 基于 [Mulan PSL 2](http://license.coscl.org.cn/MulanPSL2) 许可证。
|
||||
|
||||
由于本项目的特殊性,
|
||||
项目编译过程中会使用许多其他开源项目,如 curl 和 protobuf,
|
||||
它们都有自己的开源许可证。
|
||||
|
||||
请在编译后使用 `bin/spc dump-license` 命令导出项目中使用的开源许可证,
|
||||
并遵守相应项目的 LICENSE。
|
||||
|
||||
91
README.md
91
README.md
@@ -5,26 +5,20 @@
|
||||
[](https://github.com/crazywhalecc/static-php-cli/releases)
|
||||
[](https://github.com/crazywhalecc/static-php-cli/actions/workflows/tests.yml)
|
||||
[](https://github.com/crazywhalecc/static-php-cli/blob/main/LICENSE)
|
||||
[](https://discord.gg/nrSRbpMJ)
|
||||
|
||||
**StaticPHP** is a powerful tool designed for building portable executables including PHP, extensions, and more.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> We are preparing to release **v3**, which will include a project rename from **static-php-cli** to **StaticPHP**.
|
||||
> And this branch is for v3. For v2, please check the [v2 branch](https://github.com/crazywhalecc/static-php-cli/tree/main).
|
||||
> Please update your references and stay tuned for the official release.
|
||||
|
||||
## Features
|
||||
|
||||
- :elephant: Support multiple PHP versions - PHP 8.1, 8.2, 8.3, 8.4, 8.5
|
||||
- :handbag: Build single-file PHP executable with zero dependencies
|
||||
- :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
|
||||
- :zap: `Linux`, `macOS`, `Windows` support
|
||||
- :wrench: Easy to extend with vendor mode and custom registries
|
||||
- :zap: `Linux`, `macOS`, `FreeBSD`, `Windows` support
|
||||
- :wrench: Configurable source code patching
|
||||
- :books: Intelligent dependency management
|
||||
- 📦 Self-contained `spc` executable for easy self-installation
|
||||
- :fire: Support 100+ popular [PHP extensions](https://static-php.dev/en/guide/extensions.html)
|
||||
- 📦 Self-contained `spc` executable (built with [box](https://github.com/box-project/box))
|
||||
- :fire: Support 100+ popular [extensions](https://static-php.dev/en/guide/extensions.html)
|
||||
- :floppy_disk: UPX compression support (reduces binary size by 30-50%)
|
||||
|
||||
**Single-file standalone php-cli:**
|
||||
@@ -41,15 +35,15 @@
|
||||
|
||||
```bash
|
||||
# For Linux x86_64
|
||||
curl -fsSL -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-linux-x86_64
|
||||
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-x86_64
|
||||
# For Linux aarch64
|
||||
curl -fsSL -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-linux-aarch64
|
||||
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-aarch64
|
||||
# macOS x86_64 (Intel)
|
||||
curl -fsSL -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-macos-x86_64
|
||||
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-x86_64
|
||||
# macOS aarch64 (Apple)
|
||||
curl -fsSL -o spc https://dl.static-php.dev/v3/spc-bin/nightly/spc-macos-aarch64
|
||||
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-aarch64
|
||||
# Windows (x86_64, win10 build 17063 or later, please install VS2022 first)
|
||||
curl.exe -fsSL -o spc.exe https://dl.static-php.dev/v3/spc-bin/nightly/spc-windows-x64.exe
|
||||
curl.exe -fsSL -o spc.exe https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe
|
||||
```
|
||||
|
||||
For macOS and Linux, add execute permission first:
|
||||
@@ -64,14 +58,15 @@ First, create a `craft.yml` file and specify which extensions you want to includ
|
||||
|
||||
```yml
|
||||
# PHP version support: 8.1, 8.2, 8.3, 8.4, 8.5
|
||||
php-version: 8.5
|
||||
php-version: 8.4
|
||||
# Put your extension list here
|
||||
extensions: "apcu,bcmath,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,gd,iconv,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,readline,redis,session,simplexml,sockets,sodium,sqlite3,tokenizer,xml,xmlreader,xmlwriter,xsl,zip,zlib"
|
||||
sapi:
|
||||
- cli
|
||||
- micro
|
||||
- fpm
|
||||
download-options:
|
||||
parallel: 10
|
||||
prefer-pre-built: true
|
||||
```
|
||||
|
||||
Run command:
|
||||
@@ -80,7 +75,7 @@ Run command:
|
||||
./spc craft
|
||||
|
||||
# Output full console log
|
||||
./spc craft -vvv
|
||||
./spc craft --debug
|
||||
```
|
||||
|
||||
### 3. Static PHP usage
|
||||
@@ -95,40 +90,48 @@ buildroot/bin/php -v
|
||||
echo '<?php echo "Hello world!\n";' > a.php
|
||||
./spc micro:combine a.php -O my-app
|
||||
./my-app
|
||||
|
||||
# php-fpm
|
||||
buildroot/bin/php-fpm -v
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
The current README contains basic usage. For the complete feature set of StaticPHP,
|
||||
see <https://static-php.dev>.
|
||||
The current README contains basic usage. For all the features of StaticPHP,
|
||||
see <https://static-php.dev> .
|
||||
|
||||
## Direct Download
|
||||
|
||||
If you do not want to build yet or just want to test first, you can download example pre-compiled artifacts from [Actions](https://github.com/static-php/static-php-cli-hosted/actions/workflows/build-php-bulk.yml) or from a 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.
|
||||
|
||||
We offer 2 types of extension sets for each PHP version:
|
||||
Below are several precompiled static-php binaries with different extension combinations,
|
||||
which can be downloaded directly according to your needs.
|
||||
|
||||
- **gigantic**: Includes as many extensions as possible, the binary size is about 100-150MB.
|
||||
- **base**: Only includes a few extensions used by StaticPHP itself, the binary size is about 10MB.
|
||||
| Combination | Extension Count | OS | Comment |
|
||||
|----------------------------------------------------------------------|----------------------------------------------------------------------------|--------------|--------------------------------|
|
||||
| [common](https://dl.static-php.dev/static-php-cli/common/) | [30+](https://dl.static-php.dev/static-php-cli/common/README.txt) | Linux, macOS | The binary size is about 7.5MB |
|
||||
| [bulk](https://dl.static-php.dev/static-php-cli/bulk/) | [50+](https://dl.static-php.dev/static-php-cli/bulk/README.txt) | Linux, macOS | The binary size is about 25MB |
|
||||
| [gnu-bulk](https://dl.static-php.dev/static-php-cli/gnu-bulk/) | [50+](https://dl.static-php.dev/static-php-cli/bulk/README.txt) | Linux, macOS | Using shared glibc |
|
||||
| [minimal](https://dl.static-php.dev/static-php-cli/minimal/) | [5](https://dl.static-php.dev/static-php-cli/minimal/README.txt) | Linux, macOS | The binary size is about 3MB |
|
||||
| [spc-min](https://dl.static-php.dev/static-php-cli/windows/spc-min/) | [5](https://dl.static-php.dev/static-php-cli/windows/spc-min/README.txt) | Windows | The binary size is about 3MB |
|
||||
| [spc-max](https://dl.static-php.dev/static-php-cli/windows/spc-max/) | [40+](https://dl.static-php.dev/static-php-cli/windows/spc-max/README.txt) | Windows | The binary size is about 8.5MB |
|
||||
|
||||
> WIP
|
||||
> Linux and Windows supports UPX compression for binaries, which can reduce the size of the binary by 30% to 50%.
|
||||
> macOS does not support UPX compression, so the size of the pre-built binaries for mac is larger.
|
||||
|
||||
### Build Online (using GitHub Actions)
|
||||
|
||||
When the direct-download binaries above cannot meet your needs,
|
||||
you can use GitHub Actions to easily build a statically compiled PHP
|
||||
while defining your own extension list.
|
||||
When the above direct download binaries cannot meet your needs,
|
||||
you can use GitHub Action to easily build a statically compiled PHP,
|
||||
and at the same time define the extensions to be compiled by yourself.
|
||||
|
||||
1. Fork this repository.
|
||||
1. Fork me.
|
||||
2. Go to the Actions of the project and select `CI`.
|
||||
3. Select `Run workflow`, fill in the PHP version you want to compile, the target type, and the list of extensions. (extensions comma separated, e.g. `bcmath,curl,mbstring`)
|
||||
4. After waiting for the workflow to finish, open the corresponding run and download `Artifacts`.
|
||||
4. After waiting for about a period of time, enter the corresponding task and get `Artifacts`.
|
||||
|
||||
If you enable `debug`, all logs will be output at build time, including compiled logs, for troubleshooting.
|
||||
|
||||
> We are also planning to provide a reusable GitHub Actions workflow in the future,
|
||||
> so that you can easily build static PHP in your own repository, without forking this project.
|
||||
|
||||
## Contribution
|
||||
|
||||
If the extension you need is missing, you can create an issue.
|
||||
@@ -136,6 +139,8 @@ If you are familiar with this project, you are also welcome to initiate a pull r
|
||||
|
||||
If you want to contribute documentation, please just edit in `docs/`.
|
||||
|
||||
Now there is a [static-php](https://github.com/static-php) organization, which is used to store the repo related to the project.
|
||||
|
||||
## Sponsor this project
|
||||
|
||||
You can sponsor me or my project from [GitHub Sponsor](https://github.com/crazywhalecc). A portion of your donation will be used to maintain the **static-php.dev** server.
|
||||
@@ -148,9 +153,21 @@ You can sponsor me or my project from [GitHub Sponsor](https://github.com/crazyw
|
||||
|
||||
## Open-Source License
|
||||
|
||||
This project itself is licensed under MIT.
|
||||
Some newly added extensions and dependencies may originate from other projects.
|
||||
The headers of those source files may also include additional LICENSE and AUTHOR information.
|
||||
This project itself is based on MIT License,
|
||||
some newly added extensions and dependencies may originate from the the other projects,
|
||||
and the headers of these code files will also be given additional instructions LICENSE and AUTHOR.
|
||||
|
||||
These are similar projects:
|
||||
|
||||
- [dixyes/lwmbs](https://github.com/dixyes/lwmbs)
|
||||
- [swoole/swoole-cli](https://github.com/swoole/swoole-cli)
|
||||
|
||||
The project uses some code from [dixyes/lwmbs](https://github.com/dixyes/lwmbs), such as windows static build target and libiconv support.
|
||||
lwmbs is licensed under the [Mulan PSL 2](http://license.coscl.org.cn/MulanPSL2).
|
||||
|
||||
Due to the special nature of this project,
|
||||
many other open source projects such as curl and protobuf will be used during the project compilation process,
|
||||
and they all have their own open source licenses.
|
||||
|
||||
Please use the `bin/spc dump-license` command to export the open source licenses used in the project after compilation,
|
||||
and comply with the corresponding project's LICENSE.
|
||||
|
||||
57
TODO.md
Normal file
57
TODO.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# v3 TODO List
|
||||
|
||||
Tracking items identified during the v2 → v3 migration audit.
|
||||
|
||||
---
|
||||
|
||||
## Commands
|
||||
|
||||
- [ ] Implement `craft` command (drives full build from `craft.yml`; should be easier with v3 vendor/registry mode)
|
||||
- [ ] Migrate `micro:combine` command (combine `micro.sfx` with PHP code + INI injection)
|
||||
- [ ] Implement `dump-extensions` command (extract required extensions from `composer.json` / `composer.lock`)
|
||||
- [ ] Design and implement v3 dev toolchain commands (WIP — needs design decision):
|
||||
- [ ] `dev:extensions` / equivalent listing command
|
||||
- [ ] `dev:php-version`, `dev:ext-version`, `dev:lib-version`
|
||||
- [ ] Doc generation commands (`dev:gen-ext-docs`, `dev:gen-ext-dep-docs`, `dev:gen-lib-dep-docs`) — pending v3 doc design
|
||||
|
||||
---
|
||||
|
||||
## Source Patches (SourcePatcher → Artifact migration)
|
||||
|
||||
The following v2 `SourcePatcher` hooks are not yet migrated to v3 `src/Package/Artifact/` classes:
|
||||
|
||||
- [ ] Migrate `patchSQLSRVWin32` — removes `/sdl` compile flag to prevent Zend build failure on Windows
|
||||
- [ ] Migrate `patchSQLSRVPhp85` — fixes `pdo_sqlsrv` directory layout for PHP 8.5
|
||||
- [ ] Migrate `patchYamlWin32` — patches `config.w32` `_a.lib` detection logic for the `yaml` extension
|
||||
- [ ] Migrate `patchImagickWith84` — applies PHP 8.4 compatibility patch for `imagick` based on version detection
|
||||
|
||||
---
|
||||
|
||||
## Extension Package Classes (Unix)
|
||||
|
||||
Extensions that had non-trivial v2 build logic and are missing a v3 `src/Package/Extension/` class:
|
||||
|
||||
- [x] `gettext` — macOS: fix `config.m4` bracket syntax for cross-version compatibility + append frameworks to linker flags (critical for macOS linking; this is a Unix-side gap, not Windows-only)
|
||||
|
||||
---
|
||||
|
||||
## Windows Extensions (Early Stage)
|
||||
|
||||
Windows extension support is still in early stage. The following extensions had Windows-specific configure args or patches in v2 and are pending v3 Windows implementation:
|
||||
|
||||
- [ ] `amqp` — Windows configure args
|
||||
- [ ] `com_dotnet` — Windows-only extension
|
||||
- [ ] `dom` — remove `dllmain.c` from `config.w32`
|
||||
- [ ] `ev` — fix `PHP_EV_SHARED` in `config.w32`
|
||||
- [ ] `gmssl` — add `CHECK_LIB("gmssl.lib")` to `config.w32`
|
||||
- [ ] `intl` — fix `PHP_INTL_SHARED` in `config.w32`
|
||||
- [ ] `lz4` — Windows configure args
|
||||
- [ ] `mbregex` — Windows configure args
|
||||
- [ ] `sqlsrv` / `pdo_sqlsrv` — complex conditional build logic (independent `sqlsrv` without `pdo_sqlsrv`)
|
||||
- [ ] `xml` — remove `dllmain.c` from `config.w32`; handles `soap`, `xmlreader`, `xmlwriter`, `simplexml`
|
||||
|
||||
---
|
||||
|
||||
## Documentation
|
||||
|
||||
- [ ] Write v3 user documentation (currently zero v3 docs)
|
||||
@@ -122,7 +122,7 @@ COPY ./composer.* /app/
|
||||
ADD ./bin /app/bin
|
||||
RUN composer install --no-dev
|
||||
ADD ./config /app/config
|
||||
ADD ./spc.registry.yml /app/spc.registry.yml
|
||||
ADD ./spc.registry.json /app/spc.registry.json
|
||||
RUN bin/spc doctor --auto-fix
|
||||
RUN bin/spc install-pkg upx
|
||||
|
||||
|
||||
@@ -1,12 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Use SPC_XDEBUG=profile to enable Xdebug profiling mode, which will generate profiling files in /tmp.
|
||||
# Otherwise, it will enable Xdebug debugging mode, which allows you to connect a debugger to port 9003.
|
||||
if [ "$SPC_XDEBUG" = "profile" ]; then
|
||||
XDEBUG_PREFIX="-d xdebug.mode=profile -d xdebug.start_with_request=yes -d xdebug.output_dir=/tmp -d xdebug.output_name=spc-profile.%t.%p.%r"
|
||||
else
|
||||
XDEBUG_PREFIX="-d xdebug.mode=debug -d xdebug.client_host=127.0.0.1 -d xdebug.client_port=9003 -d xdebug.start_with_request=yes"
|
||||
fi
|
||||
|
||||
# This script runs the 'spc' command with Xdebug enabled for debugging purposes.
|
||||
php $XDEBUG_PREFIX "$(dirname "$0")/../bin/spc" "$@"
|
||||
php -d xdebug.mode=debug -d xdebug.client_host=127.0.0.1 -d xdebug.client_port=9003 -d xdebug.start_with_request=yes "$(dirname "$0")/../bin/spc" "$@"
|
||||
|
||||
236
bin/spc-gnu-docker
Executable file
236
bin/spc-gnu-docker
Executable file
@@ -0,0 +1,236 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
# This file is using docker to run commands
|
||||
SPC_DOCKER_VERSION=v6
|
||||
|
||||
# Detect docker can run
|
||||
if ! which docker >/dev/null; then
|
||||
echo "Docker is not installed, please install docker first !"
|
||||
exit 1
|
||||
fi
|
||||
DOCKER_EXECUTABLE="docker"
|
||||
# shellcheck disable=SC2046
|
||||
if [ $(id -u) -ne 0 ]; then
|
||||
if ! docker info > /dev/null 2>&1; then
|
||||
if [ "$SPC_USE_SUDO" != "yes" ] && [ "$SPC_DOCKER_DEBUG" != "yes" ]; then
|
||||
echo "Docker command requires sudo"
|
||||
# shellcheck disable=SC2039
|
||||
echo -n 'To use sudo to run docker, run "export SPC_USE_SUDO=yes" and run command again'
|
||||
exit 1
|
||||
fi
|
||||
DOCKER_EXECUTABLE="sudo docker"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Convert uname to gnu arch
|
||||
CURRENT_ARCH=$(uname -m)
|
||||
if [ "$CURRENT_ARCH" = "arm64" ]; then
|
||||
CURRENT_ARCH=aarch64
|
||||
fi
|
||||
if [ -z "$SPC_USE_ARCH" ]; then
|
||||
SPC_USE_ARCH=$CURRENT_ARCH
|
||||
fi
|
||||
# parse SPC_USE_ARCH
|
||||
case $SPC_USE_ARCH in
|
||||
x86_64|amd64)
|
||||
SPC_USE_ARCH=x86_64
|
||||
SPC_USE_ARCH_DOCKER=amd64
|
||||
if [ "$CURRENT_ARCH" != "x86_64" ]; then
|
||||
PLATFORM_ARG="--platform linux/amd64"
|
||||
fi
|
||||
;;
|
||||
aarch64|arm64)
|
||||
SPC_USE_ARCH=aarch64
|
||||
SPC_USE_ARCH_DOCKER=arm64
|
||||
if [ "$CURRENT_ARCH" != "aarch64" ]; then
|
||||
PLATFORM_ARG="--platform linux/arm64"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Current arch is not supported to run in docker: $SPC_USE_ARCH"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
# detect if we need to use qemu-static
|
||||
if [ "$SPC_USE_ARCH" != "$CURRENT_ARCH" ]; then
|
||||
if [ "$(uname -s)" = "Linux" ]; then
|
||||
echo "* Using different arch needs to setup qemu-static for docker !"
|
||||
$DOCKER_EXECUTABLE run --rm --privileged multiarch/qemu-user-static --reset -p yes > /dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
# Detect docker env is setup
|
||||
if ! $DOCKER_EXECUTABLE images | grep -q cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION; then
|
||||
echo "Docker container does not exist. Building docker image ..."
|
||||
$DOCKER_EXECUTABLE buildx build $PLATFORM_ARG -t cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION -f- . <<EOF
|
||||
FROM centos:7
|
||||
RUN sed -i 's/mirror.centos.org/vault.centos.org/g' /etc/yum.repos.d/*.repo && \
|
||||
sed -i 's/^#.*baseurl=http/baseurl=http/g' /etc/yum.repos.d/*.repo && \
|
||||
sed -i 's/^mirrorlist=http/#mirrorlist=http/g' /etc/yum.repos.d/*.repo
|
||||
RUN yum clean all && \
|
||||
yum makecache && \
|
||||
yum update -y && \
|
||||
localedef -c -i en_US -f UTF-8 en_US.UTF-8
|
||||
|
||||
RUN yum install -y centos-release-scl
|
||||
|
||||
RUN if [ "$SPC_USE_ARCH" = "aarch64" ]; then \
|
||||
sed -i 's|mirror.centos.org/centos|vault.centos.org/altarch|g' /etc/yum.repos.d/CentOS-SCLo-scl-rh.repo ; \
|
||||
sed -i 's|mirror.centos.org/centos|vault.centos.org/altarch|g' /etc/yum.repos.d/CentOS-SCLo-scl.repo ; \
|
||||
else \
|
||||
sed -i 's/mirror.centos.org/vault.centos.org/g' /etc/yum.repos.d/*.repo ; \
|
||||
fi
|
||||
RUN sed -i 's/^#.*baseurl=http/baseurl=http/g' /etc/yum.repos.d/*.repo && \
|
||||
sed -i 's/^mirrorlist=http/#mirrorlist=http/g' /etc/yum.repos.d/*.repo && \
|
||||
sed -i 's|http://|https://|g' /etc/yum.repos.d/*.repo
|
||||
|
||||
RUN yum update -y && \
|
||||
yum install -y devtoolset-10-gcc-* devtoolset-10-libatomic-devel
|
||||
RUN echo "source scl_source enable devtoolset-10" >> /etc/bashrc
|
||||
RUN source /etc/bashrc
|
||||
RUN yum install -y which
|
||||
|
||||
RUN curl -o cmake.tgz -#fSL https://github.com/Kitware/CMake/releases/download/v3.31.4/cmake-3.31.4-linux-$SPC_USE_ARCH.tar.gz && \
|
||||
mkdir /cmake && \
|
||||
tar -xzf cmake.tgz -C /cmake --strip-components 1
|
||||
|
||||
WORKDIR /app
|
||||
COPY ./composer.* /app/
|
||||
ADD ./bin/setup-runtime /app/bin/setup-runtime
|
||||
ADD ./bin/spc /app/bin/spc
|
||||
RUN /app/bin/setup-runtime
|
||||
ADD ./src /app/src
|
||||
RUN /app/bin/php /app/bin/composer install --no-dev
|
||||
ENV SPC_LIBC=glibc
|
||||
ENV PATH="/app/bin:/cmake/bin:/opt/rh/devtoolset-10/root/usr/bin:\$PATH"
|
||||
|
||||
ADD ./config /app/config
|
||||
RUN CC=gcc bin/spc doctor --auto-fix --debug
|
||||
RUN bin/spc install-pkg upx
|
||||
RUN if [ -f /app/buildroot/bin/re2c ]; then \
|
||||
cp /app/buildroot/bin/re2c /usr/local/bin/re2c ;\
|
||||
fi
|
||||
|
||||
RUN curl -o make.tgz -fsSL https://ftp.gnu.org/gnu/make/make-4.4.tar.gz && \
|
||||
tar -zxvf make.tgz && \
|
||||
cd make-4.4 && \
|
||||
./configure && \
|
||||
make && \
|
||||
make install && \
|
||||
ln -sf /usr/local/bin/make /usr/bin/make
|
||||
|
||||
RUN curl -o automake.tgz -fsSL https://ftp.gnu.org/gnu/automake/automake-1.17.tar.xz && \
|
||||
tar -xvf automake.tgz && \
|
||||
cd automake-1.17 && \
|
||||
./configure && \
|
||||
make && \
|
||||
make install && \
|
||||
ln -sf /usr/local/bin/automake /usr/bin/automake
|
||||
|
||||
RUN mv /app/pkgroot/\$(uname -m)-linux /app/pkgroot-private
|
||||
ADD bin/docker-entrypoint.sh /bin/docker-entrypoint.sh
|
||||
RUN chmod +x /bin/docker-entrypoint.sh
|
||||
ENTRYPOINT ["/bin/docker-entrypoint.sh"]
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Check if in ci (local terminal can execute with -it)
|
||||
if [ -t 0 ]; then
|
||||
INTERACT=-it
|
||||
else
|
||||
INTERACT=''
|
||||
fi
|
||||
|
||||
# Mounting volumes
|
||||
MOUNT_LIST=""
|
||||
# shellcheck disable=SC2089
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/config:/app/config"
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/src:/app/src"
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/buildroot:/app/buildroot"
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/source:/app/source"
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/dist:/app/dist"
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/downloads:/app/downloads"
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/pkgroot:/app/pkgroot"
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/log:/app/log"
|
||||
if [ -f "$(pwd)/craft.yml" ]; then
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/craft.yml:/app/craft.yml"
|
||||
fi
|
||||
|
||||
# Apply env in temp env file
|
||||
echo 'SPC_DEFAULT_C_FLAGS=-fPIC' > /tmp/spc-gnu-docker.env
|
||||
echo 'SPC_LIBC=glibc' >> /tmp/spc-gnu-docker.env
|
||||
|
||||
# Environment variable passthrough
|
||||
ENV_LIST=""
|
||||
ENV_LIST="$ENV_LIST -e SPC_FIX_DEPLOY_ROOT="$(pwd)""
|
||||
if [ ! -z "$GITHUB_TOKEN" ]; then
|
||||
ENV_LIST="$ENV_LIST -e GITHUB_TOKEN=$GITHUB_TOKEN"
|
||||
fi
|
||||
|
||||
# Intercept and rewrite --with-frankenphp-app option, and mount host path to /app/app
|
||||
FRANKENPHP_APP_PATH=""
|
||||
NEW_ARGS=()
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--with-frankenphp-app=*)
|
||||
FRANKENPHP_APP_PATH="${1#*=}"
|
||||
NEW_ARGS+=("--with-frankenphp-app=/app/app")
|
||||
shift
|
||||
;;
|
||||
--with-frankenphp-app)
|
||||
if [ -n "${2:-}" ]; then
|
||||
FRANKENPHP_APP_PATH="$2"
|
||||
NEW_ARGS+=("--with-frankenphp-app=/app/app")
|
||||
shift 2
|
||||
else
|
||||
NEW_ARGS+=("$1")
|
||||
shift
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
NEW_ARGS+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Normalize the path and add mount if provided
|
||||
if [ -n "$FRANKENPHP_APP_PATH" ]; then
|
||||
# expand ~ to $HOME
|
||||
if [ "${FRANKENPHP_APP_PATH#~}" != "$FRANKENPHP_APP_PATH" ]; then
|
||||
FRANKENPHP_APP_PATH="$HOME${FRANKENPHP_APP_PATH#~}"
|
||||
fi
|
||||
# make absolute if relative
|
||||
case "$FRANKENPHP_APP_PATH" in
|
||||
/*) ABS_APP_PATH="$FRANKENPHP_APP_PATH" ;;
|
||||
*) ABS_APP_PATH="$(pwd)/$FRANKENPHP_APP_PATH" ;;
|
||||
esac
|
||||
MOUNT_LIST="$MOUNT_LIST -v $ABS_APP_PATH:/app/app"
|
||||
fi
|
||||
|
||||
# Run docker
|
||||
# shellcheck disable=SC2068
|
||||
# shellcheck disable=SC2086
|
||||
# shellcheck disable=SC2090
|
||||
|
||||
if [ "$SPC_DOCKER_DEBUG" = "yes" ]; then
|
||||
echo "* Debug mode enabled, run docker in interactive mode."
|
||||
echo "* You can use 'exit' to exit the docker container."
|
||||
echo "* You can use 'bin/spc' like normal builds."
|
||||
echo "*"
|
||||
echo "* Mounted directories:"
|
||||
echo "* ./config: $(pwd)/config"
|
||||
echo "* ./src: $(pwd)/src"
|
||||
echo "* ./buildroot: $(pwd)/buildroot"
|
||||
echo "* ./source: $(pwd)/source"
|
||||
echo "* ./dist: $(pwd)/dist"
|
||||
echo "* ./downloads: $(pwd)/downloads"
|
||||
echo "* ./pkgroot: $(pwd)/pkgroot"
|
||||
echo "*"
|
||||
set -ex
|
||||
$DOCKER_EXECUTABLE run $PLATFORM_ARG --privileged --rm -it $INTERACT $ENV_LIST --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION /bin/bash
|
||||
else
|
||||
$DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION bin/spc "${NEW_ARGS[@]}"
|
||||
fi
|
||||
@@ -29,6 +29,7 @@
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"SPC\\": "src/SPC",
|
||||
"StaticPHP\\": "src/StaticPHP",
|
||||
"Package\\": "src/Package"
|
||||
},
|
||||
@@ -48,7 +49,7 @@
|
||||
"scripts": {
|
||||
"analyse": "phpstan analyse --memory-limit 300M",
|
||||
"cs-fix": "php-cs-fixer fix",
|
||||
"lint-config": "php bin/spc dev:lint-config",
|
||||
"lint-config": "bin/spc dev:lint-config",
|
||||
"test": "vendor/bin/phpunit tests/ --no-coverage",
|
||||
"build:phar": "vendor/bin/box compile"
|
||||
},
|
||||
@@ -62,9 +63,6 @@
|
||||
"optimize-autoloader": true,
|
||||
"sort-packages": true
|
||||
},
|
||||
"suggest": {
|
||||
"ext-yaml": "Speeds up YAML config file parsing"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"type": "other",
|
||||
|
||||
626
composer.lock
generated
626
composer.lock
generated
File diff suppressed because it is too large
Load Diff
1061
config/artifact.json
Normal file
1061
config/artifact.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -94,7 +94,7 @@ SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime
|
||||
; `native-native` - links against system libc dynamically
|
||||
; `native-native-musl` - links against musl libc statically
|
||||
; `native-native-musl -dynamic` - links against musl libc dynamically
|
||||
SPC_TARGET=${GNU_ARCH}-linux-musl
|
||||
SPC_TARGET=native-native-musl
|
||||
|
||||
; compiler environments (default value is defined by selected toolchain)
|
||||
CC=${SPC_DEFAULT_CC}
|
||||
@@ -102,9 +102,9 @@ CXX=${SPC_DEFAULT_CXX}
|
||||
AR=${SPC_DEFAULT_AR}
|
||||
LD=${SPC_DEFAULT_LD}
|
||||
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
|
||||
SPC_DEFAULT_CFLAGS="-fPIC -O3 -pipe -fno-plt -fno-semantic-interposition -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffunction-sections -fdata-sections"
|
||||
SPC_DEFAULT_CXXFLAGS="${SPC_DEFAULT_CFLAGS}"
|
||||
SPC_DEFAULT_LDFLAGS="-Wl,-z,relro -Wl,--as-needed -Wl,-z,now -Wl,-z,noexecstack -Wl,--gc-sections"
|
||||
SPC_DEFAULT_C_FLAGS="-fPIC -Os"
|
||||
SPC_DEFAULT_CXX_FLAGS="-fPIC -Os"
|
||||
SPC_DEFAULT_LD_FLAGS=""
|
||||
; upx executable path
|
||||
UPX_EXEC=${PKG_ROOT_PATH}/bin/upx
|
||||
; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches
|
||||
@@ -114,15 +114,15 @@ SPC_MICRO_PATCHES=cli_checks,disable_huge_page
|
||||
; buildconf command
|
||||
SPC_CMD_PREFIX_PHP_BUILDCONF="./buildconf --force"
|
||||
; configure command
|
||||
SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --disable-shared --enable-static --disable-all --disable-phpdbg --enable-rtld-now --enable-re2c-cgoto --disable-rpath --with-pic"
|
||||
SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --disable-shared --enable-static --disable-all --disable-phpdbg --with-pic"
|
||||
|
||||
; *** default build vars for building php ***
|
||||
; embed type for php, static (libphp.a) or shared (libphp.so)
|
||||
SPC_CMD_VAR_PHP_EMBED_TYPE="static"
|
||||
; EXTRA_CFLAGS for `configure` and `make` php
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fno-ident -fPIE -fvisibility=hidden -fvisibility-inlines-hidden ${SPC_DEFAULT_CFLAGS}"
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fno-ident -fPIE ${SPC_DEFAULT_C_FLAGS}"
|
||||
; EXTRA_CXXFLAGS for `configure` and `make` php
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_CXXFLAGS="-g -fstack-protector-strong -fno-ident -fPIE -fvisibility=hidden -fvisibility-inlines-hidden ${SPC_DEFAULT_CXXFLAGS}"
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_CXXFLAGS="-g -fstack-protector-strong -fno-ident -fPIE ${SPC_DEFAULT_CXX_FLAGS}"
|
||||
; EXTRA_LDFLAGS for `make` php, can use -release to set a soname for libphp.so
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS=""
|
||||
|
||||
@@ -142,9 +142,9 @@ CXX=${SPC_DEFAULT_CXX}
|
||||
AR=${SPC_DEFAULT_AR}
|
||||
LD=${SPC_DEFAULT_LD}
|
||||
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
|
||||
SPC_DEFAULT_CFLAGS="--target=${MAC_ARCH}-apple-darwin -O3 -fno-plt -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffunction-sections -fdata-sections"
|
||||
SPC_DEFAULT_CXXFLAGS="${SPC_DEFAULT_CFLAGS}"
|
||||
SPC_DEFAULT_LDFLAGS="-Wl,-dead_strip"
|
||||
SPC_DEFAULT_C_FLAGS="--target=${MAC_ARCH}-apple-darwin -Os"
|
||||
SPC_DEFAULT_CXX_FLAGS="--target=${MAC_ARCH}-apple-darwin -Os"
|
||||
SPC_DEFAULT_LD_FLAGS=""
|
||||
; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches
|
||||
SPC_MICRO_PATCHES=cli_checks,macos_iconv
|
||||
|
||||
@@ -152,15 +152,15 @@ SPC_MICRO_PATCHES=cli_checks,macos_iconv
|
||||
; buildconf command
|
||||
SPC_CMD_PREFIX_PHP_BUILDCONF="./buildconf --force"
|
||||
; configure command
|
||||
SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --disable-shared --enable-static --disable-all --disable-phpdbg --enable-rtld-now --enable-re2c-cgoto --disable-rpath --with-pic"
|
||||
SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-phpdbg"
|
||||
|
||||
; *** default build vars for building php ***
|
||||
; embed type for php, static (libphp.a) or shared (libphp.dylib)
|
||||
SPC_CMD_VAR_PHP_EMBED_TYPE="static"
|
||||
; EXTRA_CFLAGS for `configure` and `make` php
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fpic -fpie -fvisibility=hidden -fvisibility-inlines-hidden -Werror=unknown-warning-option ${SPC_DEFAULT_CFLAGS}"
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fpic -fpie -Werror=unknown-warning-option ${SPC_DEFAULT_C_FLAGS}"
|
||||
; EXTRA_CXXFLAGS for `configure` and `make` php
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_CXXFLAGS="-g -fstack-protector-strong -fno-ident -fpie -fvisibility=hidden -fvisibility-inlines-hidden -Werror=unknown-warning-option ${SPC_DEFAULT_CXXFLAGS}"
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_CXXFLAGS="-g -fstack-protector-strong -fno-ident -fpie -Werror=unknown-warning-option ${SPC_DEFAULT_CXX_FLAGS}"
|
||||
; EXTRA_LDFLAGS for `make` php, can use -release to set a soname for libphp.dylib
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS=""
|
||||
; minimum compatible macOS version (LLVM vars, availability not guaranteed)
|
||||
|
||||
1292
config/ext.json
Normal file
1292
config/ext.json
Normal file
File diff suppressed because it is too large
Load Diff
1065
config/lib.json
Normal file
1065
config/lib.json
Normal file
File diff suppressed because it is too large
Load Diff
1520
config/pkg.ext.json
Normal file
1520
config/pkg.ext.json
Normal file
File diff suppressed because it is too large
Load Diff
992
config/pkg.lib.json
Normal file
992
config/pkg.lib.json
Normal file
@@ -0,0 +1,992 @@
|
||||
{
|
||||
"attr": {
|
||||
"artifact": "attr",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "doc/COPYING.LGPL"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"brotli": {
|
||||
"artifact": "brotli",
|
||||
"headers": [
|
||||
"brotli"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"pkg-configs": [
|
||||
"libbrotlicommon",
|
||||
"libbrotlidec",
|
||||
"libbrotlienc"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"bzip2": {
|
||||
"artifact": "bzip2",
|
||||
"headers": [
|
||||
"bzlib.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "text",
|
||||
"text": "This program, \"bzip2\", the associated library \"libbzip2\", and all documentation, are copyright (C) 1996-2010 Julian R Seward. All rights reserved. \n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n 2. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n 3. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n 4. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nJulian Seward, jseward@bzip.org bzip2/libbzip2 version 1.0.6 of 6 September 2010\n\nPATENTS: To the best of my knowledge, bzip2 and libbzip2 do not use any patented algorithms. However, I do not have the resources to carry out a patent search. Therefore I cannot give any guarantee of the above statement."
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"curl": {
|
||||
"artifact": "curl",
|
||||
"depends": [
|
||||
"openssl",
|
||||
"zlib"
|
||||
],
|
||||
"depends@windows": [
|
||||
"zlib",
|
||||
"libssh2",
|
||||
"nghttp2"
|
||||
],
|
||||
"frameworks": [
|
||||
"CoreFoundation",
|
||||
"CoreServices",
|
||||
"SystemConfiguration"
|
||||
],
|
||||
"headers": [
|
||||
"curl"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"suggests": [
|
||||
"libssh2",
|
||||
"brotli",
|
||||
"nghttp2",
|
||||
"nghttp3",
|
||||
"ngtcp2",
|
||||
"zstd",
|
||||
"libcares",
|
||||
"ldap"
|
||||
],
|
||||
"suggests@windows": [
|
||||
"brotli",
|
||||
"zstd"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"fastlz": {
|
||||
"artifact": "fastlz",
|
||||
"headers": [
|
||||
"fastlz/fastlz.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE.MIT"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"freetype": {
|
||||
"artifact": "freetype",
|
||||
"depends": [
|
||||
"zlib"
|
||||
],
|
||||
"headers": [
|
||||
"freetype2/freetype/freetype.h",
|
||||
"freetype2/ft2build.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE.TXT"
|
||||
},
|
||||
"suggests": [
|
||||
"libpng",
|
||||
"bzip2",
|
||||
"brotli"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"gettext": {
|
||||
"artifact": "gettext",
|
||||
"depends": [
|
||||
"libiconv"
|
||||
],
|
||||
"frameworks": [
|
||||
"CoreFoundation"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "gettext-runtime/intl/COPYING.LIB"
|
||||
},
|
||||
"suggests": [
|
||||
"ncurses",
|
||||
"libxml2"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"glfw": {
|
||||
"artifact": "ext-glfw",
|
||||
"frameworks": [
|
||||
"CoreVideo",
|
||||
"OpenGL",
|
||||
"Cocoa",
|
||||
"IOKit"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"gmp": {
|
||||
"artifact": "gmp",
|
||||
"headers": [
|
||||
"gmp.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "text",
|
||||
"text": "Since version 6, GMP is distributed under the dual licenses, GNU LGPL v3 and GNU GPL v2. These licenses make the library free to use, share, and improve, and allow you to pass on the result. The GNU licenses give freedoms, but also set firm restrictions on the use with non-free programs."
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"gmssl": {
|
||||
"artifact": "gmssl",
|
||||
"frameworks": [
|
||||
"Security"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"grpc": {
|
||||
"artifact": "grpc",
|
||||
"depends": [
|
||||
"zlib",
|
||||
"openssl",
|
||||
"libcares"
|
||||
],
|
||||
"frameworks": [
|
||||
"CoreFoundation"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"pkg-configs": [
|
||||
"grpc"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"icu": {
|
||||
"artifact": "icu",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"pkg-configs": [
|
||||
"icu-uc",
|
||||
"icu-i18n",
|
||||
"icu-io"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"icu-static-win": {
|
||||
"artifact": "icu-static-win",
|
||||
"headers@windows": [
|
||||
"unicode"
|
||||
],
|
||||
"license": {
|
||||
"type": "text",
|
||||
"text": "none"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"imagemagick": {
|
||||
"artifact": "imagemagick",
|
||||
"depends": [
|
||||
"zlib",
|
||||
"libjpeg",
|
||||
"libjxl",
|
||||
"libpng",
|
||||
"libwebp",
|
||||
"freetype",
|
||||
"libtiff",
|
||||
"libheif",
|
||||
"bzip2"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"pkg-configs": [
|
||||
"Magick++-7.Q16HDRI",
|
||||
"MagickCore-7.Q16HDRI",
|
||||
"MagickWand-7.Q16HDRI"
|
||||
],
|
||||
"suggests": [
|
||||
"zstd",
|
||||
"xz",
|
||||
"libzip",
|
||||
"libxml2"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"imap": {
|
||||
"artifact": "imap",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"suggests": [
|
||||
"openssl"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"jbig": {
|
||||
"artifact": "jbig",
|
||||
"headers": [
|
||||
"jbig.h",
|
||||
"jbig85.h",
|
||||
"jbig_ar.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"ldap": {
|
||||
"artifact": "ldap",
|
||||
"depends": [
|
||||
"openssl",
|
||||
"zlib",
|
||||
"gmp",
|
||||
"libsodium"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"pkg-configs": [
|
||||
"ldap",
|
||||
"lber"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"lerc": {
|
||||
"artifact": "lerc",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libacl": {
|
||||
"artifact": "libacl",
|
||||
"depends": [
|
||||
"attr"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "doc/COPYING.LGPL"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libaom": {
|
||||
"artifact": "libaom",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libargon2": {
|
||||
"artifact": "libargon2",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libavif": {
|
||||
"artifact": "libavif",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libcares": {
|
||||
"artifact": "libcares",
|
||||
"headers": [
|
||||
"ares.h",
|
||||
"ares_dns.h",
|
||||
"ares_nameser.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE.md"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libde265": {
|
||||
"artifact": "libde265",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libedit": {
|
||||
"artifact": "libedit",
|
||||
"depends": [
|
||||
"ncurses"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libevent": {
|
||||
"artifact": "libevent",
|
||||
"depends": [
|
||||
"openssl"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libffi": {
|
||||
"artifact": "libffi",
|
||||
"headers": [
|
||||
"ffi.h",
|
||||
"ffitarget.h"
|
||||
],
|
||||
"headers@windows": [
|
||||
"ffi.h",
|
||||
"fficonfig.h",
|
||||
"ffitarget.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libffi-win": {
|
||||
"artifact": "libffi-win",
|
||||
"headers@windows": [
|
||||
"ffi.h",
|
||||
"ffitarget.h",
|
||||
"fficonfig.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libheif": {
|
||||
"artifact": "libheif",
|
||||
"depends": [
|
||||
"libde265",
|
||||
"libwebp",
|
||||
"libaom",
|
||||
"zlib",
|
||||
"brotli"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libiconv": {
|
||||
"artifact": "libiconv",
|
||||
"headers": [
|
||||
"iconv.h",
|
||||
"libcharset.h",
|
||||
"localcharset.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING.LIB"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libiconv-win": {
|
||||
"artifact": "libiconv-win",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "source/COPYING"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libjpeg": {
|
||||
"artifact": "libjpeg",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE.md"
|
||||
},
|
||||
"suggests@windows": [
|
||||
"zlib"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"libjxl": {
|
||||
"artifact": "libjxl",
|
||||
"depends": [
|
||||
"brotli",
|
||||
"libjpeg",
|
||||
"libpng",
|
||||
"libwebp"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"pkg-configs": [
|
||||
"libjxl",
|
||||
"libjxl_cms",
|
||||
"libjxl_threads",
|
||||
"libhwy"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"liblz4": {
|
||||
"artifact": "liblz4",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libmemcached": {
|
||||
"artifact": "libmemcached",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libpng": {
|
||||
"artifact": "libpng",
|
||||
"depends": [
|
||||
"zlib"
|
||||
],
|
||||
"headers": [
|
||||
"png.h",
|
||||
"pngconf.h",
|
||||
"pnglibconf.h"
|
||||
],
|
||||
"headers@windows": [
|
||||
"png.h",
|
||||
"pngconf.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"librabbitmq": {
|
||||
"artifact": "librabbitmq",
|
||||
"depends": [
|
||||
"openssl"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"librdkafka": {
|
||||
"artifact": "librdkafka",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"pkg-configs": [
|
||||
"rdkafka++-static",
|
||||
"rdkafka-static"
|
||||
],
|
||||
"suggests": [
|
||||
"curl",
|
||||
"liblz4",
|
||||
"openssl",
|
||||
"zlib",
|
||||
"zstd"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"libsodium": {
|
||||
"artifact": "libsodium",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libssh2": {
|
||||
"artifact": "libssh2",
|
||||
"depends": [
|
||||
"openssl"
|
||||
],
|
||||
"headers": [
|
||||
"libssh2.h",
|
||||
"libssh2_publickey.h",
|
||||
"libssh2_sftp.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libtiff": {
|
||||
"artifact": "libtiff",
|
||||
"depends": [
|
||||
"zlib",
|
||||
"libjpeg"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE.md"
|
||||
},
|
||||
"suggests": [
|
||||
"lerc",
|
||||
"libwebp",
|
||||
"jbig",
|
||||
"xz",
|
||||
"zstd"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"liburing": {
|
||||
"artifact": "liburing",
|
||||
"headers@linux": [
|
||||
"liburing/",
|
||||
"liburing.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"pkg-configs": [
|
||||
"liburing",
|
||||
"liburing-ffi"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"libuuid": {
|
||||
"artifact": "libuuid",
|
||||
"headers": [
|
||||
"uuid/uuid.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libuv": {
|
||||
"artifact": "libuv",
|
||||
"license": [
|
||||
{
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"path": "LICENSE-extra"
|
||||
}
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"libwebp": {
|
||||
"artifact": "libwebp",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"pkg-configs": [
|
||||
"libwebp",
|
||||
"libwebpdecoder",
|
||||
"libwebpdemux",
|
||||
"libwebpmux",
|
||||
"libsharpyuv"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"libxml2": {
|
||||
"artifact": "libxml2",
|
||||
"depends": [
|
||||
"libiconv"
|
||||
],
|
||||
"depends@windows": [
|
||||
"libiconv-win"
|
||||
],
|
||||
"headers": [
|
||||
"libxml2"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "Copyright"
|
||||
},
|
||||
"pkg-configs": [
|
||||
"libxml-2.0"
|
||||
],
|
||||
"suggests": [
|
||||
"xz",
|
||||
"zlib"
|
||||
],
|
||||
"suggests@windows": [
|
||||
"zlib"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"libxslt": {
|
||||
"artifact": "libxslt",
|
||||
"depends": [
|
||||
"libxml2"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "Copyright"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libyaml": {
|
||||
"artifact": "libyaml",
|
||||
"headers": [
|
||||
"yaml.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "License"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"libzip": {
|
||||
"artifact": "libzip",
|
||||
"depends": [
|
||||
"zlib"
|
||||
],
|
||||
"depends@windows": [
|
||||
"zlib",
|
||||
"bzip2",
|
||||
"xz"
|
||||
],
|
||||
"headers": [
|
||||
"zip.h",
|
||||
"zipconf.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"suggests": [
|
||||
"bzip2",
|
||||
"xz",
|
||||
"zstd",
|
||||
"openssl"
|
||||
],
|
||||
"suggests@windows": [
|
||||
"zstd",
|
||||
"openssl"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"mimalloc": {
|
||||
"artifact": "mimalloc",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"ncurses": {
|
||||
"artifact": "ncurses",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"static-libs@unix": [
|
||||
"libncurses.a"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"net-snmp": {
|
||||
"artifact": "net-snmp",
|
||||
"depends": [
|
||||
"openssl",
|
||||
"zlib"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"pkg-configs": [
|
||||
"netsnmp",
|
||||
"netsnmp-agent"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"nghttp2": {
|
||||
"artifact": "nghttp2",
|
||||
"depends": [
|
||||
"zlib",
|
||||
"openssl"
|
||||
],
|
||||
"headers": [
|
||||
"nghttp2"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"suggests": [
|
||||
"libxml2",
|
||||
"nghttp3",
|
||||
"ngtcp2"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"nghttp3": {
|
||||
"artifact": "nghttp3",
|
||||
"depends": [
|
||||
"openssl"
|
||||
],
|
||||
"headers": [
|
||||
"nghttp3"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"ngtcp2": {
|
||||
"artifact": "ngtcp2",
|
||||
"depends": [
|
||||
"openssl"
|
||||
],
|
||||
"headers": [
|
||||
"ngtcp2"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"suggests": [
|
||||
"nghttp3",
|
||||
"brotli"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"onig": {
|
||||
"artifact": "onig",
|
||||
"headers": [
|
||||
"oniggnu.h",
|
||||
"oniguruma.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"openssl": {
|
||||
"artifact": "openssl",
|
||||
"depends": [
|
||||
"zlib"
|
||||
],
|
||||
"headers": [
|
||||
"openssl"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE.txt"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"postgresql": {
|
||||
"artifact": "postgresql",
|
||||
"depends": [
|
||||
"libiconv",
|
||||
"libxml2",
|
||||
"openssl",
|
||||
"zlib",
|
||||
"libedit"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYRIGHT"
|
||||
},
|
||||
"pkg-configs": [
|
||||
"libpq"
|
||||
],
|
||||
"suggests": [
|
||||
"icu",
|
||||
"libxslt",
|
||||
"ldap",
|
||||
"zstd"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
"postgresql-win": {
|
||||
"artifact": "postgresql-win",
|
||||
"license": {
|
||||
"type": "text",
|
||||
"text": "PostgreSQL Database Management System\n(also known as Postgres, formerly as Postgres95)\n\nPortions Copyright (c) 1996-2025, The PostgreSQL Global Development Group\n\nPortions Copyright (c) 1994, The Regents of the University of California\n\nPermission to use, copy, modify, and distribute this software and its\ndocumentation for any purpose, without fee, and without a written\nagreement is hereby granted, provided that the above copyright notice\nand this paragraph and the following two paragraphs appear in all\ncopies.\n\nIN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY\nFOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,\nINCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS\nDOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF\nTHE POSSIBILITY OF SUCH DAMAGE.\n\nTHE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\nON AN \"AS IS\" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS\nTO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"pthreads4w": {
|
||||
"artifact": "pthreads4w",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"qdbm": {
|
||||
"artifact": "qdbm",
|
||||
"headers@windows": [
|
||||
"depot.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"re2c": {
|
||||
"artifact": "re2c",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"readline": {
|
||||
"artifact": "readline",
|
||||
"depends": [
|
||||
"ncurses"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"snappy": {
|
||||
"artifact": "snappy",
|
||||
"depends": [
|
||||
"zlib"
|
||||
],
|
||||
"headers": [
|
||||
"snappy.h",
|
||||
"snappy-c.h",
|
||||
"snappy-sinksource.h",
|
||||
"snappy-stubs-public.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"sqlite": {
|
||||
"artifact": "sqlite",
|
||||
"headers": [
|
||||
"sqlite3.h",
|
||||
"sqlite3ext.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "text",
|
||||
"text": "The author disclaims copyright to this source code. In place of\na legal notice, here is a blessing:\n\n * May you do good and not evil.\n * May you find forgiveness for yourself and forgive others.\n * May you share freely, never taking more than you give."
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"tidy": {
|
||||
"artifact": "tidy",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "README/LICENSE.md"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"unixodbc": {
|
||||
"artifact": "unixodbc",
|
||||
"depends": [
|
||||
"libiconv"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"watcher": {
|
||||
"artifact": "watcher",
|
||||
"headers": [
|
||||
"wtr/watcher-c.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "license"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"xz": {
|
||||
"artifact": "xz",
|
||||
"depends": [
|
||||
"libiconv"
|
||||
],
|
||||
"headers": [
|
||||
"lzma"
|
||||
],
|
||||
"headers@windows": [
|
||||
"lzma",
|
||||
"lzma.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"zlib": {
|
||||
"artifact": "zlib",
|
||||
"headers": [
|
||||
"zlib.h",
|
||||
"zconf.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "text",
|
||||
"text": "(C) 1995-2022 Jean-loup Gailly and Mark Adler\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must not\n claim that you wrote the original software. If you use this software\n in a product, an acknowledgment in the product documentation would be\n appreciated but is not required.\n2. Altered source versions must be plainly marked as such, and must not be\n misrepresented as being the original software.\n3. This notice may not be removed or altered from any source distribution.\n\nJean-loup Gailly Mark Adler\njloup@gzip.org madler@alumni.caltech.edu"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
"zstd": {
|
||||
"artifact": "zstd",
|
||||
"headers": [
|
||||
"zdict.h",
|
||||
"zstd.h",
|
||||
"zstd_errors.h"
|
||||
],
|
||||
"headers@windows": [
|
||||
"zstd.h",
|
||||
"zstd_errors.h"
|
||||
],
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"type": "library"
|
||||
}
|
||||
}
|
||||
@@ -9,12 +9,6 @@ ext-bz2:
|
||||
arg-type@windows: with
|
||||
ext-calendar:
|
||||
type: php-extension
|
||||
ext-com_dotnet:
|
||||
type: php-extension
|
||||
php-extension:
|
||||
os:
|
||||
- Windows
|
||||
arg-type@windows: '--enable-com-dotnet=yes'
|
||||
ext-ctype:
|
||||
type: php-extension
|
||||
ext-curl:
|
||||
@@ -36,20 +30,17 @@ ext-dba:
|
||||
ext-dom:
|
||||
type: php-extension
|
||||
depends:
|
||||
- libxml2
|
||||
- ext-xml
|
||||
php-extension:
|
||||
arg-type: enable
|
||||
arg-type: '--enable-dom@shared_suffix@ --with-libxml=@build_root_path@'
|
||||
arg-type@windows: with
|
||||
ext-exif:
|
||||
type: php-extension
|
||||
depends@windows:
|
||||
- ext-mbstring
|
||||
ext-ffi:
|
||||
type: php-extension
|
||||
depends@unix:
|
||||
- libffi
|
||||
depends@windows:
|
||||
- libffi-win
|
||||
php-extension:
|
||||
arg-type@unix: '--with-ffi=@shared_suffix@ --enable-zend-signals'
|
||||
arg-type@windows: with
|
||||
@@ -74,37 +65,28 @@ ext-gd:
|
||||
- freetype
|
||||
php-extension:
|
||||
arg-type: custom
|
||||
arg-type@windows: with
|
||||
ext-gettext:
|
||||
type: php-extension
|
||||
depends@unix:
|
||||
depends:
|
||||
- gettext
|
||||
depends@windows:
|
||||
- gettext-win
|
||||
php-extension:
|
||||
arg-type: with-path
|
||||
arg-type@windows: with
|
||||
ext-gmp:
|
||||
type: php-extension
|
||||
depends@unix:
|
||||
depends:
|
||||
- gmp
|
||||
depends@windows:
|
||||
- mpir
|
||||
php-extension:
|
||||
arg-type: with-path
|
||||
arg-type@windows: with
|
||||
ext-iconv:
|
||||
type: php-extension
|
||||
depends@unix:
|
||||
- libiconv
|
||||
depends@windows:
|
||||
- libiconv-win
|
||||
php-extension:
|
||||
arg-type@unix: with-path
|
||||
arg-type@windows: with
|
||||
ext-intl:
|
||||
type: php-extension
|
||||
depends:
|
||||
depends@unix:
|
||||
- icu
|
||||
ext-ldap:
|
||||
type: php-extension
|
||||
@@ -115,20 +97,15 @@ ext-ldap:
|
||||
- libsodium
|
||||
- ext-openssl
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
arg-type: with-path
|
||||
arg-type@windows: with
|
||||
ext-libxml:
|
||||
type: php-extension
|
||||
depends:
|
||||
- libxml2
|
||||
- ext-xml
|
||||
php-extension:
|
||||
build-with-php: true
|
||||
build-shared: false
|
||||
arg-type@unix: with-path
|
||||
arg-type@windows: with
|
||||
arg-type: none
|
||||
ext-mbregex:
|
||||
type: php-extension
|
||||
depends:
|
||||
@@ -164,7 +141,6 @@ ext-odbc:
|
||||
- unixodbc
|
||||
php-extension:
|
||||
arg-type@unix: '--with-unixODBC@shared_path_suffix@'
|
||||
arg-type@windows: enable
|
||||
ext-opcache:
|
||||
type: php-extension
|
||||
php-extension:
|
||||
@@ -188,17 +164,10 @@ ext-password-argon2:
|
||||
- libargon2
|
||||
- ext-openssl
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
arg-type: custom
|
||||
display-name: ''
|
||||
ext-pcntl:
|
||||
type: php-extension
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
ext-pdo:
|
||||
type: php-extension
|
||||
ext-pdo_mysql:
|
||||
@@ -212,6 +181,7 @@ ext-pdo_odbc:
|
||||
type: php-extension
|
||||
depends:
|
||||
- ext-pdo
|
||||
- ext-odbc
|
||||
depends@unix:
|
||||
- unixodbc
|
||||
- ext-pdo
|
||||
@@ -220,7 +190,7 @@ ext-pdo_odbc:
|
||||
arg-type: custom
|
||||
ext-pdo_pgsql:
|
||||
type: php-extension
|
||||
depends:
|
||||
depends@unix:
|
||||
- ext-pdo
|
||||
- ext-pgsql
|
||||
- postgresql
|
||||
@@ -237,7 +207,7 @@ ext-pdo_sqlite:
|
||||
arg-type: with
|
||||
ext-pgsql:
|
||||
type: php-extension
|
||||
depends:
|
||||
depends@unix:
|
||||
- postgresql
|
||||
php-extension:
|
||||
arg-type: custom
|
||||
@@ -247,19 +217,15 @@ ext-phar:
|
||||
- zlib
|
||||
ext-posix:
|
||||
type: php-extension
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
ext-readline:
|
||||
type: php-extension
|
||||
depends@unix:
|
||||
depends:
|
||||
- libedit
|
||||
depends@windows:
|
||||
- wineditline
|
||||
php-extension:
|
||||
support:
|
||||
Windows: wip
|
||||
BSD: wip
|
||||
arg-type: '--with-libedit --without-readline'
|
||||
arg-type@windows: with
|
||||
build-shared: false
|
||||
build-static: true
|
||||
ext-session:
|
||||
@@ -273,7 +239,7 @@ ext-simplexml:
|
||||
depends:
|
||||
- ext-xml
|
||||
php-extension:
|
||||
arg-type@unix: enable
|
||||
arg-type@unix: '--enable-simplexml@shared_suffix@ --with-libxml=@build_root_path@'
|
||||
arg-type@windows: with
|
||||
build-with-php: true
|
||||
ext-snmp:
|
||||
@@ -281,9 +247,6 @@ ext-snmp:
|
||||
depends:
|
||||
- net-snmp
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
arg-type: with
|
||||
ext-soap:
|
||||
type: php-extension
|
||||
@@ -291,7 +254,8 @@ ext-soap:
|
||||
- ext-xml
|
||||
- ext-session
|
||||
php-extension:
|
||||
arg-type: enable
|
||||
arg-type@unix: '--enable-soap@shared_suffix@ --with-libxml=@build_root_path@'
|
||||
arg-type@windows: with
|
||||
build-with-php: true
|
||||
ext-sockets:
|
||||
type: php-extension
|
||||
@@ -312,22 +276,28 @@ ext-sqlite3:
|
||||
ext-sysvmsg:
|
||||
type: php-extension
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
support:
|
||||
Windows: 'no'
|
||||
BSD: wip
|
||||
ext-sysvsem:
|
||||
type: php-extension
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
support:
|
||||
Windows: 'no'
|
||||
BSD: wip
|
||||
ext-sysvshm:
|
||||
type: php-extension
|
||||
php-extension:
|
||||
support:
|
||||
BSD: wip
|
||||
ext-tidy:
|
||||
type: php-extension
|
||||
depends:
|
||||
- tidy
|
||||
php-extension:
|
||||
support:
|
||||
Windows: wip
|
||||
BSD: wip
|
||||
arg-type: with-path
|
||||
ext-tokenizer:
|
||||
type: php-extension
|
||||
@@ -336,27 +306,27 @@ ext-tokenizer:
|
||||
ext-xml:
|
||||
type: php-extension
|
||||
depends:
|
||||
- ext-libxml
|
||||
- libxml2
|
||||
depends@windows:
|
||||
- libxml2
|
||||
- ext-iconv
|
||||
- ext-libxml
|
||||
php-extension:
|
||||
arg-type@unix: enable
|
||||
arg-type: '--enable-xml@shared_suffix@ --with-libxml=@build_root_path@'
|
||||
arg-type@windows: with
|
||||
build-with-php: true
|
||||
ext-xmlreader:
|
||||
type: php-extension
|
||||
depends:
|
||||
- ext-xml
|
||||
- libxml2
|
||||
php-extension:
|
||||
arg-type: enable
|
||||
arg-type: '--enable-xmlreader@shared_suffix@ --with-libxml=@build_root_path@'
|
||||
build-with-php: true
|
||||
ext-xmlwriter:
|
||||
type: php-extension
|
||||
depends:
|
||||
- ext-xml
|
||||
- libxml2
|
||||
php-extension:
|
||||
arg-type: enable
|
||||
arg-type: '--enable-xmlwriter@shared_suffix@ --with-libxml=@build_root_path@'
|
||||
build-with-php: true
|
||||
ext-xsl:
|
||||
type: php-extension
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
ext-decimal:
|
||||
type: php-extension
|
||||
artifact:
|
||||
source:
|
||||
type: ghtagtar
|
||||
repo: php-decimal/ext-decimal
|
||||
match: 'v2\.\d.*'
|
||||
extract: php-src/ext/decimal
|
||||
metadata:
|
||||
license-files: [LICENSE]
|
||||
license: MIT
|
||||
depends:
|
||||
- libmpdec
|
||||
php-extension:
|
||||
arg-type@unix: '--enable-decimal --with-libmpdec-path=@build_root_path@'
|
||||
arg-type@windows: '--with-decimal'
|
||||
@@ -1,10 +0,0 @@
|
||||
ext-deepclone:
|
||||
type: php-extension
|
||||
artifact:
|
||||
source:
|
||||
type: ghtagtar
|
||||
repo: symfony/php-ext-deepclone
|
||||
extract: php-src/ext/deepclone
|
||||
metadata:
|
||||
license-files: [LICENSE]
|
||||
license: PHP-3.01
|
||||
@@ -14,7 +14,6 @@ ext-event:
|
||||
suggests:
|
||||
- ext-sockets
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
support:
|
||||
Windows: wip
|
||||
arg-type: custom
|
||||
|
||||
@@ -7,7 +7,3 @@ ext-excimer:
|
||||
metadata:
|
||||
license-files: [LICENSE]
|
||||
license: PHP-3.01
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
ext-gearman:
|
||||
type: php-extension
|
||||
artifact:
|
||||
source:
|
||||
type: pecl
|
||||
name: gearman
|
||||
metadata:
|
||||
license-files: [LICENSE]
|
||||
license: PHP-3.01
|
||||
depends:
|
||||
- libgearman
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
arg-type: '--with-gearman@shared_path_suffix@'
|
||||
@@ -11,7 +11,4 @@ ext-grpc:
|
||||
- grpc
|
||||
lang: cpp
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
arg-type@unix: enable-path
|
||||
|
||||
@@ -10,7 +10,4 @@ ext-imagick:
|
||||
depends:
|
||||
- imagemagick
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
arg-type: custom
|
||||
|
||||
@@ -12,7 +12,4 @@ ext-imap:
|
||||
suggests:
|
||||
- ext-openssl
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
arg-type: custom
|
||||
|
||||
@@ -7,6 +7,3 @@ ext-inotify:
|
||||
metadata:
|
||||
license-files: [LICENSE]
|
||||
license: PHP-3.01
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
|
||||
@@ -2,9 +2,8 @@ ext-lz4:
|
||||
type: php-extension
|
||||
artifact:
|
||||
source:
|
||||
type: git
|
||||
url: 'https://github.com/kjdev/php-ext-lz4.git'
|
||||
rev: master
|
||||
type: ghtagtar
|
||||
repo: kjdev/php-ext-lz4
|
||||
extract: php-src/ext/lz4
|
||||
metadata:
|
||||
license-files: [LICENSE]
|
||||
|
||||
@@ -11,7 +11,4 @@ ext-memcache:
|
||||
- ext-zlib
|
||||
- ext-session
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
arg-type: '--enable-memcache@shared_suffix@ --with-zlib-dir=@build_root_path@'
|
||||
|
||||
@@ -20,7 +20,4 @@ ext-memcached:
|
||||
- ext-msgpack
|
||||
- ext-session
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
arg-type: '--enable-memcached@shared_suffix@ --with-zlib-dir=@build_root_path@'
|
||||
|
||||
@@ -9,9 +9,7 @@ ext-mongodb:
|
||||
metadata:
|
||||
license-files: [LICENSE]
|
||||
license: PHP-3.01
|
||||
depends@windows:
|
||||
- ext-openssl
|
||||
suggests@unix:
|
||||
suggests:
|
||||
- icu
|
||||
- openssl
|
||||
- zstd
|
||||
@@ -20,5 +18,4 @@ ext-mongodb:
|
||||
- CoreFoundation
|
||||
- Security
|
||||
php-extension:
|
||||
arg-type@unix: custom
|
||||
arg-type@windows: '--enable-mongodb --with-mongodb-client-side-encryption'
|
||||
arg-type: custom
|
||||
|
||||
@@ -7,7 +7,3 @@ ext-parallel:
|
||||
metadata:
|
||||
license-files: [LICENSE]
|
||||
license: PHP-3.01
|
||||
depends@windows:
|
||||
- pthreads4w
|
||||
php-extension:
|
||||
arg-type@windows: with
|
||||
|
||||
@@ -7,7 +7,3 @@ ext-protobuf:
|
||||
metadata:
|
||||
license-files: [LICENSE]
|
||||
license: BSD-3-Clause
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
|
||||
@@ -3,7 +3,7 @@ ext-rdkafka:
|
||||
artifact:
|
||||
source:
|
||||
type: ghtar
|
||||
repo: php-rdkafka/php-rdkafka
|
||||
repo: arnaud-lb/php-rdkafka
|
||||
extract: php-src/ext/rdkafka
|
||||
metadata:
|
||||
license-files: [LICENSE]
|
||||
@@ -12,7 +12,4 @@ ext-rdkafka:
|
||||
- librdkafka
|
||||
lang: cpp
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
arg-type: custom
|
||||
|
||||
@@ -16,4 +16,3 @@ ext-snappy:
|
||||
lang: cpp
|
||||
php-extension:
|
||||
arg-type@unix: '--enable-snappy --with-snappy-includedir=@build_root_path@'
|
||||
arg-type@windows: '--enable-snappy'
|
||||
|
||||
@@ -11,7 +11,4 @@ ext-spx:
|
||||
depends:
|
||||
- ext-zlib
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
arg-type: '--enable-SPX@shared_suffix@'
|
||||
|
||||
@@ -5,6 +5,7 @@ ext-swoole:
|
||||
type: ghtar
|
||||
repo: swoole/swoole-src
|
||||
extract: php-src/ext/swoole
|
||||
match: v6\.+
|
||||
prefer-stable: true
|
||||
metadata:
|
||||
license-files: [LICENSE]
|
||||
@@ -33,9 +34,6 @@ ext-swoole:
|
||||
- ext-swoole-hook-odbc
|
||||
lang: cpp
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
arg-type: custom
|
||||
ext-swoole-hook-mysql:
|
||||
type: php-extension
|
||||
@@ -46,9 +44,6 @@ ext-swoole-hook-mysql:
|
||||
suggests:
|
||||
- ext-mysqli
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
arg-type: none
|
||||
display-name: swoole
|
||||
ext-swoole-hook-odbc:
|
||||
@@ -57,9 +52,6 @@ ext-swoole-hook-odbc:
|
||||
- ext-pdo
|
||||
- unixodbc
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
arg-type: none
|
||||
display-name: swoole
|
||||
ext-swoole-hook-pgsql:
|
||||
@@ -68,9 +60,6 @@ ext-swoole-hook-pgsql:
|
||||
- ext-pgsql
|
||||
- ext-pdo
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
arg-type: none
|
||||
display-name: swoole
|
||||
ext-swoole-hook-sqlite:
|
||||
@@ -79,8 +68,5 @@ ext-swoole-hook-sqlite:
|
||||
- ext-sqlite3
|
||||
- ext-pdo
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
arg-type: none
|
||||
display-name: swoole
|
||||
|
||||
@@ -8,4 +8,7 @@ ext-trader:
|
||||
license-files: [LICENSE]
|
||||
license: BSD-2-Clause
|
||||
php-extension:
|
||||
support:
|
||||
BSD: wip
|
||||
Windows: wip
|
||||
arg-type: enable
|
||||
|
||||
@@ -10,7 +10,7 @@ ext-uuid:
|
||||
depends:
|
||||
- libuuid
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
support:
|
||||
Windows: wip
|
||||
BSD: wip
|
||||
arg-type: with-path
|
||||
|
||||
@@ -12,4 +12,7 @@ ext-uv:
|
||||
- libuv
|
||||
- ext-sockets
|
||||
php-extension:
|
||||
support:
|
||||
Windows: wip
|
||||
BSD: wip
|
||||
arg-type: with-path
|
||||
|
||||
@@ -8,9 +8,6 @@ ext-xdebug:
|
||||
license-files: [LICENSE]
|
||||
license: Xdebug-1.03
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
zend-extension: true
|
||||
build-static: false
|
||||
build-shared: true
|
||||
|
||||
@@ -11,8 +11,8 @@ ext-xhprof:
|
||||
depends:
|
||||
- ext-ctype
|
||||
php-extension:
|
||||
os:
|
||||
- Linux
|
||||
- Darwin
|
||||
support:
|
||||
Windows: wip
|
||||
BSD: wip
|
||||
arg-type: enable
|
||||
build-with-php: true
|
||||
|
||||
@@ -13,5 +13,6 @@ ext-xlswriter:
|
||||
suggests:
|
||||
- openssl
|
||||
php-extension:
|
||||
support:
|
||||
BSD: wip
|
||||
arg-type: custom
|
||||
arg-type@windows: '--with-xlswriter'
|
||||
|
||||
@@ -13,4 +13,3 @@ ext-xz:
|
||||
- xz
|
||||
php-extension:
|
||||
arg-type: with-path
|
||||
arg-type@windows: enable
|
||||
|
||||
@@ -8,8 +8,10 @@ ext-zip:
|
||||
metadata:
|
||||
license-files: [LICENSE]
|
||||
license: PHP-3.01
|
||||
depends:
|
||||
depends@unix:
|
||||
- libzip
|
||||
php-extension:
|
||||
support:
|
||||
BSD: wip
|
||||
arg-type: custom
|
||||
arg-type@windows: enable
|
||||
|
||||
@@ -11,8 +11,5 @@ ext-zstd:
|
||||
license: MIT
|
||||
depends:
|
||||
- zstd
|
||||
suggests:
|
||||
- ext-apcu
|
||||
php-extension:
|
||||
arg-type: '--enable-zstd --with-libzstd=@build_root_path@'
|
||||
arg-type@windows: '--enable-zstd'
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
gettext-win:
|
||||
type: library
|
||||
artifact:
|
||||
source:
|
||||
type: git
|
||||
url: 'https://github.com/winlibs/gettext.git'
|
||||
rev: master
|
||||
static-libs@windows:
|
||||
- libintl_a.lib
|
||||
@@ -1,11 +1,6 @@
|
||||
glfw:
|
||||
type: library
|
||||
artifact: glfw
|
||||
headers:
|
||||
- GLFW/glfw3.h
|
||||
- GLFW/glfw3native.h
|
||||
lang: cpp
|
||||
static-libs@unix:
|
||||
- libglfw3.a
|
||||
static-libs@windows:
|
||||
- glfw3.lib
|
||||
|
||||
@@ -2,8 +2,9 @@ krb5:
|
||||
type: library
|
||||
artifact:
|
||||
source:
|
||||
type: url
|
||||
url: 'https://web.mit.edu/kerberos/dist/krb5/1.22/krb5-1.22.2.tar.gz'
|
||||
type: ghtagtar
|
||||
repo: krb5/krb5
|
||||
match: krb5.+-final
|
||||
metadata:
|
||||
license-files: [NOTICE]
|
||||
license: BSD-3-Clause
|
||||
|
||||
@@ -16,4 +16,3 @@ libevent:
|
||||
- libevent_core.a
|
||||
- libevent_extra.a
|
||||
- libevent_openssl.a
|
||||
- libevent_pthreads.a
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
libgearman:
|
||||
type: library
|
||||
artifact:
|
||||
source:
|
||||
type: ghrel
|
||||
repo: gearman/gearmand
|
||||
match: gearmand-.+\.tar\.gz
|
||||
prefer-stable: true
|
||||
metadata:
|
||||
license-files: [COPYING]
|
||||
license: BSD-3-Clause
|
||||
depends:
|
||||
- libevent
|
||||
- libuuid
|
||||
suggests:
|
||||
- libmemcached
|
||||
headers@unix:
|
||||
- libgearman-1.0/gearman.h
|
||||
lang: cpp
|
||||
pkg-configs:
|
||||
- gearmand
|
||||
static-libs@unix:
|
||||
- libgearman.a
|
||||
@@ -11,5 +11,3 @@ liblz4:
|
||||
license: BSD-2-Clause
|
||||
static-libs@unix:
|
||||
- liblz4.a
|
||||
static-libs@windows:
|
||||
- lz4.lib
|
||||
|
||||
@@ -14,5 +14,3 @@ libmaxminddb:
|
||||
- maxminddb_config.h
|
||||
static-libs@unix:
|
||||
- libmaxminddb.a
|
||||
static-libs@windows:
|
||||
- libmaxminddb.lib
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
libmpdec:
|
||||
type: library
|
||||
artifact:
|
||||
source:
|
||||
type: url
|
||||
url: 'https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-4.0.1.tar.gz'
|
||||
metadata:
|
||||
license-files: [COPYRIGHT.txt]
|
||||
license: BSD-2-Clause
|
||||
headers:
|
||||
- mpdecimal.h
|
||||
static-libs@unix:
|
||||
- libmpdec.a
|
||||
static-libs@windows:
|
||||
- libmpdec_a.lib
|
||||
@@ -9,5 +9,3 @@ libuv:
|
||||
license: MIT
|
||||
static-libs@unix:
|
||||
- libuv.a
|
||||
static-libs@windows:
|
||||
- libuv.lib
|
||||
|
||||
@@ -13,6 +13,3 @@ libxslt:
|
||||
static-libs@unix:
|
||||
- libxslt.a
|
||||
- libexslt.a
|
||||
static-libs@windows:
|
||||
- libxslt_a.lib
|
||||
- libexslt_a.lib
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
mpir:
|
||||
type: library
|
||||
artifact:
|
||||
source:
|
||||
type: git
|
||||
url: 'https://github.com/winlibs/mpir.git'
|
||||
rev: master
|
||||
static-libs@windows:
|
||||
- mpir_a.lib
|
||||
@@ -4,12 +4,12 @@ openssl:
|
||||
source:
|
||||
type: ghrel
|
||||
repo: openssl/openssl
|
||||
match: openssl-3.+\.tar\.gz
|
||||
match: openssl.+\.tar\.gz
|
||||
prefer-stable: true
|
||||
source-mirror:
|
||||
type: filelist
|
||||
url: 'https://www.openssl.org/source/'
|
||||
regex: '/href="(?<file>openssl-(?<version>3\.[^"]+)\.tar\.gz)"/'
|
||||
regex: '/href="(?<file>openssl-(?<version>[^"]+)\.tar\.gz)"/'
|
||||
binary: hosted
|
||||
metadata:
|
||||
license-files: [LICENSE.txt]
|
||||
|
||||
@@ -10,4 +10,3 @@ pthreads4w:
|
||||
license: Apache-2.0
|
||||
static-libs@windows:
|
||||
- libpthreadVC3.lib
|
||||
- pthreadVC3.lib
|
||||
|
||||
@@ -15,13 +15,6 @@ snappy:
|
||||
- snappy-c.h
|
||||
- snappy-sinksource.h
|
||||
- snappy-stubs-public.h
|
||||
headers@windows:
|
||||
- snappy.h
|
||||
- snappy-c.h
|
||||
- snappy-sinksource.h
|
||||
- snappy-stubs-public.h
|
||||
lang: cpp
|
||||
static-libs@unix:
|
||||
- libsnappy.a
|
||||
static-libs@windows:
|
||||
- snappy.lib
|
||||
|
||||
@@ -10,5 +10,3 @@ tidy:
|
||||
license: W3C
|
||||
static-libs@unix:
|
||||
- libtidy.a
|
||||
static-libs@windows:
|
||||
- tidy_a.lib
|
||||
|
||||
@@ -8,8 +8,6 @@ watcher:
|
||||
metadata:
|
||||
license-files: [license]
|
||||
license: MIT
|
||||
frameworks:
|
||||
- CoreServices
|
||||
headers:
|
||||
- wtr/watcher-c.h
|
||||
lang: cpp
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
wineditline:
|
||||
type: library
|
||||
artifact:
|
||||
source:
|
||||
type: git
|
||||
url: 'https://github.com/winlibs/wineditline.git'
|
||||
rev: master
|
||||
metadata:
|
||||
license-files: [COPYING]
|
||||
license: GPL-2.0-or-later
|
||||
headers:
|
||||
- editline
|
||||
static-libs@windows:
|
||||
- edit_a.lib
|
||||
@@ -18,4 +18,4 @@ zstd:
|
||||
static-libs@unix:
|
||||
- libzstd.a
|
||||
static-libs@windows:
|
||||
- zstd.lib
|
||||
- zstd_static.lib
|
||||
|
||||
@@ -11,16 +11,8 @@ frankenphp:
|
||||
depends:
|
||||
- php-embed
|
||||
- go-xcaddy
|
||||
depends@windows:
|
||||
- php-embed
|
||||
- go-win
|
||||
- pthreads4w
|
||||
suggests@unix:
|
||||
- brotli
|
||||
- watcher
|
||||
suggests@windows:
|
||||
- brotli
|
||||
static-bins@unix:
|
||||
- frankenphp
|
||||
static-bins@windows:
|
||||
- frankenphp.exe
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
go-win:
|
||||
type: target
|
||||
artifact:
|
||||
binary: custom
|
||||
env:
|
||||
GOROOT: '{pkg_root_path}/go-win'
|
||||
GOBIN: '{pkg_root_path}/go-win/bin'
|
||||
GOPATH: '{pkg_root_path}/go-win/go'
|
||||
path@windows:
|
||||
- '{pkg_root_path}/go-win/bin'
|
||||
7
config/pre-built.json
Normal file
7
config/pre-built.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"repo": "static-php/static-php-cli-hosted",
|
||||
"prefer-stable": true,
|
||||
"match-pattern-linux": "{name}-{arch}-{os}-{libc}-{libcver}.txz",
|
||||
"match-pattern-macos": "{name}-{arch}-{os}.txz",
|
||||
"match-pattern-windows": "{name}-{arch}-{os}.tgz"
|
||||
}
|
||||
1296
config/source.json
Normal file
1296
config/source.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,9 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="missing" class="warning custom-block" style="margin-bottom: 16px">
|
||||
<p class="custom-block-title">WARNING</p>
|
||||
<p>Extension list is not generated yet. Run <code>bin/spc dev:gen-ext-docs</code> to generate it.</p>
|
||||
</div>
|
||||
|
||||
<h2>{{ I18N[lang].selectedSystem }}</h2>
|
||||
<div class="option-line">
|
||||
<span v-for="(item, index) in osList" :key="index" style="margin-right: 8px">
|
||||
<input type="radio" :id="'os-' + item.os" :value="item.os" v-model="selectedSystem" />
|
||||
<input type="radio" :id="'os-' + item.os" :value="item.os" :disabled="item.disabled === true" v-model="selectedSystem" />
|
||||
<label :for="'os-' + item.os">{{ item.label }}</label>
|
||||
</span>
|
||||
</div>
|
||||
@@ -18,14 +13,13 @@
|
||||
<option value="aarch64" :disabled="selectedSystem === 'windows'">aarch64</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<h2>{{ I18N[lang].selectExt }}{{ checkedExts.length > 0 ? (' (' + checkedExts.length + ')') : '' }}</h2>
|
||||
<div class="box">
|
||||
<input class="input" v-model="filterText" :placeholder="I18N[lang].searchPlaceholder" />
|
||||
<br>
|
||||
<div v-for="item in extByOS" :key="item" class="ext-item">
|
||||
<div v-for="item in extFilter" :key="item" class="ext-item">
|
||||
<span>
|
||||
<input type="checkbox" :id="item" :value="item" v-model="checkedExts" />
|
||||
<input type="checkbox" :id="item" :value="item" v-model="checkedExts" :disabled="extDisableList.indexOf(item) !== -1">
|
||||
<label :for="item">
|
||||
<span>{{ highlightItem(item, 0) }}</span>
|
||||
<span style="color: orangered; font-weight: bolder">{{ highlightItem(item, 1) }}</span>
|
||||
@@ -38,31 +32,50 @@
|
||||
<div class="my-btn" v-if="selectedSystem !== 'windows'" @click="selectAll">{{ I18N[lang].selectAll }}</div>
|
||||
<div class="my-btn" @click="checkedExts = []">{{ I18N[lang].selectNone }}</div>
|
||||
|
||||
<details class="details custom-block" open>
|
||||
<summary>{{ I18N[lang].buildLibs }}{{ checkedLibs.length > 0 ? (' (' + checkedLibs.length + ')') : '' }}</summary>
|
||||
<div class="box">
|
||||
<div v-for="(item, index) in libContain" :key="index" class="ext-item">
|
||||
<input type="checkbox" :id="index" :value="item" v-model="checkedLibs" :disabled="libDisableList.indexOf(item) !== -1">
|
||||
<label :for="index">{{ item }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
<div class="tip custom-block">
|
||||
<p class="custom-block-title">TIP</p>
|
||||
<p>{{ I18N[lang].depTips }}</p>
|
||||
<p>{{ I18N[lang].depTips2 }}</p>
|
||||
</div>
|
||||
<h2>{{ I18N[lang].buildTarget }}</h2>
|
||||
<div class="box">
|
||||
<div v-for="item in TARGET" :key="item" class="ext-item">
|
||||
<input type="checkbox" :id="'build_' + item" :value="item" v-model="checkedTargets" />
|
||||
<input type="checkbox" :id="'build_' + item" :value="item" v-model="checkedTargets" @change="onTargetChange">
|
||||
<label :for="'build_' + item">{{ item }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="selectedSystem === 'windows' && (checkedTargets.includes('fpm') || checkedTargets.includes('embed') || checkedTargets.includes('frankenphp'))" class="warning custom-block">
|
||||
<div v-if="selectedPhpVersion === '7.4' && (checkedTargets.indexOf('micro') !== -1 || checkedTargets.indexOf('all') !== -1)" class="warning custom-block">
|
||||
<p class="custom-block-title">WARNING</p>
|
||||
<p>{{ I18N[lang].microUnavailable }}</p>
|
||||
</div>
|
||||
<div v-if="selectedSystem === 'windows' && (checkedTargets.indexOf('fpm') !== -1 || checkedTargets.indexOf('embed') !== -1 || checkedTargets.indexOf('frankenphp') !== -1)" class="warning custom-block">
|
||||
<p class="custom-block-title">WARNING</p>
|
||||
<p>{{ I18N[lang].windowsSAPIUnavailable }}</p>
|
||||
</div>
|
||||
|
||||
<h2>{{ I18N[lang].buildOptions }}</h2>
|
||||
<!-- Refactor all build options in table -->
|
||||
<table>
|
||||
<!-- Build Environment -->
|
||||
<!-- buildEnvironment -->
|
||||
<tr>
|
||||
<td>{{ I18N[lang].buildEnvironment }}</td>
|
||||
<td>
|
||||
<select v-model="selectedEnv">
|
||||
<option value="spc">{{ I18N[lang].buildEnvSpc }}</option>
|
||||
<option value="native">{{ I18N[lang].buildEnvNative }}</option>
|
||||
<option value="spc">{{ I18N[lang].buildEnvSpc }}</option>
|
||||
<option value="docker" v-if="selectedSystem !== 'windows'">{{ I18N[lang].buildEnvDocker }}</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- PHP Version -->
|
||||
<!-- Download PHP version -->
|
||||
<tr>
|
||||
<td>{{ I18N[lang].downloadPhpVersion }}</td>
|
||||
<td>
|
||||
@@ -71,85 +84,70 @@
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Verbose log -->
|
||||
<!-- Enable debug message -->
|
||||
<tr>
|
||||
<td>{{ I18N[lang].useVerbose }}</td>
|
||||
<td>{{ I18N[lang].useDebug }}</td>
|
||||
<td>
|
||||
<select v-model="verbosity">
|
||||
<option value="">{{ I18N[lang].verboseNone }}</option>
|
||||
<option value="-v">-v</option>
|
||||
<option value="-vv">-vv</option>
|
||||
<option value="-vvv">-vvv</option>
|
||||
</select>
|
||||
<input type="radio" id="debug-yes" :value="1" v-model="debug" />
|
||||
<label for="debug-yes">{{ I18N[lang].yes }}</label>
|
||||
<input type="radio" id="debug-no" :value="0" v-model="debug" />
|
||||
<label for="debug-no">{{ I18N[lang].no }}</label>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Enable ZTS -->
|
||||
<tr>
|
||||
<td>{{ I18N[lang].useZTS }}</td>
|
||||
<td>
|
||||
<input type="radio" id="zts-yes" :value="true" v-model="zts" />
|
||||
<input type="radio" id="zts-yes" :value="1" v-model="zts" />
|
||||
<label for="zts-yes">{{ I18N[lang].yes }}</label>
|
||||
<input type="radio" id="zts-no" :value="false" v-model="zts" />
|
||||
<input type="radio" id="zts-no" :value="0" v-model="zts" />
|
||||
<label for="zts-no">{{ I18N[lang].no }}</label>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Parallel downloads -->
|
||||
<!-- download corresponding extensions -->
|
||||
<tr>
|
||||
<td>{{ I18N[lang].dlParallel }}</td>
|
||||
<td>{{ I18N[lang].resultShowDownload }}</td>
|
||||
<td>
|
||||
<input class="number-input" type="number" v-model.number="dlParallel" min="1" max="50" />
|
||||
<input type="radio" id="show-download-yes" :value="1" v-model="downloadByExt" />
|
||||
<label for="show-download-yes">{{ I18N[lang].yes }}</label>
|
||||
<input type="radio" id="show-download-no" :value="0" v-model="downloadByExt" />
|
||||
<label for="show-download-no">{{ I18N[lang].no }}</label>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Retry count -->
|
||||
<tr>
|
||||
<td>{{ I18N[lang].dlRetry }}</td>
|
||||
<td>
|
||||
<input class="number-input" type="number" v-model.number="dlRetry" min="0" max="100" />
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Prefer binary (pre-built) -->
|
||||
<!-- Download pre-built -->
|
||||
<tr>
|
||||
<td>{{ I18N[lang].usePreBuilt }}</td>
|
||||
<td>
|
||||
<input type="radio" id="pre-built-yes" :value="true" v-model="preBuilt" />
|
||||
<input type="radio" id="pre-built-yes" :value="1" v-model="preBuilt" />
|
||||
<label for="pre-built-yes">{{ I18N[lang].yes }}</label>
|
||||
<input type="radio" id="pre-built-no" :value="false" v-model="preBuilt" />
|
||||
<input type="radio" id="pre-built-no" :value="0" v-model="preBuilt" />
|
||||
<label for="pre-built-no">{{ I18N[lang].no }}</label>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Enable UPX (linux/windows only) -->
|
||||
<!-- Enable UPX -->
|
||||
<tr v-if="selectedSystem !== 'macos'">
|
||||
<td>{{ I18N[lang].useUPX }}</td>
|
||||
<td>
|
||||
<input type="radio" id="upx-yes" :value="true" v-model="enableUPX" />
|
||||
<input type="radio" id="upx-yes" :value="1" v-model="enableUPX" />
|
||||
<label for="upx-yes">{{ I18N[lang].yes }}</label>
|
||||
<input type="radio" id="upx-no" :value="false" v-model="enableUPX" />
|
||||
<input type="radio" id="upx-no" :value="0" v-model="enableUPX" />
|
||||
<label for="upx-no">{{ I18N[lang].no }}</label>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Keep debug symbols (--no-strip) -->
|
||||
<tr>
|
||||
<td>{{ I18N[lang].noStrip }}</td>
|
||||
<td>
|
||||
<input type="radio" id="nostrip-yes" :value="true" v-model="noStrip" />
|
||||
<label for="nostrip-yes">{{ I18N[lang].yes }}</label>
|
||||
<input type="radio" id="nostrip-no" :value="false" v-model="noStrip" />
|
||||
<label for="nostrip-no">{{ I18N[lang].no }}</label>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2>{{ I18N[lang].hardcodedINI }}</h2>
|
||||
<textarea class="textarea" :placeholder="I18N[lang].hardcodedINIPlaceholder" v-model="hardcodedINIData" rows="5" />
|
||||
|
||||
<textarea class="textarea" :placeholder="I18N[lang].hardcodedINIPlacehoder" v-model="hardcodedINIData" rows="5" />
|
||||
<h2>{{ I18N[lang].resultShow }}</h2>
|
||||
|
||||
<!-- SPC Binary Download Command (spc env only) -->
|
||||
<!-- SPC Binary Download Command -->
|
||||
<div v-if="selectedEnv === 'spc'" class="command-container">
|
||||
<b>{{ I18N[lang].downloadSPCBinaryCommand }}</b>
|
||||
<div v-if="selectedSystem !== 'windows'" class="command-preview">
|
||||
<div class="command-content">{{ spcDownloadCommand }}</div>
|
||||
<button class="copy-btn" @click="copyToClipboard(spcDownloadCommand, 'spcDownload')" :class="{ 'copied': copiedStates.spcDownload }">
|
||||
<div class="command-content">
|
||||
{{ spcDownloadCommand }}
|
||||
</div>
|
||||
<button class="copy-btn" @click="copyToClipboard(spcDownloadCommand)" :class="{ 'copied': copiedStates.spcDownload }">
|
||||
{{ copiedStates.spcDownload ? I18N[lang].copied : I18N[lang].copy }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -157,17 +155,56 @@
|
||||
<div class="warning custom-block">
|
||||
<p class="custom-block-title">WARNING</p>
|
||||
<p>{{ I18N[lang].windowsDownSPCWarning }}</p>
|
||||
<a href="https://dl.static-php.dev/v3/spc-bin/latest/spc-windows-x86_64.exe" target="_blank">https://dl.static-php.dev/v3/spc-bin/latest/spc-windows-x86_64.exe</a>
|
||||
<a href="https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe" target="_blank">https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Download Commands -->
|
||||
<div v-if="downloadByExt" class="command-container">
|
||||
<b>{{ I18N[lang].downloadExtOnlyCommand }}</b>
|
||||
<div class="command-preview">
|
||||
<div class="command-content">
|
||||
{{ downloadExtCommand }}
|
||||
</div>
|
||||
<button class="copy-btn" @click="copyToClipboard(downloadExtCommand)" :class="{ 'copied': copiedStates.downloadExt }">
|
||||
{{ copiedStates.downloadExt ? I18N[lang].copied : I18N[lang].copy }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="command-container">
|
||||
<b>{{ I18N[lang].downloadAllCommand }}</b>
|
||||
<div class="command-preview">
|
||||
<div class="command-content">
|
||||
{{ downloadAllCommand }}
|
||||
</div>
|
||||
<button class="copy-btn" @click="copyToClipboard(downloadAllCommand)" :class="{ 'copied': copiedStates.downloadAll }">
|
||||
{{ copiedStates.downloadAll ? I18N[lang].copied : I18N[lang].copy }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- UPX Download Command -->
|
||||
<div class="command-container" v-if="enableUPX">
|
||||
<b>{{ I18N[lang].downloadUPXCommand }}</b>
|
||||
<div class="command-preview">
|
||||
<div class="command-content">
|
||||
{{ downloadPkgCommand }}
|
||||
</div>
|
||||
<button class="copy-btn" @click="copyToClipboard(downloadPkgCommand)" :class="{ 'copied': copiedStates.downloadPkg }">
|
||||
{{ copiedStates.downloadPkg ? I18N[lang].copied : I18N[lang].copy }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Doctor Command -->
|
||||
<div class="command-container">
|
||||
<b>{{ I18N[lang].doctorCommand }}</b>
|
||||
<div class="command-preview">
|
||||
<div class="command-content">{{ doctorCommandString }}</div>
|
||||
<button class="copy-btn" @click="copyToClipboard(doctorCommandString, 'doctor')" :class="{ 'copied': copiedStates.doctor }">
|
||||
<div class="command-content">
|
||||
{{ doctorCommandString }}
|
||||
</div>
|
||||
<button class="copy-btn" @click="copyToClipboard(doctorCommandString)" :class="{ 'copied': copiedStates.doctor }">
|
||||
{{ copiedStates.doctor ? I18N[lang].copied : I18N[lang].copy }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -177,19 +214,23 @@
|
||||
<div class="command-container">
|
||||
<b>{{ I18N[lang].compileCommand }}</b>
|
||||
<div class="command-preview">
|
||||
<div class="command-content">{{ buildCommandString }}</div>
|
||||
<button class="copy-btn" @click="copyToClipboard(buildCommandString, 'build')" :class="{ 'copied': copiedStates.build }">
|
||||
<div class="command-content">
|
||||
{{ buildCommandString }}
|
||||
</div>
|
||||
<button class="copy-btn" @click="copyToClipboard(buildCommandString)" :class="{ 'copied': copiedStates.build }">
|
||||
{{ copiedStates.build ? I18N[lang].copied : I18N[lang].copy }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- craft.yml -->
|
||||
<!-- Craft.yml -->
|
||||
<div class="command-container">
|
||||
<b>craft.yml</b>
|
||||
<div class="command-preview pre">
|
||||
<div class="command-content">{{ craftCommandString }}</div>
|
||||
<button class="copy-btn" @click="copyToClipboard(craftCommandString, 'craft')" :class="{ 'copied': copiedStates.craft }">
|
||||
<div class="command-content">
|
||||
{{ craftCommandString }}
|
||||
</div>
|
||||
<button class="copy-btn" @click="copyToClipboard(craftCommandString)" :class="{ 'copied': copiedStates.craft }">
|
||||
{{ copiedStates.craft ? I18N[lang].copied : I18N[lang].copy }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -204,12 +245,14 @@ export default {
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue';
|
||||
// @ts-ignore VitePress data loader — transformed at build time
|
||||
import { data as extDataRaw } from '../extensions.data.js';
|
||||
import {computed, ref, watch} from "vue";
|
||||
import extData from '../config/ext.json';
|
||||
import libData from '../config/lib.json';
|
||||
import { getAllExtLibsByDeps } from './DependencyUtil.js';
|
||||
|
||||
// Constants
|
||||
const TARGET = ['cli', 'fpm', 'micro', 'embed', 'frankenphp', 'cgi'];
|
||||
const OS_MAP = new Map([['linux', 'Linux'], ['macos', 'Darwin'], ['windows', 'Windows']]);
|
||||
const TARGET = ['cli', 'fpm', 'micro', 'embed', 'frankenphp', 'all'];
|
||||
const availablePhpVersions = ['8.0', '8.1', '8.2', '8.3', '8.4', '8.5'];
|
||||
|
||||
// Props
|
||||
@@ -220,135 +263,154 @@ const props = defineProps({
|
||||
}
|
||||
});
|
||||
|
||||
// Extension data
|
||||
const missing = extDataRaw.missing ?? false;
|
||||
const allExtensions: Array<{ name: string; linux: boolean; macos: boolean; windows: boolean }> = extDataRaw.extensions ?? [];
|
||||
|
||||
// Reactive state
|
||||
// Reactive data
|
||||
const ext = ref(extData);
|
||||
const lib = ref(libData);
|
||||
const libContain = ref([]);
|
||||
const filterText = ref('');
|
||||
const checkedExts = ref<string[]>([]);
|
||||
const checkedTargets = ref<string[]>(['cli']);
|
||||
const selectedEnv = ref<'spc' | 'native'>('spc');
|
||||
const checkedExts = ref([]);
|
||||
const checkedLibs = ref([]);
|
||||
const extDisableList = ref([]);
|
||||
const libDisableList = ref([]);
|
||||
const checkedTargets = ref(['cli']);
|
||||
const selectedEnv = ref('spc');
|
||||
const selectedPhpVersion = ref('8.4');
|
||||
const selectedSystem = ref<'linux' | 'macos' | 'windows'>('linux');
|
||||
const selectedArch = ref<'x86_64' | 'aarch64'>('x86_64');
|
||||
const verbosity = ref('');
|
||||
const zts = ref(false);
|
||||
const preBuilt = ref(true);
|
||||
const enableUPX = ref(false);
|
||||
const noStrip = ref(false);
|
||||
const dlParallel = ref(10);
|
||||
const dlRetry = ref(5);
|
||||
const selectedSystem = ref('linux');
|
||||
const selectedArch = ref('x86_64');
|
||||
const debug = ref(0);
|
||||
const zts = ref(0);
|
||||
const downloadByExt = ref(1);
|
||||
const preBuilt = ref(1);
|
||||
const enableUPX = ref(0);
|
||||
const hardcodedINIData = ref('');
|
||||
const buildCommand = ref('--build-cli');
|
||||
|
||||
// Copy states
|
||||
const copiedStates = ref<Record<string, boolean>>({
|
||||
const copiedStates = ref({
|
||||
spcDownload: false,
|
||||
doctor: false,
|
||||
downloadExt: false,
|
||||
downloadAll: false,
|
||||
downloadPkg: false,
|
||||
build: false,
|
||||
craft: false,
|
||||
doctor: false
|
||||
});
|
||||
|
||||
// OS list
|
||||
const osList = [
|
||||
{ os: 'linux', label: 'Linux' },
|
||||
{ os: 'macos', label: 'macOS' },
|
||||
{ os: 'windows', label: 'Windows' },
|
||||
{ os: 'linux', label: 'Linux', disabled: false },
|
||||
{ os: 'macos', label: 'macOS', disabled: false },
|
||||
{ os: 'windows', label: 'Windows', disabled: false },
|
||||
];
|
||||
|
||||
// Computed: extensions filtered by selected OS
|
||||
const extByOS = computed(() => {
|
||||
return allExtensions
|
||||
.filter(item => {
|
||||
if (selectedSystem.value === 'linux') return item.linux;
|
||||
if (selectedSystem.value === 'macos') return item.macos;
|
||||
if (selectedSystem.value === 'windows') return item.windows;
|
||||
return true;
|
||||
})
|
||||
.map(item => item.name);
|
||||
// Computed properties
|
||||
const extFilter = computed(() => {
|
||||
return Object.entries(ext.value)
|
||||
.filter(([name]) => isSupported(name, selectedSystem.value))
|
||||
.map(([name]) => name);
|
||||
});
|
||||
|
||||
const extList = computed(() => [...checkedExts.value].sort().join(','));
|
||||
const extList = computed(() => checkedExts.value.join(','));
|
||||
|
||||
const additionalLibs = computed(() => {
|
||||
const ls = checkedLibs.value.filter(item => libDisableList.value.indexOf(item) === -1);
|
||||
return ls.length > 0 ? ` --with-libs="${ls.join(',')}"` : '';
|
||||
});
|
||||
|
||||
const spcCommand = computed(() => {
|
||||
if (selectedEnv.value === 'native') return 'bin/spc';
|
||||
return selectedSystem.value === 'windows' ? '.\\spc.exe' : './spc';
|
||||
switch (selectedEnv.value) {
|
||||
case 'native':
|
||||
return 'bin/spc';
|
||||
case 'spc':
|
||||
return selectedSystem.value === 'windows' ? '.\\spc.exe' : './spc';
|
||||
case 'docker':
|
||||
return 'bin/spc-alpine-docker';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
const spcDownloadCommand = computed(() => {
|
||||
const os = selectedSystem.value === 'macos' ? 'macos' : 'linux';
|
||||
const arch = selectedArch.value;
|
||||
return `curl -#fSL https://dl.static-php.dev/v3/spc-bin/latest/spc-${os}-${arch} -o spc && chmod +x spc`;
|
||||
if (selectedSystem.value === 'windows') return '';
|
||||
return `curl -fsSL -o spc.tgz https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-${selectedSystem.value}-${selectedArch.value}.tar.gz && tar -zxvf spc.tgz && rm spc.tgz`;
|
||||
});
|
||||
|
||||
const doctorCommandString = computed(() => `${spcCommand.value} doctor --auto-fix`);
|
||||
|
||||
const displayINI = computed(() => {
|
||||
const lines = hardcodedINIData.value.split('\n').filter(x => x.indexOf('=') >= 1);
|
||||
return lines.length > 0 ? ' ' + lines.map(x => `-I "${x}"`).join(' ') : '';
|
||||
const split = hardcodedINIData.value.split('\n');
|
||||
const validLines = split.filter(x => x.indexOf('=') >= 1);
|
||||
return validLines.length > 0 ? ' ' + validLines.map(x => `-I "${x}"`).join(' ') : '';
|
||||
});
|
||||
|
||||
const downloadAllCommand = computed(() => {
|
||||
return `${spcCommand.value} download --all --with-php=${selectedPhpVersion.value}${preBuilt.value ? ' --prefer-pre-built' : ''}${debug.value ? ' --debug' : ''}`;
|
||||
});
|
||||
|
||||
const downloadExtCommand = computed(() => {
|
||||
return `${spcCommand.value} download --with-php=${selectedPhpVersion.value} --for-extensions "${extList.value}"${preBuilt.value ? ' --prefer-pre-built' : ''}${debug.value ? ' --debug' : ''}`;
|
||||
});
|
||||
|
||||
const downloadPkgCommand = computed(() => {
|
||||
return `${spcCommand.value} install-pkg upx${debug.value ? ' --debug' : ''}`;
|
||||
});
|
||||
|
||||
const doctorCommandString = computed(() => {
|
||||
return `${spcCommand.value} doctor --auto-fix${debug.value ? ' --debug' : ''}`;
|
||||
});
|
||||
|
||||
const buildCommandString = computed(() => {
|
||||
const sapi = checkedTargets.value.map(x => `--build-${x}`).join(' ');
|
||||
const php = ` --dl-with-php=${selectedPhpVersion.value}`;
|
||||
const parallel = ` --dl-parallel=${dlParallel.value}`;
|
||||
const retry = ` --dl-retry=${dlRetry.value}`;
|
||||
const ignoreCache = ' --dl-ignore-cache=php-src';
|
||||
const binary = preBuilt.value ? ' --dl-prefer-binary' : '';
|
||||
const strip = noStrip.value ? ' --no-strip' : '';
|
||||
const upx = enableUPX.value ? ' --with-upx-pack' : '';
|
||||
const ztsFlag = zts.value ? ' --enable-zts' : '';
|
||||
const verbose = verbosity.value ? ` ${verbosity.value}` : '';
|
||||
return `${spcCommand.value} build:php "${extList.value}" ${sapi}${php}${parallel}${retry}${ignoreCache}${binary}${strip}${upx}${ztsFlag}${displayINI.value}${verbose}`;
|
||||
return `${spcCommand.value} build ${buildCommand.value} "${extList.value}"${additionalLibs.value}${debug.value ? ' --debug' : ''}${zts.value ? ' --enable-zts' : ''}${enableUPX.value ? ' --with-upx-pack' : ''}${displayINI.value}`;
|
||||
});
|
||||
|
||||
const craftCommandString = computed(() => {
|
||||
let str = `php-version: ${selectedPhpVersion.value}\n`;
|
||||
str += `extensions: "${extList.value}"\n`;
|
||||
|
||||
// sapi
|
||||
if (checkedTargets.value.length === 1) {
|
||||
str += `sapi:\n - ${checkedTargets.value[0]}\n`;
|
||||
if (checkedTargets.value.join(',') === 'all') {
|
||||
str += 'sapi: ' + ['cli', 'fpm', 'micro', 'embed', 'frankenphp'].join(',') + '\n';
|
||||
} else {
|
||||
str += `sapi:\n`;
|
||||
checkedTargets.value.forEach(s => { str += ` - ${s}\n`; });
|
||||
str += `sapi: ${checkedTargets.value.join(',')}\n`;
|
||||
}
|
||||
|
||||
// verbosity (Symfony OutputInterface constants: 64=-v, 128=-vv, 256=-vvv)
|
||||
const verbosityMap: Record<string, number> = { '-v': 64, '-vv': 128, '-vvv': 256 };
|
||||
if (verbosity.value && verbosityMap[verbosity.value]) {
|
||||
str += `verbosity: ${verbosityMap[verbosity.value]}\n`;
|
||||
if (additionalLibs.value) {
|
||||
str += `libs: ${additionalLibs.value.replace('--with-libs="', '').replace('"', '').trim()}\n`;
|
||||
}
|
||||
|
||||
// download-options
|
||||
str += `download-options:\n`;
|
||||
str += ` parallel: ${dlParallel.value}\n`;
|
||||
str += ` retry: ${dlRetry.value}\n`;
|
||||
str += ` ignore-cache: php-src\n`;
|
||||
if (preBuilt.value) str += ` prefer-binary: true\n`;
|
||||
|
||||
// build-options (only when needed)
|
||||
const buildOpts: string[] = [];
|
||||
if (noStrip.value) buildOpts.push(` no-strip: true`);
|
||||
if (enableUPX.value) buildOpts.push(` with-upx-pack: true`);
|
||||
if (zts.value) buildOpts.push(` enable-zts: true`);
|
||||
|
||||
const iniLines = hardcodedINIData.value.split('\n').filter(x => x.indexOf('=') >= 1);
|
||||
if (iniLines.length > 0) {
|
||||
buildOpts.push(` with-hardcoded-ini:`);
|
||||
iniLines.forEach(line => buildOpts.push(` - "${line}"`));
|
||||
if (debug.value) {
|
||||
str += 'debug: true\n';
|
||||
}
|
||||
|
||||
if (buildOpts.length > 0) {
|
||||
str += `build-options:\n${buildOpts.join('\n')}\n`;
|
||||
if (preBuilt.value) {
|
||||
str += 'download-options:\n';
|
||||
str += ' prefer-pre-built: true\n';
|
||||
}
|
||||
|
||||
str += '{{position_hold}}';
|
||||
|
||||
if (enableUPX.value) {
|
||||
str += ' with-upx-pack: true\n';
|
||||
}
|
||||
if (zts.value) {
|
||||
str += ' enable-zts: true\n';
|
||||
}
|
||||
|
||||
if (!str.endsWith('{{position_hold}}')) {
|
||||
str = str.replace('{{position_hold}}', 'build-options:\n');
|
||||
} else {
|
||||
str = str.replace('{{position_hold}}', '');
|
||||
}
|
||||
|
||||
return str;
|
||||
});
|
||||
|
||||
// Methods
|
||||
const isSupported = (extName: string, os: string) => {
|
||||
const osName = OS_MAP.get(os);
|
||||
const osSupport = ext.value[extName]?.support?.[osName] ?? 'yes';
|
||||
return osSupport === 'yes' || osSupport === 'partial';
|
||||
};
|
||||
|
||||
const selectCommon = () => {
|
||||
const common = [
|
||||
checkedExts.value = [
|
||||
'apcu', 'bcmath', 'calendar', 'ctype', 'curl', 'dba', 'dom', 'exif',
|
||||
'filter', 'fileinfo', 'gd', 'iconv', 'intl', 'mbstring', 'mbregex',
|
||||
'mysqli', 'mysqlnd', 'openssl', 'opcache', 'pcntl', 'pdo', 'pdo_mysql',
|
||||
@@ -356,18 +418,30 @@ const selectCommon = () => {
|
||||
'session', 'simplexml', 'sockets', 'sodium', 'sqlite3', 'tokenizer',
|
||||
'xml', 'xmlreader', 'xmlwriter', 'xsl', 'zip', 'zlib',
|
||||
];
|
||||
const supported = new Set(extByOS.value);
|
||||
checkedExts.value = common.filter(e => supported.has(e));
|
||||
};
|
||||
|
||||
const selectAll = () => {
|
||||
checkedExts.value = [...extByOS.value];
|
||||
checkedExts.value = [...extFilter.value];
|
||||
};
|
||||
|
||||
const onTargetChange = (event: Event) => {
|
||||
const target = (event.target as HTMLInputElement).value;
|
||||
if (target === 'all') {
|
||||
checkedTargets.value = ['all'];
|
||||
} else {
|
||||
const allIndex = checkedTargets.value.indexOf('all');
|
||||
if (allIndex !== -1) {
|
||||
checkedTargets.value.splice(allIndex, 1);
|
||||
}
|
||||
}
|
||||
buildCommand.value = checkedTargets.value.map(x => `--build-${x}`).join(' ');
|
||||
};
|
||||
|
||||
const highlightItem = (item: string, step: number) => {
|
||||
if (!filterText.value || !item.includes(filterText.value)) {
|
||||
return step === 0 ? item : '';
|
||||
}
|
||||
|
||||
const index = item.indexOf(filterText.value);
|
||||
switch (step) {
|
||||
case 0: return item.substring(0, index);
|
||||
@@ -377,12 +451,30 @@ const highlightItem = (item: string, step: number) => {
|
||||
}
|
||||
};
|
||||
|
||||
const copyToClipboard = async (text: string, key: string) => {
|
||||
const copyToClipboard = async (text: string) => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
copiedStates.value[key] = true;
|
||||
setTimeout(() => { copiedStates.value[key] = false; }, 2000);
|
||||
} catch {
|
||||
// Find which command was copied and update its state
|
||||
const commandMap = {
|
||||
[spcDownloadCommand.value]: 'spcDownload',
|
||||
[downloadExtCommand.value]: 'downloadExt',
|
||||
[downloadAllCommand.value]: 'downloadAll',
|
||||
[downloadPkgCommand.value]: 'downloadPkg',
|
||||
[doctorCommandString.value]: 'doctor',
|
||||
[buildCommandString.value]: 'build',
|
||||
[craftCommandString.value]: 'craft'
|
||||
};
|
||||
|
||||
const key = commandMap[text];
|
||||
if (key) {
|
||||
copiedStates.value[key] = true;
|
||||
setTimeout(() => {
|
||||
copiedStates.value[key] = false;
|
||||
}, 2000);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to copy text: ', err);
|
||||
// Fallback for older browsers
|
||||
const textArea = document.createElement('textarea');
|
||||
textArea.value = text;
|
||||
document.body.appendChild(textArea);
|
||||
@@ -392,17 +484,113 @@ const copyToClipboard = async (text: string, key: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
const calculateExtDepends = (input: string[]) => {
|
||||
const result = new Set<string>();
|
||||
|
||||
const dfs = (node: string) => {
|
||||
let depends: string[] = [];
|
||||
|
||||
if (selectedSystem.value === 'linux') {
|
||||
depends = ext.value[node]?.['ext-depends-linux'] ?? ext.value[node]?.['ext-depends-unix'] ?? ext.value[node]?.['ext-depends'] ?? [];
|
||||
} else if (selectedSystem.value === 'macos') {
|
||||
depends = ext.value[node]?.['ext-depends-macos'] ?? ext.value[node]?.['ext-depends-unix'] ?? ext.value[node]?.['ext-depends'] ?? [];
|
||||
} else if (selectedSystem.value === 'windows') {
|
||||
depends = ext.value[node]?.['ext-depends-windows'] ?? ext.value[node]?.['ext-depends'] ?? [];
|
||||
}
|
||||
|
||||
if (depends.length === 0) return;
|
||||
|
||||
depends.forEach(dep => {
|
||||
result.add(dep);
|
||||
dfs(dep);
|
||||
});
|
||||
};
|
||||
|
||||
input.forEach(dfs);
|
||||
return Array.from(result);
|
||||
};
|
||||
|
||||
const calculateExtLibDepends = (input: string[]) => {
|
||||
const result = new Set<string>();
|
||||
|
||||
const dfsLib = (node: string) => {
|
||||
let depends: string[] = [];
|
||||
|
||||
if (selectedSystem.value === 'linux') {
|
||||
depends = lib.value[node]?.['lib-depends-linux'] ?? lib.value[node]?.['lib-depends-unix'] ?? lib.value[node]?.['lib-depends'] ?? [];
|
||||
} else if (selectedSystem.value === 'macos') {
|
||||
depends = lib.value[node]?.['lib-depends-macos'] ?? lib.value[node]?.['lib-depends-unix'] ?? lib.value[node]?.['lib-depends'] ?? [];
|
||||
} else if (selectedSystem.value === 'windows') {
|
||||
depends = lib.value[node]?.['lib-depends-windows'] ?? lib.value[node]?.['lib-depends'] ?? [];
|
||||
}
|
||||
|
||||
if (depends.length === 0) return;
|
||||
|
||||
depends.forEach(dep => {
|
||||
result.add(dep);
|
||||
dfsLib(dep);
|
||||
});
|
||||
};
|
||||
|
||||
const dfsExt = (node: string) => {
|
||||
let depends: string[] = [];
|
||||
|
||||
if (selectedSystem.value === 'linux') {
|
||||
depends = ext.value[node]?.['lib-depends-linux'] ?? ext.value[node]?.['lib-depends-unix'] ?? ext.value[node]?.['lib-depends'] ?? [];
|
||||
} else if (selectedSystem.value === 'macos') {
|
||||
depends = ext.value[node]?.['lib-depends-macos'] ?? ext.value[node]?.['lib-depends-unix'] ?? ext.value[node]?.['lib-depends'] ?? [];
|
||||
} else if (selectedSystem.value === 'windows') {
|
||||
depends = ext.value[node]?.['lib-depends-windows'] ?? ext.value[node]?.['lib-depends'] ?? [];
|
||||
}
|
||||
|
||||
if (depends.length === 0) return;
|
||||
|
||||
depends.forEach(dep => {
|
||||
result.add(dep);
|
||||
dfsLib(dep);
|
||||
});
|
||||
};
|
||||
|
||||
input.forEach(dfsExt);
|
||||
return Array.from(result);
|
||||
};
|
||||
|
||||
// Watchers
|
||||
watch(selectedSystem, () => {
|
||||
if (selectedSystem.value === 'windows') {
|
||||
selectedArch.value = 'x86_64';
|
||||
enableUPX.value = false;
|
||||
}
|
||||
// Reset related values when OS changes
|
||||
checkedExts.value = [];
|
||||
enableUPX.value = 0;
|
||||
});
|
||||
|
||||
watch(checkedExts, (newValue) => {
|
||||
// Apply ext-depends
|
||||
extDisableList.value = calculateExtDepends(newValue);
|
||||
extDisableList.value.forEach(x => {
|
||||
if (checkedExts.value.indexOf(x) === -1) {
|
||||
checkedExts.value.push(x);
|
||||
}
|
||||
});
|
||||
|
||||
checkedExts.value.sort();
|
||||
|
||||
const calculated = getAllExtLibsByDeps({ ext: ext.value, lib: lib.value, os: selectedSystem.value }, checkedExts.value);
|
||||
libContain.value = calculated.libs.sort();
|
||||
|
||||
// Apply lib-depends
|
||||
checkedLibs.value = [];
|
||||
libDisableList.value = calculateExtLibDepends(calculated.exts);
|
||||
libDisableList.value.forEach(x => {
|
||||
if (checkedLibs.value.indexOf(x) === -1) {
|
||||
checkedLibs.value.push(x);
|
||||
}
|
||||
});
|
||||
}, { deep: true });
|
||||
|
||||
// I18N
|
||||
const I18N: Record<string, Record<string, string>> = {
|
||||
const I18N = {
|
||||
zh: {
|
||||
selectExt: '选择扩展',
|
||||
buildTarget: '选择编译目标',
|
||||
@@ -410,8 +598,8 @@ const I18N: Record<string, Record<string, string>> = {
|
||||
buildEnvironment: '编译环境',
|
||||
buildEnvNative: '本地构建(Git 源码)',
|
||||
buildEnvSpc: '本地构建(独立 spc 二进制)',
|
||||
useVerbose: '是否输出详细日志',
|
||||
verboseNone: '不输出(默认)',
|
||||
buildEnvDocker: 'Alpine Docker 构建',
|
||||
useDebug: '是否开启调试输出',
|
||||
yes: '是',
|
||||
no: '否',
|
||||
resultShow: '结果展示',
|
||||
@@ -420,22 +608,28 @@ const I18N: Record<string, Record<string, string>> = {
|
||||
selectNone: '全部取消选择',
|
||||
useZTS: '是否编译线程安全版',
|
||||
hardcodedINI: '硬编码 INI 选项',
|
||||
hardcodedINIPlaceholder: '如需要硬编码 ini,每行写一个,例如:memory_limit=2G',
|
||||
hardcodedINIPlacehoder: '如需要硬编码 ini,每行写一个,例如:memory_limit=2G',
|
||||
resultShowDownload: '是否展示仅下载对应扩展依赖的命令',
|
||||
downloadExtOnlyCommand: '只下载对应扩展的依赖包命令',
|
||||
downloadAllCommand: '下载所有依赖包命令',
|
||||
downloadUPXCommand: '下载 UPX 命令',
|
||||
compileCommand: '编译命令',
|
||||
downloadPhpVersion: '下载 PHP 版本',
|
||||
downloadSPCBinaryCommand: '下载 spc 二进制命令',
|
||||
selectedArch: '选择系统架构',
|
||||
selectedSystem: '选择操作系统',
|
||||
buildLibs: '要构建的库',
|
||||
depTips: '选择扩展后,不可选中的项目为必需的依赖,编译的依赖库列表中可选的为现有扩展和依赖库的可选依赖。选择可选依赖后,将生成 --with-libs 参数。',
|
||||
depTips2: '无法同时构建所有扩展,因为有些扩展之间相互冲突。请根据需要选择扩展。',
|
||||
microUnavailable: 'micro 不支持 PHP 7.4 及更早版本!',
|
||||
windowsSAPIUnavailable: 'Windows 目前不支持 fpm、embed、frankenphp 构建!',
|
||||
useUPX: '是否开启 UPX 压缩(减小二进制体积)',
|
||||
windowsDownSPCWarning: 'Windows 下请手动下载 spc.exe 二进制文件!',
|
||||
usePreBuilt: '如果可能,使用预编译的依赖库(减少编译时间)',
|
||||
windowsDownSPCWarning: 'Windows 下请手动下载 spc.exe 二进制文件,解压到当前目录并重命名为 spc.exe!',
|
||||
usePreBuilt: '如果可能,下载预编译的依赖库(减少编译时间)',
|
||||
searchPlaceholder: '搜索扩展...',
|
||||
copy: '复制',
|
||||
copied: '已复制',
|
||||
doctorCommand: '自动检查和准备构建环境命令',
|
||||
dlParallel: '并行下载数(1-50)',
|
||||
dlRetry: '失败重试次数',
|
||||
noStrip: '保留调试符号(--no-strip)',
|
||||
},
|
||||
en: {
|
||||
selectExt: 'Select Extensions',
|
||||
@@ -444,58 +638,43 @@ const I18N: Record<string, Record<string, string>> = {
|
||||
buildEnvironment: 'Build Environment',
|
||||
buildEnvNative: 'Native build (Git source code)',
|
||||
buildEnvSpc: 'Native build (standalone spc binary)',
|
||||
useVerbose: 'Verbose log output',
|
||||
verboseNone: 'None (default)',
|
||||
buildEnvDocker: 'Alpine docker build',
|
||||
useDebug: 'Enable debug message',
|
||||
yes: 'Yes',
|
||||
no: 'No',
|
||||
resultShow: 'Result',
|
||||
selectCommon: 'Select common extensions',
|
||||
selectAll: 'Select all',
|
||||
selectNone: 'Unselect all',
|
||||
useZTS: 'Enable ZTS (thread-safe)',
|
||||
useZTS: 'Enable ZTS',
|
||||
hardcodedINI: 'Hardcoded INI options',
|
||||
hardcodedINIPlaceholder: 'If you need to hardcode ini, write one per line, for example: memory_limit=2G',
|
||||
compileCommand: 'Build command',
|
||||
downloadPhpVersion: 'PHP version',
|
||||
downloadSPCBinaryCommand: 'Download spc binary',
|
||||
selectedSystem: 'Select OS',
|
||||
hardcodedINIPlacehoder: 'If you need to hardcode ini, write one per line, for example: memory_limit=2G',
|
||||
resultShowDownload: 'Download with corresponding extension dependencies',
|
||||
downloadExtOnlyCommand: 'Download sources by extensions command',
|
||||
downloadAllCommand: 'Download all sources command',
|
||||
downloadUPXCommand: 'Download UPX command',
|
||||
compileCommand: 'Compile command',
|
||||
downloadPhpVersion: 'Download PHP version',
|
||||
downloadSPCBinaryCommand: 'Download spc binary command',
|
||||
selectedArch: 'Select build architecture',
|
||||
selectedSystem: 'Select Build OS',
|
||||
buildLibs: 'Select Dependencies',
|
||||
depTips: 'After selecting the extensions, the unselectable items are essential dependencies. In the compiled dependencies list, optional dependencies consist of existing extensions and optional dependencies of libraries. Optional dependencies will be added in --with-libs parameter.',
|
||||
depTips2: 'It is not possible to build all extensions at the same time, as some extensions conflict with each other. Please select the extensions you need.',
|
||||
microUnavailable: 'Micro does not support PHP 7.4 and earlier versions!',
|
||||
windowsSAPIUnavailable: 'Windows does not support fpm, embed and frankenphp build!',
|
||||
useUPX: 'Enable UPX compression (reduce binary size)',
|
||||
windowsDownSPCWarning: 'Please download the spc.exe binary manually on Windows!',
|
||||
usePreBuilt: 'Use pre-built dependencies where available (reduce compile time)',
|
||||
windowsDownSPCWarning: 'Please download the binary file manually, extract it to the current directory and rename to spc.exe on Windows!',
|
||||
usePreBuilt: 'Download pre-built dependencies if possible (reduce compile time)',
|
||||
searchPlaceholder: 'Search extensions...',
|
||||
copy: 'Copy',
|
||||
copied: 'Copied',
|
||||
doctorCommand: 'Auto-check and prepare build environment',
|
||||
dlParallel: 'Parallel downloads (1-50)',
|
||||
dlRetry: 'Retry count on failure',
|
||||
noStrip: 'Keep debug symbols (--no-strip)',
|
||||
doctorCommand: 'Auto-check and prepare build environment command',
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.number-input {
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
width: 80px;
|
||||
padding: 6px 10px;
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
color: var(--vp-c-text-1);
|
||||
font-size: 14px;
|
||||
outline: none;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.number-input:hover {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.number-input:focus {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
box-shadow: 0 0 0 3px var(--vp-c-brand-soft);
|
||||
}
|
||||
|
||||
.box {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@@ -1,589 +0,0 @@
|
||||
<template>
|
||||
<div class="deps-map">
|
||||
<!-- Warning if data missing -->
|
||||
<div v-if="missing" class="warning custom-block" style="margin-bottom: 16px">
|
||||
<p class="custom-block-title">WARNING</p>
|
||||
<p>Dependency data not generated yet. Run <code>bin/spc dev:gen-deps-data</code> to generate it.</p>
|
||||
</div>
|
||||
|
||||
<template v-else>
|
||||
<!-- Toolbar -->
|
||||
<div class="deps-toolbar">
|
||||
<input
|
||||
class="deps-search"
|
||||
v-model="searchText"
|
||||
:placeholder="i18n.searchPlaceholder"
|
||||
@input="selectedPkg = null"
|
||||
/>
|
||||
<div class="deps-filters">
|
||||
<div class="filter-group">
|
||||
<button
|
||||
v-for="t in typeOptions"
|
||||
:key="t.value"
|
||||
:class="['filter-btn', { active: selectedType === t.value }]"
|
||||
@click="selectedType = t.value; selectedPkg = null"
|
||||
>{{ t.label }}</button>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<button
|
||||
v-for="p in platformOptions"
|
||||
:key="p.value"
|
||||
:class="['filter-btn', { active: selectedPlatform === p.value }]"
|
||||
@click="selectedPlatform = p.value"
|
||||
>{{ p.label }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="deps-layout">
|
||||
<!-- Package list -->
|
||||
<div class="deps-list">
|
||||
<div v-if="filteredPackages.length === 0" class="no-results">{{ i18n.noResults }}</div>
|
||||
<div
|
||||
v-for="pkg in filteredPackages"
|
||||
:key="pkg.name"
|
||||
:class="['pkg-item', { selected: selectedPkg === pkg.name }]"
|
||||
@click="selectPkg(pkg.name)"
|
||||
>
|
||||
<span class="pkg-name">{{ pkg.name }}</span>
|
||||
<span :class="['pkg-badge', pkg.type === 'php-extension' ? 'badge-ext' : 'badge-lib']">
|
||||
{{ typeLabel(pkg.type) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Detail panel -->
|
||||
<div class="deps-detail" v-if="selectedPkg && selectedPkgData">
|
||||
<h3 class="detail-title">{{ selectedPkg }}</h3>
|
||||
<span :class="['detail-type-badge', selectedPkgData.type === 'php-extension' ? 'badge-ext' : 'badge-lib']">
|
||||
{{ typeLabel(selectedPkgData.type) }}
|
||||
</span>
|
||||
|
||||
<!-- OS support for extensions -->
|
||||
<div v-if="selectedPkgData.type === 'php-extension' && selectedPkgData.os" class="detail-section">
|
||||
<div class="detail-label">{{ i18n.supportedPlatforms }}</div>
|
||||
<div class="detail-chips">
|
||||
<span v-for="os in selectedPkgData.os" :key="os" class="chip chip-os">{{ os }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Required deps -->
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">{{ i18n.requiredDeps }}</div>
|
||||
<div class="detail-chips" v-if="currentDepends.length > 0">
|
||||
<span
|
||||
v-for="dep in currentDepends"
|
||||
:key="dep"
|
||||
:class="['chip', 'chip-required', { clickable: packages[dep] }]"
|
||||
@click="packages[dep] && selectPkg(dep)"
|
||||
>{{ dep }}</span>
|
||||
</div>
|
||||
<div v-else class="no-deps">{{ i18n.none }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Suggested deps -->
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">{{ i18n.suggestedDeps }}</div>
|
||||
<div class="detail-chips" v-if="currentSuggests.length > 0">
|
||||
<span
|
||||
v-for="dep in currentSuggests"
|
||||
:key="dep"
|
||||
:class="['chip', 'chip-suggested', { clickable: packages[dep] }]"
|
||||
@click="packages[dep] && selectPkg(dep)"
|
||||
>{{ dep }}</span>
|
||||
</div>
|
||||
<div v-else class="no-deps">{{ i18n.none }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Required by -->
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">{{ i18n.requiredBy }}</div>
|
||||
<div class="detail-chips" v-if="requiredBy.length > 0">
|
||||
<span
|
||||
v-for="dep in requiredBy"
|
||||
:key="dep"
|
||||
class="chip chip-rev clickable"
|
||||
@click="selectPkg(dep)"
|
||||
>{{ dep }}</span>
|
||||
</div>
|
||||
<div v-else class="no-deps">{{ i18n.none }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Suggested by -->
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">{{ i18n.suggestedBy }}</div>
|
||||
<div class="detail-chips" v-if="suggestedBy.length > 0">
|
||||
<span
|
||||
v-for="dep in suggestedBy"
|
||||
:key="dep"
|
||||
class="chip chip-rev-sug clickable"
|
||||
@click="selectPkg(dep)"
|
||||
>{{ dep }}</span>
|
||||
</div>
|
||||
<div v-else class="no-deps">{{ i18n.none }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Mermaid graph -->
|
||||
<div class="detail-section" v-if="hasMermaid">
|
||||
<div class="detail-label">{{ i18n.depGraph }}</div>
|
||||
<div ref="mermaidEl" class="mermaid-wrap"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Empty state -->
|
||||
<div class="deps-detail deps-detail-empty" v-else>
|
||||
<p>{{ i18n.selectHint }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch, onMounted, nextTick } from 'vue'
|
||||
import { useData } from 'vitepress'
|
||||
import { data as depsData } from '../deps-map.data.js'
|
||||
|
||||
const { lang, isDark } = useData()
|
||||
|
||||
const missing = depsData.missing
|
||||
const packages = depsData.packages ?? {}
|
||||
|
||||
// --- i18n ---
|
||||
const I18N = {
|
||||
zh: {
|
||||
searchPlaceholder: '搜索包名...',
|
||||
noResults: '未找到包。',
|
||||
selectHint: '← 选择一个包以查看其依赖关系。',
|
||||
supportedPlatforms: '支持的平台',
|
||||
requiredDeps: '必需依赖',
|
||||
suggestedDeps: '可选依赖',
|
||||
requiredBy: '被哪些包依赖',
|
||||
suggestedBy: '被哪些包建议',
|
||||
depGraph: '依赖关系图',
|
||||
none: '无',
|
||||
},
|
||||
en: {
|
||||
searchPlaceholder: 'Search package...',
|
||||
noResults: 'No packages found.',
|
||||
selectHint: '← Select a package to view its dependency details.',
|
||||
supportedPlatforms: 'Supported Platforms',
|
||||
requiredDeps: 'Required Dependencies',
|
||||
suggestedDeps: 'Suggested Dependencies',
|
||||
requiredBy: 'Required By',
|
||||
suggestedBy: 'Suggested By',
|
||||
depGraph: 'Dependency Graph',
|
||||
none: 'None',
|
||||
},
|
||||
}
|
||||
const i18n = computed(() => I18N[lang.value] ?? I18N.en)
|
||||
|
||||
// --- State ---
|
||||
const searchText = ref('')
|
||||
const selectedType = ref('all')
|
||||
const selectedPlatform = ref('linux')
|
||||
const selectedPkg = ref(null)
|
||||
const mermaidEl = ref(null)
|
||||
|
||||
// --- Options ---
|
||||
const typeOptions = computed(() => [
|
||||
{ value: 'all', label: lang.value === 'zh' ? '全部' : 'All' },
|
||||
{ value: 'php-extension', label: lang.value === 'zh' ? '扩展' : 'Extensions' },
|
||||
{ value: 'library', label: lang.value === 'zh' ? '库' : 'Libraries' },
|
||||
])
|
||||
const platformOptions = [
|
||||
{ value: 'linux', label: 'Linux' },
|
||||
{ value: 'macos', label: 'macOS' },
|
||||
{ value: 'windows', label: 'Windows' },
|
||||
]
|
||||
|
||||
function typeLabel(type) {
|
||||
if (type === 'php-extension') return 'ext'
|
||||
if (type === 'library') return 'lib'
|
||||
return type
|
||||
}
|
||||
|
||||
// --- Package list ---
|
||||
const allPackages = computed(() =>
|
||||
Object.entries(packages).map(([name, data]) => ({ name, ...data }))
|
||||
)
|
||||
|
||||
const filteredPackages = computed(() => {
|
||||
let list = allPackages.value
|
||||
if (selectedType.value !== 'all') {
|
||||
list = list.filter(p => p.type === selectedType.value)
|
||||
}
|
||||
if (searchText.value.trim()) {
|
||||
const q = searchText.value.trim().toLowerCase()
|
||||
list = list.filter(p => p.name.toLowerCase().includes(q))
|
||||
}
|
||||
return list
|
||||
})
|
||||
|
||||
// --- Selected package ---
|
||||
const selectedPkgData = computed(() =>
|
||||
selectedPkg.value ? (packages[selectedPkg.value] ?? null) : null
|
||||
)
|
||||
|
||||
const currentDepends = computed(() =>
|
||||
selectedPkgData.value?.platforms?.[selectedPlatform.value]?.depends ?? []
|
||||
)
|
||||
const currentSuggests = computed(() =>
|
||||
selectedPkgData.value?.platforms?.[selectedPlatform.value]?.suggests ?? []
|
||||
)
|
||||
|
||||
const requiredBy = computed(() => {
|
||||
if (!selectedPkg.value) return []
|
||||
const name = selectedPkg.value
|
||||
const plat = selectedPlatform.value
|
||||
return Object.entries(packages)
|
||||
.filter(([, d]) => (d.platforms?.[plat]?.depends ?? []).includes(name))
|
||||
.map(([n]) => n)
|
||||
})
|
||||
|
||||
const suggestedBy = computed(() => {
|
||||
if (!selectedPkg.value) return []
|
||||
const name = selectedPkg.value
|
||||
const plat = selectedPlatform.value
|
||||
return Object.entries(packages)
|
||||
.filter(([, d]) => (d.platforms?.[plat]?.suggests ?? []).includes(name))
|
||||
.map(([n]) => n)
|
||||
})
|
||||
|
||||
// --- Mermaid ---
|
||||
const hasMermaid = computed(
|
||||
() => currentDepends.value.length > 0 || currentSuggests.value.length > 0
|
||||
)
|
||||
|
||||
function buildMermaidCode() {
|
||||
const deps = currentDepends.value
|
||||
const sugs = currentSuggests.value
|
||||
if (deps.length === 0 && sugs.length === 0) return ''
|
||||
|
||||
const safe = s => s.replace(/[^a-zA-Z0-9_]/g, '_')
|
||||
const root = safe(selectedPkg.value)
|
||||
const lines = ['graph LR', ` ${root}["${selectedPkg.value}"]`]
|
||||
|
||||
const MAX_DEPTH = 6 // max hops from root
|
||||
const MAX_CHILDREN = 6 // per-node child limit for levels 2+
|
||||
|
||||
const visitedNodes = new Set([selectedPkg.value])
|
||||
const visitedEdges = new Set()
|
||||
const queue = []
|
||||
|
||||
// Level 1: direct required deps — solid arrows, no child limit
|
||||
for (const dep of deps) {
|
||||
const ek = `${selectedPkg.value}\0${dep}`
|
||||
if (!visitedEdges.has(ek)) {
|
||||
visitedEdges.add(ek)
|
||||
lines.push(` ${root} --> ${safe(dep)}["${dep}"]`)
|
||||
}
|
||||
if (!visitedNodes.has(dep)) {
|
||||
visitedNodes.add(dep)
|
||||
queue.push({ name: dep, depth: 1 })
|
||||
}
|
||||
}
|
||||
|
||||
// BFS: levels 2–MAX_DEPTH — dotted arrows, capped children per node
|
||||
while (queue.length > 0) {
|
||||
const { name, depth } = queue.shift()
|
||||
if (depth >= MAX_DEPTH) continue
|
||||
const children = packages[name]?.platforms?.[selectedPlatform.value]?.depends ?? []
|
||||
for (const child of children.slice(0, MAX_CHILDREN)) {
|
||||
const ek = `${name}\0${child}`
|
||||
if (!visitedEdges.has(ek)) {
|
||||
visitedEdges.add(ek)
|
||||
lines.push(` ${safe(name)} -.-> ${safe(child)}["${child}"]`)
|
||||
}
|
||||
if (!visitedNodes.has(child)) {
|
||||
visitedNodes.add(child)
|
||||
queue.push({ name: child, depth: depth + 1 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Suggested deps from root (single level, optional dotted)
|
||||
for (const sug of sugs) {
|
||||
lines.push(` ${root} -. optional .-> ${safe(sug)}["${sug}"]`)
|
||||
}
|
||||
|
||||
return lines.join('\n')
|
||||
}
|
||||
|
||||
let mermaidLib = null
|
||||
|
||||
async function renderMermaid() {
|
||||
if (!mermaidEl.value || !hasMermaid.value) return
|
||||
const code = buildMermaidCode()
|
||||
if (!code) return
|
||||
|
||||
try {
|
||||
if (!mermaidLib) {
|
||||
const m = await import('mermaid')
|
||||
mermaidLib = m.default
|
||||
}
|
||||
mermaidLib.initialize({
|
||||
startOnLoad: false,
|
||||
theme: isDark.value ? 'dark' : 'default',
|
||||
securityLevel: 'loose',
|
||||
})
|
||||
const id = 'deps-graph-' + Date.now()
|
||||
const { svg } = await mermaidLib.render(id, code)
|
||||
if (mermaidEl.value) {
|
||||
mermaidEl.value.innerHTML = svg
|
||||
}
|
||||
} catch {
|
||||
if (mermaidEl.value) {
|
||||
mermaidEl.value.innerHTML = `<pre class="mermaid-fallback">${code}</pre>`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function selectPkg(name) {
|
||||
selectedPkg.value = name
|
||||
}
|
||||
|
||||
watch([selectedPkg, selectedPlatform, isDark], async () => {
|
||||
await nextTick()
|
||||
await renderMermaid()
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick()
|
||||
await renderMermaid()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.deps-map {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Toolbar */
|
||||
.deps-toolbar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.deps-search {
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
background: var(--vp-c-bg);
|
||||
color: var(--vp-c-text-1);
|
||||
outline: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.deps-search:focus {
|
||||
border-color: var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.deps-filters {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.filter-group {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.filter-btn {
|
||||
padding: 4px 12px;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 20px;
|
||||
background: var(--vp-c-bg);
|
||||
color: var(--vp-c-text-2);
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
.filter-btn:hover {
|
||||
border-color: var(--vp-c-brand);
|
||||
color: var(--vp-c-brand);
|
||||
}
|
||||
.filter-btn.active {
|
||||
background: var(--vp-c-brand);
|
||||
border-color: var(--vp-c-brand);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Layout */
|
||||
.deps-layout {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
/* Package list */
|
||||
.deps-list {
|
||||
width: 260px;
|
||||
flex-shrink: 0;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
overflow-y: auto;
|
||||
max-height: 600px;
|
||||
}
|
||||
|
||||
.no-results {
|
||||
padding: 16px;
|
||||
color: var(--vp-c-text-3);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pkg-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
border-bottom: 1px solid var(--vp-c-divider);
|
||||
transition: background 0.1s;
|
||||
}
|
||||
.pkg-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
.pkg-item:hover {
|
||||
background: var(--vp-c-bg-soft);
|
||||
}
|
||||
.pkg-item.selected {
|
||||
background: var(--vp-c-brand-soft);
|
||||
}
|
||||
|
||||
.pkg-name {
|
||||
font-family: var(--vp-font-family-mono);
|
||||
font-size: 13px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.pkg-badge {
|
||||
font-size: 11px;
|
||||
padding: 1px 6px;
|
||||
border-radius: 10px;
|
||||
flex-shrink: 0;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
/* Detail panel */
|
||||
.deps-detail {
|
||||
flex: 1;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
max-height: 600px;
|
||||
}
|
||||
|
||||
.deps-detail-empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--vp-c-text-3);
|
||||
}
|
||||
|
||||
.detail-title {
|
||||
margin: 0 0 8px 0;
|
||||
font-size: 16px;
|
||||
font-family: var(--vp-font-family-mono);
|
||||
}
|
||||
|
||||
.detail-type-badge {
|
||||
font-size: 12px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 10px;
|
||||
display: inline-block;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.detail-section {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--vp-c-text-2);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.detail-chips {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.no-deps {
|
||||
color: var(--vp-c-text-3);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* Chips */
|
||||
.chip {
|
||||
font-family: var(--vp-font-family-mono);
|
||||
font-size: 12px;
|
||||
padding: 3px 10px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid transparent;
|
||||
display: inline-block;
|
||||
}
|
||||
.chip.clickable {
|
||||
cursor: pointer;
|
||||
transition: opacity 0.15s;
|
||||
}
|
||||
.chip.clickable:hover {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.chip-required {
|
||||
background: var(--vp-c-danger-soft);
|
||||
border-color: var(--vp-c-danger-1);
|
||||
color: var(--vp-c-danger-1);
|
||||
}
|
||||
.chip-suggested {
|
||||
background: var(--vp-c-warning-soft);
|
||||
border-color: var(--vp-c-warning-1);
|
||||
color: var(--vp-c-warning-1);
|
||||
}
|
||||
.chip-rev {
|
||||
background: var(--vp-c-brand-soft);
|
||||
border-color: var(--vp-c-brand-1);
|
||||
color: var(--vp-c-brand-1);
|
||||
}
|
||||
.chip-rev-sug {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border-color: var(--vp-c-divider);
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
.chip-os {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border-color: var(--vp-c-divider);
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
/* Badges */
|
||||
.badge-ext {
|
||||
background: var(--vp-c-brand-soft);
|
||||
color: var(--vp-c-brand-1);
|
||||
}
|
||||
.badge-lib {
|
||||
background: var(--vp-c-tip-soft);
|
||||
color: var(--vp-c-tip-1);
|
||||
}
|
||||
|
||||
/* Mermaid */
|
||||
.mermaid-wrap {
|
||||
overflow-x: auto;
|
||||
padding: 8px 0;
|
||||
}
|
||||
.mermaid-fallback {
|
||||
font-size: 12px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
@@ -1,46 +1,36 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="missing" class="warning custom-block" style="margin-bottom: 16px">
|
||||
<p class="custom-block-title">WARNING</p>
|
||||
<p>Extension list is not generated yet. Run <code>bin/spc dev:gen-ext-docs</code> to generate it.</p>
|
||||
<header class="DocSearch-SearchBar" style="padding: 0">
|
||||
<form class="DocSearch-Form searchinput">
|
||||
<input class="DocSearch-Input" v-model="filterText" placeholder="Filter name..." @input="doFilter" />
|
||||
</form>
|
||||
</header>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Extension Name</th>
|
||||
<th>Linux</th>
|
||||
<th>macOS</th>
|
||||
<th>FreeBSD</th>
|
||||
<th>Windows</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="item in filterData">
|
||||
<td v-if="!item.notes">{{ item.name }}</td>
|
||||
<td v-else>
|
||||
<a :href="'./extension-notes.html#' + item.name">{{ item.name }}</a>
|
||||
</td>
|
||||
<td>{{ item.linux }}</td>
|
||||
<td>{{ item.macos }}</td>
|
||||
<td>{{ item.freebsd }}</td>
|
||||
<td>{{ item.windows }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div v-if="filterData.length === 0" style="margin: 0 4px 20px 4px; color: var(--vp-c-text-2); font-size: 14px">
|
||||
No result, please try another keyword.
|
||||
</div>
|
||||
<template v-else>
|
||||
<header class="DocSearch-SearchBar" style="padding: 0">
|
||||
<form class="DocSearch-Form searchinput">
|
||||
<input class="DocSearch-Input" v-model="filterText" placeholder="Filter name..." @input="doFilter" />
|
||||
</form>
|
||||
</header>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Extension Name</th>
|
||||
<th>Linux</th>
|
||||
<th>macOS</th>
|
||||
<th>Windows</th>
|
||||
<th>Website</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="item in filterData" :key="item.name">
|
||||
<td>
|
||||
<span v-if="!item.hasNotes">{{ item.name }}</span>
|
||||
<a v-else :href="'./extension-notes.html#' + item.name">{{ item.name }}</a>
|
||||
</td>
|
||||
<td>{{ item.linux ? '✅' : '' }}</td>
|
||||
<td>{{ item.macos ? '✅' : '' }}</td>
|
||||
<td>{{ item.windows ? '✅' : '' }}</td>
|
||||
<td>
|
||||
<a v-if="item.url" :href="item.url" target="_blank" rel="noopener noreferrer" class="ext-source-link">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="12" height="12" fill="currentColor"><path d="M10 6v2H5v11h11v-5h2v6a1 1 0 01-1 1H4a1 1 0 01-1-1V7a1 1 0 011-1h6zm11-3v8h-2V6.413l-7.793 7.794-1.414-1.414L17.585 5H13V3h8z"/></svg>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div v-if="filterData.length === 0" style="margin: 0 4px 20px 4px; color: var(--vp-c-text-2); font-size: 14px">
|
||||
No result, please try another keyword.
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -51,22 +41,34 @@ export default {
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { data as extData } from '../extensions.data.js'
|
||||
import {ref} from "vue";
|
||||
import ext from '../../../config/ext.json';
|
||||
|
||||
const missing = extData.missing
|
||||
const data = ref(extData.extensions)
|
||||
const filterData = ref(extData.extensions)
|
||||
const filterText = ref('')
|
||||
// 将 ext 转换为列表,方便后续操作
|
||||
const data = ref([]);
|
||||
for (const [name, item] of Object.entries(ext)) {
|
||||
data.value.push({
|
||||
name,
|
||||
linux: item.support?.Linux === undefined ? 'yes' : (item.support?.Linux === 'wip' ? '' : item.support?.Linux),
|
||||
macos: item.support?.Darwin === undefined ? 'yes' : (item.support?.Darwin === 'wip' ? '' : item.support?.Darwin),
|
||||
freebsd: item.support?.BSD === undefined ? 'yes' : (item.support?.BSD === 'wip' ? '' : item.support?.BSD),
|
||||
windows: item.support?.Windows === undefined ? 'yes' : (item.support?.Windows === 'wip' ? '' : item.support?.Windows),
|
||||
notes: item.notes === true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const filterData = ref(data.value);
|
||||
const filterText = ref('');
|
||||
|
||||
const doFilter = () => {
|
||||
if (filterText.value === '') {
|
||||
filterData.value = data.value
|
||||
return
|
||||
filterData.value = data.value;
|
||||
return;
|
||||
}
|
||||
filterData.value = data.value.filter(item =>
|
||||
item.name.toLowerCase().includes(filterText.value.toLowerCase())
|
||||
)
|
||||
filterData.value = data.value.filter(item => {
|
||||
return item.name.toLowerCase().includes(filterText.value.toLowerCase());
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -74,14 +76,4 @@ const doFilter = () => {
|
||||
.searchinput {
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
.ext-source-link {
|
||||
color: var(--vp-c-text-3);
|
||||
vertical-align: middle;
|
||||
opacity: 0.6;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
.ext-source-link:hover {
|
||||
opacity: 1;
|
||||
color: var(--vp-c-brand-1);
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -1,84 +1,65 @@
|
||||
import sidebarEn from "./sidebar.en";
|
||||
import sidebarZh from "./sidebar.zh";
|
||||
|
||||
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default {
|
||||
title: "StaticPHP",
|
||||
description: "A powerful tool designed for building portable executables including PHP, extensions, and more.",
|
||||
title: "Static PHP",
|
||||
description: "Build single static PHP binary, with PHP project together, with popular extensions included.",
|
||||
locales: {
|
||||
en: {
|
||||
label: 'English',
|
||||
lang: 'en',
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: 'Guide', link: '/en/guide/' },
|
||||
{ text: 'Develop', link: '/en/develop/' },
|
||||
{ text: 'Contributing', link: '/en/contributing/' },
|
||||
{ text: 'FAQ', link: '/en/faq/' },
|
||||
{
|
||||
text: 'v3 (alpha)',
|
||||
items: [
|
||||
{ text: 'v3 (alpha)', link: '/en/' },
|
||||
{ text: 'v2', link: 'https://static-php.github.io/v2-docs/' },
|
||||
],
|
||||
},
|
||||
{text: 'Guide', link: '/en/guide/',},
|
||||
{text: 'Advanced', link: '/en/develop/'},
|
||||
{text: 'Contributing', link: '/en/contributing/'},
|
||||
{text: 'FAQ', link: '/en/faq/'},
|
||||
],
|
||||
sidebar: sidebarEn,
|
||||
footer: {
|
||||
message: 'Released under the MIT License.',
|
||||
copyright: 'Copyright © 2023-present crazywhalecc',
|
||||
},
|
||||
copyright: 'Copyright © 2023-present crazywhalecc'
|
||||
}
|
||||
},
|
||||
},
|
||||
zh: {
|
||||
label: '简体中文',
|
||||
lang: 'zh',
|
||||
lang: 'zh', // optional, will be added as `lang` attribute on `html` tag
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: '构建指南', link: '/zh/guide/' },
|
||||
{ text: '开发者', link: '/zh/develop/' },
|
||||
{ text: '贡献', link: '/zh/contributing/' },
|
||||
{ text: 'FAQ', link: '/zh/faq/' },
|
||||
{
|
||||
text: 'v3 (alpha)',
|
||||
items: [
|
||||
{ text: 'v3 (alpha)', link: '/zh/' },
|
||||
{ text: 'v2', link: 'https://static-php.github.io/v2-docs/' },
|
||||
],
|
||||
},
|
||||
{text: '构建指南', link: '/zh/guide/'},
|
||||
{text: '进阶', link: '/zh/develop/'},
|
||||
{text: '贡献', link: '/zh/contributing/'},
|
||||
{text: 'FAQ', link: '/zh/faq/'},
|
||||
],
|
||||
sidebar: sidebarZh,
|
||||
footer: {
|
||||
message: 'Released under the MIT License.',
|
||||
copyright: 'Copyright © 2023-present crazywhalecc',
|
||||
},
|
||||
copyright: 'Copyright © 2023-present crazywhalecc'
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
themeConfig: {
|
||||
// https://vitepress.dev/reference/default-theme-config
|
||||
logo: '/images/static-php_nobg.png',
|
||||
nav: [],
|
||||
socialLinks: [
|
||||
{ icon: 'github', link: 'https://github.com/crazywhalecc/static-php-cli' },
|
||||
{icon: 'github', link: 'https://github.com/crazywhalecc/static-php-cli'}
|
||||
],
|
||||
footer: {
|
||||
message: 'Released under the MIT License.',
|
||||
copyright: 'Copyright © 2023-present crazywhalecc',
|
||||
copyright: 'Copyright © 2023-present crazywhalecc'
|
||||
},
|
||||
externalLinkIcon: true,
|
||||
search: {
|
||||
provider: 'algolia',
|
||||
options: {
|
||||
appId: 'IHJHUB1SF1',
|
||||
apiKey: '8266d31cc2ffbd0e059f1c6e5bdaf8fc',
|
||||
indexName: 'static-php docs',
|
||||
askAi: {
|
||||
assistantId: 'b72369b2-60a5-461d-902c-5c18d8c05902',
|
||||
agentStudio: true,
|
||||
sidePanel: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import { readFileSync, existsSync } from 'node:fs'
|
||||
import { resolve, dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||
const DATA_PATH = resolve(__dirname, 'deps-data.json')
|
||||
|
||||
export default {
|
||||
watch: [DATA_PATH],
|
||||
|
||||
load() {
|
||||
if (!existsSync(DATA_PATH)) {
|
||||
console.warn(
|
||||
'[deps-map.data.js] deps-data.json not found. ' +
|
||||
'Run `bin/spc dev:gen-deps-data` to generate it.'
|
||||
)
|
||||
return { packages: {}, missing: true }
|
||||
}
|
||||
|
||||
const raw = JSON.parse(readFileSync(DATA_PATH, 'utf-8'))
|
||||
return { packages: raw.packages ?? {}, missing: false }
|
||||
},
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
import { readFileSync, existsSync } from 'node:fs'
|
||||
import { resolve, dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||
const DATA_PATH = resolve(__dirname, 'ext-data.json')
|
||||
const NOTES_PATH = resolve(__dirname, '../en/guide/extension-notes.md')
|
||||
|
||||
export default {
|
||||
watch: [DATA_PATH, NOTES_PATH],
|
||||
|
||||
load() {
|
||||
if (!existsSync(DATA_PATH)) {
|
||||
console.warn(
|
||||
'[extensions.data.js] ext-data.json not found. ' +
|
||||
'Run `bin/spc dev:gen-ext-docs` to generate it.'
|
||||
)
|
||||
return { extensions: [], missing: true }
|
||||
}
|
||||
|
||||
const raw = JSON.parse(readFileSync(DATA_PATH, 'utf-8'))
|
||||
|
||||
// Build the set of extension names that have a section in extension-notes.md.
|
||||
// Headings at level 2 or 3 are matched; leading/trailing whitespace is stripped.
|
||||
const notesSet = new Set()
|
||||
if (existsSync(NOTES_PATH)) {
|
||||
const notesContent = readFileSync(NOTES_PATH, 'utf-8')
|
||||
for (const match of notesContent.matchAll(/^#{2,3}\s+(\S+)/gm)) {
|
||||
notesSet.add(match[1].toLowerCase())
|
||||
}
|
||||
}
|
||||
|
||||
const extensions = raw.extensions.map(ext => ({
|
||||
...ext,
|
||||
hasNotes: notesSet.has(ext.name.toLowerCase()),
|
||||
}))
|
||||
|
||||
return { extensions, missing: false }
|
||||
},
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* docs:gen-meta — Pre-build metadata generator for VitePress docs.
|
||||
*
|
||||
* Checks that the environment is ready (PHP installed, composer dependencies
|
||||
* present, bin/spc executable), then runs:
|
||||
* bin/spc dev:gen-deps-data → docs/.vitepress/deps-data.json
|
||||
* bin/spc dev:gen-ext-docs → docs/.vitepress/ext-data.json
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const { execSync, spawnSync } = require('child_process')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
// __dirname is docs/.vitepress/, so two levels up is the project root
|
||||
const ROOT = path.resolve(__dirname, '../..')
|
||||
|
||||
function fail(msg) {
|
||||
console.error(`\x1b[31m[gen-meta] ERROR: ${msg}\x1b[0m`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
function info(msg) {
|
||||
console.log(`\x1b[36m[gen-meta] ${msg}\x1b[0m`)
|
||||
}
|
||||
|
||||
function ok(msg) {
|
||||
console.log(`\x1b[32m[gen-meta] ${msg}\x1b[0m`)
|
||||
}
|
||||
|
||||
// --- 1. Check PHP ------------------------------------------------------------
|
||||
info('Checking PHP installation...')
|
||||
const phpResult = spawnSync('php', ['--version'], { encoding: 'utf8' })
|
||||
if (phpResult.status !== 0 || phpResult.error) {
|
||||
fail(
|
||||
'PHP is not installed or not in PATH.\n' +
|
||||
' Please install PHP 8.1+ and ensure it is available in your PATH.'
|
||||
)
|
||||
}
|
||||
const phpVersion = phpResult.stdout.split('\n')[0].trim()
|
||||
ok(`Found: ${phpVersion}`)
|
||||
|
||||
// --- 2. Check composer CLI ---------------------------------------------------
|
||||
info('Checking composer...')
|
||||
const composerCheck = spawnSync('composer', ['--version'], { encoding: 'utf8' })
|
||||
if (composerCheck.status !== 0 || composerCheck.error) {
|
||||
fail(
|
||||
'composer is not installed or not in PATH.\n' +
|
||||
' Please install Composer: https://getcomposer.org/download/'
|
||||
)
|
||||
}
|
||||
ok(`Found: ${composerCheck.stdout.split('\n')[0].trim()}`)
|
||||
|
||||
// --- 3. Install composer dependencies if missing ----------------------------
|
||||
info('Checking composer dependencies...')
|
||||
const autoload = path.join(ROOT, 'vendor', 'autoload.php')
|
||||
if (!fs.existsSync(autoload)) {
|
||||
info('vendor/autoload.php not found — running composer install --no-dev ...')
|
||||
const installResult = spawnSync('composer', ['install', '--no-dev'], {
|
||||
cwd: ROOT,
|
||||
stdio: 'inherit',
|
||||
})
|
||||
if (installResult.status !== 0) {
|
||||
fail('composer install --no-dev failed (exit code ' + installResult.status + ').')
|
||||
}
|
||||
ok('Composer dependencies installed.')
|
||||
} else {
|
||||
ok('Composer vendor directory found.')
|
||||
}
|
||||
|
||||
// --- 4. Check bin/spc --------------------------------------------------------
|
||||
info('Checking bin/spc...')
|
||||
const spc = path.join(ROOT, 'bin', 'spc')
|
||||
if (!fs.existsSync(spc)) {
|
||||
fail('bin/spc not found. Make sure you are in the project root.')
|
||||
}
|
||||
// Quick sanity check — list commands
|
||||
const spcCheck = spawnSync('php', [spc, 'list', '--format=txt'], {
|
||||
cwd: ROOT,
|
||||
encoding: 'utf8',
|
||||
env: { ...process.env, SPC_EXECUTION_SOURCE: '1' },
|
||||
})
|
||||
if (spcCheck.status !== 0) {
|
||||
fail(
|
||||
'bin/spc failed to run.\n' +
|
||||
(spcCheck.stderr ?? '') +
|
||||
'\n Make sure PHP extensions required by static-php-cli are available.'
|
||||
)
|
||||
}
|
||||
ok('bin/spc is operational.')
|
||||
|
||||
// --- 5. Run dev:gen-deps-data ------------------------------------------------
|
||||
info('Running bin/spc dev:gen-deps-data ...')
|
||||
const depsResult = spawnSync('php', [spc, 'dev:gen-deps-data'], {
|
||||
cwd: ROOT,
|
||||
stdio: 'inherit',
|
||||
env: { ...process.env, SPC_EXECUTION_SOURCE: '1' },
|
||||
})
|
||||
if (depsResult.status !== 0) {
|
||||
fail('dev:gen-deps-data failed (exit code ' + depsResult.status + ').')
|
||||
}
|
||||
ok('deps-data.json generated.')
|
||||
|
||||
// --- 6. Run dev:gen-ext-docs -------------------------------------------------
|
||||
info('Running bin/spc dev:gen-ext-docs ...')
|
||||
const extResult = spawnSync('php', [spc, 'dev:gen-ext-docs'], {
|
||||
cwd: ROOT,
|
||||
stdio: 'inherit',
|
||||
env: { ...process.env, SPC_EXECUTION_SOURCE: '1' },
|
||||
})
|
||||
if (extResult.status !== 0) {
|
||||
fail('dev:gen-ext-docs failed (exit code ' + extResult.status + ').')
|
||||
}
|
||||
ok('ext-data.json generated.')
|
||||
|
||||
ok('Metadata generation complete. Proceeding to VitePress build...')
|
||||
@@ -1,85 +1,57 @@
|
||||
export default {
|
||||
'/en/guide/': [
|
||||
{
|
||||
text: 'Getting Started',
|
||||
items: [
|
||||
{ text: 'Overview', link: '/en/guide/' },
|
||||
{ text: 'Installation', link: '/en/guide/installation' },
|
||||
{ text: 'First Build', link: '/en/guide/first-build' },
|
||||
{ text: 'PHP SAPI Reference', link: '/en/guide/sapi-reference' },
|
||||
{ text: 'CLI Reference', link: '/en/guide/cli-reference' },
|
||||
{ text: 'Migrating from v2', link: '/en/guide/migrate-from-v2' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Extensions',
|
||||
items: [
|
||||
{ text: 'Supported Extensions', link: '/en/guide/extensions' },
|
||||
{ text: 'Extension Notes', link: '/en/guide/extension-notes' },
|
||||
{ text: 'Build Command Generator', link: '/en/guide/cli-generator' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Reference',
|
||||
items: [
|
||||
{ text: 'Environment Variables', link: '/en/guide/env-vars' },
|
||||
{ text: 'Dependency Table', link: '/en/guide/deps-map' },
|
||||
{ text: 'Troubleshooting', link: '/en/guide/troubleshooting' },
|
||||
],
|
||||
},
|
||||
],
|
||||
'/en/develop/': [
|
||||
{
|
||||
text: 'Overview',
|
||||
items: [
|
||||
{ text: 'Get Started', link: '/en/develop/' },
|
||||
{ text: 'Project Structure', link: '/en/develop/structure' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Configuration Reference',
|
||||
items: [
|
||||
{ text: 'Registry', link: '/en/develop/registry' },
|
||||
{ text: 'Package Model', link: '/en/develop/package-model' },
|
||||
{ text: 'Artifact Model', link: '/en/develop/artifact-model' },
|
||||
{ text: 'craft.yml', link: '/en/develop/craft-yml' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Build System',
|
||||
items: [
|
||||
{ text: 'Build Lifecycle', link: '/en/develop/build-lifecycle' },
|
||||
{ text: 'Compilation Tools', link: '/en/develop/system-build-tools' },
|
||||
{ text: 'Doctor', link: '/en/develop/doctor-module' },
|
||||
{ text: 'PHP Source Modifications', link: '/en/develop/php-src-changes' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Extending StaticPHP',
|
||||
items: [
|
||||
{ text: 'Introduction', link: '/en/develop/extending/' },
|
||||
{ text: 'Writing Package Classes', link: '/en/develop/extending/package-classes' },
|
||||
{ text: 'Annotations Reference', link: '/en/develop/extending/annotations' },
|
||||
{ text: 'Lifecycle Hooks', link: '/en/develop/extending/lifecycle-hooks' },
|
||||
{ text: 'Dependency Injection', link: '/en/develop/extending/dependency-injection' },
|
||||
{ text: 'Custom Artifact', link: '/en/develop/extending/custom-artifact' },
|
||||
],
|
||||
},
|
||||
],
|
||||
'/en/contributing/': [
|
||||
{
|
||||
text: 'Contributing',
|
||||
items: [
|
||||
{ text: 'Contributing Guide', link: '/en/contributing/' },
|
||||
],
|
||||
},
|
||||
],
|
||||
'/en/faq/': [
|
||||
{
|
||||
text: 'FAQ',
|
||||
items: [
|
||||
{ text: 'Frequently Asked Questions', link: '/en/faq/' },
|
||||
],
|
||||
},
|
||||
],
|
||||
'/en/guide/': [
|
||||
{
|
||||
text: 'Basic Build Guides',
|
||||
items: [
|
||||
{text: 'Guide', link: '/en/guide/'},
|
||||
{text: 'Build (Local)', link: '/en/guide/manual-build'},
|
||||
{text: 'Build (CI)', link: '/en/guide/action-build'},
|
||||
{text: 'Supported Extensions', link: '/en/guide/extensions'},
|
||||
{text: 'Extension Notes', link: '/en/guide/extension-notes'},
|
||||
{text: 'Build Command Generator', link: '/en/guide/cli-generator'},
|
||||
{text: 'Environment Variables', link: '/en/guide/env-vars', collapsed: true,},
|
||||
{text: 'Dependency Table', link: '/en/guide/deps-map'},
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Extended Build Guides',
|
||||
items: [
|
||||
{text: 'Troubleshooting', link: '/en/guide/troubleshooting'},
|
||||
{text: 'Build on Windows', link: '/en/guide/build-on-windows'},
|
||||
{text: 'Build with GNU libc', link: '/en/guide/build-with-glibc'},
|
||||
],
|
||||
}
|
||||
],
|
||||
'/en/develop/': [
|
||||
{
|
||||
text: 'Development',
|
||||
items: [
|
||||
{text: 'Get Started', link: '/en/develop/'},
|
||||
{text: 'Project Structure', link: '/en/develop/structure'},
|
||||
{text: 'PHP Source Modification', link: '/en/develop/php-src-changes'},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Module',
|
||||
items: [
|
||||
{text: 'Doctor ', link: '/en/develop/doctor-module'},
|
||||
{text: 'Source', link: '/en/develop/source-module'},
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Extra',
|
||||
items: [
|
||||
{text: 'Compilation Tools', link: '/en/develop/system-build-tools'},
|
||||
{text: 'craft.yml Configuration', link: '/zh/develop/craft-yml'},
|
||||
]
|
||||
}
|
||||
],
|
||||
'/en/contributing/': [
|
||||
{
|
||||
text: 'Contributing',
|
||||
items: [
|
||||
{text: 'Contributing', link: '/en/contributing/'},
|
||||
],
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,85 +1,57 @@
|
||||
export default {
|
||||
'/zh/guide/': [
|
||||
{
|
||||
text: '快速上手',
|
||||
items: [
|
||||
{ text: '概览', link: '/zh/guide/' },
|
||||
{ text: '安装', link: '/zh/guide/installation' },
|
||||
{ text: '第一次构建', link: '/zh/guide/first-build' },
|
||||
{ text: 'PHP SAPI 构建参考', link: '/zh/guide/sapi-reference' },
|
||||
{ text: '命令行参考', link: '/zh/guide/cli-reference' },
|
||||
{ text: '从 v2 迁移', link: '/zh/guide/migrate-from-v2' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '扩展',
|
||||
items: [
|
||||
{ text: '支持的扩展列表', link: '/zh/guide/extensions' },
|
||||
{ text: '扩展注意事项', link: '/zh/guide/extension-notes' },
|
||||
{ text: '命令生成器', link: '/zh/guide/cli-generator' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '参考',
|
||||
items: [
|
||||
{ text: '环境变量', link: '/zh/guide/env-vars' },
|
||||
{ text: '依赖关系图', link: '/zh/guide/deps-map' },
|
||||
{ text: '故障排除', link: '/zh/guide/troubleshooting' },
|
||||
],
|
||||
},
|
||||
],
|
||||
'/zh/develop/': [
|
||||
{
|
||||
text: '概览',
|
||||
items: [
|
||||
{ text: '开发简介', link: '/zh/develop/' },
|
||||
{ text: '项目结构', link: '/zh/develop/structure' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '配置参考',
|
||||
items: [
|
||||
{ text: 'Registry', link: '/zh/develop/registry' },
|
||||
{ text: 'Package 模型', link: '/zh/develop/package-model' },
|
||||
{ text: 'Artifact 模型', link: '/zh/develop/artifact-model' },
|
||||
{ text: 'craft.yml 配置', link: '/zh/develop/craft-yml' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '构建系统',
|
||||
items: [
|
||||
{ text: '构建生命周期', link: '/zh/develop/build-lifecycle' },
|
||||
{ text: '编译工具', link: '/zh/develop/system-build-tools' },
|
||||
{ text: 'Doctor 环境检查', link: '/zh/develop/doctor-module' },
|
||||
{ text: '对 PHP 源码的修改', link: '/zh/develop/php-src-changes' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '扩展 StaticPHP',
|
||||
items: [
|
||||
{ text: '简介', link: '/zh/develop/extending/' },
|
||||
{ text: '编写 Package 类', link: '/zh/develop/extending/package-classes' },
|
||||
{ text: '注解参考', link: '/zh/develop/extending/annotations' },
|
||||
{ text: '生命周期 Hook', link: '/zh/develop/extending/lifecycle-hooks' },
|
||||
{ text: '依赖注入', link: '/zh/develop/extending/dependency-injection' },
|
||||
{ text: '自定义 Artifact', link: '/zh/develop/extending/custom-artifact' },
|
||||
],
|
||||
},
|
||||
],
|
||||
'/zh/contributing/': [
|
||||
{
|
||||
text: '贡献指南',
|
||||
items: [
|
||||
{ text: '贡献指南', link: '/zh/contributing/' },
|
||||
],
|
||||
},
|
||||
],
|
||||
'/zh/faq/': [
|
||||
{
|
||||
text: 'FAQ',
|
||||
items: [
|
||||
{ text: '常见问题', link: '/zh/faq/' },
|
||||
],
|
||||
},
|
||||
],
|
||||
'/zh/guide/': [
|
||||
{
|
||||
text: '构建指南',
|
||||
items: [
|
||||
{text: '指南', link: '/zh/guide/'},
|
||||
{text: '本地构建', link: '/zh/guide/manual-build'},
|
||||
{text: 'Actions 构建', link: '/zh/guide/action-build'},
|
||||
{text: '扩展列表', link: '/zh/guide/extensions'},
|
||||
{text: '扩展注意事项', link: '/zh/guide/extension-notes'},
|
||||
{text: '编译命令生成器', link: '/zh/guide/cli-generator'},
|
||||
{text: '环境变量列表', link: '/zh/guide/env-vars'},
|
||||
{text: '依赖关系图表', link: '/zh/guide/deps-map'},
|
||||
]
|
||||
},
|
||||
{
|
||||
text: '扩展构建指南',
|
||||
items: [
|
||||
{text: '故障排除', link: '/zh/guide/troubleshooting'},
|
||||
{text: '在 Windows 上构建', link: '/zh/guide/build-on-windows'},
|
||||
{text: '构建 GNU libc 兼容的二进制', link: '/zh/guide/build-with-glibc'},
|
||||
],
|
||||
}
|
||||
],
|
||||
'/zh/develop/': [
|
||||
{
|
||||
text: '开发指南',
|
||||
items: [
|
||||
{text: '开发简介', link: '/zh/develop/'},
|
||||
{text: '项目结构简介', link: '/zh/develop/structure'},
|
||||
{text: '对 PHP 源码的修改', link: '/zh/develop/php-src-changes'},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '模块',
|
||||
items: [
|
||||
{text: 'Doctor 环境检查工具', link: '/zh/develop/doctor-module'},
|
||||
{text: '资源模块', link: '/zh/develop/source-module'},
|
||||
]
|
||||
},
|
||||
{
|
||||
text: '其他',
|
||||
items: [
|
||||
{text: '系统编译工具', link: '/zh/develop/system-build-tools'},
|
||||
{text: 'craft.yml 配置详解', link: '/zh/develop/craft-yml'},
|
||||
]
|
||||
}
|
||||
],
|
||||
'/zh/contributing/': [
|
||||
{
|
||||
text: '贡献指南',
|
||||
items: [
|
||||
{text: '贡献指南', link: '/zh/contributing/'},
|
||||
],
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
@@ -3,13 +3,9 @@ import DefaultTheme from 'vitepress/theme'
|
||||
import {inBrowser, useData} from "vitepress";
|
||||
import {watchEffect} from "vue";
|
||||
import './style.css';
|
||||
import DepsMap from '../components/DepsMap.vue';
|
||||
|
||||
export default {
|
||||
...DefaultTheme,
|
||||
enhanceApp({ app }) {
|
||||
app.component('DepsMap', DepsMap)
|
||||
},
|
||||
setup() {
|
||||
const { lang } = useData()
|
||||
watchEffect(() => {
|
||||
|
||||
@@ -1,31 +1,28 @@
|
||||
```yaml
|
||||
# PHP version to build (default: 8.5)
|
||||
php-version: 8.5
|
||||
# PHP version to build (default: 8.4)
|
||||
php-version: 8.4
|
||||
# [REQUIRED] Static PHP extensions to build (list or comma-separated are both accepted)
|
||||
extensions: bcmath,fileinfo,phar,zlib,sodium,posix,pcntl
|
||||
# Extra packages to build (list or comma-separated are both accepted)
|
||||
packages: [ ]
|
||||
# Extra libraries to build (list or comma-separated are both accepted)
|
||||
libs: [ ]
|
||||
# [REQUIRED] Build SAPIs (list or comma-separated are both accepted)
|
||||
# Available: cli, micro, fpm, embed, frankenphp, cgi, all
|
||||
sapi: cli,micro,fpm
|
||||
# Show full console output (default: false)
|
||||
debug: false
|
||||
# Before build, remove all old build files and sources (default: false)
|
||||
clean-build: false
|
||||
# Build options (same as `build:php` command options, all options are optional)
|
||||
# Build options (same as `build` command options, all options are optional)
|
||||
build-options:
|
||||
# Build with all suggested packages (libraries and extensions) as well (default: false)
|
||||
with-suggests: false
|
||||
# Build extra shared extensions (comma-separated string)
|
||||
build-shared: ""
|
||||
# Before build, remove all old build files and sources (default: false)
|
||||
with-clean: false
|
||||
# Build with all suggested libraries (default: false)
|
||||
with-suggested-libs: false
|
||||
# Build with all suggested extensions (default: false)
|
||||
with-suggested-exts: false
|
||||
# Build extra shared extensions (list or comma-separated are both accepted)
|
||||
build-shared: [ ]
|
||||
# Build without stripping the binary (default: false)
|
||||
no-strip: false
|
||||
# Disable Opcache JIT (default: false)
|
||||
disable-opcache-jit: false
|
||||
# Enable thread-safe (ZTS) support (default: false)
|
||||
enable-zts: false
|
||||
# Disable smoke test, or for specific SAPIs comma-separated (default: false)
|
||||
no-smoke-test: false
|
||||
# PHP configuration options (same as --with-config-file-path)
|
||||
with-config-file-path: ""
|
||||
# PHP configuration options (same as --with-config-file-scan-dir)
|
||||
@@ -44,42 +41,27 @@ build-options:
|
||||
with-micro-logo: ""
|
||||
# Set micro SAPI as win32 mode, without this, micro SAPI will be compiled as a console application (only for Windows, default: false)
|
||||
enable-micro-win32: false
|
||||
# Path to a folder to be embedded in FrankenPHP (frankenphp SAPI only)
|
||||
with-frankenphp-app: ""
|
||||
|
||||
# Build options for shared extensions (list or comma-separated are both accepted)
|
||||
shared-extensions: [ ]
|
||||
|
||||
# Download options
|
||||
download-options:
|
||||
# Number of parallel downloads (default: 1)
|
||||
parallel: 1
|
||||
# Retries count for downloading sources (default: 0)
|
||||
retry: 0
|
||||
# Prefer source downloads when both source and binary are available (default: false)
|
||||
prefer-source: false
|
||||
# Prefer binary downloads when both source and binary are available (default: false)
|
||||
prefer-binary: false
|
||||
# Only download source artifacts, skip binary artifacts (default: false)
|
||||
source-only: false
|
||||
# Only download binary artifacts, skip source artifacts (default: false)
|
||||
binary-only: false
|
||||
# Ignore download cache for specified packages, comma separated (default: false)
|
||||
ignore-cache: false
|
||||
# Do not use alternative mirror download sources (default: false)
|
||||
no-alt: false
|
||||
# Do not clone shallowly repositories when downloading sources (default: false)
|
||||
no-shallow-clone: false
|
||||
# Use custom url for specified sources, format: "{source-name}:{url}" (e.g. "php-src:https://example.com/php-8.4.0.tar.gz")
|
||||
custom-url: [ ]
|
||||
# Use custom git repo for specified sources, format: "{source-name}:{branch}:{url}" (e.g. "php-src:master:https://github.com/php/php-src.git")
|
||||
custom-git: [ ]
|
||||
# Use custom local source path, format: "{source-name}:{path}" (e.g. "php-src:/path/to/php-src")
|
||||
custom-local: [ ]
|
||||
# Retries count for downloading sources (default: 5)
|
||||
retry: 5
|
||||
# Use pre-built libraries if available (default: false)
|
||||
prefer-pre-built: true
|
||||
# Do not download from alternative sources (default: false)
|
||||
no-alt: false
|
||||
|
||||
craft-options:
|
||||
doctor: true
|
||||
download: true
|
||||
build: true
|
||||
|
||||
# Extra environment variables
|
||||
extra-env:
|
||||
|
||||
0
docs/deps-map-ext.md
Normal file
0
docs/deps-map-ext.md
Normal file
0
docs/deps-map-lib.md
Normal file
0
docs/deps-map-lib.md
Normal file
@@ -1,5 +1,63 @@
|
||||
# Contributing
|
||||
|
||||
<!-- TODO: v3 contribution guide.
|
||||
Sections: code style (php-cs-fixer, phpstan), adding a new library/extension,
|
||||
adding a doctor check, submitting PRs, security disclosures. -->
|
||||
Thank you for being here, this project welcomes your contributions!
|
||||
|
||||
## Contribution Guide
|
||||
|
||||
If you have code or documentation to contribute, here's what you need to know first.
|
||||
|
||||
1. What type of code are you contributing? (new extensions, bug fixes, security issues, project framework optimizations, documentation)
|
||||
2. If you contribute new files or new snippets, is your code checked by `php-cs-fixer` and `phpstan`?
|
||||
3. Have you fully read the [Developer Guide](../develop/) before contributing code?
|
||||
|
||||
If you can answer the above questions and have made changes to the code,
|
||||
you can initiate a Pull Request in the project GitHub repository in time.
|
||||
After the code review is completed, the code can be modified according to the suggestion, or directly merged into the main branch.
|
||||
|
||||
## Contribution Type
|
||||
|
||||
The main purpose of this project is to compile statically linked PHP binaries,
|
||||
and the command line processing function is written based on `symfony/console`.
|
||||
Before development, if you are not familiar with it,
|
||||
Check out the [symfony/console documentation](https://symfony.com/doc/current/components/console.html) first.
|
||||
|
||||
### Security Update
|
||||
|
||||
Because this project is basically a PHP project running locally, generally speaking, there will be no remote attacks.
|
||||
But if you find such a problem, please **DO NOT submit a PR or Issue in the GitHub repository,
|
||||
You need to contact the project maintainer (crazywhalecc) via [mail](mailto:admin@zhamao.me).
|
||||
|
||||
### Fix Bugs
|
||||
|
||||
Fixing bugs generally does not involve modification of the project structure and framework,
|
||||
so if you can locate the wrong code and fix it directly, please submit a PR directly.
|
||||
|
||||
### New Extensions
|
||||
|
||||
For adding a new extension,
|
||||
you need to understand some basic structure of the project and how to add a new extension according to the existing logic.
|
||||
It will be covered in detail in the next section on this page.
|
||||
In general, you will need:
|
||||
|
||||
1. Evaluate whether the extension can be compiled inline into PHP.
|
||||
2. Evaluate whether the extension's dependent libraries (if any) can be compiled statically.
|
||||
3. Write library compile commands on different platforms.
|
||||
4. Verify that the extension and its dependencies are compatible with existing extensions and dependencies.
|
||||
5. Verify that the extension works normally in `cli`, `micro`, `fpm`, `embed` SAPIs.
|
||||
6. Write documentation and add your extension.
|
||||
|
||||
### Project Framework Optimization
|
||||
|
||||
If you are already familiar with the working principle of `symfony/console`,
|
||||
and at the same time want to make some modifications or optimizations to the framework of the project,
|
||||
please understand the following things first:
|
||||
|
||||
1. Adding extensions does not belong to project framework optimization,
|
||||
but if you find that you have to optimize the framework when adding new extensions,
|
||||
you need to modify the framework itself before adding extensions.
|
||||
2. For some large-scale logical modifications (such as those involving LibraryBase, Extension objects, etc.),
|
||||
it is recommended to submit an Issue or Draft PR for discussion first.
|
||||
3. In the early stage of the project, it was a pure private development project, and there were some Chinese comments in the code.
|
||||
After internationalizing your project you can submit a PR to translate these comments into English.
|
||||
4. Please do not submit more useless code fragments in the code,
|
||||
such as a large number of unused variables, methods, classes, and code that has been rewritten many times.
|
||||
|
||||
@@ -1,451 +0,0 @@
|
||||
---
|
||||
outline: 'deep'
|
||||
---
|
||||
|
||||
# Artifact Model
|
||||
|
||||
An **Artifact** is a core concept in the StaticPHP build system. It represents a source archive or pre-built binary required to build a package. Each artifact describes where to download the file, how to extract it, and the resulting path layout. Packages reference one or more artifacts via the `artifact` field to obtain the source code or binaries they need.
|
||||
|
||||
## Defining an Artifact
|
||||
|
||||
Here is a minimal artifact object that points to a source archive (curl's source code):
|
||||
|
||||
```yaml
|
||||
&:
|
||||
source:
|
||||
type: ghrel
|
||||
repo: curl/curl
|
||||
match: curl.+\.tar\.xz
|
||||
prefer-stable: true
|
||||
```
|
||||
|
||||
There are two ways to define an artifact and associate it with a package: **inline** (defined directly inside the package file) or **standalone** (defined in a separate file and referenced by name):
|
||||
|
||||
::: code-group
|
||||
```yaml [Inline Artifact]
|
||||
# This is a package declaration
|
||||
curl:
|
||||
type: target
|
||||
artifact:
|
||||
source:
|
||||
type: ghrel
|
||||
repo: curl/curl
|
||||
match: curl.+\.tar\.xz
|
||||
prefer-stable: true
|
||||
```
|
||||
```yaml [Standalone Artifact]
|
||||
# This is a standalone artifact declaration, typically placed under config/artifact/
|
||||
curl-src:
|
||||
source:
|
||||
type: ghrel
|
||||
repo: curl/curl
|
||||
match: curl.+\.tar\.xz
|
||||
prefer-stable: true
|
||||
```
|
||||
```yaml [Package Referencing a Standalone Artifact]
|
||||
# This is a package declaration
|
||||
curl:
|
||||
type: target
|
||||
artifact: curl-src
|
||||
```
|
||||
:::
|
||||
|
||||
## Structure
|
||||
|
||||
An artifact has three top-level sections: `source`, `binary`, and `metadata`.
|
||||
|
||||
- `source` — the source code archive
|
||||
- `binary` — pre-built binaries for specific platforms
|
||||
- `metadata` — additional information such as license paths
|
||||
|
||||
Both `source` and `binary` accept either an inline source object or a reference to a standalone artifact by name (as shown above).
|
||||
|
||||
Full artifact object format:
|
||||
|
||||
```yaml
|
||||
&:
|
||||
source: {source-object} # (optional)
|
||||
binary:
|
||||
windows-x86_64: {source-object} # (optional)
|
||||
linux-x86_64: {source-object} # (optional)
|
||||
linux-aarch64: {source-object} # (optional)
|
||||
macos-x86_64: {source-object} # (optional)
|
||||
macos-aarch64: {source-object} # (optional)
|
||||
metadata: # (optional)
|
||||
license: "" # (optional) SPDX identifier
|
||||
license-files: ["LICENSE"] # License files from the source directory
|
||||
source-root: "subdir" # (optional) Use if the actual source root is inside a subdirectory
|
||||
```
|
||||
|
||||
The basic format of a `source-object`:
|
||||
|
||||
```yaml
|
||||
&:
|
||||
type: "url" # Download type
|
||||
# ...: Additional keys depend on the type; see below
|
||||
extract: "path/to/dir" # (optional) Override extract path; default: SOURCE_PATH/{artifact-name}
|
||||
```
|
||||
|
||||
## Metadata
|
||||
|
||||
The `metadata` field provides supplementary information about an artifact. It supports three subfields:
|
||||
|
||||
### license
|
||||
|
||||
- **Type**: `string` (optional)
|
||||
- **Description**: The open-source license identifier for this package, following the [SPDX License Identifier](https://spdx.org/licenses/) format (e.g. `MIT`, `Apache-2.0`, `GPL-2.0-only`). This is used only for annotation in the license summary of the build output and has no effect on the build process itself.
|
||||
|
||||
```yaml
|
||||
metadata:
|
||||
license: MIT
|
||||
```
|
||||
|
||||
### license-files
|
||||
|
||||
- **Type**: `string[]` (optional)
|
||||
- **Description**: A list of paths to license files. After a successful build, the framework collects these files and places them in the `license/` directory of the build output. Two path formats are supported:
|
||||
- **Relative paths** (e.g. `LICENSE`, `COPYING`, `gettext-runtime/intl/COPYING.LIB`): resolved relative to the artifact's source root directory.
|
||||
- **`@/` prefix** (e.g. `@/bzip2.txt`): references a license file bundled with the framework itself, resolved to `src/globals/licenses/`. This is useful when the upstream source package does not include a license file (or the license text is embedded in other documentation) — in such cases, the license text can be placed in the built-in directory and referenced with `@/`.
|
||||
|
||||
The following built-in license files are currently available: `bzip2.txt`, `gmp.txt`, `icu.txt`, `postgresql.txt`, `sqlite.txt`, `zlib.txt`.
|
||||
|
||||
```yaml
|
||||
# Common case: read from the source directory
|
||||
metadata:
|
||||
license-files: [LICENSE]
|
||||
|
||||
# Multiple license files
|
||||
metadata:
|
||||
license-files: [LICENSE, COPYING.LESSER]
|
||||
|
||||
# License file inside a subdirectory
|
||||
metadata:
|
||||
license-files: [gettext-runtime/intl/COPYING.LIB]
|
||||
|
||||
# Use a built-in license file when the source package does not include one
|
||||
metadata:
|
||||
license-files: ['@/bzip2.txt']
|
||||
```
|
||||
|
||||
### source-root
|
||||
|
||||
- **Type**: `string` (optional)
|
||||
- **Description**: When the actual source root is located inside a subdirectory of the extracted archive, this field specifies that subdirectory name. The framework will use this path as the working directory during the build instead of the top-level extraction directory.
|
||||
|
||||
```yaml
|
||||
# krb5's actual source root is in the src/ subdirectory after extraction
|
||||
metadata:
|
||||
source-root: src
|
||||
```
|
||||
|
||||
## Download Types
|
||||
|
||||
Artifacts support a variety of download types. Choose the one that best fits where the package is hosted.
|
||||
|
||||
| Type | Description |
|
||||
|---|---|
|
||||
| `url` | Download from a fixed URL. Supports `filename` (custom local filename) and `version` (manually set version). |
|
||||
| `git` | Clone from a Git repository. Supports `rev` (branch/tag/commit), `submodules` (fetch submodules), and `extract`. |
|
||||
| `ghrel` | Download from GitHub Release Assets by regex match. Requires `repo` (`owner/repo`) and `match` (filename regex). Supports `prefer-stable`. |
|
||||
| `ghtar` | Download the source tarball from a GitHub Release (`/releases` API), matching by release name with `match`. Supports `prefer-stable`. |
|
||||
| `ghtagtar` | Download the source tarball from a GitHub Tag (`/tags` API), matching by tag name with `match`. Supports `prefer-stable`. |
|
||||
| `filelist` | Scrape an HTML page for a file listing, extract the filename and version via `regex`, then download the matched file. Suitable for official download index pages (e.g. ftp.gnu.org, openssl.org). |
|
||||
| `pecl` | Download a PHP extension from [PECL](https://pecl.php.net) by `name`. Supports `prefer-stable`. |
|
||||
| `pie` | Download a PHP extension from Packagist via the [PIE](https://github.com/php/pie) spec. Requires `repo` (`vendor/package`). |
|
||||
| `php-release` | Download official PHP source from php.net. The version is controlled by the `--with-php` build argument. |
|
||||
| `bitbuckettag` | Download source tarball from the latest Bitbucket tag. Requires `repo` (`workspace/repo`). |
|
||||
| `local` | Use a pre-existing local directory as the source. Requires `dirname`. Useful for offline or development scenarios. |
|
||||
| `custom` | Fully custom download logic implemented in a PHP class under `src/Package/Artifact/`. Optionally calls a specific method via `func`. |
|
||||
|
||||
## Type Reference
|
||||
|
||||
### url
|
||||
|
||||
Downloads a file from a fixed URL and extracts it automatically.
|
||||
|
||||
- **Class**: `StaticPHP\Artifact\Downloader\Type\Url`
|
||||
- **Capabilities**: Basic download only; no automatic version update checking
|
||||
- **Required**: `url` — the download address
|
||||
- **Optional**:
|
||||
- `filename` — local filename to save as (defaults to the last path segment of the URL)
|
||||
- `version` — manually specify a version string (this type cannot auto-detect versions)
|
||||
- `extract` — override the extraction directory (default: `SOURCE_PATH/{artifact-name}`)
|
||||
|
||||
```yaml
|
||||
# sqlite downloaded from a fixed URL
|
||||
artifact:
|
||||
source:
|
||||
type: url
|
||||
url: 'https://www.sqlite.org/2024/sqlite-autoconf-3450200.tar.gz'
|
||||
```
|
||||
|
||||
::: tip
|
||||
|
||||
Inside an artifact, a bare string starting with `http://` or `https://` is automatically expanded into a `type: url` object, so you can often just write the URL directly:
|
||||
|
||||
```yaml
|
||||
artifact:
|
||||
source: 'https://www.sqlite.org/2024/sqlite-autoconf-3450200.tar.gz'
|
||||
```
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
### git
|
||||
|
||||
Clones a Git repository as the source. Supports two modes: clone a specific branch/tag/commit (`rev`), or use a regex to match the highest-versioned branch from all remote refs (`regex`).
|
||||
|
||||
- **Class**: `StaticPHP\Artifact\Downloader\Type\Git`
|
||||
- **Capabilities**: Version update checking (`CheckUpdateInterface`)
|
||||
- **Required**: `url` — repository URL
|
||||
- **Optional** (at least one of `rev` or `regex` is required):
|
||||
- `rev` — clone a specific branch, tag, or commit hash
|
||||
- `regex` — match remote branch names with a PCRE regex; the highest matching version is selected (must include a named capture group `(?P<version>...)`)
|
||||
- `submodules` — whether to fetch git submodules (boolean)
|
||||
- `extract` — override the clone target directory
|
||||
|
||||
```yaml
|
||||
# php-glfw cloned from the master branch
|
||||
artifact:
|
||||
source:
|
||||
type: git
|
||||
url: 'https://github.com/mario-deluna/php-glfw'
|
||||
rev: master
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ghrel
|
||||
|
||||
Downloads a file from GitHub Release Assets using a regex to match the asset filename. Best suited for repositories that upload pre-compiled packages or source archives as release assets.
|
||||
|
||||
- **Class**: `StaticPHP\Artifact\Downloader\Type\GitHubRelease`
|
||||
- **Capabilities**: Version update checking (`CheckUpdateInterface`), integrity verification (`ValidatorInterface`, SHA256)
|
||||
- **Required**:
|
||||
- `repo` — repository path in `owner/repo` format
|
||||
- `match` — PCRE regex (without delimiters) to match the asset filename, e.g. `openssl.+\.tar\.gz`
|
||||
- **Optional**:
|
||||
- `prefer-stable` — skip pre-release versions (default: `true`)
|
||||
- `query` — query string appended to the API URL (e.g. `?per_page=5`)
|
||||
- `extract` — override extraction directory
|
||||
|
||||
```yaml
|
||||
# openssl downloaded from GitHub Release Assets
|
||||
artifact:
|
||||
source:
|
||||
type: ghrel
|
||||
repo: openssl/openssl
|
||||
match: openssl.+\.tar\.gz
|
||||
prefer-stable: true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ghtar
|
||||
|
||||
Downloads the source tarball automatically generated by a GitHub Release (the "Source code" archive on the Release page). Unlike `ghrel` which downloads uploaded assets, `ghtar` uses the auto-generated tarball from the `/releases` API.
|
||||
|
||||
- **Class**: `StaticPHP\Artifact\Downloader\Type\GitHubTarball`
|
||||
- **Capabilities**: Version update checking (`CheckUpdateInterface`)
|
||||
- **Required**: `repo` — repository path in `owner/repo` format
|
||||
- **Optional**:
|
||||
- `prefer-stable` — skip pre-release versions (default: `true`)
|
||||
- `match` — regex filter applied to `tarball_url` (if omitted, the first result is used)
|
||||
- `query` — query string appended to the API URL
|
||||
- `extract` — override extraction directory
|
||||
|
||||
```yaml
|
||||
# librdkafka downloaded via GitHub Release tarball
|
||||
artifact:
|
||||
source:
|
||||
type: ghtar
|
||||
repo: confluentinc/librdkafka
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ghtagtar
|
||||
|
||||
Downloads a source tarball from a GitHub Tag via the `/tags` API. Functionally identical to `ghtar`, but targets the tags endpoint instead of releases — useful for repositories that tag releases without creating a formal GitHub Release.
|
||||
|
||||
- **Class**: `StaticPHP\Artifact\Downloader\Type\GitHubTarball` (shared with `ghtar`)
|
||||
- **Capabilities**: Version update checking (`CheckUpdateInterface`)
|
||||
- **Required**: `repo` — repository path in `owner/repo` format
|
||||
- **Optional**:
|
||||
- `prefer-stable` — skip pre-release versions (default: `true`)
|
||||
- `match` — regex filter applied to tag names (if omitted, the latest tag is used)
|
||||
- `query` — query string appended to the API URL
|
||||
- `extract` — override extraction directory
|
||||
|
||||
```yaml
|
||||
# brotli: only match v1.x tags
|
||||
artifact:
|
||||
source:
|
||||
type: ghtagtar
|
||||
repo: google/brotli
|
||||
match: 'v1\.\d.*'
|
||||
|
||||
# libpng: match v1.6.x tags, with pagination
|
||||
artifact:
|
||||
source:
|
||||
type: ghtagtar
|
||||
repo: pnggroup/libpng
|
||||
match: v1\.6\.\d+
|
||||
query: '?per_page=150'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### filelist
|
||||
|
||||
Fetches an HTML page (typically an official download index), extracts filenames and version numbers from the page content using a regex, then automatically selects and downloads the highest stable version. Pre-release versions (those containing keywords like alpha, beta, rc, dev, nightly, or snapshot) are automatically skipped.
|
||||
|
||||
**Best for**: projects without GitHub that publish versioned archives on their own FTP or web index, such as `https://ftp.gnu.org/pub/gnu/ncurses/`.
|
||||
|
||||
- **Class**: `StaticPHP\Artifact\Downloader\Type\FileList`
|
||||
- **Capabilities**: Version update checking (`CheckUpdateInterface`)
|
||||
- **Required**:
|
||||
- `url` — URL of the HTML page containing the file listing
|
||||
- `regex` — PCRE regex to extract filenames and versions from the page (must include named capture groups `(?<file>...)` and `(?<version>...)`)
|
||||
- **Optional**:
|
||||
- `extract` — override extraction directory
|
||||
- `download-url` — custom download URL template supporting `{file}` and `{version}` placeholders (by default the filename is appended directly to `url`)
|
||||
|
||||
```yaml
|
||||
# ncurses: scrape latest version from the GNU FTP index
|
||||
artifact:
|
||||
source:
|
||||
type: filelist
|
||||
url: 'https://ftp.gnu.org/pub/gnu/ncurses/'
|
||||
regex: '/href="(?<file>ncurses-(?<version>[^"]+)\.tar\.gz)"/'
|
||||
|
||||
# openssl: mirror source using filelist
|
||||
artifact:
|
||||
source-mirror:
|
||||
type: filelist
|
||||
url: 'https://www.openssl.org/source/'
|
||||
regex: '/href="(?<file>openssl-(?<version>[^"]+)\.tar\.gz)"/'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### pecl
|
||||
|
||||
Downloads a PHP extension source package from [PECL](https://pecl.php.net) using the PECL REST API. The latest stable version is selected automatically.
|
||||
|
||||
- **Class**: `StaticPHP\Artifact\Downloader\Type\PECL`
|
||||
- **Capabilities**: Version update checking (`CheckUpdateInterface`)
|
||||
- **Required**: `name` — PECL package name (case-insensitive, e.g. `APCu`)
|
||||
- **Optional**:
|
||||
- `prefer-stable` — download stable releases only (default: `true`)
|
||||
- `extract` — override extraction directory (default: `php-src/ext/{name}`)
|
||||
|
||||
```yaml
|
||||
# APCu downloaded from PECL
|
||||
artifact:
|
||||
source:
|
||||
type: pecl
|
||||
name: APCu
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### pie
|
||||
|
||||
Downloads a PHP extension from [Packagist](https://repo.packagist.org) following the [PIE](https://github.com/php/pie) specification. Package metadata is fetched via the Packagist `p2/` API, and the source archive is downloaded from the `dist` field.
|
||||
|
||||
- **Class**: `StaticPHP\Artifact\Downloader\Type\PIE`
|
||||
- **Capabilities**: Version update checking (`CheckUpdateInterface`)
|
||||
- **Required**: `repo` — Packagist package path in `vendor/package` format
|
||||
- **Optional**:
|
||||
- `extract` — override extraction directory
|
||||
|
||||
```yaml
|
||||
# xdebug downloaded from Packagist
|
||||
artifact:
|
||||
source:
|
||||
type: pie
|
||||
repo: xdebug/xdebug
|
||||
|
||||
# php-spx with a custom extraction path
|
||||
artifact:
|
||||
source:
|
||||
type: pie
|
||||
repo: noisebynorthwest/php-spx
|
||||
extract: php-src/ext/spx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### php-release
|
||||
|
||||
Downloads the official PHP source from [php.net](https://www.php.net). The version is determined at build time by the `--with-php` argument. SHA256 integrity is verified automatically. Passing `git` as the version will clone the `master` branch of `php/php-src` directly.
|
||||
|
||||
- **Class**: `StaticPHP\Artifact\Downloader\Type\PhpRelease`
|
||||
- **Capabilities**: Version update checking (`CheckUpdateInterface`), integrity verification (`ValidatorInterface`, SHA256)
|
||||
- **Required**: `domain` — download domain (e.g. `https://www.php.net` or a custom mirror)
|
||||
- **Optional**:
|
||||
- `extract` — override extraction directory
|
||||
|
||||
```yaml
|
||||
# php-src with primary and mirror sources
|
||||
artifact:
|
||||
source:
|
||||
type: php-release
|
||||
domain: 'https://www.php.net'
|
||||
source-mirror:
|
||||
type: php-release
|
||||
domain: 'https://phpmirror.static-php.dev'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### bitbuckettag
|
||||
|
||||
Downloads a source tarball from the latest tag of a Bitbucket repository via the Bitbucket REST API.
|
||||
|
||||
- **Class**: `StaticPHP\Artifact\Downloader\Type\BitBucketTag`
|
||||
- **Capabilities**: Basic download only; no automatic version update checking
|
||||
- **Required**: `repo` — repository path in `workspace/repo` format
|
||||
- **Optional**:
|
||||
- `extract` — override extraction directory
|
||||
|
||||
```yaml
|
||||
artifact:
|
||||
source:
|
||||
type: bitbuckettag
|
||||
repo: snappy-m-o/php-snappy
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### local
|
||||
|
||||
Uses a pre-existing local directory as the source without performing any download. Useful for offline environments or local development where the source has already been placed on disk.
|
||||
|
||||
- **Class**: `StaticPHP\Artifact\Downloader\Type\LocalDir`
|
||||
- **Capabilities**: Basic download only; no automatic version update checking
|
||||
- **Required**: `dirname` — absolute path to the local directory
|
||||
- **Optional**:
|
||||
- `extract` — override extraction directory
|
||||
|
||||
```yaml
|
||||
artifact:
|
||||
source:
|
||||
type: local
|
||||
dirname: /path/to/local/source
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### custom
|
||||
|
||||
Delegates download logic entirely to a PHP class under `src/Package/Artifact/`. If `func` is not specified, the class's default download method is called.
|
||||
|
||||
- **Optional**: `func` — name of the specific method to invoke in the implementation class
|
||||
|
||||
```yaml
|
||||
artifact:
|
||||
source:
|
||||
type: custom
|
||||
```
|
||||
@@ -1,6 +0,0 @@
|
||||
# Build Lifecycle
|
||||
|
||||
<!-- TODO: Describe the full build pipeline stage sequence.
|
||||
When each hook fires: #[BeforeStage], #[AfterStage], #[PatchBeforeBuild].
|
||||
How platform selection (#[BuildFor]) works at runtime.
|
||||
Diagram of stage order for a typical library and extension build. -->
|
||||
@@ -1,4 +1,70 @@
|
||||
# Doctor Module
|
||||
# Doctor module
|
||||
|
||||
<!-- TODO: Migrate and update from v2 doctor-module.md.
|
||||
Cover v3 changes: --auto-fix, .spc-doctor.lock, new check items for v3 toolchain. -->
|
||||
The Doctor module is a relatively independent module used to check the system environment, which can be entered with the command `bin/spc doctor`, and the entry command class is in `DoctorCommand.php`.
|
||||
|
||||
The Doctor module is a checklist with a series of check items and automatic repair items.
|
||||
These items are stored in the `src/SPC/doctor/item/` directory,
|
||||
And two Attributes are used as check item tags and auto-fix item tags: `#[AsCheckItem]` and `#[AsFixItem]`.
|
||||
|
||||
Take the existing check item `if necessary tools are installed`,
|
||||
which is used to check whether the packages necessary for compilation are installed in the macOS system.
|
||||
The following is its source code:
|
||||
|
||||
```php
|
||||
use SPC\doctor\AsCheckItem;
|
||||
use SPC\doctor\AsFixItem;
|
||||
use SPC\doctor\CheckResult;
|
||||
|
||||
#[AsCheckItem('if necessary tools are installed', limit_os: 'Darwin', level: 997)]
|
||||
public function checkCliTools(): ?CheckResult
|
||||
{
|
||||
$missing = [];
|
||||
foreach (self::REQUIRED_COMMANDS as $cmd) {
|
||||
if ($this->findCommand($cmd) === null) {
|
||||
$missing[] = $cmd;
|
||||
}
|
||||
}
|
||||
if (!empty($missing)) {
|
||||
return CheckResult::fail('missing system commands: ' . implode(', ', $missing), 'build-tools', [$missing]);
|
||||
}
|
||||
return CheckResult::ok();
|
||||
}
|
||||
```
|
||||
|
||||
The first parameter of the attribute is the name of the check item,
|
||||
and the following `limit_os` parameter restricts the check item to be triggered only under the specified system,
|
||||
and `level` is the priority of executing the check item, the larger the number, the higher the priority higher.
|
||||
|
||||
The `$this->findCommand()` method used in it is the method of `SPC\builder\traits\UnixSystemUtilTrait`,
|
||||
the purpose is to find the location of the system command, and return NULL if it cannot be found.
|
||||
|
||||
Each check item method should return a `SPC\doctor\CheckResult`:
|
||||
|
||||
- When returning `CheckResult::fail()`, the first parameter is used to output the error prompt of the terminal,
|
||||
and the second parameter is the name of the repair item when this check item can be automatically repaired.
|
||||
- When `CheckResult::ok()` is returned, the check passed. You can also pass a parameter to return the check result, for example: `CheckResult::ok('OS supported')`.
|
||||
- When returning `CheckResult::fail()`, if the third parameter is included, the array of the third parameter will be used as the parameter of `AsFixItem`.
|
||||
|
||||
The following is the method for automatically repairing items corresponding to this check item:
|
||||
|
||||
```php
|
||||
#[AsFixItem('build-tools')]
|
||||
public function fixBuildTools(array $missing): bool
|
||||
{
|
||||
foreach ($missing as $cmd) {
|
||||
try {
|
||||
shell(true)->exec('brew install ' . escapeshellarg($cmd));
|
||||
} catch (RuntimeException) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
`#[AsFixItem()]` first parameter is the name of the fix item, and this method must return True or False.
|
||||
When False is returned, the automatic repair failed and manual handling is required.
|
||||
|
||||
In the code here, `shell()->exec()` is the method of executing commands of the project,
|
||||
which is used to replace `exec()` and `system()`, and also provides debugging, obtaining execution status,
|
||||
entering directories, etc. characteristic.
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# Annotations Reference
|
||||
|
||||
<!-- TODO: Complete reference for all v3 PHP attributes.
|
||||
#[Library], #[Extension], #[BuildFor], #[BeforeStage], #[AfterStage],
|
||||
#[PatchBeforeBuild], #[CustomPhpConfigureArg], #[AsCheckItem], #[AsFixItem].
|
||||
Per-attribute: parameters, types, allowed targets, example. -->
|
||||
@@ -1,8 +0,0 @@
|
||||
# Custom Artifact
|
||||
|
||||
<!-- TODO: Guide for implementing a custom artifact download class under src/Package/Artifact/.
|
||||
Explain when type: custom is appropriate (e.g. proprietary auth, non-standard archives).
|
||||
Cover: class placement and naming, method signatures (default download method + func dispatch),
|
||||
accessing source config fields, returning the extracted source path,
|
||||
registering the class via spc.registry.yml artifact psr-4 mapping.
|
||||
Provide an annotated code example. -->
|
||||
@@ -1,6 +0,0 @@
|
||||
# Dependency Injection
|
||||
|
||||
<!-- TODO: How PHP-DI autowiring works in v3.
|
||||
ApplicationContext::get() usage.
|
||||
Registering custom services.
|
||||
Injecting into command classes, build classes, and stage methods. -->
|
||||
@@ -1,8 +0,0 @@
|
||||
# Extending StaticPHP
|
||||
|
||||
<!-- TODO: Introduce the three extension strategies:
|
||||
1. Contributing to core — edit src/Package/ and config/pkg/ directly.
|
||||
2. External Registry — point SPC_REGISTRIES at a custom spc.registry.yml.
|
||||
3. Vendor Mode — package classes + config as a Composer library (composer require).
|
||||
Explain when to use each approach. Show a minimal end-to-end example:
|
||||
one Library class, one config YAML, one spc.registry.yml, run spc. -->
|
||||
@@ -1,6 +0,0 @@
|
||||
# Lifecycle Hooks
|
||||
|
||||
<!-- TODO: Detailed explanation of hook execution order and method signatures.
|
||||
#[BeforeStage('lib-name', 'build')], #[AfterStage(...)], #[PatchBeforeBuild].
|
||||
How hooks from different packages are merged and ordered.
|
||||
Common patterns: patching config.m4, injecting compile flags, post-install fixups. -->
|
||||
@@ -1,6 +0,0 @@
|
||||
# Writing Package Classes
|
||||
|
||||
<!-- TODO: Step-by-step guide to writing a Library class and an Extension class.
|
||||
Full annotated code examples using #[Library], #[Extension], #[BuildFor].
|
||||
UnixAutoconfExecutor / UnixCmakeExecutor / WindowsCMakeExecutor usage.
|
||||
File placement (src/Package/Library/, src/Package/Extension/) and autoloading. -->
|
||||
@@ -1,49 +1,35 @@
|
||||
# Developer Guide
|
||||
# Start Developing
|
||||
|
||||
This section covers the StaticPHP development workflow and the foundational knowledge needed to understand how StaticPHP works under the hood.
|
||||
Developing this project requires the installation and deployment of a PHP environment,
|
||||
as well as some extensions and Composer commonly used in PHP projects.
|
||||
|
||||
## Overview
|
||||
The development environment and running environment of the project are almost exactly the same.
|
||||
You can refer to the **Manual Build** section to install system PHP or use the pre-built static PHP of this project as the environment.
|
||||
I will not go into details here.
|
||||
|
||||
StaticPHP is a binary build tool whose core purpose is managing the build pipeline — downloading and configuring PHP source code, resolving extension dependencies, and invoking the underlying build system (e.g., Docker or a local compiler).
|
||||
Regardless of its purpose, this project itself is actually a `php-cli` program. You can edit and develop it as a normal PHP project.
|
||||
At the same time, you need to understand the Shell languages of different systems.
|
||||
|
||||
From a development perspective, StaticPHP is an open framework that provides the ability to statically build PHP and other open-source tools together. The project is maintained by [@crazywhalecc](https://github.com/crazywhalecc) and [@henderkes](https://github.com/henderkes), with contributions from the community.
|
||||
The current purpose of this project is to compile statically compiled independent PHP,
|
||||
but the main part also includes compiling static versions of many dependent libraries,
|
||||
so you can reuse this set of compilation logic to build independent binary versions of other programs, such as Nginx, etc.
|
||||
|
||||
You can think of StaticPHP as a typical PHP CLI project built on [symfony/console](https://symfony.com/doc/current/components/console.html).
|
||||
## Environment preparation
|
||||
|
||||
## Development Environment
|
||||
A PHP environment is required to develop this project. You can use the PHP that comes with the system,
|
||||
or you can use the static PHP built by this project.
|
||||
|
||||
To get started with StaticPHP development, you'll need a PHP development environment with the required dependencies installed.
|
||||
Regardless of which PHP you use, in your development environment you need to install these extensions:
|
||||
|
||||
Requirements:
|
||||
```
|
||||
curl,dom,filter,mbstring,openssl,pcntl,phar,posix,sodium,tokenizer,xml,xmlwriter
|
||||
```
|
||||
|
||||
- PHP 8.4 or later
|
||||
- Composer
|
||||
- Git
|
||||
- PHP extensions: `curl, dom, filter, mbstring, openssl, pcntl, phar, posix, sodium, tokenizer, xml, xmlwriter`
|
||||
The static-php-cli project itself does not require so many extensions, but during the development process,
|
||||
you will use tools such as Composer and PHPUnit, which require these extensions.
|
||||
|
||||
> These PHP extensions are required for StaticPHP's `dev` environment.
|
||||
> For micro self-executing binaries built by static-php-cli itself, only `pcntl,posix,mbstring,tokenizer,phar` is required.
|
||||
|
||||
### Setup Steps
|
||||
## Start development
|
||||
|
||||
1. Clone the repository:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/crazywhalecc/static-php-cli.git
|
||||
cd static-php-cli
|
||||
```
|
||||
|
||||
2. Install PHP dependencies:
|
||||
|
||||
```bash
|
||||
composer install
|
||||
```
|
||||
|
||||
3. Verify the setup:
|
||||
|
||||
```bash
|
||||
bin/spc --version
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
You can continue reading [Project Structure](./structure) to learn more about StaticPHP's framework architecture.
|
||||
Continuing down to see the project structure documentation, you can learn how `static-php-cli` works.
|
||||
|
||||
@@ -1,247 +0,0 @@
|
||||
# Package Model
|
||||
|
||||
## Package Definition
|
||||
|
||||
A Package is the core concept in StaticPHP's build system, representing a buildable/installable unit such as a PHP extension, library, or build target.
|
||||
|
||||
Each Package contains build information, dependencies, and build logic, forming StaticPHP's build model. Package definitions are primarily implemented through YAML/JSON configuration files. The package configuration files for the `core` registry are located in the `config/pkg/` directory, and the corresponding build classes are in the `src/Package/` directory.
|
||||
|
||||
Packages are primarily divided into four types:
|
||||
|
||||
- **php-extension**: A PHP extension package containing build information and logic for a PHP extension.
|
||||
- **library**: A library package containing build information and logic for build tools, dependency libraries, etc.
|
||||
- **target**: A build target package representing the final build artifact, such as a PHP binary or curl binary. Inherits from the `library` package type.
|
||||
- **virtual-target**: A virtual build target package representing an abstract build target that doesn't directly correspond to a build artifact, primarily used for dependency management and build scheduling.
|
||||
|
||||
```yaml
|
||||
{pkg-name}:
|
||||
type: {pkg-type}
|
||||
...
|
||||
```
|
||||
|
||||
## Artifact Definition
|
||||
|
||||
An Artifact is a definition independent of Packages. It contains the source archive file or pre-built binary for building packages. Each Artifact defines download URLs, extraction methods, and build artifact file paths. Packages can reference one or more Artifacts via the `artifact` field to obtain the source or binaries needed for building.
|
||||
|
||||
In simple terms, by default one Package corresponds to one Artifact; if multiple Packages share the same source, you can define a single Artifact for multiple Packages to reference. Artifact definitions are located in the `config/artifact/` directory, and the corresponding custom download/extract logic classes are in the `src/Package/Artifact/` directory. For special package types like virtual targets and PHP built-in extensions, a Package may also omit the Artifact field entirely.
|
||||
|
||||
Assuming `example-library-package` is a dependency library whose source archive is hosted at `https://example.com/example-library.tar.gz`, its Package and Artifact definitions would look like this:
|
||||
|
||||
```yaml
|
||||
example-library-package:
|
||||
type: library
|
||||
artifact:
|
||||
source:
|
||||
type: url
|
||||
url: 'https://example.com/example-library.tar.gz'
|
||||
```
|
||||
|
||||
For more on Artifact definitions, see the [Artifact Model](./artifact-model) chapter.
|
||||
|
||||
## php-extension Package Type
|
||||
|
||||
A php-extension package represents a PHP extension. Its configuration file is located in the `config/pkg/ext/` directory, and its build class inherits from `PhpExtensionPackage` in the `src/Package/Extension/` directory. PHP extension package configurations include extension name, version, dependencies, build options, and more.
|
||||
|
||||
```yaml
|
||||
ext-lz4:
|
||||
type: php-extension
|
||||
artifact:
|
||||
source:
|
||||
type: git
|
||||
url: 'https://github.com/kjdev/php-ext-lz4.git'
|
||||
rev: master
|
||||
extract: php-src/ext/lz4
|
||||
metadata:
|
||||
license-files: [LICENSE]
|
||||
license: MIT
|
||||
depends:
|
||||
- liblz4
|
||||
php-extension:
|
||||
arg-type@unix: '--enable-lz4=@shared_suffix@ --with-lz4-includedir=@build_root_path@'
|
||||
arg-type@windows: '--enable-lz4'
|
||||
```
|
||||
|
||||
Allowed fields for `php-extension`:
|
||||
|
||||
```yaml
|
||||
ext-{ext-name}: # Package name must start with ext- prefix
|
||||
type: php-extension
|
||||
|
||||
# ── Common Fields ────────────────────────────────────────────────────────
|
||||
description: '..' # Optional, human-readable package description
|
||||
lang: c # Optional, implementation language of the extension (c / c++ etc.)
|
||||
frameworks: [] # Optional, list of related macOS framework dependencies
|
||||
|
||||
artifact: '{artifact-name}' # Optional; when a string, references an Artifact definition
|
||||
# with the same name; when an object, is an inline Artifact
|
||||
# (built-in extensions don't need this field)
|
||||
|
||||
# depends / suggests support @windows / @unix / @linux / @macos suffixes
|
||||
depends: [] # Optional, hard dependency list (library names as-is, PHP extensions need ext- prefix)
|
||||
depends@unix: [] # Optional, hard dependencies only effective on Unix platforms
|
||||
depends@windows: [] # Optional, hard dependencies only effective on Windows platforms
|
||||
suggests: [] # Optional, optional dependency list (same format as depends)
|
||||
suggests@unix: []
|
||||
|
||||
# ── php-extension Specific Fields (nested under php-extension: object) ────
|
||||
php-extension:
|
||||
# arg-type determines the form of arguments passed to ./configure, supports platform suffixes
|
||||
# Supported platform suffixes: @unix (Linux + macOS), @linux, @macos, @windows
|
||||
# Priority (using Linux as example): arg-type@linux > arg-type@unix > arg-type (no suffix)
|
||||
# Built-in keywords:
|
||||
# enable → --enable-{extname} (default value, used when not configured)
|
||||
# enable-path → --enable-{extname}={buildroot}
|
||||
# with → --with-{extname}
|
||||
# with-path → --with-{extname}={buildroot}
|
||||
# custom/none → Pass no arguments (handled by the #[CustomPhpConfigureArg] method in the PHP class)
|
||||
# You can also write the full argument string directly, supporting the following placeholders:
|
||||
# @build_root_path@ → BUILD_ROOT_PATH (absolute path of buildroot)
|
||||
# @shared_suffix@ → Expands to =shared in shared builds, empty in static builds
|
||||
# @shared_path_suffix@ → Expands to =shared,{buildroot} in shared builds,
|
||||
# expands to ={buildroot} in static builds
|
||||
arg-type: enable
|
||||
arg-type@unix: '--enable-{extname}=@shared_suffix@'
|
||||
arg-type@windows: with-path
|
||||
|
||||
zend-extension: false # Optional, true indicates this is a Zend extension (e.g., opcache, xdebug)
|
||||
build-shared: true # Optional, whether building as a shared extension (.so) is allowed, default true
|
||||
build-static: true # Optional, whether inline static building (compiled into PHP) is allowed, default true
|
||||
build-with-php: true # Optional, true means the extension is built together via the PHP source tree
|
||||
# (used for built-in extensions)
|
||||
|
||||
# display-name affects the php --ri argument in smoke tests and the license export display name
|
||||
# If not set, defaults to the extension name (the part after ext-); if set to empty string, skips --ri check
|
||||
display-name: 'My Extension'
|
||||
|
||||
# os restricts the extension to be available only on specified platforms;
|
||||
# platforms not in the list will be rejected for building
|
||||
# Allowed values: Linux, Darwin, Windows
|
||||
os: [Linux, Darwin]
|
||||
```
|
||||
|
||||
## library Package Type
|
||||
|
||||
A library package represents a dependency library that needs to be compiled from source (such as openssl, zlib, etc.). Its configuration file is located in the `config/pkg/lib/` directory, and its build class inherits from `LibraryPackage` in the `src/Package/Library/` directory.
|
||||
|
||||
Taking openssl as an example:
|
||||
|
||||
```yaml
|
||||
openssl:
|
||||
type: library
|
||||
artifact:
|
||||
source:
|
||||
type: ghrel
|
||||
repo: openssl/openssl
|
||||
match: openssl.+\.tar\.gz
|
||||
prefer-stable: true
|
||||
binary: hosted
|
||||
metadata:
|
||||
license-files: [LICENSE.txt]
|
||||
license: OpenSSL
|
||||
depends:
|
||||
- zlib
|
||||
depends@windows:
|
||||
- zlib
|
||||
- jom
|
||||
headers:
|
||||
- openssl
|
||||
static-libs@unix:
|
||||
- libssl.a
|
||||
- libcrypto.a
|
||||
static-libs@windows:
|
||||
- libssl.lib
|
||||
- libcrypto.lib
|
||||
```
|
||||
|
||||
Allowed fields for `library`:
|
||||
|
||||
```yaml
|
||||
{lib-name}:
|
||||
type: library # library or target (target inherits all fields from library)
|
||||
|
||||
# ── Common Fields ─────────────────────────────────────────────────────────
|
||||
description: '..' # Optional, human-readable package description
|
||||
license: MIT # Optional, SPDX license identifier (for license export)
|
||||
lang: c # Optional, implementation language of the library (c / c++ etc.)
|
||||
frameworks: [] # Optional, list of related framework tags
|
||||
|
||||
artifact: '{artifact-name}' # Required; when a string, references an Artifact definition
|
||||
# with the same name; when an object, is an inline Artifact
|
||||
|
||||
# depends / suggests support @windows / @unix / @linux / @macos suffixes
|
||||
depends: [] # Optional, hard dependency list (library names or PHP extension names with ext- prefix)
|
||||
depends@unix: []
|
||||
depends@windows: []
|
||||
suggests: [] # Optional, optional dependency list (same format as depends)
|
||||
|
||||
# ── library / target Specific Fields ───────────────────────────────────────
|
||||
# The following fields are used to verify that artifacts have been correctly
|
||||
# installed after the build. They support @unix / @windows / @linux / @macos suffixes.
|
||||
|
||||
# Verify that specified header files or directories exist under buildroot/include/
|
||||
# Relative paths are based on buildroot/include/, absolute paths are used directly
|
||||
headers:
|
||||
- openssl # Corresponds to buildroot/include/openssl/
|
||||
- zlib.h # Corresponds to buildroot/include/zlib.h
|
||||
headers@unix:
|
||||
- ffi.h
|
||||
|
||||
# Verify that specified static library files exist under buildroot/lib/
|
||||
# Relative paths are based on buildroot/lib/, absolute paths are used directly
|
||||
static-libs@unix:
|
||||
- libssl.a
|
||||
static-libs@windows:
|
||||
- libssl.lib
|
||||
|
||||
# Verify that specified .pc files exist under buildroot/lib/pkgconfig/
|
||||
# Only checked on non-Windows platforms (pkg-config is not applicable on Windows)
|
||||
pkg-configs:
|
||||
- openssl # Corresponds to buildroot/lib/pkgconfig/openssl.pc
|
||||
- libssl # Auto-completes .pc suffix
|
||||
|
||||
# Verify that specified executable files exist under buildroot/bin/
|
||||
# Relative paths are based on buildroot/bin/, absolute paths are used directly
|
||||
static-bins:
|
||||
- my-tool
|
||||
|
||||
# List of directories injected into the global PATH after the package is installed.
|
||||
# Path placeholders are supported (see below for details).
|
||||
path:
|
||||
- '{pkg_root_path}/rust/bin'
|
||||
|
||||
# Environment variables set after the package is installed (overwrites existing values).
|
||||
# Path placeholders are supported.
|
||||
env:
|
||||
MY_VAR: '{build_root_path}/lib'
|
||||
|
||||
# Values appended to the end of existing environment variables after the package is installed.
|
||||
# Path placeholders are supported.
|
||||
append-env:
|
||||
CFLAGS: ' -I{build_root_path}/include'
|
||||
```
|
||||
|
||||
The following path placeholders are supported in string values of the `path`, `env`, and `append-env` fields:
|
||||
|
||||
| Placeholder | Actual Path |
|
||||
|---|---|
|
||||
| `{build_root_path}` | buildroot directory (`buildroot/`) |
|
||||
| `{pkg_root_path}` | pkgroot directory (`pkgroot/`) |
|
||||
| `{working_dir}` | Working directory (project root) |
|
||||
| `{download_path}` | Download cache directory (`downloads/`) |
|
||||
| `{source_path}` | Extracted source directory (`source/`) |
|
||||
| `{php_sdk_path}` | Windows PHP SDK directory |
|
||||
|
||||
## target Package Type
|
||||
|
||||
A `target` package represents a final build artifact. It inherits from `library`, so it includes all definition fields of `library`. The configuration file for `target` packages is located in the `config/pkg/target/` directory, and its build class inherits from `TargetPackage` in the `src/Package/Target/` directory.
|
||||
|
||||
The only difference from `library` is that a `target` package can be registered as a build target and automatically registers the build command `spc build:{target-name}`.
|
||||
|
||||
## virtual-target Package Type
|
||||
|
||||
Unlike `target`, a `virtual-target` may not include an `artifact`, meaning it doesn't directly correspond to a buildable entity but is instead an abstract build target, primarily used for dependency management and build scheduling. The configuration file for `virtual-target` is located in the `config/pkg/target/` directory, and its build class inherits from `TargetPackage` in the `src/Package/Target/` directory. Its definition is essentially the same as `target`, but the `artifact` field is optional and typically not set. `virtual-target` is primarily used in the following scenarios:
|
||||
|
||||
- Defining an abstract build target for other packages to depend on, without directly corresponding to a buildable entity.
|
||||
- Serving as a common dependency for multiple `target` packages, simplifying dependency management.
|
||||
|
||||
A typical example is the `php-cli`, `php-fpm` build targets for PHP. They have no independent source code and depend on `php-src`, with the final build outcome (CLI or FPM binary) determined through build scheduling.
|
||||
@@ -1,4 +1,59 @@
|
||||
# PHP Source Modifications
|
||||
# Modifications to PHP source code
|
||||
|
||||
<!-- TODO: Migrate and update from v2 php-src-changes.md.
|
||||
Add v3-specific patches (FrankenPHP embed, Windows fiber fix, etc.). -->
|
||||
During the static compilation process, static-php-cli made some modifications to the PHP source code
|
||||
in order to achieve good compatibility, performance, and security.
|
||||
The following is a description of the current modifications to the PHP source code.
|
||||
|
||||
## Micro related patches
|
||||
|
||||
Based on the patches provided by the phpmicro project,
|
||||
static-php-cli has made some modifications to the PHP source code to meet the needs of static compilation.
|
||||
The patches currently used by static-php-cli during compilation in the [patch list](https://github.com/easysoft/phpmicro/tree/master/patches) are:
|
||||
|
||||
- static_opcache
|
||||
- static_extensions_win32
|
||||
- cli_checks
|
||||
- disable_huge_page
|
||||
- vcruntime140
|
||||
- win32
|
||||
- zend_stream
|
||||
- cli_static
|
||||
- macos_iconv
|
||||
- phar
|
||||
|
||||
## PHP <= 8.1 libxml patch
|
||||
|
||||
Because PHP only provides security updates for 8.1 and stops updating older versions,
|
||||
static-php-cli applies the libxml compilation patch that has been applied in newer versions of PHP to PHP 8.1 and below.
|
||||
|
||||
## gd extension Windows patch
|
||||
|
||||
Compiling the gd extension under Windows requires major changes to the `config.w32` file.
|
||||
static-php-cli has made some changes to the gd extension to make it easier to compile under Windows.
|
||||
|
||||
## YAML extension Windows patch
|
||||
|
||||
YAML extension needs to modify the `config.w32` file to compile under Windows.
|
||||
static-php-cli has made some modifications to the YAML extension to make it easier to compile under Windows.
|
||||
|
||||
## static-php-cli version information insertion
|
||||
|
||||
When compiling, static-php-cli will insert the static-php-cli version information into the PHP version information for easy identification.
|
||||
|
||||
## Add option to hardcode INI
|
||||
|
||||
When using the `-I` parameter to hardcode INI into static PHP functionality,
|
||||
static-php-cli will modify the PHP source code to insert the hardcoded content.
|
||||
|
||||
## Linux system repair patch
|
||||
|
||||
Some compilation environments may lack some system header files or libraries.
|
||||
static-php-cli will automatically fix these problems during compilation, such as:
|
||||
|
||||
- HAVE_STRLCAT missing problem
|
||||
- HAVE_STRLCPY missing problem
|
||||
|
||||
## Fiber issue fix patch for Windows
|
||||
|
||||
When compiling PHP on Windows, there will be some issues with the Fiber extension.
|
||||
static-php-cli will automatically fix these issues during compilation (modify `config.w32` in php-src).
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
# Registry & Plugin System
|
||||
|
||||
## Overview
|
||||
|
||||
The **Registry** is StaticPHP's core extension mechanism. Think of it as a "plugin package": a Registry consists of a declaration file (`spc.registry.yml`) and the configuration files and PHP classes it points to, describing a set of package definitions (YAML configuration) and their corresponding build logic (PHP classes). The build system loads all registered Registries at startup and merges their package definitions for use throughout the entire build process.
|
||||
|
||||
StaticPHP ships with a built-in core registry (`core`) that contains all definitions for PHP and related extensions, libraries, build tools, and more. The declaration file for the `core` registry is `spc.registry.yml` in the project root, which describes the mapping between the configuration file directory (`config/pkg/`, `config/artifact/`) and the build class PSR-4 namespace (`src/Package/`).
|
||||
|
||||
External Registries can only define new packages that don't already exist in `core`; they cannot override or modify existing definitions in the core registry. Depending on your needs, there are three ways to extend or modify StaticPHP's build capabilities:
|
||||
|
||||
- **Modify the `core` registry**: Directly edit files under `src/Package` and `config/pkg/`, suitable when you want to contribute changes back to the StaticPHP mainline. Please read the [Contributing Guide](../contributing/) section on contributing new packages before submitting a PR.
|
||||
- **Vendor Mode**: Package your custom packages as a standalone sub-registry distributed as a Composer package, suitable for private packages or scenarios where you want to reuse build logic as a library. See [Extending StaticPHP](./extending/) for details.
|
||||
- **External Registry (`SPC_REGISTRIES`)**: Specify one or more external registry file paths via the `SPC_REGISTRIES` environment variable, which StaticPHP loads at startup. Suitable for temporary extensions or scenarios where packaging as a Composer package isn't practical, similar to external source mechanisms in other package managers.
|
||||
|
||||
## Registry Declaration File
|
||||
|
||||
Each Registry has a declaration file, typically named `spc.registry.yml`, located in the project root or the root of a Composer package. The file format supports YAML (`.yml` / `.yaml`) and JSON (`.json`). All paths within the file are resolved relative to the directory containing the declaration file itself.
|
||||
|
||||
In source mode (direct git clone), StaticPHP loads `spc.registry.yml` in the project root as the core registry (`core`) by default. In Vendor mode, it automatically detects whether `spc.registry.yml` exists in the current Composer package root and loads it as a standalone registry. External registries specified via the `SPC_REGISTRIES` environment variable must also contain a valid declaration file.
|
||||
|
||||
Below is a complete example with all available fields (based on the `core` registry):
|
||||
|
||||
```yaml
|
||||
# [Required] Unique registry name; loading a registry with a duplicate name is automatically skipped
|
||||
name: my-registry
|
||||
|
||||
# [Optional] Composer autoload file path, used when an external registry has its own dependencies
|
||||
autoload: vendor/autoload.php
|
||||
|
||||
# Package (library / php-extension / target) related configuration
|
||||
package:
|
||||
# YAML configuration file directory or specific file paths for packages, can be an array
|
||||
config:
|
||||
- config/pkg/lib/
|
||||
- config/pkg/target/
|
||||
- config/pkg/ext/
|
||||
# PSR-4 namespace → directory path mapping for package build classes; the loader scans all PHP classes in the directory
|
||||
psr-4:
|
||||
Package: src/Package
|
||||
# You can also load specific classes as needed, supporting array format or {"ClassName": "file path"} mapping
|
||||
# classes:
|
||||
# - Package\Library\MyLib
|
||||
# MyLib: src/Package/Library/MyLib.php
|
||||
|
||||
# Artifact (build artifact) related configuration
|
||||
artifact:
|
||||
# YAML configuration file directory or specific file paths for artifacts
|
||||
config:
|
||||
- config/artifact/
|
||||
# PSR-4 namespace → directory path mapping for custom artifact download/extract classes
|
||||
psr-4:
|
||||
Package\Artifact: src/Package/Artifact
|
||||
# classes: ... (same format as package.classes)
|
||||
|
||||
# Doctor environment check configuration
|
||||
doctor:
|
||||
# PSR-4 namespace → directory path mapping for Doctor check item classes
|
||||
psr-4:
|
||||
StaticPHP\Doctor\Item: src/StaticPHP/Doctor/Item
|
||||
# classes: ... (same format as package.classes)
|
||||
|
||||
# Additional CLI command configuration
|
||||
command:
|
||||
# PSR-4 namespace → directory path mapping for custom command classes
|
||||
psr-4:
|
||||
Package\Command: src/Package\Command
|
||||
# classes: ... (same format as package.classes)
|
||||
```
|
||||
|
||||
Top-level field descriptions:
|
||||
|
||||
| Field | Required | Description |
|
||||
|---|---|---|
|
||||
| `name` | ✅ | Unique registry name; loading a registry with a duplicate name is automatically skipped |
|
||||
| `autoload` | | Composer autoload file path, for external registries that carry their own dependencies |
|
||||
| `package` | | Package definition, including YAML config (`config`) and build classes (`psr-4` / `classes`) |
|
||||
| `artifact` | | Artifact definition, including YAML config (`config`) and custom classes (`psr-4` / `classes`) |
|
||||
| `doctor` | | Doctor check item definition, class loading only (`psr-4` / `classes`) |
|
||||
| `command` | | Additional CLI command definition, class loading only (`psr-4` / `classes`) |
|
||||
|
||||
The difference between `psr-4` and `classes`: `psr-4` scans all PHP classes in the entire directory that match the namespace rules and registers them in bulk; `classes` is used to precisely specify individual classes, supporting plain array format (`["ClassName"]`, must already be available in autoload) or key-value mapping format (`{"ClassName": "path/to/file.php"}`, the loader will automatically `require` the corresponding file).
|
||||
372
docs/en/develop/source-module.md
Normal file
372
docs/en/develop/source-module.md
Normal file
@@ -0,0 +1,372 @@
|
||||
# Source module
|
||||
|
||||
The download source module of static-php-cli is a major module.
|
||||
It includes dependent libraries, external extensions, PHP source code download methods and file decompression methods.
|
||||
The download configuration file mainly involves the `source.json` and `pkg.json` file, which records the download method of all downloadable sources.
|
||||
|
||||
The main commands involved in the download function are `bin/spc download` and `bin/spc extract`.
|
||||
The `download` command is a downloader that downloads sources according to the configuration file,
|
||||
and the `extract` command is an extractor that extract sources from downloaded files.
|
||||
|
||||
Generally speaking, downloading sources may be slow because these sources come from various official websites, GitHub,
|
||||
and other different locations.
|
||||
At the same time, they also occupy a large space, so you can download the sources once and reuse them.
|
||||
|
||||
The configuration file of the downloader is `source.json`, which contains the download methods of all sources.
|
||||
You can add the source download methods you need, or modify the existing source download methods.
|
||||
|
||||
The download configuration structure of each source is as follows.
|
||||
The following is the source download configuration corresponding to the `libevent` extension:
|
||||
|
||||
```json
|
||||
{
|
||||
"libevent": {
|
||||
"type": "ghrel",
|
||||
"repo": "libevent/libevent",
|
||||
"match": "libevent.+\\.tar\\.gz",
|
||||
"provide-pre-built": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The most important field here is `type`. Currently, the types it supports are:
|
||||
|
||||
- `url`: Directly use URL to download, for example: `https://download.libsodium.org/libsodium/releases/libsodium-1.0.18.tar.gz`.
|
||||
- `pie`: Download PHP extensions from Packagist using the PIE (PHP Installer for Extensions) standard.
|
||||
- `ghrel`: Use the GitHub Release API to download, download the artifacts uploaded from the latest version released by maintainers.
|
||||
- `ghtar`: Use the GitHub Release API to download.
|
||||
Different from `ghrel`, `ghtar` is downloaded from the `source code (tar.gz)` in the latest Release of the project.
|
||||
- `ghtagtar`: Use GitHub Release API to download.
|
||||
Compared with `ghtar`, `ghtagtar` can find the latest one from the `tags` list and download the source code in `tar.gz` format
|
||||
(because some projects only use `tag` release version).
|
||||
- `bitbuckettag`: Download using BitBucket API, basically the same as `ghtagtar`, except this one applies to BitBucket.
|
||||
- `git`: Clone the project directly from a Git address to download sources, applicable to any public Git repository.
|
||||
- `filelist`: Use a crawler to crawl the Web download site that provides file index,
|
||||
and get the latest version of the file name and download it.
|
||||
- `custom`: If none of the above download methods are satisfactory, you can write `custom`,
|
||||
create a new class under `src/SPC/store/source/`, extends `CustomSourceBase`, and write the download script yourself.
|
||||
|
||||
## source.json Common parameters
|
||||
|
||||
Each source file in source.json has the following params:
|
||||
|
||||
- `license`: the open source license of the source code, see **Open Source License** section below
|
||||
- `type`: must be one of the types mentioned above
|
||||
- `path` (optional): release the source code to the specified directory instead of `source/{name}`
|
||||
- `provide-pre-built` (optional): whether to provide precompiled binary files.
|
||||
If `true`, it will automatically try to download precompiled binary files when running `bin/spc download`
|
||||
|
||||
::: tip
|
||||
The `path` parameter in `source.json` can specify a relative or absolute path. When specified as a relative path, the path is based on `source/`.
|
||||
:::
|
||||
|
||||
## Download type - url
|
||||
|
||||
URL type sources refer to downloading files directly from the URL.
|
||||
|
||||
The parameters included are:
|
||||
|
||||
- `url`: The download address of the file, such as `https://example.com/file.tgz`
|
||||
- `filename` (optional): The file name saved to the local area. If not specified, the file name of the url will be used.
|
||||
|
||||
Example (download the imagick extension and extract it to the extension storage path of the php source code):
|
||||
|
||||
```json
|
||||
{
|
||||
"ext-imagick": {
|
||||
"type": "url",
|
||||
"url": "https://pecl.php.net/get/imagick",
|
||||
"path": "php-src/ext/imagick",
|
||||
"filename": "imagick.tgz",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Download type - pie
|
||||
|
||||
PIE (PHP Installer for Extensions) type sources refer to downloading PHP extensions from Packagist that follow the PIE standard.
|
||||
This method automatically fetches extension information from the Packagist repository and downloads the appropriate distribution file.
|
||||
|
||||
The parameters included are:
|
||||
|
||||
- `repo`: The Packagist vendor/package name, such as `vendor/package-name`
|
||||
|
||||
Example (download a PHP extension from Packagist using PIE):
|
||||
|
||||
```json
|
||||
{
|
||||
"ext-example": {
|
||||
"type": "pie",
|
||||
"repo": "vendor/example-extension",
|
||||
"path": "php-src/ext/example",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
The PIE download type will automatically detect the extension information from Packagist metadata,
|
||||
including the download URL, version, and distribution type.
|
||||
The extension must be marked as `type: php-ext` or contain `php-ext` metadata in its Packagist package definition.
|
||||
:::
|
||||
|
||||
## Download type - ghrel
|
||||
|
||||
ghrel will download files from Assets uploaded in GitHub Release.
|
||||
First use the GitHub Release API to get the latest version, and then download the corresponding files according to the regular matching method.
|
||||
|
||||
The parameters included are:
|
||||
|
||||
- `repo`: GitHub repository name
|
||||
- `match`: regular expression matching Assets files
|
||||
- `prefer-stable`: Whether to download stable versions first (default is `false`)
|
||||
|
||||
Example (download the libsodium library, matching the libsodium-x.y.tar.gz file in Release):
|
||||
|
||||
```json
|
||||
{
|
||||
"libsodium": {
|
||||
"type": "ghrel",
|
||||
"repo": "jedisct1/libsodium",
|
||||
"match": "libsodium-\\d+(\\.\\d+)*\\.tar\\.gz",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Download type - ghtar
|
||||
|
||||
ghtar will download the file from the GitHub Release Tag.
|
||||
Unlike `ghrel`, `ghtar` will download the `source code (tar.gz)` from the latest Release of the project.
|
||||
|
||||
The parameters included are:
|
||||
|
||||
- `repo`: GitHub repository name
|
||||
- `prefer-stable`: Whether to download stable versions first (default is `false`)
|
||||
|
||||
Example (brotli library):
|
||||
|
||||
```json
|
||||
{
|
||||
"brotli": {
|
||||
"type": "ghtar",
|
||||
"repo": "google/brotli",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Download type - ghtagtar
|
||||
|
||||
Use the GitHub Release API to download.
|
||||
Compared with `ghtar`, `ghtagtar` can find the latest one from the `tags` list and download the source code in `tar.gz` format
|
||||
(because some projects only use the `tag` version).
|
||||
|
||||
The parameters included are:
|
||||
|
||||
- `repo`: GitHub repository name
|
||||
- `prefer-stable`: Whether to download stable versions first (default is `false`)
|
||||
|
||||
Example (gmp library):
|
||||
|
||||
```json
|
||||
{
|
||||
"gmp": {
|
||||
"type": "ghtagtar",
|
||||
"repo": "alisw/GMP",
|
||||
"license": {
|
||||
"type": "text",
|
||||
"text": "EXAMPLE LICENSE"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Download Type - bitbuckettag
|
||||
|
||||
Download using BitBucket API, basically the same as `ghtagtar`, except this one works with BitBucket.
|
||||
|
||||
The parameters included are:
|
||||
|
||||
- `repo`: BitBucket repository name
|
||||
|
||||
## Download type - git
|
||||
|
||||
Clone the project directly from a Git address to download sources, applicable to any public Git repository.
|
||||
|
||||
The parameters included are:
|
||||
|
||||
- `url`: Git link (HTTPS only)
|
||||
- `rev`: branch name
|
||||
|
||||
```json
|
||||
{
|
||||
"imap": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/static-php/imap.git",
|
||||
"rev": "master",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Download type - filelist
|
||||
|
||||
Use a crawler to crawl a web download site that provides a file index and get the latest version of the file name and download it.
|
||||
|
||||
Note that this method is only applicable to static sites with page index functions such as mirror sites and GNU official websites.
|
||||
|
||||
The parameters included are:
|
||||
|
||||
- `url`: The URL of the page to crawl the latest version of the file
|
||||
- `regex`: regular expression matching file names and download links
|
||||
|
||||
Example (download the libiconv library from the GNU official website):
|
||||
|
||||
```json
|
||||
{
|
||||
"libiconv": {
|
||||
"type": "filelist",
|
||||
"url": "https://ftp.gnu.org/gnu/libiconv/",
|
||||
"regex": "/href=\"(?<file>libiconv-(?<version>[^\"]+)\\.tar\\.gz)\"/",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Download type - custom
|
||||
|
||||
If the above downloading methods are not satisfactory, you can write `custom`,
|
||||
create a new class under `src/SPC/store/source/`, extends `CustomSourceBase`, and write the download script yourself.
|
||||
|
||||
I won’t go into details here, you can look at `src/SPC/store/source/PhpSource.php` or `src/SPC/store/source/PostgreSQLSource.php` as examples.
|
||||
|
||||
## pkg.json General parameters
|
||||
|
||||
pkg.json stores non-source-code files, such as precompiled tools musl-toolchain and UPX. It includes:
|
||||
|
||||
- `type`: The same type as `source.json` and different kinds of parameters.
|
||||
- `extract` (optional): The path to decompress after downloading, the default is `pkgroot/{pkg_name}`.
|
||||
- `extract-files` (optional): Extract only the specified files to the specified location after downloading.
|
||||
|
||||
It should be noted that `pkg.json` does not involve compilation, modification and distribution of source code,
|
||||
so there is no `license` open source license field.
|
||||
And you cannot use the `extract` and `extract-files` parameters at the same time.
|
||||
|
||||
Example (download nasm locally and extract only program files to PHP SDK):
|
||||
|
||||
```json
|
||||
{
|
||||
"nasm-x86_64-win": {
|
||||
"type": "url",
|
||||
"url": "https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win64/nasm-2.16.01-win64.zip",
|
||||
"extract-files": {
|
||||
"nasm-2.16.01/nasm.exe": "{php_sdk_path}/bin/nasm.exe",
|
||||
"nasm-2.16.01/ndisasm.exe": "{php_sdk_path}/bin/ndisasm.exe"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The key name in `extract-files` is the file in the source folder, and the key value is the storage path. The storage path can use the following variables:
|
||||
|
||||
- `{php_sdk_path}`: (Windows only) PHP SDK path
|
||||
- `{pkg_root_path}`: `pkgroot/`
|
||||
- `{working_dir}`: current working directory
|
||||
- `{download_path}`: download directory
|
||||
- `{source_path}`: source code decompression directory
|
||||
|
||||
When `extract-files` does not use variables and is a relative path, the directory of the relative path is `{working_dir}`.
|
||||
|
||||
## Open source license
|
||||
|
||||
For `source.json`, each source file should contain an open source license.
|
||||
The `license` field stores the open source license information.
|
||||
|
||||
Each `license` contains the following parameters:
|
||||
|
||||
- `type`: `file` or `text`
|
||||
- `path`: the license file in the source code directory (required when `type` is `file`)
|
||||
- `text`: License text (required when `type` is `text`)
|
||||
|
||||
Example (yaml extension source code with LICENSE file):
|
||||
|
||||
```json
|
||||
{
|
||||
"yaml": {
|
||||
"type": "git",
|
||||
"path": "php-src/ext/yaml",
|
||||
"rev": "php7",
|
||||
"url": "https://github.com/php/pecl-file_formats-yaml",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When an open source project has multiple licenses, multiple files can be specified:
|
||||
|
||||
```json
|
||||
{
|
||||
"libuv": {
|
||||
"type": "ghtar",
|
||||
"repo": "libuv/libuv",
|
||||
"license": [
|
||||
{
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"path": "LICENSE-extra"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When the license of an open source project uses different files between versions,
|
||||
`path` can be used as an array to list the possible license files:
|
||||
|
||||
```json
|
||||
{
|
||||
"redis": {
|
||||
"type": "git",
|
||||
"path": "php-src/ext/redis",
|
||||
"rev": "release/6.0.2",
|
||||
"url": "https://github.com/phpredis/phpredis",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": [
|
||||
"LICENSE",
|
||||
"COPYING"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1,84 +1,180 @@
|
||||
# Project Structure
|
||||
# Introduction to project structure
|
||||
|
||||
## Concepts
|
||||
static-php-cli mainly contains three logical components: sources, dependent libraries, and extensions.
|
||||
These components contains 4 configuration files: `source.json`, `pkg.json`, `lib.json`, and `ext.json`.
|
||||
|
||||
StaticPHP is a CLI application built on `symfony/console`, with core code located in the `src/StaticPHP` directory. It is organized into several modules:
|
||||
A complete process for building standalone static PHP is:
|
||||
|
||||
- **Registry**: Manages registry data. Each registry contains multiple packages (Package), and the StaticPHP project ships with a built-in `core` registry that includes PHP and related extensions, dependencies, and more.
|
||||
- **Package**: Represents a single package. There are four package types: `php-extension` (PHP extension), `library` (library), `target` (build target), and `virtual-target` (virtual build target). Each package contains build information, dependencies, and more.
|
||||
- **Installer/Builder**: Handles installation and build logic for packages — executing build commands, extracting build artifacts, processing build results, etc.
|
||||
- **Doctor**: Provides system environment checking, responsible for installing and verifying system-level dependencies such as `make`, `cmake`, `autoconf`, and more.
|
||||
- **Runtime/Executor**: Contains runtime-related utility classes, such as shell command execution and CMake build execution.
|
||||
- **Toolchain**: Provides toolchain abstraction interfaces for different operating systems and environments, handling system-level differences during the build process.
|
||||
- **Utils**: General-purpose utility classes, such as file system operations, logging, and OS-specific helper methods.
|
||||
- **DependencyResolver**: Resolves dependencies between packages and generates build order.
|
||||
1. Use the source download module `Downloader` to download specified or all source codes.
|
||||
These sources include PHP source code, dependent library source code, and extension source code.
|
||||
2. Use the source decompression module `SourceExtractor` to decompress the downloaded sources to the compilation directory.
|
||||
3. Use the dependency tool to calculate the dependent extensions and dependent libraries of the currently added extension,
|
||||
and then compile each library that needs to be compiled in the order of dependencies.
|
||||
4. After building each dependent library using `Builder` under the corresponding operating system, install it to the `buildroot` directory.
|
||||
5. If external extensions are included (the source code does not contain extensions within PHP),
|
||||
copy the external extensions to the `source/php-src/ext/` directory.
|
||||
6. Use `Builder` to build the PHP source code and build target to the `buildroot` directory.
|
||||
|
||||
## Directory Layout
|
||||
The project is mainly divided into several folders:
|
||||
|
||||
- `bin/`: used to store program entry files, including `bin/spc`, `bin/spc-alpine-docker`, `bin/setup-runtime`.
|
||||
- `config/`: Contains all the extensions and dependent libraries supported by the project,
|
||||
as well as the download link and download methods of these sources. It is divided into files: `lib.json`, `ext.json`, `source.json`, `pkg.json`, `pre-built.json` .
|
||||
- `src/`: The core code of the project, including the entire framework and commands for compiling various extensions and libraries.
|
||||
- `vendor/`: The directory that Composer depends on, you do not need to make any modifications to it.
|
||||
|
||||
The operating principle is to start a `ConsoleApplication` of `symfony/console`, and then parse the commands entered by the user in the terminal.
|
||||
|
||||
## Basic command line structure
|
||||
|
||||
`bin/spc` is an entry file, including the Unix common `#!/usr/bin/env php`,
|
||||
which is used to allow the system to automatically execute with the PHP interpreter installed on the system.
|
||||
After the project executes `new ConsoleApplication()`, the framework will automatically register them as commands.
|
||||
|
||||
The project does not directly use the Command registration method and command execution method recommended by Symfony. Here are small changes:
|
||||
|
||||
1. Each command uses the `#[AsCommand()]` Attribute to register the name and description.
|
||||
2. Abstract `execute()` so that all commands are based on `BaseCommand` (which is based on `Symfony\Component\Console\Command\Command`),
|
||||
and the execution code of each command itself is written in the `handle()` method .
|
||||
3. Added variable `$no_motd` to `BaseCommand`, which is used to display the Figlet greeting when the command is executed.
|
||||
4. `BaseCommand` saves `InputInterface` and `OutputInterface` as member variables. You can use `$this->input` and `$this->output` within the command class.
|
||||
|
||||
## Basic source code structure
|
||||
|
||||
The source code of the project is located in the `src/SPC` directory,
|
||||
supports automatic loading of the PSR-4 standard, and contains the following subdirectories and classes:
|
||||
|
||||
- `src/SPC/builder/`: The core compilation command code used to build libraries,
|
||||
PHP and related extensions under different operating systems, and also includes some compilation system tool methods.
|
||||
- `src/SPC/command/`: All commands of the project are here.
|
||||
- `src/SPC/doctor/`: Doctor module, which is a relatively independent module used to check the system environment.
|
||||
It can be entered using the command `bin/spc doctor`.
|
||||
- `src/SPC/exception/`: exception class.
|
||||
- `src/SPC/store/`: Classes related to storage, files and sources are all here.
|
||||
- `src/SPC/util/`: Some reusable tool methods are here.
|
||||
- `src/SPC/ConsoleApplication.php`: command line program entry file.
|
||||
|
||||
If you have read the source code, you may find that there is also a `src/globals/` directory,
|
||||
which is used to store some global variables, global methods,
|
||||
and non-PSR-4 standard PHP source code that is relied upon during the build process, such as extension sanity check code etc.
|
||||
|
||||
## Phar application directory issue
|
||||
|
||||
Like other php-cli projects, spc itself has additional considerations for paths.
|
||||
Because spc can run in multiple modes such as `php-cli directly`, `micro SAPI`, `php-cli with Phar`, `vendor with Phar`, etc.,
|
||||
there are ambiguities in various root directories. A complete explanation is given here.
|
||||
This problem is generally common in the base class path selection problem of accessing files in PHP projects, especially when used with `micro.sfx`.
|
||||
|
||||
Note that this may only be useful for you when developing Phar projects or PHP frameworks.
|
||||
|
||||
> Next, we will treat `static-php-cli` (that is, spc) as a normal `php` command line program. You can understand spc as any of your own php-cli applications for reference.
|
||||
|
||||
There are three basic constant theoretical values below. We recommend that you introduce these three constants when writing PHP projects:
|
||||
|
||||
- `WORKING_DIR`: the working directory when executing PHP scripts
|
||||
|
||||
- `SOURCE_ROOT_DIR` or `ROOT_DIR`: the root directory of the project folder, generally the directory where `composer.json` is located
|
||||
|
||||
- `FRAMEWORK_ROOT_DIR`: the root directory of the framework used, which may be used by self-developed frameworks. Generally, the framework directory is read-only
|
||||
|
||||
You can define these constants in your framework entry or cli applications to facilitate the use of paths in your project.
|
||||
|
||||
The following are PHP built-in constant values, which have been defined inside the PHP interpreter:
|
||||
|
||||
- `__DIR__`: the directory where the file of the currently executed script is located
|
||||
|
||||
- `__FILE__`: the file path of the currently executed script
|
||||
|
||||
### Git project mode (source)
|
||||
|
||||
Git project mode refers to a framework or program itself stored in plain text in the current folder, and running through `php path/to/entry.php`.
|
||||
|
||||
Assume that your project is stored in the `/home/example/static-php-cli/` directory, or your project is the framework itself,
|
||||
which contains project files such as `composer.json`:
|
||||
|
||||
```
|
||||
static-php-cli/
|
||||
├── bin/ # Executable entry scripts (spc, spc.ps1, setup-runtime, etc.)
|
||||
├── config/
|
||||
│ ├── env.ini # Default environment variable configuration
|
||||
│ ├── env.custom.ini # User-defined environment variables (overrides env.ini)
|
||||
│ ├── artifact/ # Build artifact configuration (toolchain downloads, pre-built binaries, etc.)
|
||||
│ └── pkg/ # Package configuration files (YAML)
|
||||
│ ├── ext/ # PHP extension package config (ext-*.yml, builtin-extensions.yml)
|
||||
│ ├── lib/ # Library package config (*.yml)
|
||||
│ └── target/ # Build target config (php.yml, curl.yml, etc.)
|
||||
├── src/
|
||||
│ ├── bootstrap.php # Application bootstrap (auto-loading, DI container, etc.)
|
||||
│ ├── globals/ # Global helper functions
|
||||
│ ├── Package/ # Build logic implementations for each package (PHP classes)
|
||||
│ │ ├── Artifact/ # Custom download/extract logic for build artifacts
|
||||
│ │ ├── Command/ # Package-level custom commands
|
||||
│ │ ├── Extension/ # PHP extension build classes (ext-*.php)
|
||||
│ │ ├── Library/ # Library build classes (*.php)
|
||||
│ │ └── Target/ # Build target classes (php.php, curl.php, etc.)
|
||||
│ └── StaticPHP/ # Framework core code
|
||||
│ ├── ConsoleApplication.php # Symfony Console application entry
|
||||
│ ├── Artifact/ # Build artifact download and extraction (Downloader, Extractor, etc.)
|
||||
│ ├── Attribute/ # PHP attribute definitions
|
||||
│ │ ├── Artifact/ # Artifact-related attributes (CustomSource, BinaryExtract, etc.)
|
||||
│ │ ├── Doctor/ # Doctor-related attributes (CheckItem, FixItem, etc.)
|
||||
│ │ └── Package/ # Package build-related attributes (BuildFor, BeforeStage, AfterStage,
|
||||
│ │ # CustomPhpConfigureArg, PatchBeforeBuild, etc.)
|
||||
│ ├── Command/ # CLI command implementations (build-libs, build-target, doctor, etc.)
|
||||
│ ├── Config/ # Configuration loading and validation (PackageConfig, ArtifactConfig, etc.)
|
||||
│ ├── DI/ # Dependency injection container (ApplicationContext, CallbackInvoker, etc.)
|
||||
│ ├── Doctor/ # System environment checking and fixing (Doctor, CheckResult)
|
||||
│ ├── Exception/ # Custom exception classes
|
||||
│ ├── Package/ # Core package models and build scheduling
|
||||
│ │ ├── Package.php # Base package class
|
||||
│ │ ├── LibraryPackage.php # Library package type
|
||||
│ │ ├── PhpExtensionPackage.php # PHP extension package type
|
||||
│ │ ├── TargetPackage.php # Build target package type
|
||||
│ │ ├── PackageInstaller.php # Package installer (download, extract source)
|
||||
│ │ └── PackageBuilder.php # Package builder (execute build pipeline)
|
||||
│ ├── Registry/ # Registry management (Registry, PackageLoader, ArtifactLoader)
|
||||
│ ├── Runtime/ # Runtime utilities
|
||||
│ │ ├── Executor/ # Command executors (UnixAutoconfExecutor, UnixCMakeExecutor,
|
||||
│ │ │ # WindowsCMakeExecutor, Executor base class)
|
||||
│ │ ├── Shell/ # Shell abstraction (UnixShell, WindowsCmd, etc.)
|
||||
│ │ └── SystemTarget.php # System target information
|
||||
│ ├── Toolchain/ # Toolchain abstraction (GccNative, Musl, MSVC, Zig, ClangBrew, etc.)
|
||||
│ └── Util/ # General utility classes
|
||||
│ ├── System/ # OS platform utilities (LinuxUtil, MacOSUtil, WindowsUtil, etc.)
|
||||
│ ├── BuildRootTracker.php # buildroot file tracking
|
||||
│ ├── DependencyResolver.php # Dependency resolution and build order
|
||||
│ ├── FileSystem.php # File system operations
|
||||
│ ├── GlobalEnvManager.php # Global environment variable management
|
||||
│ ├── InteractiveTerm.php # Interactive terminal output
|
||||
│ ├── LicenseDumper.php # License export
|
||||
│ ├── PkgConfigUtil.php # pkg-config utility wrapper
|
||||
│ ├── SourcePatcher.php # Source code patching utility
|
||||
│ └── SPCConfigUtil.php # SPC configuration reader
|
||||
├── tests/ # Unit tests and integration tests
|
||||
├── downloads/ # Download cache directory (source packages, pre-built binaries)
|
||||
├── source/ # Extracted source code directory
|
||||
├── buildroot/ # Build output directory (headers, static libraries, etc.)
|
||||
├── pkgroot/ # Platform-archived build artifacts
|
||||
└── spc.registry.yml # core registry definition file
|
||||
composer.json
|
||||
src/App/MyCommand.app
|
||||
vendor/*
|
||||
bin/entry.php
|
||||
```
|
||||
|
||||
Note that the classes in `src/Package` are responsible for implementing the build logic of specific packages, while the classes in `src/StaticPHP` provide the core functionality of the build framework, such as command scheduling, environment checking, and toolchain abstraction. The two are decoupled: `src/Package` corresponds to the packages in the `core` registry (including PHP, extensions, libraries, and build targets), while `src/StaticPHP` is the infrastructure that supports build needs across different registries and packages.
|
||||
We assume that the above constants are obtained from `src/App/MyCommand.php`:
|
||||
|
||||
| Constant | Value |
|
||||
|----------------------|------------------------------------------------------|
|
||||
| `WORKING_DIR` | `/home/example/static-php-cli` |
|
||||
| `SOURCE_ROOT_DIR` | `/home/example/static-php-cli` |
|
||||
| `FRAMEWORK_ROOT_DIR` | `/home/example/static-php-cli` |
|
||||
| `__DIR__` | `/home/example/static-php-cli/src/App` |
|
||||
| `__FILE__` | `/home/example/static-php-cli/src/App/MyCommand.php` |
|
||||
|
||||
In this case, the values of `WORKING_DIR`, `SOURCE_ROOT_DIR`, and `FRAMEWORK_ROOT_DIR` are exactly the same: `/home/example/static-php-cli`.
|
||||
|
||||
The source code of the framework and the source code of the application are both in the current path.
|
||||
|
||||
### Vendor library mode (vendor)
|
||||
|
||||
The vendor library mode generally means that your project is a framework or is installed into the project as a composer dependency by other applications,
|
||||
and the storage location is in the `vendor/author/XXX` directory.
|
||||
|
||||
Suppose your project is `crazywhalecc/static-php-cli`, and you or others install this project in another project using `composer require`.
|
||||
|
||||
We assume that static-php-cli contains all files except the `vendor` directory with the same `Git mode`, and get the constant value from `src/App/MyCommand`,
|
||||
Directory constant should be:
|
||||
|
||||
| Constant | Value |
|
||||
|----------------------|--------------------------------------------------------------------------------------|
|
||||
| `WORKING_DIR` | `/home/example/another-app` |
|
||||
| `SOURCE_ROOT_DIR` | `/home/example/another-app` |
|
||||
| `FRAMEWORK_ROOT_DIR` | `/home/example/another-app/vendor/crazywhalecc/static-php-cli` |
|
||||
| `__DIR__` | `/home/example/another-app/vendor/crazywhalecc/static-php-cli/src/App` |
|
||||
| `__FILE__` | `/home/example/another-app/vendor/crazywhalecc/static-php-cli/src/App/MyCommand.php` |
|
||||
|
||||
Here `SOURCE_ROOT_DIR` refers to the root directory of the project using `static-php-cli`.
|
||||
|
||||
### Git project Phar mode (source-phar)
|
||||
|
||||
Git project Phar mode refers to the mode of packaging the project directory of the Git project mode into a `phar` file. We assume that `/home/example/static-php-cli` will be packaged into a Phar file, and the directory has the following files:
|
||||
|
||||
```
|
||||
composer.json
|
||||
src/App/MyCommand.app
|
||||
vendor/*
|
||||
bin/entry.php
|
||||
```
|
||||
|
||||
When packaged into `app.phar` and stored in the `/home/example/static-php-cli` directory, `app.phar` is executed at this time. Assuming that the `src/App/MyCommand` code is executed, the constant is obtained in the file:
|
||||
|
||||
| Constant | Value |
|
||||
|----------------------|----------------------------------------------------------------------|
|
||||
| `WORKING_DIR` | `/home/example/static-php-cli` |
|
||||
| `SOURCE_ROOT_DIR` | `phar:///home/example/static-php-cli/app.phar/` |
|
||||
| `FRAMEWORK_ROOT_DIR` | `phar:///home/example/static-php-cli/app.phar/` |
|
||||
| `__DIR__` | `phar:///home/example/static-php-cli/app.phar/src/App` |
|
||||
| `__FILE__` | `phar:///home/example/static-php-cli/app.phar/src/App/MyCommand.php` |
|
||||
|
||||
Because the `phar://` protocol is required to read files in the phar itself, the project root directory and the framework directory will be different from `WORKING_DIR`.
|
||||
|
||||
### Vendor Library Phar Mode (vendor-phar)
|
||||
|
||||
Vendor Library Phar Mode means that your project is installed as a framework in other projects and stored in the `vendor` directory.
|
||||
|
||||
We assume that your project directory structure is as follows:
|
||||
|
||||
```
|
||||
composer.json # Composer configuration file of the current project
|
||||
box.json # Configuration file for packaging Phar
|
||||
another-app.php # Entry file of another project
|
||||
vendor/crazywhalecc/static-php-cli/* # Your project is used as a dependent library
|
||||
```
|
||||
|
||||
When packaging these files under the directory `/home/example/another-app/` into `app.phar`, the value of the following constant for your project should be:
|
||||
|
||||
| Constant | Value |
|
||||
|----------------------|------------------------------------------------------------------------------------------------------|
|
||||
| `WORKING_DIR` | `/home/example/another-app` |
|
||||
| `SOURCE_ROOT_DIR` | `phar:///home/example/another-app/app.phar/` |
|
||||
| `FRAMEWORK_ROOT_DIR` | `phar:///home/example/another-app/app.phar/vendor/crazywhalecc/static-php-cli` |
|
||||
| `__DIR__` | `phar:///home/example/another-app/app.phar/vendor/crazywhalecc/static-php-cli/src/App` |
|
||||
| `__FILE__` | `phar:///home/example/another-app/app.phar/vendor/crazywhalecc/static-php-cli/src/App/MyCommand.php` |
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user