Compare commits

...

67 Commits

Author SHA1 Message Date
crazywhalecc
25a2684e5a add ldap patches (why ext-ldap doesn't use pkg-config to find ldap?) 2024-01-07 12:20:58 +08:00
crazywhalecc
13e0e12181 update patch order 2024-01-07 12:20:58 +08:00
crazywhalecc
81df124b42 update README badge [skip ci] 2024-01-07 12:20:58 +08:00
crazywhalecc
d3d8230a09 add openssl patch 2024-01-07 12:20:58 +08:00
crazywhalecc
d4eb199504 use non-static suffix for brotli 2024-01-07 12:20:58 +08:00
crazywhalecc
6562bc200c fix ldap for macos x86_64 2024-01-07 12:20:58 +08:00
crazywhalecc
0b322f494b test 2024-01-07 12:20:58 +08:00
crazywhalecc
ceed1005cc remove unused download-cache workflow 2024-01-07 12:20:58 +08:00
crazywhalecc
6efcb75224 test ldap 2024-01-07 12:20:58 +08:00
crazywhalecc
a45f2f357d test ldap 2024-01-07 02:28:44 +08:00
crazywhalecc
0c2de9f936 run build test when changing test-extensions.php 2024-01-07 02:22:35 +08:00
crazywhalecc
ac005d1e0f update config to test actions 2024-01-07 02:16:50 +08:00
crazywhalecc
fce0c2f896 update config to test actions 2024-01-07 02:16:17 +08:00
crazywhalecc
a0a0b01cc3 update config to test actions 2024-01-07 02:14:45 +08:00
crazywhalecc
450ec21c90 remove main push test 2024-01-07 02:11:46 +08:00
crazywhalecc
7b2c3ac12d fix if statement for workflow 2024-01-07 02:10:14 +08:00
crazywhalecc
8d4a375400 fix if statement for workflow 2024-01-07 02:03:04 +08:00
crazywhalecc
eda3a9b486 add docs config actions 2024-01-07 01:58:31 +08:00
crazywhalecc
5b581a54aa add docs config actions 2024-01-07 01:57:55 +08:00
crazywhalecc
5549068275 add download cache for tests 2024-01-07 01:24:43 +08:00
crazywhalecc
daf0d2eb32 fix dependency sort 2024-01-07 01:24:43 +08:00
crazywhalecc
bff1a6168f fix imagemagick with curl,brotli errors
symlink breaks imagemagick build
2024-01-07 01:24:43 +08:00
crazywhalecc
54ba41d1b3 fix imap executable permission 2024-01-07 01:24:43 +08:00
crazywhalecc
cb5e13e39a update release-build (Build SPC Binary) workflow 2024-01-07 01:24:43 +08:00
霸气千秋
269e95e0fe fix #307 (#308)
* fix #307 uv 和 swoole 同时启用的时候会提示 uv 找不到

* Update test-extensions.php

* update cs-fixer config for newer version

* revert composer.lock to fit 8.1

---------

Co-authored-by: Jerry Ma <jesse2061@outlook.com>
2024-01-05 19:21:07 +08:00
crazywhalecc
dabdb518ce xz use github 2024-01-03 14:56:39 +08:00
Jerry Ma
eac4763d82 fix libxml2 with icu finding issue (#304)
* fix libxml2 with icu finding issue

* add test
2024-01-03 13:40:48 +08:00
Jerry Ma
fa0ea5443d Update to 2.0.0 2024-01-03 10:36:04 +08:00
好吧,你想说啥
31c71f180b Feature perfect swoole extension config (#297)
* improve swoole static build config

* improve swoole static build config

* improve swoole static build config

* improve swoole static build config

* improve swoole static build config

* add cares config

* update swoole depend  config

* update swoole depend  config

* update cares build   config

* update workflow tests.yaml   config

* fix setup-runtime

* test with clang build

* test with clang build

* update cares build config

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* update cares license

* test build

* test build

* test build

* test build

* test add enable libpq

* test add enable libpq

* test add enable libpq

* test add enable libpq

* test add enable libpq

* test add enable libpq

* test add enable libpq

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* update

* update

* update

* update

* update

* update

* update

* update

* update

* compatible old

* fix code format

* fix code format

* add swoole test case

* add swoole test case

* add phpstan ignore error

* add phpstan ignore error

* add phpstan ignore error

* add phpstan ignore error

* add phpstan ignore error

* update phpstan.neon

* update swoole extension test case

* update swoole test case

* adjust config order and depends

* revert LinuxBuilder

* remove swoole.phpt

* re-adjust swoole args

* update test-extensions and some PHPDoc

* revert: debian and alpine clang doctor install

* revert: MacOSBuilder

* fix: extract hook for archive not working

* revert: build tests

* use addon mode to swoole database hook

* add hook tests

* test minimal

* test minimal

* sort config

---------

Co-authored-by: crazywhalecc <jesse2061@outlook.com>
2024-01-03 10:31:21 +08:00
Jerry Ma
5c7552f826 Update README.md 2023-12-26 01:47:33 +08:00
Jerry Ma
fa1bd340f1 Update README.md 2023-12-26 01:42:52 +08:00
Jerry Ma
539aaefd72 Add initial windows runtime setup (#292)
* add initial windows runtime setup

* add cool console output

* doctor support windows base

* add `add-path` and `remove-path` for bin/setup-runtime

* fix composer.ps1 path

* add windows system util

* add windows cmd and doctor base check

* add windows fallback for laravel/prompts

* cd fix [skip ci]

* dir separator and typo fix [skip ci]
2023-12-24 20:17:06 +08:00
crazywhalecc
d54bf42ba8 add extension xhprof test 2023-12-24 20:15:44 +08:00
crazywhalecc
cbfbec41b4 add extension xhprof 2023-12-24 20:15:44 +08:00
crazywhalecc
db7532cad3 add composer library mode 2023-12-24 14:53:46 +08:00
Jerry Ma
6b8df97282 Add uv/libuv support (#296)
* add uv/libuv support

* sort config
2023-12-23 16:23:37 +08:00
crazywhalecc
584f96484c add liblz4 suggest 2023-12-23 15:18:39 +08:00
crazywhalecc
e1e5515694 fix tests 2023-12-23 15:18:39 +08:00
crazywhalecc
d3ff6fd8c0 sort config 2023-12-23 15:18:39 +08:00
crazywhalecc
6bcda6a5a0 add lz4, igbinary support for redis 2023-12-23 15:18:39 +08:00
crazywhalecc
3828ba7c77 fix x86_64 build 2023-12-22 13:28:22 +08:00
crazywhalecc
a632caed54 add sqlsrv support test 2023-12-22 13:28:22 +08:00
crazywhalecc
1e0265e673 add sqlsrv support 2023-12-22 13:28:22 +08:00
Jerry Ma
a39cd9a238 Update README.md 2023-12-21 12:55:20 +08:00
Jerry Ma
2d437952f2 Update README.md 2023-12-21 12:54:43 +08:00
crazywhalecc
7e5b0d6f43 use bulk combination for setup-runtime 2023-12-21 01:45:54 +08:00
Jerry Ma
cf198e0f0a Merge pull request #64 from mpociot/libargon2-support
Add support for libargon2
2023-12-19 20:49:50 +08:00
crazywhalecc
248918e458 remove ldap test for known reason 2023-12-19 20:04:13 +08:00
crazywhalecc
c4cfc01b88 fix linux build (dont know why linux failed) 2023-12-19 19:37:19 +08:00
crazywhalecc
339c03adb2 fix linux build (dont know why linux failed) 2023-12-19 19:31:56 +08:00
crazywhalecc
48551cc602 add linux support for libargon2 2023-12-19 19:13:19 +08:00
crazywhalecc
e0550b4a45 add argon2 test 2023-12-19 19:04:49 +08:00
crazywhalecc
93a55e87d5 temporarily use pkg-config mirror (freedesktop.org down) 2023-12-19 19:03:16 +08:00
Marcel Pociot
e68f1ce3fe Merge branch 'main' into libargon2-support 2023-12-19 10:05:45 +01:00
crazywhalecc
3573007485 Merge remote-tracking branch 'origin/main' 2023-12-18 00:14:34 +08:00
crazywhalecc
b961c34d9a add ldap test 2023-12-18 00:14:14 +08:00
Jerry Ma
33e1759caa Update README.md 2023-12-17 12:16:54 +08:00
crazywhalecc
fbf5c958d0 sort configs 2023-11-05 17:55:39 +08:00
crazywhalecc
672a4102cd overwrite password-argon2 cli check 2023-11-05 17:53:48 +08:00
crazywhalecc
52d61365b7 Merge branch 'main' into libargon2-support 2023-11-05 17:50:00 +08:00
crazywhalecc
3604ea6d67 Update lock 2023-11-05 17:32:29 +08:00
crazywhalecc
967292be5c Remove old configure_env 2023-11-05 17:31:17 +08:00
crazywhalecc
4f5335bba4 Merge branch 'main' into libargon2-support
# Conflicts:
#	config/lib.json
#	config/source.json
2023-11-05 17:25:36 +08:00
Marcel Pociot
0569c69634 remove path 2023-06-03 00:04:02 +02:00
Marcel Pociot
1b734073b0 Merge refactor 2023-06-02 22:47:59 +02:00
Marcel Pociot
47d068e6d3 Merge branch 'refactor' into libargon2-support 2023-06-02 22:47:47 +02:00
Marcel Pociot
4537bfb247 Add support for libargon2 2023-05-31 10:03:40 +02:00
70 changed files with 1672 additions and 495 deletions

View File

@@ -1,40 +0,0 @@
name: archive download sources weekly
on:
workflow_dispatch:
schedule:
- cron: "* 14 * * 5"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
download:
name: cache download sources
runs-on: ubuntu-latest
strategy:
matrix:
php-version: [ "8.0", "8.1", "8.2", "8.3" ]
steps:
- uses: actions/checkout@v3
# Cache composer dependencies
- id: cache-composer-deps
uses: actions/cache@v3
with:
path: vendor
key: composer-dependencies
# If there's no Composer cache, install dependencies
- if: steps.cache-composer-deps.outputs.cache-hit != 'true'
run: composer update --no-dev
# If there's no dependencies cache, fetch sources, with or without debug
- if: steps.cache-download.outputs.cache-hit != 'true'
run: ./bin/spc download --with-php=${{ matrix.php-version }} --all --debug
# Upload downloaded files
- uses: actions/upload-artifact@v3
with:
name: download-files-${{ matrix.php-version }}
path: downloads/

View File

@@ -1,6 +1,8 @@
name: Upload SPC Binary (Release) name: Build SPC Binary
on: on:
push:
branches: [ "main" ]
release: release:
types: types:
- published - published
@@ -8,10 +10,14 @@ on:
jobs: jobs:
build-release-artifacts: build-release-artifacts:
name: "Upload SPC Binary (Release)" name: "Build SPC Binary"
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
php-version:
- "8.1"
micro-version:
- "8.1.26"
operating-system: operating-system:
- "linux-x86_64" - "linux-x86_64"
- "macos-x86_64" - "macos-x86_64"
@@ -21,18 +27,57 @@ jobs:
- name: "Checkout" - name: "Checkout"
uses: "actions/checkout@v4" uses: "actions/checkout@v4"
- name: Reuse static-php-cli-hosted artifacts - if: inputs.debug == true
uses: dawidd6/action-download-artifact@v2 run: echo "SPC_BUILD_DEBUG=--debug" >> $GITHUB_ENV
- name: "Install PHP for official runners"
uses: "shivammathur/setup-php@v2"
with: with:
repo: static-php/static-php-cli-hosted coverage: none
branch: master tools: composer:v2
workflow: build-spc-release.yml php-version: "${{ matrix.php-version }}"
name: "spc-${{ matrix.operating-system }}" ini-values: memory_limit=-1
- 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@v3"
with:
path: "${{ steps.composer-cache.outputs.dir }}"
key: "php-${{ matrix.php-version }}-locked-composer-${{ hashFiles('**/composer.lock') }}"
restore-keys: |
php-${{ matrix.php-version }}-locked-composer
- name: "Install Locked Dependencies"
run: "composer install --no-interaction --no-progress"
- name: "Build PHAR File"
run: "composer build:phar"
- name: "Download minimal combination"
run: |
curl https://dl.static-php.dev/static-php-cli/minimal/php-${{ matrix.micro-version }}-micro-${{ matrix.operating-system }}.tar.gz -o tmp.tgz
tar -zxvf tmp.tgz
- name: "Generate Executable"
run: |
cat micro.sfx spc.phar > spc
chmod +x spc
- name: "Archive Executable" - name: "Archive Executable"
run: | run: |
tar -czf spc-${{ matrix.operating-system }}.tar.gz spc tar -czf spc-${{ matrix.operating-system }}.tar.gz spc
echo "filename=spc-${{ matrix.operating-system }}.tar.gz" >> $GITHUB_ENV echo "filename=spc-${{ matrix.operating-system }}.tar.gz" >> $GITHUB_ENV
echo "OS=${{ matrix.operating-system }}" >> $GITHUB_ENV
if [ "${{ matrix.operating-system }}" == "linux-x86_64" ]; then
./spc dev:extensions
fi
- name: "Copy file"
run: "mkdir dist/ && cp ${{ env.filename }} dist/ && cp spc dist/spc-$OS"
- name: upload binaries to release - name: upload binaries to release
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
@@ -40,6 +85,18 @@ jobs:
with: with:
files: ${{ env.filename }} files: ${{ env.filename }}
- name: "Deploy to Self-Hosted Server"
if: github.repository == 'crazywhalecc/static-php-cli'
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SERVER_SECRET_KEY }}
ARGS: "-rltgoDzvO"
SOURCE: "dist/"
REMOTE_HOST: ${{ secrets.DEPLOY_SERVER_HOST }}
REMOTE_PORT: ${{ secrets.DEPLOY_SERVER_PORT }}
REMOTE_USER: ${{ secrets.DEPLOY_SERVER_USER }}
TARGET: ${{ secrets.DEPLOY_SERVER_TARGET_SPC_NIGHTLY }}
- name: "Upload Artifact" - name: "Upload Artifact"
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:

View File

@@ -2,7 +2,10 @@ name: Tests
on: on:
push: push:
branches: [ "main" ] branches:
- main
paths:
- 'src/globals/test-extensions.php'
pull_request: pull_request:
branches: [ "main" ] branches: [ "main" ]
@@ -133,6 +136,13 @@ jobs:
restore-keys: | restore-keys: |
${{ runner.os }}-php- ${{ runner.os }}-php-
# Cache downloaded source
- id: cache-download
uses: actions/cache@v3
with:
path: downloads
key: php-${{ matrix.php }}-dependencies
- name: "Install Dependencies" - name: "Install Dependencies"
run: composer update -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist run: composer update -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
@@ -140,7 +150,7 @@ jobs:
run: bin/spc doctor --auto-fix run: bin/spc doctor --auto-fix
- name: "Run Build Tests (download)" - name: "Run Build Tests (download)"
run: bin/spc download --for-extensions="$(php src/globals/test-extensions.php)" --with-php=${{ matrix.php }} --debug run: bin/spc download --for-extensions="$(php src/globals/test-extensions.php extensions)" --with-php=${{ matrix.php }} --debug
- name: "Run Build Tests (build)" - name: "Run Build Tests (build)"
run: bin/spc build "$(php src/globals/test-extensions.php)" --build-cli --build-micro --build-fpm --debug run: bin/spc build $(php src/globals/test-extensions.php cmd) --build-cli --build-micro --build-fpm --debug

View File

@@ -0,0 +1,43 @@
name: Update Docs Config
on:
push:
branches:
- main
paths:
- 'config/**.json'
jobs:
update-docs-config:
name: "Update Docs Config"
runs-on: ubuntu-latest
if: github.repository == 'crazywhalecc/static-php-cli'
steps:
- name: "Checkout static-php-cli"
uses: actions/checkout@v4
with:
ref: main
path: static-php-cli
- name: "Checkout static-php-cli-docs"
uses: actions/checkout@v4
with:
repository: static-php/static-php-cli-docs
ref: master
token: ${{ secrets.DOCS_REPO_TOKEN }}
path: static-php-cli-docs
- name: "Set up Git"
run: |
git config --global user.email "actions@github.com"
git config --global user.name "GitHub Actions"
- name: "Copy Config Files"
run: cp -r static-php-cli/config/* static-php-cli-docs/docs/.vitepress/config/
- name: "Commit and Push Changes"
run: |
cd static-php-cli-docs
git add -A
git commit -m "Sync config files from main"
git push origin master

7
.gitignore vendored
View File

@@ -22,9 +22,12 @@ docker/source/
# exclude self-runtime # exclude self-runtime
/bin/* /bin/*
!/bin/spc !/bin/spc*
!/bin/setup-runtime !/bin/setup-runtime*
!/bin/spc-alpine-docker !/bin/spc-alpine-docker
# exclude windows build tools
/php-sdk-binary-tools/
# default test directory # default test directory
/tests/var/ /tests/var/

View File

@@ -63,6 +63,7 @@ return (new PhpCsFixer\Config())
'phpdoc_summary' => false, 'phpdoc_summary' => false,
'php_unit_test_class_requires_covers' => false, 'php_unit_test_class_requires_covers' => false,
'phpdoc_var_without_name' => false, 'phpdoc_var_without_name' => false,
'fully_qualified_strict_types' => false,
]) ])
->setFinder( ->setFinder(
PhpCsFixer\Finder::create()->in([__DIR__ . '/src', __DIR__ . '/tests/SPC']) PhpCsFixer\Finder::create()->in([__DIR__ . '/src', __DIR__ . '/tests/SPC'])

View File

@@ -14,10 +14,10 @@ Build single static PHP binary, with PHP project together, with popular extensio
> 该 SAPI 源自 [dixyes/phpmicro](https://github.com/dixyes/phpmicro) 的 [Fork 仓库](https://github.com/static-php/phpmicro)。 > 该 SAPI 源自 [dixyes/phpmicro](https://github.com/dixyes/phpmicro) 的 [Fork 仓库](https://github.com/static-php/phpmicro)。
[![Version](https://img.shields.io/badge/Version-2.0--rc8-pink.svg?style=flat-square)]() [![Version](https://img.shields.io/badge/Version-2.0.0-green.svg?style=flat-square)]()
[![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)]() [![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)]()
[![](https://img.shields.io/github/actions/workflow/status/static-php/static-php-cli-hosted/build-php-common.yml?branch=refactor&label=Build%20Common%20Extensions&style=flat-square)](https://github.com/static-php/static-php-cli-hosted/actions/workflows/build-php-common.yml) [![](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/tests.yml?branch=main&label=Build%20Test&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/tests.yml)
[![](https://img.shields.io/badge/Extension%20Counter-65+-yellow.svg?style=flat-square)]() [![](https://img.shields.io/badge/Extension%20Counter-75+-yellow.svg?style=flat-square)]()
[![](https://img.shields.io/github/search/crazywhalecc/static-php-cli/TODO?label=TODO%20Counter&style=flat-square)]() [![](https://img.shields.io/github/search/crazywhalecc/static-php-cli/TODO?label=TODO%20Counter&style=flat-square)]()
> 项目名称是 static-php-cli但其实支持 cli、fpm、micro 和 embed SAPI 😎 > 项目名称是 static-php-cli但其实支持 cli、fpm、micro 和 embed SAPI 😎

View File

@@ -4,6 +4,8 @@ Build single static PHP binary, with PHP project together, with popular extensio
🌐 **[中文](README-zh.md)** | **[English](README.md)** 🌐 **[中文](README-zh.md)** | **[English](README.md)**
> 2.0 Release is coming soon, windows support will be added in v2.1.
The project name is static-php-cli, but it actually supports cli, fpm, micro and embed SAPI 😎 The project name is static-php-cli, but it actually supports cli, fpm, micro and embed SAPI 😎
Compile a purely static php-cli binary file with various extensions to make PHP applications more portable! (cli SAPI) Compile a purely static php-cli binary file with various extensions to make PHP applications more portable! (cli SAPI)
@@ -16,12 +18,10 @@ You can also use the micro binary file to combine php binary and php source code
> This SAPI feature is from the [Fork](https://github.com/static-php/phpmicro) of [dixyes/phpmicro](https://github.com/dixyes/phpmicro). > This SAPI feature is from the [Fork](https://github.com/static-php/phpmicro) of [dixyes/phpmicro](https://github.com/dixyes/phpmicro).
[![Version](https://img.shields.io/badge/Version-2.0--rc8-pink.svg?style=flat-square)]() [![Version](https://img.shields.io/badge/Version-2.0.0-green.svg?style=flat-square)]()
[![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)]() [![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)]()
[![](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/build-linux-x86_64.yml?branch=refactor&label=Linux%20Build&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml) [![](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/tests.yml?branch=main&label=Build%20Test&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/tests.yml)
[![](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/build-macos-x86_64.yml?branch=refactor&label=macOS%20Build&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml) [![](https://img.shields.io/badge/Extension%20Counter-75+-yellow.svg?style=flat-square)]([https://static-php.dev/](https://static-php.dev/en/guide/extensions.html))
[![](https://img.shields.io/badge/Extension%20Counter-65+-yellow.svg?style=flat-square)]()
[![](https://img.shields.io/github/search/crazywhalecc/static-php-cli/TODO?label=TODO%20Counter&style=flat-square)]() [![](https://img.shields.io/github/search/crazywhalecc/static-php-cli/TODO?label=TODO%20Counter&style=flat-square)]()
## Documentation ## Documentation
@@ -36,9 +36,9 @@ If you don't want to compile yourself, you can download example pre-compiled art
Below are several precompiled static-php binaries with different extension combinations, Below are several precompiled static-php binaries with different extension combinations,
which can be downloaded directly according to your needs. which can be downloaded directly according to your needs.
- [Extension-Combination - common](https://dl.static-php.dev/static-php-cli/common/): `common` combination contains about [30+](https://dl.static-php.dev/static-php-cli/common/README.txt) commonly used extensions, and the size is about 22MB. - [Extension-Combination - common](https://dl.static-php.dev/static-php-cli/common/): `common` contains about [30+](https://dl.static-php.dev/static-php-cli/common/README.txt) commonly used extensions, and the size is about 22MB.
- [Extension-Combination - bulk](https://dl.static-php.dev/static-php-cli/bulk/): `bulk` combination contains [50+](https://dl.static-php.dev/static-php-cli/bulk/README.txt) extensions and is about 70MB in size. - [Extension-Combination - bulk](https://dl.static-php.dev/static-php-cli/bulk/): `bulk` contains [50+](https://dl.static-php.dev/static-php-cli/bulk/README.txt) extensions and is about 70MB in size.
- [Extension-Combination - minimal](https://dl.static-php.dev/static-php-cli/minimal/): `minimal` combination contains [5](https://dl.static-php.dev/static-php-cli/minimal/README.txt) extensions and is about 6MB in size. - [Extension-Combination - minimal](https://dl.static-php.dev/static-php-cli/minimal/): `minimal` contains [5](https://dl.static-php.dev/static-php-cli/minimal/README.txt) extensions and is about 6MB in size.
## Use static-php-cli to build PHP ## Use static-php-cli to build PHP

View File

@@ -25,7 +25,7 @@ __DIR__=$(cd "$(dirname "$0")" && pwd)
__PROJECT__=$(cd "${__DIR__}"/../ && pwd) __PROJECT__=$(cd "${__DIR__}"/../ && pwd)
# set download dir # set download dir
__PHP_RUNTIME_URL__="https://dl.static-php.dev/static-php-cli/common/php-8.2.12-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz" __PHP_RUNTIME_URL__="https://dl.static-php.dev/static-php-cli/bulk/php-8.2.13-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz"
__COMPOSER_URL__="https://getcomposer.org/download/latest-stable/composer.phar" __COMPOSER_URL__="https://getcomposer.org/download/latest-stable/composer.phar"
# use china mirror # use china mirror
@@ -35,7 +35,6 @@ while [ $# -gt 0 ]; do
case "$1" in case "$1" in
--mirror) --mirror)
mirror="$2" mirror="$2"
shift
;; ;;
--*) --*)
echo "Illegal option $1" echo "Illegal option $1"
@@ -46,8 +45,8 @@ done
case "$mirror" in case "$mirror" in
china) china)
__PHP_RUNTIME_URL__="https://dl.static-php.dev/static-php-cli/common/php-8.2.12-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz" __PHP_RUNTIME_URL__="https://dl.static-php.dev/static-php-cli/bulk/php-8.2.13-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz"
__COMPOSER_URL__="https://mirrors.aliyun.com/composer/composer.phar" __COMPOSER_URL__="https://mirrors.tencent.com/composer/composer.phar"
;; ;;
esac esac

115
bin/setup-runtime.ps1 Normal file
View File

@@ -0,0 +1,115 @@
param (
[string] ${action}
)
function AddToPath {
param (
[string]$pathToAdd
)
$currentPath = [System.Environment]::GetEnvironmentVariable('Path', 'User')
if ($currentPath -notlike "*$pathToAdd*") {
$newPath = $currentPath + ";$pathToAdd"
[System.Environment]::SetEnvironmentVariable('Path', $newPath, 'User')
Write-Host "Added '$pathToAdd' to Path."
Write-Host "To remove path, use: " -NoNewline
Write-Host "bin/setup-runtime remove-path" -ForegroundColor Cyan
} else {
Write-Host "Path already exists."
}
}
function RemoveFromPath {
param (
[string]$pathToRemove
)
$currentPath = [System.Environment]::GetEnvironmentVariable('Path', 'User')
if ($currentPath -like "*$pathToRemove*") {
$newPath = $currentPath -replace [regex]::Escape($pathToRemove), ''
[System.Environment]::SetEnvironmentVariable('Path', $newPath, 'User')
Write-Host "Removed Path '$pathToRemove'"
} else {
Write-Host "Path '$pathToRemove' not in Path"
}
}
# working dir
$WorkingDir = (Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Definition))
if ($action -eq 'add-path') {
AddToPath ($WorkingDir + '\runtime')
exit 0
} elseif ($action -eq 'remove-path') {
RemoveFromPath ($WorkingDir + '\runtime')
exit 0
} elseif (-not($action -eq '')) {
Write-Host ("Invalid action: " + $action) -ForegroundColor Red
exit 1
}
# get php 8.1 specific version
$API = (Invoke-WebRequest -Uri "https://www.php.net/releases/index.php?json&version=8.1") | ConvertFrom-Json
# php windows download
$PHPRuntimeUrl = "https://windows.php.net/downloads/releases/php-" + $API.version + "-Win32-vs16-x64.zip"
$ComposerUrl = "https://getcomposer.org/download/latest-stable/composer.phar"
# create dir
New-Item -Path "downloads" -ItemType Directory -Force | Out-Null
# download php
if (-not(Test-Path "downloads\php.zip"))
{
Write-Host "Downloading PHP ..."
Invoke-WebRequest $PHPRuntimeUrl -OutFile "downloads\php.zip"
}
# extract php
New-Item -Path "runtime" -ItemType Directory -Force | Out-Null
Write-Host "Extracting php.zip ..."
Expand-Archive -Path "downloads/php.zip" -DestinationPath "runtime" -Force
# make php.ini
Move-Item -Path "runtime\php.ini-production" -Destination "runtime\php.ini" -Force
$OriginINI = Get-Content -Path "runtime\php.ini" -Raw
$OriginINI = $OriginINI -replace ';extension=openssl', 'extension=openssl'
$OriginINI = $OriginINI -replace ';extension=curl', 'extension=curl'
$OriginINI = $OriginINI -replace ';extension=mbstring', 'extension=mbstring'
$OriginINI = $OriginINI -replace ';extension=sodium', 'extension=sodium'
$OriginINI = $OriginINI -replace ';extension_dir = "./"', ('extension_dir = "' + (Split-Path -Parent $MyInvocation.MyCommand.Definition) + '\..\runtime\ext"')
$OriginINI | Set-Content -Path "runtime\php.ini"
# download composer
if (-not(Test-Path "runtime\composer.phar"))
{
Write-Host "Downloading composer ..."
Invoke-WebRequest $ComposerUrl -OutFile "downloads\composer.phar"
Move-Item -Path "downloads\composer.phar" -Destination "runtime\composer.phar" -Force
}
# create runtime\composer.ps1
$ComposerContent = '
$WorkingDir = (Split-Path -Parent $MyInvocation.MyCommand.Definition)
Start-Process ($WorkingDir + "\php.exe") ($WorkingDir + "\composer.phar " + $args) -NoNewWindow -Wait
'
$ComposerContent | Set-Content -Path 'runtime\composer.ps1' -Encoding UTF8
Write-Host "Successfully downloaded PHP and Composer !" -ForegroundColor Green
Write-Host "Use static-php-cli: " -NoNewline
Write-Host "bin/spc" -ForegroundColor Cyan
Write-Host "Use php: " -NoNewline
Write-Host "runtime/php" -ForegroundColor Cyan
Write-Host "Use composer: " -NoNewline
Write-Host "runtime/composer" -ForegroundColor Cyan
Write-Host ""
Write-Host "Don't forget installing composer dependencies '" -NoNewline
Write-Host "runtime/composer install" -ForegroundColor Cyan -NoNewline
Write-Host "' before using static-php-cli !"
Write-Host ""
Write-Host "If you want to use this PHP for quality tools (like phpstan, php-cs-fixer) or other project,"
Write-Host "or use PHP, Composer as system executable,"
Write-Host "use '" -NoNewline
Write-Host "bin/setup-runtime add-path" -ForegroundColor Cyan -NoNewline
Write-Host "' to add runtime dir in Path."

View File

@@ -4,7 +4,13 @@
use SPC\ConsoleApplication; use SPC\ConsoleApplication;
use SPC\exception\ExceptionHandler; use SPC\exception\ExceptionHandler;
require_once __DIR__ . '/../vendor/autoload.php'; if (file_exists(dirname(__DIR__) . '/vendor/autoload.php')) {
// Current: ./bin (git/project mode)
require_once dirname(__DIR__) . '/vendor/autoload.php';
} else {
// Current: ./vendor/crazywhalecc/static-php-cli/bin (composer library mode)
require_once dirname(__DIR__, 3) . '/autoload.php';
}
// 防止 Micro 打包状态下不支持中文的显示(虽然这个项目目前好像没输出过中文?) // 防止 Micro 打包状态下不支持中文的显示(虽然这个项目目前好像没输出过中文?)
if (PHP_OS_FAMILY === 'Windows' && Phar::running()) { if (PHP_OS_FAMILY === 'Windows' && Phar::running()) {

12
bin/spc.ps1 Normal file
View File

@@ -0,0 +1,12 @@
$PHP_Exec = "runtime\php.exe"
if (-not(Test-Path $PHP_Exec)) {
$PHP_Exec = Get-Command php.exe -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Definition
if (-not $PHP_Exec) {
Write-Host "Error: PHP not found, you need to install PHP on your system or use 'bin/setup-runtime'." -ForegroundColor Red
exit 1
}
}
$phpArgs = "bin\spc " + $args
Start-Process $PHP_Exec -ArgumentList $phpArgs -NoNewWindow -Wait

View File

@@ -11,7 +11,6 @@
"require": { "require": {
"php": ">= 8.1", "php": ">= 8.1",
"ext-mbstring": "*", "ext-mbstring": "*",
"ext-pcntl": "*",
"laravel/prompts": "^0.1.12", "laravel/prompts": "^0.1.12",
"symfony/console": "^5.4 || ^6 || ^7", "symfony/console": "^5.4 || ^6 || ^7",
"zhamao/logger": "^1.0" "zhamao/logger": "^1.0"

449
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -122,6 +122,10 @@
"libiconv" "libiconv"
] ]
}, },
"igbinary": {
"type": "external",
"source": "igbinary"
},
"imagick": { "imagick": {
"type": "external", "type": "external",
"source": "ext-imagick", "source": "ext-imagick",
@@ -242,6 +246,13 @@
"zlib" "zlib"
] ]
}, },
"password-argon2": {
"type": "builtin",
"arg-type": "with-prefix",
"lib-depends": [
"libargon2"
]
},
"pcntl": { "pcntl": {
"type": "builtin", "type": "builtin",
"unix-only": true "unix-only": true
@@ -324,7 +335,12 @@
"source": "redis", "source": "redis",
"arg-type": "custom", "arg-type": "custom",
"ext-suggests": [ "ext-suggests": [
"session" "session",
"igbinary"
],
"lib-suggests": [
"zstd",
"liblz4"
] ]
}, },
"session": { "session": {
@@ -384,6 +400,17 @@
"sqlite" "sqlite"
] ]
}, },
"sqlsrv": {
"type": "external",
"source": "sqlsrv",
"lib-depends": [
"unixodbc"
],
"ext-depends-linux": [
"pcntl"
],
"cpp-extension": true
},
"ssh2": { "ssh2": {
"type": "external", "type": "external",
"source": "ext-ssh2", "source": "ext-ssh2",
@@ -397,17 +424,50 @@
"source": "swoole", "source": "swoole",
"arg-type": "custom", "arg-type": "custom",
"cpp-extension": true, "cpp-extension": true,
"unix-only": true,
"lib-depends": [ "lib-depends": [
"openssl" "libcares",
"brotli",
"nghttp2",
"zlib"
], ],
"ext-depends": [ "ext-depends": [
"openssl" "openssl",
"curl"
], ],
"ext-suggests": [ "ext-suggests": [
"curl", "swoole-hook-pgsql",
"pgsql" "swoole-hook-mysql",
"swoole-hook-sqlite"
]
},
"swoole-hook-mysql": {
"type": "addon",
"arg-type": "custom",
"ext-depends": [
"mysqlnd",
"pdo",
"pdo_mysql"
], ],
"unix-only": true "ext-suggests": [
"mysqli"
]
},
"swoole-hook-pgsql": {
"type": "addon",
"arg-type": "custom",
"ext-depends": [
"pgsql",
"pdo"
]
},
"swoole-hook-sqlite": {
"type": "addon",
"arg-type": "custom",
"ext-depends": [
"sqlite3",
"pdo"
]
}, },
"swow": { "swow": {
"type": "external", "type": "external",
@@ -444,6 +504,24 @@
"tokenizer": { "tokenizer": {
"type": "builtin" "type": "builtin"
}, },
"uv": {
"type": "external",
"source": "ext-uv",
"arg-type": "with-prefix",
"lib-depends": [
"libuv"
],
"ext-depends": [
"sockets"
]
},
"xhprof": {
"type": "external",
"source": "xhprof",
"ext-depends": [
"ctype"
]
},
"xlswriter": { "xlswriter": {
"type": "external", "type": "external",
"source": "xlswriter", "source": "xlswriter",

View File

@@ -2,14 +2,14 @@
"brotli": { "brotli": {
"source": "brotli", "source": "brotli",
"static-libs-unix": [ "static-libs-unix": [
"libbrotlidec-static.a", "libbrotlidec.a",
"libbrotlienc-static.a", "libbrotlienc.a",
"libbrotlicommon-static.a" "libbrotlicommon.a"
], ],
"static-libs-windows": [ "static-libs-windows": [
"brotlicommon-static.lib", "brotlicommon.lib",
"brotlienc-static.lib", "brotlienc.lib",
"brotlidec-static.lib" "brotlidec.lib"
], ],
"headers": [ "headers": [
"brotli" "brotli"
@@ -163,12 +163,30 @@
"libsodium" "libsodium"
] ]
}, },
"libargon2": {
"source": "libargon2",
"static-libs-unix": [
"libargon2.a"
]
},
"libavif": { "libavif": {
"source": "libavif", "source": "libavif",
"static-libs-unix": [ "static-libs-unix": [
"libavif.a" "libavif.a"
] ]
}, },
"libcares": {
"source": "libcares",
"static-libs-unix": [
"libcares.a"
],
"headers-unix": [
"ares.h",
"ares_dns.h",
"ares_nameser.h",
"ares_rules.h"
]
},
"libevent": { "libevent": {
"source": "libevent", "source": "libevent",
"static-libs-unix": [ "static-libs-unix": [
@@ -218,10 +236,10 @@
"libturbojpeg.a" "libturbojpeg.a"
] ]
}, },
"libmcrypt": { "liblz4": {
"source": "libmcrypt", "source": "liblz4",
"static-libs-unix": [ "static-libs-unix": [
"libmcrypt.a" "liblz4.a"
] ]
}, },
"libmemcached": { "libmemcached": {
@@ -278,6 +296,12 @@
"zlib" "zlib"
] ]
}, },
"libuv": {
"source": "libuv",
"static-libs-unix": [
"libuv.a"
]
},
"libwebp": { "libwebp": {
"source": "libwebp", "source": "libwebp",
"static-libs-unix": [ "static-libs-unix": [
@@ -303,16 +327,12 @@
"libxml2" "libxml2"
], ],
"lib-depends": [ "lib-depends": [
"libiconv", "libiconv"
"zlib"
], ],
"lib-suggests": [ "lib-suggests": [
"xz", "xz",
"icu"
],
"lib-suggests-windows": [
"icu", "icu",
"xz" "zlib"
] ]
}, },
"libxslt": { "libxslt": {
@@ -362,12 +382,6 @@
"openssl" "openssl"
] ]
}, },
"mcrypt": {
"source": "mcrypt",
"static-libs-unix": [
"libmcrypt.a"
]
},
"ncurses": { "ncurses": {
"source": "ncurses", "source": "ncurses",
"static-libs-unix": [ "static-libs-unix": [
@@ -490,6 +504,17 @@
"libtidy.a" "libtidy.a"
] ]
}, },
"unixodbc": {
"source": "unixodbc",
"static-libs-unix": [
"libodbc.a",
"libodbccr.a",
"libodbcinst.a"
],
"lib-depends": [
"libiconv"
]
},
"xz": { "xz": {
"source": "xz", "source": "xz",
"static-libs-unix": [ "static-libs-unix": [

View File

@@ -100,6 +100,16 @@
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"ext-uv": {
"type": "url",
"url": "https://pecl.php.net/get/uv",
"path": "php-src/ext/uv",
"filename": "uv.tgz",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"ext-zstd": { "ext-zstd": {
"type": "git", "type": "git",
"path": "php-src/ext/zstd", "path": "php-src/ext/zstd",
@@ -136,6 +146,16 @@
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"igbinary": {
"type": "url",
"url": "https://pecl.php.net/get/igbinary",
"path": "php-src/ext/igbinary",
"filename": "igbinary.tgz",
"license": {
"type": "file",
"path": "COPYING"
}
},
"imagemagick": { "imagemagick": {
"type": "ghtar", "type": "ghtar",
"repo": "ImageMagick/ImageMagick", "repo": "ImageMagick/ImageMagick",
@@ -172,6 +192,15 @@
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"libargon2": {
"type": "git",
"rev": "master",
"url": "https://github.com/mpociot/phc-winner-argon2",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"libavif": { "libavif": {
"type": "ghtar", "type": "ghtar",
"repo": "AOMediaCodec/libavif", "repo": "AOMediaCodec/libavif",
@@ -180,6 +209,15 @@
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"libcares": {
"type": "filelist",
"url": "https://c-ares.org/download/",
"regex": "/href=\"\\/download\\/(?<file>c-ares-(?<version>[^\"]+)\\.tar\\.gz)\"/",
"license": {
"type": "file",
"path": "LICENSE.md"
}
},
"libevent": { "libevent": {
"type": "ghrel", "type": "ghrel",
"repo": "libevent/libevent", "repo": "libevent/libevent",
@@ -215,12 +253,13 @@
"path": "LICENSE.md" "path": "LICENSE.md"
} }
}, },
"libmcrypt": { "liblz4": {
"type": "url", "type": "ghrel",
"url": "https://downloads.sourceforge.net/project/mcrypt/Libmcrypt/2.5.8/libmcrypt-2.5.8.tar.gz", "repo": "lz4/lz4",
"match": "lz4-.+\\.tar\\.gz",
"license": { "license": {
"type": "file", "type": "file",
"path": "COPYING" "path": "LICENSE"
} }
}, },
"libmemcached": { "libmemcached": {
@@ -242,8 +281,9 @@
} }
}, },
"libsodium": { "libsodium": {
"type": "url", "type": "ghrel",
"url": "https://download.libsodium.org/libsodium/releases/libsodium-1.0.18.tar.gz", "repo": "jedisct1/libsodium",
"match": "libsodium-\\d+(\\.\\d+)*\\.tar\\.gz",
"license": { "license": {
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
@@ -258,6 +298,20 @@
"path": "COPYING" "path": "COPYING"
} }
}, },
"libuv": {
"type": "ghtar",
"repo": "libuv/libuv",
"license": [
{
"type": "file",
"path": "LICENSE"
},
{
"type": "file",
"path": "LICENSE-extra"
}
]
},
"libwebp": { "libwebp": {
"type": "url", "type": "url",
"url": "https://github.com/webmproject/libwebp/archive/refs/tags/v1.3.2.tar.gz", "url": "https://github.com/webmproject/libwebp/archive/refs/tags/v1.3.2.tar.gz",
@@ -301,14 +355,6 @@
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"mcrypt": {
"type": "url",
"url": "https://downloads.sourceforge.net/project/mcrypt/MCrypt/2.6.8/mcrypt-2.6.8.tar.gz",
"license": {
"type": "file",
"path": "COPYING"
}
},
"memcached": { "memcached": {
"type": "url", "type": "url",
"url": "https://pecl.php.net/get/memcached", "url": "https://pecl.php.net/get/memcached",
@@ -376,9 +422,8 @@
} }
}, },
"pkg-config": { "pkg-config": {
"type": "filelist", "type": "url",
"url": "https://pkgconfig.freedesktop.org/releases/", "url": "https://dl.static-php.dev/static-php-cli/deps/pkg-config/pkg-config-0.29.2.tar.gz",
"regex": "/href=\"(?<file>pkg-config-(?<version>[^\"]+)\\.tar\\.gz)\"/",
"license": { "license": {
"type": "file", "type": "file",
"path": "COPYING" "path": "COPYING"
@@ -449,6 +494,16 @@
"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." "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."
} }
}, },
"sqlsrv": {
"type": "url",
"url": "https://pecl.php.net/get/sqlsrv",
"path": "php-src/ext/sqlsrv",
"filename": "sqlsrv.tgz",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"swoole": { "swoole": {
"type": "ghtar", "type": "ghtar",
"path": "php-src/ext/swoole", "path": "php-src/ext/swoole",
@@ -478,6 +533,24 @@
"path": "README/LICENSE.md" "path": "README/LICENSE.md"
} }
}, },
"unixodbc": {
"type": "url",
"url": "https://www.unixodbc.org/unixODBC-2.3.12.tar.gz",
"license": {
"type": "file",
"path": "COPYING"
}
},
"xhprof": {
"type": "url",
"url": "https://pecl.php.net/get/xhprof",
"path": "php-src/ext/xhprof-src",
"filename": "xhprof.tgz",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"xlswriter": { "xlswriter": {
"type": "url", "type": "url",
"url": "https://pecl.php.net/get/xlswriter", "url": "https://pecl.php.net/get/xlswriter",
@@ -489,9 +562,9 @@
} }
}, },
"xz": { "xz": {
"type": "filelist", "type": "ghrel",
"url": "https://tukaani.org/xz/", "repo": "tukaani-project/xz",
"regex": "/href=\"(?<file>xz-(?<version>[^\"]+)\\.tar\\.xz)\"/", "match": "xz-.+\\.tar\\.gz",
"license": { "license": {
"type": "file", "type": "file",
"path": "COPYING" "path": "COPYING"

View File

@@ -8,5 +8,10 @@ parameters:
- '#Unsafe usage of new static#' - '#Unsafe usage of new static#'
- '#class Fiber#' - '#class Fiber#'
- '#Attribute class JetBrains\\PhpStorm\\ArrayShape does not exist#' - '#Attribute class JetBrains\\PhpStorm\\ArrayShape does not exist#'
- '#Function Swoole\\Coroutine\\run not found.#'
dynamicConstantNames: dynamicConstantNames:
- PHP_OS_FAMILY - PHP_OS_FAMILY
excludePaths:
analyseAndScan:
- ./src/globals/tests/swoole.php
- ./src/globals/tests/swoole.phpt

View File

@@ -23,7 +23,7 @@ use Symfony\Component\Console\Command\ListCommand;
*/ */
final class ConsoleApplication extends Application final class ConsoleApplication extends Application
{ {
public const VERSION = '2.0.0-rc9'; public const VERSION = '2.0.0';
public function __construct() public function __construct()
{ {

View File

@@ -33,12 +33,12 @@ abstract class BuilderBase
/** /**
* Build libraries * Build libraries
* *
* @param array<string> $libraries Libraries to build * @param array<string> $sorted_libraries Libraries to build (if not empty, must sort first)
* @throws FileSystemException * @throws FileSystemException
* @throws RuntimeException * @throws RuntimeException
* @throws WrongUsageException * @throws WrongUsageException
*/ */
public function buildLibs(array $libraries): void public function buildLibs(array $sorted_libraries): void
{ {
// search all supported libs // search all supported libs
$support_lib_list = []; $support_lib_list = [];
@@ -53,20 +53,18 @@ abstract class BuilderBase
} }
// if no libs specified, compile all supported libs // if no libs specified, compile all supported libs
if ($libraries === [] && $this->isLibsOnly()) { if ($sorted_libraries === [] && $this->isLibsOnly()) {
$libraries = array_keys($support_lib_list); $libraries = array_keys($support_lib_list);
$sorted_libraries = DependencyUtil::getLibsByDeps($libraries);
} }
// pkg-config must be compiled first, whether it is specified or not // pkg-config must be compiled first, whether it is specified or not
if (!in_array('pkg-config', $libraries)) { if (!in_array('pkg-config', $sorted_libraries)) {
array_unshift($libraries, 'pkg-config'); array_unshift($sorted_libraries, 'pkg-config');
} }
// append dependencies
$libraries = DependencyUtil::getLibsByDeps($libraries);
// add lib object for builder // add lib object for builder
foreach ($libraries as $library) { foreach ($sorted_libraries as $library) {
// if some libs are not supported (but in config "lib.json", throw exception) // if some libs are not supported (but in config "lib.json", throw exception)
if (!isset($support_lib_list[$library])) { if (!isset($support_lib_list[$library])) {
throw new WrongUsageException('library [' . $library . '] is in the lib.json list but not supported to compile, but in the future I will support it!'); throw new WrongUsageException('library [' . $library . '] is in the lib.json list but not supported to compile, but in the future I will support it!');
@@ -81,7 +79,7 @@ abstract class BuilderBase
} }
// extract sources // extract sources
SourceExtractor::initSource(libs: $libraries); SourceExtractor::initSource(libs: $sorted_libraries);
// build all libs // build all libs
foreach ($this->libs as $lib) { foreach ($this->libs as $lib) {
@@ -227,7 +225,7 @@ abstract class BuilderBase
foreach ($this->exts as $ext) { foreach ($this->exts as $ext) {
$ret[] = trim($ext->getConfigureArg()); $ret[] = trim($ext->getConfigureArg());
} }
logger()->info('Using configure: ' . implode(' ', $ret)); logger()->debug('Using configure: ' . implode(' ', $ret));
return implode(' ', $ret); return implode(' ', $ret);
} }

View File

@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('ldap')]
class ldap extends Extension
{
public function patchBeforeConfigure(): bool
{
$output = shell()->execWithResult('$PKG_CONFIG --libs-only-l --static ldap');
if (!empty($output[1][0])) {
$libs = $output[1][0];
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/configure', '-lldap ', $libs . ' ');
}
return true;
}
}

View File

@@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\RuntimeException;
use SPC\util\CustomExt;
#[CustomExt('password-argon2')]
class password_argon2 extends Extension
{
public function runCliCheck(): void
{
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -r "assert(defined(\'PASSWORD_ARGON2I\'));"');
if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed sanity check');
}
}
}

View File

@@ -13,14 +13,14 @@ class redis extends Extension
public function getUnixConfigureArg(): string public function getUnixConfigureArg(): string
{ {
$arg = '--enable-redis'; $arg = '--enable-redis';
if (!$this->builder->getExt('session')) { $arg .= $this->builder->getExt('session') ? ' --enable-redis-session' : ' --disable-redis-session';
$arg .= ' --disable-redis-session'; $arg .= $this->builder->getExt('igbinary') ? ' --enable-redis-igbinary' : ' --disable-redis-igbinary';
} else {
$arg .= ' --enable-redis-session';
}
if ($this->builder->getLib('zstd')) { if ($this->builder->getLib('zstd')) {
$arg .= ' --enable-redis-zstd --with-libzstd="' . BUILD_ROOT_PATH . '"'; $arg .= ' --enable-redis-zstd --with-libzstd="' . BUILD_ROOT_PATH . '"';
} }
if ($this->builder->getLib('liblz4')) {
$arg .= ' --enable-redis-lz4 --with-liblz4="' . BUILD_ROOT_PATH . '"';
}
return $arg; return $arg;
} }
} }

View File

@@ -12,13 +12,31 @@ class swoole extends Extension
{ {
public function getUnixConfigureArg(): string public function getUnixConfigureArg(): string
{ {
// enable swoole
$arg = '--enable-swoole'; $arg = '--enable-swoole';
// pgsql hook is buggy for static php
$arg .= ' --disable-swoole-pgsql'; // commonly-used feature: coroutine-time, thread-context
$arg .= $this->builder->getLib('openssl') ? ' --enable-openssl' : ' --disable-openssl --without-openssl'; $arg .= ' --enable-swoole-coro-time --enable-thread-context';
$arg .= $this->builder->getLib('brotli') ? (' --enable-brotli --with-brotli-dir=' . BUILD_ROOT_PATH) : ' --disable-brotli';
// swoole curl hook is buggy for php 8.0 // required feature: curl, openssl (but curl hook is buggy for php 8.0)
$arg .= $this->builder->getExt('curl') && $this->builder->getPHPVersionID() >= 80100 ? ' --enable-swoole-curl' : ' --disable-swoole-curl'; $arg .= $this->builder->getPHPVersionID() >= 80100 ? ' --enable-swoole-curl' : ' --disable-swoole-curl';
$arg .= ' --enable-openssl';
// additional feature: c-ares, brotli, nghttp2 (can be disabled, but we enable it by default in config to support full network feature)
$arg .= $this->builder->getLib('libcares') ? ' --enable-cares' : '';
$arg .= $this->builder->getLib('brotli') ? (' --with-brotli-dir=' . BUILD_ROOT_PATH) : '';
$arg .= $this->builder->getLib('nghttp2') ? (' --with-nghttp2-dir=' . BUILD_ROOT_PATH) : '';
// additional feature: swoole-pgsql, it should depend on lib [postgresql], but it will lack of CFLAGS etc.
// so this is a tricky way (enable ext [pgsql,pdo] to add postgresql hook and pdo_pgsql support)
$arg .= $this->builder->getExt('swoole-hook-pgsql') ? '' : ' --disable-swoole-pgsql';
// enable this feature , need remove pdo_sqlite
// more info : https://wenda.swoole.com/detail/109023
$arg .= $this->builder->getExt('swoole-hook-sqlite') ? '' : ' --disable-swoole-sqlite';
// enable this feature , need stop pdo_*
// $arg .= $this->builder->getLib('unixodbc') ? ' --with-swoole-odbc=unixODBC,' : ' ';
return $arg; return $arg;
} }
} }

View File

@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\RuntimeException;
use SPC\util\CustomExt;
#[CustomExt('swoole-hook-mysql')]
class swoole_hook_mysql extends Extension
{
public function getUnixConfigureArg(): string
{
// pdo_mysql doesn't need to be disabled
// enable swoole-hook-mysql will enable mysqli, pdo, pdo_mysql, we don't need to add any additional options
return '';
}
public function runCliCheck(): void
{
// skip if not enable swoole
if ($this->builder->getExt('swoole') === null) {
return;
}
[$ret, $out] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php --ri "swoole"', false);
$out = implode('', $out);
if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret);
}
if (!str_contains($out, 'mysqlnd')) {
throw new RuntimeException('swoole mysql hook is not enabled correctly.');
}
}
}

View File

@@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\util\CustomExt;
#[CustomExt('swoole-hook-pgsql')]
class swoole_hook_pgsql extends Extension
{
public function getUnixConfigureArg(): string
{
// pdo_pgsql need to be disabled
if ($this->builder->getExt('pdo_pgsql') !== null) {
throw new WrongUsageException('swoole-hook-pgsql provides pdo_pgsql, if you enable pgsql hook for swoole, you must remove pdo_pgsql extension.');
}
// enable swoole pgsql hook
return '--enable-swoole-pgsql';
}
public function runCliCheck(): void
{
// skip if not enable swoole
if ($this->builder->getExt('swoole') === null) {
return;
}
[$ret, $out] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php --ri "swoole"', false);
$out = implode('', $out);
if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret);
}
if (!str_contains($out, 'coroutine_pgsql')) {
throw new RuntimeException('swoole pgsql hook is not enabled correctly.');
}
}
}

View File

@@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\util\CustomExt;
#[CustomExt('swoole-hook-sqlite')]
class swoole_hook_sqlite extends Extension
{
public function getUnixConfigureArg(): string
{
// pdo_pgsql need to be disabled
if ($this->builder->getExt('pdo_sqlite') !== null) {
throw new WrongUsageException('swoole-hook-sqlite provides pdo_sqlite, if you enable sqlite hook for swoole, you must remove pdo_sqlite extension.');
}
// enable swoole pgsql hook
return '--enable-swoole-sqlite';
}
public function runCliCheck(): void
{
// skip if not enable swoole
if ($this->builder->getExt('swoole') === null) {
return;
}
[$ret, $out] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php --ri "swoole"', false);
$out = implode('', $out);
if ($ret !== 0) {
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret);
}
if (!str_contains($out, 'coroutine_sqlite')) {
throw new RuntimeException('swoole sqlite hook is not enabled correctly.');
}
}
}

View File

@@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('xhprof')]
class xhprof extends Extension
{
public function patchBeforeBuildconf(): bool
{
if (!is_link(SOURCE_PATH . '/php-src/ext/xhprof')) {
if (PHP_OS_FAMILY === 'Windows') {
f_passthru('cd ' . SOURCE_PATH . '/php-src/ext && mklink /D xhprof xhprof-src\extension');
} else {
f_passthru('cd ' . SOURCE_PATH . '/php-src/ext && ln -s xhprof-src/extension xhprof');
}
// patch config.m4
FileSystem::replaceFileStr(
SOURCE_PATH . '/php-src/ext/xhprof/config.m4',
'if test -f $phpincludedir/ext/pcre/php_pcre.h; then',
'if test -f $abs_srcdir/ext/pcre/php_pcre.h; then'
);
return true;
}
return false;
}
}

View File

@@ -138,15 +138,15 @@ class LinuxBuilder extends BuilderBase
// add libstdc++, some extensions or libraries need it // add libstdc++, some extensions or libraries need it
$extra_libs .= (empty($extra_libs) ? '' : ' ') . ($this->hasCpp() ? '-lstdc++ ' : ''); $extra_libs .= (empty($extra_libs) ? '' : ' ') . ($this->hasCpp() ? '-lstdc++ ' : '');
$this->setOption('extra-libs', $extra_libs); $this->setOption('extra-libs', $extra_libs);
$cflags = $this->arch_c_flags; $cflags = $this->arch_c_flags;
// prepare build php envs // prepare build php envs
$envs_build_php = SystemUtil::makeEnvVarString([ $envs_build_php = SystemUtil::makeEnvVarString([
'CFLAGS' => $cflags, 'CFLAGS' => $cflags,
'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH,
'LDFLAGS' => '-L' . BUILD_LIB_PATH,
'LIBS' => '-ldl -lpthread', 'LIBS' => '-ldl -lpthread',
]); ]);
SourcePatcher::patchBeforeBuildconf($this); SourcePatcher::patchBeforeBuildconf($this);
shell()->cd(SOURCE_PATH . '/php-src')->exec('./buildconf --force'); shell()->cd(SOURCE_PATH . '/php-src')->exec('./buildconf --force');
@@ -189,8 +189,8 @@ class LinuxBuilder extends BuilderBase
$json_74 . $json_74 .
$zts . $zts .
$maxExecutionTimers . $maxExecutionTimers .
$this->makeExtensionArgs() . ' ' . $this->makeExtensionArgs() .
$envs_build_php ' ' . $envs_build_php . ' '
); );
SourcePatcher::patchBeforeMake($this); SourcePatcher::patchBeforeMake($this);
@@ -322,10 +322,11 @@ class LinuxBuilder extends BuilderBase
$cflags = isset($input['EXTRA_CFLAGS']) && $input['EXTRA_CFLAGS'] ? " {$input['EXTRA_CFLAGS']}" : ''; $cflags = isset($input['EXTRA_CFLAGS']) && $input['EXTRA_CFLAGS'] ? " {$input['EXTRA_CFLAGS']}" : '';
$libs = isset($input['EXTRA_LIBS']) && $input['EXTRA_LIBS'] ? " {$input['EXTRA_LIBS']}" : ''; $libs = isset($input['EXTRA_LIBS']) && $input['EXTRA_LIBS'] ? " {$input['EXTRA_LIBS']}" : '';
$ldflags = isset($input['EXTRA_LDFLAGS_PROGRAM']) && $input['EXTRA_LDFLAGS_PROGRAM'] ? " {$input['EXTRA_LDFLAGS_PROGRAM']}" : ''; $ldflags = isset($input['EXTRA_LDFLAGS_PROGRAM']) && $input['EXTRA_LDFLAGS_PROGRAM'] ? " {$input['EXTRA_LDFLAGS_PROGRAM']}" : '';
$tune_c_flags = implode(' ', array_map(fn ($x) => "-Xcompiler {$x}", $this->tune_c_flags));
return [ return [
'EXTRA_CFLAGS' => "{$optimization} -fno-ident -fPIE " . implode(' ', array_map(fn ($x) => "-Xcompiler {$x}", $this->tune_c_flags)) . $cflags, 'EXTRA_CFLAGS' => "{$optimization} -fno-ident -fPIE {$tune_c_flags}{$cflags}",
'EXTRA_LIBS' => $this->getOption('extra-libs', '') . $libs, 'EXTRA_LIBS' => "{$this->getOption('extra-libs', '')} {$libs}",
'EXTRA_LDFLAGS_PROGRAM' => "{$use_lld} -all-static" . $ldflags, 'EXTRA_LDFLAGS_PROGRAM' => "{$use_lld} -all-static{$ldflags}",
]; ];
} }
} }

View File

@@ -47,6 +47,10 @@ class imap extends LinuxLibraryBase
shell()->cd($this->source_dir) shell()->cd($this->source_dir)
->exec('make clean') ->exec('make clean')
->exec('touch ip6') ->exec('touch ip6')
->exec('chmod +x tools/an')
->exec('chmod +x tools/ua')
->exec('chmod +x src/osdep/unix/drivers')
->exec('chmod +x src/osdep/unix/mkauths')
->exec( ->exec(
"yes | make slx {$ssl_options}" "yes | make slx {$ssl_options}"
); );

View File

@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\WrongUsageException;
use SPC\store\FileSystem;
class libargon2 extends LinuxLibraryBase
{
use \SPC\builder\unix\library\libargon2;
public const NAME = 'libargon2';
public function patchBeforeBuild(): bool
{
// detect libsodium (The libargon2 conflicts with the libsodium library.)
if ($this->builder->getLib('libsodium') !== null) {
throw new WrongUsageException('libargon2 (required by password-argon2) conflicts with the libsodium library !');
}
FileSystem::replaceFileStr($this->source_dir . '/Makefile', 'LIBRARY_REL ?= lib/x86_64-linux-gnu', 'LIBRARY_REL ?= lib');
return true;
}
}

View File

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

View File

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

View File

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

View File

@@ -26,7 +26,9 @@ class libxml2 extends LinuxLibraryBase
shell()->cd($this->source_dir . '/build') shell()->cd($this->source_dir . '/build')
->exec( ->exec(
'cmake ' . 'cmake ' .
"{$this->builder->makeCmakeArgs()} " . '-DCMAKE_BUILD_TYPE=Release ' .
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' .
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
'-DBUILD_SHARED_LIBS=OFF ' . '-DBUILD_SHARED_LIBS=OFF ' .
'-DIconv_IS_BUILT_IN=OFF ' . '-DIconv_IS_BUILT_IN=OFF ' .
'-DLIBXML2_WITH_ICONV=ON ' . '-DLIBXML2_WITH_ICONV=ON ' .
@@ -39,7 +41,7 @@ class libxml2 extends LinuxLibraryBase
'..' '..'
) )
->exec("cmake --build . -j {$this->builder->concurrency}") ->exec("cmake --build . -j {$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH); ->exec('make install');
FileSystem::replaceFileStr( FileSystem::replaceFileStr(
BUILD_LIB_PATH . '/pkgconfig/libxml-2.0.pc', BUILD_LIB_PATH . '/pkgconfig/libxml-2.0.pc',

View File

@@ -1,72 +1,12 @@
<?php <?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*
* lwmbs is licensed under Mulan PSL v2. You can use this
* software according to the terms and conditions of the
* Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
*/
declare(strict_types=1); declare(strict_types=1);
namespace SPC\builder\linux\library; namespace SPC\builder\linux\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
class nghttp2 extends LinuxLibraryBase class nghttp2 extends LinuxLibraryBase
{ {
use \SPC\builder\unix\library\nghttp2;
public const NAME = 'nghttp2'; public const NAME = 'nghttp2';
/**
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
public function build(): void
{
$args = $this->builder->makeAutoconfArgs(static::NAME, [
'zlib' => null,
'openssl' => null,
'libxml2' => null,
'libev' => null,
'libcares' => null,
'libngtcp2' => null,
'libnghttp3' => null,
'libbpf' => null,
'libevent-openssl' => null,
'jansson' => null,
'jemalloc' => null,
'systemd' => null,
'cunit' => null,
]);
[,,$destdir] = SEPARATED_PATH;
shell()->cd($this->source_dir)
->exec(
'./configure ' .
'--enable-static ' .
'--disable-shared ' .
"--host={$this->builder->getOption('gnu-arch')}-unknown-linux " .
'--enable-lib-only ' .
'--with-boost=no ' .
$args . ' ' .
'--prefix='
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec("make install DESTDIR={$destdir}");
$this->patchPkgconfPrefix(['libnghttp2.pc']);
}
} }

View File

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

View File

@@ -155,6 +155,21 @@ class MacOSBuilder extends BuilderBase
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO; $enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
$enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED; $enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
// prepare build php envs
$envs_build_php = SystemUtil::makeEnvVarString([
'CFLAGS' => " {$this->arch_c_flags} -Werror=unknown-warning-option ",
'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH,
'LDFLAGS' => '-L' . BUILD_LIB_PATH,
]);
if ($this->getLib('postgresql')) {
shell()
->cd(SOURCE_PATH . '/php-src')
->exec(
'sed -i.backup "s/ac_cv_func_explicit_bzero\" = xyes/ac_cv_func_explicit_bzero\" = x_fake_yes/" ./configure'
);
}
shell()->cd(SOURCE_PATH . '/php-src') shell()->cd(SOURCE_PATH . '/php-src')
->exec( ->exec(
'./configure ' . './configure ' .
@@ -162,7 +177,6 @@ class MacOSBuilder extends BuilderBase
'--with-valgrind=no ' . // Not detect memory leak '--with-valgrind=no ' . // Not detect memory leak
'--enable-shared=no ' . '--enable-shared=no ' .
'--enable-static=yes ' . '--enable-static=yes ' .
"CFLAGS='{$this->arch_c_flags} -Werror=unknown-warning-option' " .
'--disable-all ' . '--disable-all ' .
'--disable-cgi ' . '--disable-cgi ' .
'--disable-phpdbg ' . '--disable-phpdbg ' .
@@ -172,7 +186,8 @@ class MacOSBuilder extends BuilderBase
($enableMicro ? '--enable-micro ' : '--disable-micro ') . ($enableMicro ? '--enable-micro ' : '--disable-micro ') .
$json_74 . $json_74 .
$zts . $zts .
$this->makeExtensionArgs() $this->makeExtensionArgs() . ' ' .
$envs_build_php
); );
SourcePatcher::patchBeforeMake($this); SourcePatcher::patchBeforeMake($this);
@@ -212,10 +227,7 @@ class MacOSBuilder extends BuilderBase
*/ */
public function buildCli(): void public function buildCli(): void
{ {
$vars = SystemUtil::makeEnvVarString([ $vars = SystemUtil::makeEnvVarString($this->getBuildVars());
'EXTRA_CFLAGS' => '-g -Os', // with debug information, but optimize for size
'EXTRA_LIBS' => "{$this->getOption('extra-libs')} -lresolv", // link resolv library (macOS needs it)
]);
$shell = shell()->cd(SOURCE_PATH . '/php-src'); $shell = shell()->cd(SOURCE_PATH . '/php-src');
$shell->exec("make -j{$this->concurrency} {$vars} cli"); $shell->exec("make -j{$this->concurrency} {$vars} cli");
@@ -246,9 +258,8 @@ class MacOSBuilder extends BuilderBase
$vars = [ $vars = [
// with debug information, optimize for size, remove identifiers, patch fake cli for micro // with debug information, optimize for size, remove identifiers, patch fake cli for micro
'EXTRA_CFLAGS' => '-g -Os -fno-ident' . $enable_fake_cli, 'EXTRA_CFLAGS' => '-g -Os -fno-ident' . $enable_fake_cli,
// link resolv library (macOS needs it)
'EXTRA_LIBS' => "{$this->getOption('extra-libs')} -lresolv",
]; ];
$vars = $this->getBuildVars($vars);
if (!$this->getOption('no-strip', false)) { if (!$this->getOption('no-strip', false)) {
$vars['STRIP'] = 'dsymutil -f '; $vars['STRIP'] = 'dsymutil -f ';
} }
@@ -271,10 +282,7 @@ class MacOSBuilder extends BuilderBase
*/ */
public function buildFpm(): void public function buildFpm(): void
{ {
$vars = SystemUtil::makeEnvVarString([ $vars = SystemUtil::makeEnvVarString($this->getBuildVars());
'EXTRA_CFLAGS' => '-g -Os', // with debug information, but optimize for size
'EXTRA_LIBS' => "{$this->getOption('extra-libs')} -lresolv", // link resolv library (macOS needs it)
]);
$shell = shell()->cd(SOURCE_PATH . '/php-src'); $shell = shell()->cd(SOURCE_PATH . '/php-src');
$shell->exec("make -j{$this->concurrency} {$vars} fpm"); $shell->exec("make -j{$this->concurrency} {$vars} fpm");
@@ -291,10 +299,7 @@ class MacOSBuilder extends BuilderBase
*/ */
public function buildEmbed(): void public function buildEmbed(): void
{ {
$vars = SystemUtil::makeEnvVarString([ $vars = SystemUtil::makeEnvVarString($this->getBuildVars());
'EXTRA_CFLAGS' => '-g -Os', // with debug information, but optimize for size
'EXTRA_LIBS' => "{$this->getOption('extra-libs')} -lresolv", // link resolv library (macOS needs it)
]);
shell() shell()
->cd(SOURCE_PATH . '/php-src') ->cd(SOURCE_PATH . '/php-src')
@@ -308,4 +313,15 @@ class MacOSBuilder extends BuilderBase
->exec('ar rcs ' . BUILD_ROOT_PATH . '/lib/libphp.a *.o') ->exec('ar rcs ' . BUILD_ROOT_PATH . '/lib/libphp.a *.o')
->exec('rm -Rf ' . BUILD_ROOT_PATH . '/lib/php-o'); ->exec('rm -Rf ' . BUILD_ROOT_PATH . '/lib/php-o');
} }
private function getBuildVars($input = []): array
{
$optimization = $this->getOption('no-strip', false) ? '-g -O0' : '-g0 -Os';
$cflags = isset($input['EXTRA_CFLAGS']) && $input['EXTRA_CFLAGS'] ? " {$input['EXTRA_CFLAGS']}" : '';
$libs = isset($input['EXTRA_LIBS']) && $input['EXTRA_LIBS'] ? " {$input['EXTRA_LIBS']}" : '';
return [
'EXTRA_CFLAGS' => "{$optimization} {$cflags} " . $this->getOption('x-extra-cflags'),
'EXTRA_LIBS' => "{$this->getOption('extra-libs')} -lresolv {$libs} " . $this->getOption('x-extra-libs'),
];
}
} }

View File

@@ -50,6 +50,10 @@ class imap extends MacOSLibraryBase
shell()->cd($this->source_dir) shell()->cd($this->source_dir)
->exec('make clean') ->exec('make clean')
->exec('touch ip6') ->exec('touch ip6')
->exec('chmod +x tools/an')
->exec('chmod +x tools/ua')
->exec('chmod +x src/osdep/unix/drivers')
->exec('chmod +x src/osdep/unix/mkauths')
->exec( ->exec(
"yes | EXTRACFLAGS='-Wimplicit-function-declaration -include $(xcrun --show-sdk-path)/usr/include/poll.h -include $(xcrun --show-sdk-path)/usr/include/time.h -include $(xcrun --show-sdk-path)/usr/include/utime.h' make osx {$ssl_options}" "yes | EXTRACFLAGS='-Wimplicit-function-declaration -include $(xcrun --show-sdk-path)/usr/include/poll.h -include $(xcrun --show-sdk-path)/usr/include/time.h -include $(xcrun --show-sdk-path)/usr/include/utime.h' make osx {$ssl_options}"
); );

View File

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

View File

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

View File

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

View File

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

View File

@@ -27,7 +27,9 @@ class libxml2 extends MacOSLibraryBase
->exec( ->exec(
'cmake ' . 'cmake ' .
// '--debug-find ' . // '--debug-find ' .
"{$this->builder->makeCmakeArgs()} " . '-DCMAKE_BUILD_TYPE=Release ' .
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' .
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
'-DBUILD_SHARED_LIBS=OFF ' . '-DBUILD_SHARED_LIBS=OFF ' .
'-DLIBXML2_WITH_ICONV=ON ' . '-DLIBXML2_WITH_ICONV=ON ' .
"-DLIBXML2_WITH_ZLIB={$enable_zlib} " . "-DLIBXML2_WITH_ZLIB={$enable_zlib} " .
@@ -39,6 +41,6 @@ class libxml2 extends MacOSLibraryBase
'..' '..'
) )
->exec("cmake --build . -j {$this->builder->concurrency}") ->exec("cmake --build . -j {$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH); ->exec('make install');
} }
} }

View File

@@ -20,51 +20,9 @@ declare(strict_types=1);
namespace SPC\builder\macos\library; namespace SPC\builder\macos\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
class nghttp2 extends MacOSLibraryBase class nghttp2 extends MacOSLibraryBase
{ {
use \SPC\builder\unix\library\nghttp2;
public const NAME = 'nghttp2'; public const NAME = 'nghttp2';
/**
* @throws FileSystemException
* @throws RuntimeException
*/
protected function build(): void
{
$args = $this->builder->makeAutoconfArgs(static::NAME, [
'zlib' => null,
'openssl' => null,
'libxml2' => null,
'libev' => null,
'libcares' => null,
'libngtcp2' => null,
'libnghttp3' => null,
'libbpf' => null,
'libevent-openssl' => null,
'jansson' => null,
'jemalloc' => null,
'systemd' => null,
'cunit' => null,
]);
[,,$destdir] = SEPARATED_PATH;
shell()->cd($this->source_dir)
->exec(
'./configure ' .
'--enable-static ' .
'--disable-shared ' .
"--host={$this->builder->getOption('gnu-arch')}-apple-darwin " .
'--enable-lib-only ' .
'--with-boost=no ' .
$args . ' ' .
'--prefix='
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec("make install DESTDIR={$destdir}");
$this->patchPkgconfPrefix(['libnghttp2.pc']);
}
} }

View File

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

View File

@@ -27,10 +27,7 @@ trait brotli
->exec("cmake --build . -j {$this->builder->concurrency}") ->exec("cmake --build . -j {$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH); ->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
$this->patchPkgconfPrefix(['libbrotlicommon.pc', 'libbrotlidec.pc', 'libbrotlienc.pc']); $this->patchPkgconfPrefix(['libbrotlicommon.pc', 'libbrotlidec.pc', 'libbrotlienc.pc']);
shell()->cd(BUILD_ROOT_PATH . '/lib') shell()->cd(BUILD_ROOT_PATH . '/lib')->exec('ln -sf libbrotlicommon.a libbrotli.a');
->exec('ln -s libbrotlicommon.a libbrotlicommon-static.a')
->exec('ln -s libbrotlidec.a libbrotlidec-static.a')
->exec('ln -s libbrotlienc.a libbrotlienc-static.a');
foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) { foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) {
if (str_starts_with($filename, 'libbrotli') && (str_contains($filename, '.so') || str_ends_with($filename, '.dylib'))) { if (str_starts_with($filename, 'libbrotli') && (str_contains($filename, '.so') || str_ends_with($filename, '.dylib'))) {
unlink(BUILD_ROOT_PATH . '/lib/' . $filename); unlink(BUILD_ROOT_PATH . '/lib/' . $filename);

View File

@@ -4,17 +4,25 @@ declare(strict_types=1);
namespace SPC\builder\unix\library; namespace SPC\builder\unix\library;
use SPC\store\FileSystem;
trait ldap trait ldap
{ {
public function patchBeforeBuild(): bool
{
FileSystem::replaceFileStr($this->source_dir . '/configure', '"-lssl -lcrypto', '"-lssl -lcrypto -lz');
return true;
}
protected function build(): void protected function build(): void
{ {
$alt = ''; $alt = '';
// openssl support // openssl support
$alt .= $this->builder->getLib('openssl') && $this->builder->getExt('zlib') ? '--with-tls=openssl ' : ''; $alt .= $this->builder->getLib('openssl') ? '--with-tls=openssl ' : '';
// gmp support // gmp support
$alt .= $this->builder->getLib('gmp') ? '--with-mp=gmp ' : ''; $alt .= $this->builder->getLib('gmp') ? '--with-mp=gmp ' : '';
// libsodium support // libsodium support
$alt .= $this->builder->getLib('libsodium') ? '--with-argon2=libsodium ' : ''; $alt .= $this->builder->getLib('libsodium') ? '--with-argon2=libsodium ' : '--enable-argon2=no ';
f_putenv('PKG_CONFIG=' . BUILD_ROOT_PATH . '/bin/pkg-config'); f_putenv('PKG_CONFIG=' . BUILD_ROOT_PATH . '/bin/pkg-config');
f_putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig'); f_putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig');
shell()->cd($this->source_dir) shell()->cd($this->source_dir)
@@ -24,7 +32,6 @@ trait ldap
'--enable-static ' . '--enable-static ' .
'--disable-shared ' . '--disable-shared ' .
'--disable-slapd ' . '--disable-slapd ' .
'--disable-slurpd ' .
'--without-systemd ' . '--without-systemd ' .
'--without-cyrus-sasl ' . '--without-cyrus-sasl ' .
$alt . $alt .

View File

@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\store\FileSystem;
trait libargon2
{
protected function build()
{
shell()->cd($this->source_dir)
->exec("make PREFIX='' clean")
->exec("make -j{$this->builder->concurrency} PREFIX=''")
->exec("make install PREFIX='' DESTDIR=" . BUILD_ROOT_PATH);
$this->patchPkgconfPrefix(['libargon2.pc']);
foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) {
if (str_starts_with($filename, 'libargon2') && (str_contains($filename, '.so') || str_ends_with($filename, '.dylib'))) {
unlink(BUILD_ROOT_PATH . '/lib/' . $filename);
}
}
}
}

View File

@@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\exception\RuntimeException;
trait libcares
{
/**
* @throws RuntimeException
*/
protected function build(): void
{
shell()->cd($this->source_dir)
->exec('./configure --prefix=' . BUILD_ROOT_PATH . ' --enable-static --disable-shared --disable-tests')
->exec("make -j {$this->builder->concurrency}")
->exec('make install');
}
}

View File

@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\store\FileSystem;
trait liblz4
{
protected function build()
{
shell()->cd($this->source_dir)
->exec("make PREFIX='' clean")
->exec("make -j{$this->builder->concurrency} PREFIX=''")
->exec("make install PREFIX='' DESTDIR=" . BUILD_ROOT_PATH);
$this->patchPkgconfPrefix(['liblz4.pc']);
foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) {
if (str_starts_with($filename, 'liblz4') && (str_contains($filename, '.so') || str_ends_with($filename, '.dylib'))) {
unlink(BUILD_ROOT_PATH . '/lib/' . $filename);
}
}
}
}

View File

@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
trait libuv
{
/**
* @throws FileSystemException
* @throws RuntimeException
*/
protected function build(): void
{
// CMake needs a clean build directory
FileSystem::resetDir($this->source_dir . '/build');
// Start build
shell()->cd($this->source_dir . '/build')
->exec("cmake {$this->builder->makeCmakeArgs()} -DLIBUV_BUILD_SHARED=OFF ..")
->exec("cmake --build . -j {$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
// patch pkgconfig
$this->patchPkgconfPrefix(['libuv-static.pc']);
}
}

View File

@@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
trait nghttp2
{
/**
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
protected function build(): void
{
$args = $this->builder->makeAutoconfArgs(static::NAME, [
'zlib' => null,
'openssl' => null,
'libxml2' => null,
'libev' => null,
'libcares' => null,
'libngtcp2' => null,
'libnghttp3' => null,
'libbpf' => null,
'libevent-openssl' => null,
'jansson' => null,
'jemalloc' => null,
'systemd' => null,
'cunit' => null,
]);
[,,$destdir] = SEPARATED_PATH;
shell()->cd($this->source_dir)
->exec(
'./configure ' .
'--enable-static ' .
'--disable-shared ' .
'--enable-lib-only ' .
'--with-boost=no ' .
$args . ' ' .
'--prefix='
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec("make install DESTDIR={$destdir}");
$this->patchPkgconfPrefix(['libnghttp2.pc']);
}
}

View File

@@ -28,9 +28,6 @@ trait postgresql
'icu' => 'icu-i18n', 'icu' => 'icu-i18n',
]; ];
f_putenv('PKG_CONFIG=' . BUILD_ROOT_PATH . '/bin/pkg-config');
f_putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig');
foreach ($optional_packages as $lib => $pkg) { foreach ($optional_packages as $lib => $pkg) {
if ($this->getBuilder()->getLib($lib)) { if ($this->getBuilder()->getLib($lib)) {
$packages .= ' ' . $pkg; $packages .= ' ' . $pkg;

View File

@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
trait unixodbc
{
/**
* @throws FileSystemException
* @throws RuntimeException
*/
protected function build(): void
{
shell()->cd($this->source_dir)
->exec(
'./configure ' .
'--enable-static --disable-shared ' .
'--disable-debug ' .
'--disable-dependency-tracking ' .
'--with-libiconv-prefix=' . BUILD_ROOT_PATH . ' ' .
'--with-included-ltdl ' .
'--enable-gui=no ' .
'--prefix='
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
$this->patchPkgconfPrefix(['odbc.pc', 'odbccr.pc', 'odbcinst.pc']);
$this->cleanLaFiles();
}
}

View File

@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace SPC\builder\windows;
class SystemUtil
{
/**
* @param string $name 命令名称
* @param array $paths 寻找的目标路径(如果不传入,则使用环境变量 PATH
* @return null|string 找到了返回命令路径,找不到返回 null
*/
public static function findCommand(string $name, array $paths = []): ?string
{
if (!$paths) {
$paths = explode(PATH_SEPARATOR, getenv('Path'));
}
foreach ($paths as $path) {
if (file_exists($path . DIRECTORY_SEPARATOR . $name)) {
return $path . DIRECTORY_SEPARATOR . $name;
}
}
return null;
}
}

View File

@@ -4,13 +4,17 @@ declare(strict_types=1);
namespace SPC\command; namespace SPC\command;
use Laravel\Prompts\ConfirmPrompt;
use Laravel\Prompts\Prompt;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use SPC\ConsoleApplication; use SPC\ConsoleApplication;
use SPC\exception\ExceptionHandler; use SPC\exception\ExceptionHandler;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;
use ZM\Logger\ConsoleLogger; use ZM\Logger\ConsoleLogger;
abstract class BaseCommand extends Command abstract class BaseCommand extends Command
@@ -78,6 +82,15 @@ abstract class BaseCommand extends Command
{ {
$this->input = $input; $this->input = $input;
$this->output = $output; $this->output = $output;
// windows fallback
Prompt::fallbackWhen(PHP_OS_FAMILY === 'Windows');
ConfirmPrompt::fallbackUsing(function (ConfirmPrompt $prompt) use ($input, $output) {
$helper = new QuestionHelper();
$case = $prompt->default ? ' [Y/n] ' : ' [y/N] ';
$question = new ConfirmationQuestion($prompt->label . $case, $prompt->default);
return $helper->ask($input, $output, $question);
});
if ($this->shouldExecute()) { if ($this->shouldExecute()) {
try { try {
return $this->handle(); return $this->handle();

View File

@@ -7,6 +7,7 @@ namespace SPC\command;
use SPC\builder\BuilderProvider; use SPC\builder\BuilderProvider;
use SPC\exception\ExceptionHandler; use SPC\exception\ExceptionHandler;
use SPC\exception\RuntimeException; use SPC\exception\RuntimeException;
use SPC\util\DependencyUtil;
use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
@@ -59,6 +60,7 @@ class BuildLibsCommand extends BuildCommand
// 只编译 library 的情况下,标记 // 只编译 library 的情况下,标记
$builder->setLibsOnly(); $builder->setLibsOnly();
// 编译和检查库完整 // 编译和检查库完整
$libraries = DependencyUtil::getLibsByDeps($libraries);
$builder->buildLibs($libraries); $builder->buildLibs($libraries);
$time = round(microtime(true) - START_TIME, 3); $time = round(microtime(true) - START_TIME, 3);

View File

@@ -75,8 +75,9 @@ class DoctorCommand extends BaseCommand
} catch (\Throwable $e) { } catch (\Throwable $e) {
$this->output->writeln('<error>' . $e->getMessage() . '</error>'); $this->output->writeln('<error>' . $e->getMessage() . '</error>');
if (extension_loaded('pcntl')) {
pcntl_signal(SIGINT, SIG_IGN); pcntl_signal(SIGINT, SIG_IGN);
}
return static::FAILURE; return static::FAILURE;
} }

View File

@@ -34,12 +34,23 @@ final class CheckListHandler
*/ */
public function emitFix(OutputInterface $output, CheckResult $result): void public function emitFix(OutputInterface $output, CheckResult $result): void
{ {
if (PHP_OS_FAMILY === 'Windows') {
sapi_windows_set_ctrl_handler(function () use ($output) {
$output->writeln('<error>You cancelled fix</error>');
});
} elseif (extension_loaded('pcntl')) {
pcntl_signal(SIGINT, function () use ($output) { pcntl_signal(SIGINT, function () use ($output) {
$output->writeln('<error>You cancelled fix</error>'); $output->writeln('<error>You cancelled fix</error>');
}); });
}
$fix_result = call_user_func($this->fix_map[$result->getFixItem()], ...$result->getFixParams()); $fix_result = call_user_func($this->fix_map[$result->getFixItem()], ...$result->getFixParams());
if (PHP_OS_FAMILY === 'Windows') {
sapi_windows_set_ctrl_handler(null);
} elseif (extension_loaded('pcntl')) {
pcntl_signal(SIGINT, SIG_IGN); pcntl_signal(SIGINT, SIG_IGN);
}
if ($fix_result) { if ($fix_result) {
$output->writeln('<info>Fix done</info>'); $output->writeln('<info>Fix done</info>');

View File

@@ -16,8 +16,8 @@ class OSCheckList
#[AsCheckItem('if current OS are supported', level: 999)] #[AsCheckItem('if current OS are supported', level: 999)]
public function checkOS(): ?CheckResult public function checkOS(): ?CheckResult
{ {
if (!in_array(PHP_OS_FAMILY, ['Darwin', 'Linux', 'BSD'])) { if (!in_array(PHP_OS_FAMILY, ['Darwin', 'Linux', 'BSD', 'Windows'])) {
return CheckResult::fail('Current OS is not supported'); return CheckResult::fail('Current OS is not supported: ' . PHP_OS_FAMILY);
} }
$distro = PHP_OS_FAMILY === 'Linux' ? (' ' . SystemUtil::getOSRelease()['dist']) : ''; $distro = PHP_OS_FAMILY === 'Linux' ? (' ' . SystemUtil::getOSRelease()['dist']) : '';
return CheckResult::ok(PHP_OS_FAMILY . ' ' . php_uname('m') . $distro . ', supported'); return CheckResult::ok(PHP_OS_FAMILY . ' ' . php_uname('m') . $distro . ', supported');

View File

@@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace SPC\doctor\item;
use SPC\builder\windows\SystemUtil;
use SPC\doctor\AsCheckItem;
use SPC\doctor\AsFixItem;
use SPC\doctor\CheckResult;
use SPC\exception\RuntimeException;
class WindowsToolCheckList
{
#[AsCheckItem('if git are installed', limit_os: 'Windows', level: 999)]
public function checkGit(): ?CheckResult
{
if (SystemUtil::findCommand('git.exe') === null) {
return CheckResult::fail('Git not installed, please install git for windows manually, see: https://git-scm.com/download/win');
// return CheckResult::fail('Git not installed, see https://static-php.dev/en/guide/windows-setup.html');
}
return CheckResult::ok();
}
#[AsCheckItem('if php-sdk-binary-tools are downloaded', limit_os: 'Windows', level: 998)]
public function checkSDK(): ?CheckResult
{
if (!file_exists(PHP_SDK_PATH . DIRECTORY_SEPARATOR . 'phpsdk-starter.bat')) {
return CheckResult::fail('php-sdk-binary-tools not downloaded', 'install-php-sdk');
}
return CheckResult::ok(PHP_SDK_PATH);
}
#[AsFixItem('install-php-sdk')]
public function installPhpSdk(): bool
{
try {
cmd(true)->exec('git clone https://github.com/php/php-sdk-binary-tools.git ' . PHP_SDK_PATH);
} catch (RuntimeException) {
return false;
}
return true;
}
}

View File

@@ -233,6 +233,7 @@ class FileSystem
throw new FileSystemException("unknown archive format: {$filename}"); throw new FileSystemException("unknown archive format: {$filename}");
} }
} }
self::emitSourceExtractHook($name);
} catch (RuntimeException $e) { } catch (RuntimeException $e) {
if (PHP_OS_FAMILY === 'Windows') { if (PHP_OS_FAMILY === 'Windows') {
f_passthru('rmdir /s /q ' . SOURCE_PATH . "/{$name}"); f_passthru('rmdir /s /q ' . SOURCE_PATH . "/{$name}");

View File

@@ -16,6 +16,7 @@ class SourcePatcher
// FileSystem::addSourceExtractHook('swow', [SourcePatcher::class, 'patchSwow']); // FileSystem::addSourceExtractHook('swow', [SourcePatcher::class, 'patchSwow']);
FileSystem::addSourceExtractHook('micro', [SourcePatcher::class, 'patchMicro']); FileSystem::addSourceExtractHook('micro', [SourcePatcher::class, 'patchMicro']);
FileSystem::addSourceExtractHook('openssl', [SourcePatcher::class, 'patchOpenssl11Darwin']); FileSystem::addSourceExtractHook('openssl', [SourcePatcher::class, 'patchOpenssl11Darwin']);
FileSystem::addSourceExtractHook('swoole', [SourcePatcher::class, 'patchSwoole']);
} }
/** /**
@@ -159,6 +160,17 @@ class SourcePatcher
return false; return false;
} }
public static function patchSwoole(): bool
{
// swoole hook needs pdo/pdo.h
FileSystem::replaceFileStr(
SOURCE_PATH . '/php-src/ext/swoole/config.m4',
'PHP_ADD_INCLUDE([$ext_srcdir])',
"PHP_ADD_INCLUDE( [\$ext_srcdir] )\n PHP_ADD_INCLUDE([\$abs_srcdir/ext])"
);
return true;
}
/** /**
* @throws FileSystemException * @throws FileSystemException
*/ */

View File

@@ -17,6 +17,9 @@ class UnixShell
public function __construct(?bool $debug = null) public function __construct(?bool $debug = null)
{ {
if (PHP_OS_FAMILY === 'Windows') {
throw new RuntimeException('Windows cannot use UnixShell');
}
$this->debug = $debug ?? defined('DEBUG_MODE'); $this->debug = $debug ?? defined('DEBUG_MODE');
} }

View File

@@ -0,0 +1,90 @@
<?php
declare(strict_types=1);
namespace SPC\util;
use SPC\exception\RuntimeException;
use ZM\Logger\ConsoleColor;
class WindowsCmd
{
private ?string $cd = null;
private bool $debug;
private array $env = [];
public function __construct(?bool $debug = null)
{
if (PHP_OS_FAMILY !== 'Windows') {
throw new RuntimeException('Only windows can use WindowsCmd');
}
$this->debug = $debug ?? defined('DEBUG_MODE');
}
public function cd(string $dir): WindowsCmd
{
logger()->info('Entering dir: ' . $dir);
$c = clone $this;
$c->cd = $dir;
return $c;
}
/**
* @throws RuntimeException
*/
public function exec(string $cmd): WindowsCmd
{
/* @phpstan-ignore-next-line */
logger()->info(ConsoleColor::yellow('[EXEC] ') . ConsoleColor::green($cmd));
if ($this->cd !== null) {
$cmd = 'cd /d ' . escapeshellarg($this->cd) . ' && ' . $cmd;
}
if (!$this->debug) {
$cmd .= ' >nul 2>&1';
}
echo $cmd . PHP_EOL;
f_passthru($cmd);
return $this;
}
public function execWithResult(string $cmd, bool $with_log = true): array
{
if ($with_log) {
/* @phpstan-ignore-next-line */
logger()->info(ConsoleColor::blue('[EXEC] ') . ConsoleColor::green($cmd));
} else {
logger()->debug('Running command with result: ' . $cmd);
}
exec($cmd, $out, $code);
return [$code, $out];
}
public function setEnv(array $env): WindowsCmd
{
$this->env = array_merge($this->env, $env);
return $this;
}
/**
* @throws RuntimeException
*/
public function execWithEnv(string $cmd): WindowsCmd
{
if ($this->getEnvString() !== '') {
return $this->exec($this->getEnvString() . "call {$cmd}");
}
return $this->exec($cmd);
}
private function getEnvString(): string
{
$str = '';
foreach ($this->env as $k => $v) {
$str .= 'set ' . $k . '=' . $v . ' && ';
}
return $str;
}
}

View File

@@ -5,7 +5,7 @@ declare(strict_types=1);
use ZM\Logger\ConsoleLogger; use ZM\Logger\ConsoleLogger;
define('WORKING_DIR', getcwd()); define('WORKING_DIR', getcwd());
const ROOT_DIR = __DIR__ . '/../..'; define('ROOT_DIR', dirname(__DIR__, 2));
// CLI start time // CLI start time
define('START_TIME', microtime(true)); define('START_TIME', microtime(true));
@@ -22,6 +22,10 @@ define('SEPARATED_PATH', [
BUILD_ROOT_PATH, BUILD_ROOT_PATH,
]); ]);
if (PHP_OS_FAMILY === 'Windows') {
define('PHP_SDK_PATH', is_string($a = getenv('PHP_SDK_PATH')) ? $a : (WORKING_DIR . DIRECTORY_SEPARATOR . 'php-sdk-binary-tools'));
}
// dangerous command // dangerous command
const DANGER_CMD = [ const DANGER_CMD = [
'rm', 'rm',

View File

@@ -3,8 +3,10 @@
declare(strict_types=1); declare(strict_types=1);
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
use SPC\util\UnixShell; use SPC\util\UnixShell;
use SPC\util\WindowsCmd;
use ZM\Logger\ConsoleLogger; use ZM\Logger\ConsoleLogger;
/** /**
@@ -68,7 +70,7 @@ function osfamily2dir(): string
/** /**
* Execute the shell command, and the output will be directly printed in the terminal. If there is an error, an exception will be thrown * Execute the shell command, and the output will be directly printed in the terminal. If there is an error, an exception will be thrown
* *
* @throws \SPC\exception\RuntimeException * @throws RuntimeException
*/ */
function f_passthru(string $cmd): ?bool function f_passthru(string $cmd): ?bool
{ {
@@ -86,7 +88,7 @@ function f_passthru(string $cmd): ?bool
} }
$ret = passthru($cmd, $code); $ret = passthru($cmd, $code);
if ($code !== 0) { if ($code !== 0) {
throw new \SPC\exception\RuntimeException('Command run failed with code[' . $code . ']: ' . $cmd, $code); throw new RuntimeException('Command run failed with code[' . $code . ']: ' . $cmd, $code);
} }
return $ret; return $ret;
} }
@@ -120,3 +122,8 @@ function shell(?bool $debug = null): UnixShell
{ {
return new UnixShell($debug); return new UnixShell($debug);
} }
function cmd(?bool $debug = null): WindowsCmd
{
return new WindowsCmd($debug);
}

View File

@@ -2,7 +2,55 @@
declare(strict_types=1); declare(strict_types=1);
# If you want to test new extensions here, just modify it. /**
$extensions = 'apcu,bcmath,bz2,calendar,ctype,curl,dba,dom,event,exif,fileinfo,filter,ftp,gd,gmp,iconv,imagick,imap,intl,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pdo_pgsql,pdo_sqlite,pgsql,phar,posix,protobuf,readline,redis,session,shmop,simplexml,soap,sockets,sodium,sqlite3,swoole,sysvmsg,sysvsem,sysvshm,tokenizer,xml,xmlreader,xmlwriter,xsl,zip,zlib'; * This is GitHub Actions automatic test extension args generator.
* You can edit $extensions, $with_libs and $base_combination.
*/
echo $extensions; // --------------------------------- edit area ---------------------------------
// If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`).
$extensions = 'ldap';
// If you want to test lib-suggests feature with extension, add them below (comma separated, example `libwebp,libavif`).
$with_libs = '';
// Please change your test base combination. We recommend testing with `common`.
// You can use `common`, `bulk`, `minimal` or `none`.
$base_combination = 'minimal';
// -------------------------- code area, do not modify --------------------------
/**
* get combination for tests, do not modify it if not necessary.
*/
function _getCombination(string $type = 'common'): string
{
return match ($type) {
'common' => 'bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,gd,gmp,iconv,xml,mbstring,mbregex,' .
'mysqlnd,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,redis,session,simplexml,soap,sockets,' .
'sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip',
'bulk' => 'apcu,bcmath,bz2,calendar,ctype,curl,dba,dom,event,exif,fileinfo,filter,ftp,gd,gmp,iconv,imagick,imap,' .
'intl,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pdo_pgsql,pdo_sqlite,pgsql,phar,' .
'posix,protobuf,readline,redis,session,shmop,simplexml,soap,sockets,sodium,sqlite3,swoole,sysvmsg,sysvsem,' .
'sysvshm,tokenizer,xml,xmlreader,xmlwriter,xsl,zip,zlib',
'minimal' => 'pcntl,posix,mbstring,tokenizer,phar',
default => '', // none
};
}
if (!isset($argv[1])) {
exit("Please use 'extensions', 'cmd' or 'libs' as output type");
}
$trim_value = "\r\n \t,";
$final_extensions = trim(trim($extensions, $trim_value) . ',' . _getCombination($base_combination), $trim_value);
$final_libs = trim($with_libs, $trim_value);
echo match ($argv[1]) {
'extensions' => $final_extensions,
'libs' => $final_libs,
'cmd' => $final_extensions . ($final_libs === '' ? '' : (' --with-libs=' . $final_libs)),
default => '',
};

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
assert(function_exists('swoole_cpu_num'));
assert(function_exists('swoole_string'));
assert(class_exists('Swoole\Coroutine'));
assert(class_exists('Swoole\Coroutine\Http2\Client'));
assert(class_exists('Swoole\Coroutine\Redis'));
assert(class_exists('Swoole\Coroutine\WaitGroup'));
assert(class_exists('Swoole\Http2\Request'));
assert(constant('SWOOLE_VERSION'));