mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-02 22:35:43 +08:00
Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bad28fa263 | ||
|
|
985cd6781e | ||
|
|
44dcc830f4 | ||
|
|
10ef4c0d3b | ||
|
|
d0fbc5ab2d | ||
|
|
1bc7bc3421 | ||
|
|
8b9b70704a | ||
|
|
804020210d | ||
|
|
5c51305978 | ||
|
|
43cc9d0ba3 | ||
|
|
52869218e0 | ||
|
|
82e11e52dd | ||
|
|
955c367a47 | ||
|
|
a613e9a84f | ||
|
|
c4b9660cd7 | ||
|
|
f433866671 | ||
|
|
fdc4a907c7 | ||
|
|
cf37e16e38 | ||
|
|
2aa42123f6 | ||
|
|
bc7dba6125 | ||
|
|
3ce24da15c | ||
|
|
3659e20b0d | ||
|
|
a90a57ffab | ||
|
|
45bdb6a66b | ||
|
|
64258e3513 | ||
|
|
fe72b800c6 | ||
|
|
39bc44322e | ||
|
|
1a0e6ee717 | ||
|
|
cc088b6382 | ||
|
|
b9f709c23d | ||
|
|
05b602d38c | ||
|
|
a8a071de1a | ||
|
|
391555b1f5 | ||
|
|
62b0bf8eca | ||
|
|
1ab464431f | ||
|
|
f04b54bc2a | ||
|
|
e1652a4b36 | ||
|
|
8c586fe7d9 | ||
|
|
d2c929cb72 | ||
|
|
b9584e48ac | ||
|
|
e269d1ba00 | ||
|
|
87750c462f | ||
|
|
219edb6b59 | ||
|
|
4f87e01bff | ||
|
|
5f69e957ac | ||
|
|
756bdbf92f | ||
|
|
610fb66b0c | ||
|
|
1186bac49c | ||
|
|
f6fe902c76 | ||
|
|
f984516a67 | ||
|
|
0d2f6456fb | ||
|
|
2fc61d8e5c | ||
|
|
12b119e235 | ||
|
|
6fa5f75963 | ||
|
|
1fa5514c57 | ||
|
|
73e3480bdf | ||
|
|
ddafdf8987 | ||
|
|
2bfc5e1d74 | ||
|
|
3c4d47d072 | ||
|
|
c840165fa8 | ||
|
|
4e95d969e3 | ||
|
|
330dd2bfc6 | ||
|
|
c0b52fc2d1 |
3
.github/workflows/build-linux-arm.yml
vendored
3
.github/workflows/build-linux-arm.yml
vendored
@@ -12,9 +12,10 @@ on:
|
|||||||
version:
|
version:
|
||||||
required: true
|
required: true
|
||||||
description: php version to compile
|
description: php version to compile
|
||||||
default: '8.2'
|
default: '8.3'
|
||||||
type: choice
|
type: choice
|
||||||
options:
|
options:
|
||||||
|
- '8.4'
|
||||||
- '8.3'
|
- '8.3'
|
||||||
- '8.2'
|
- '8.2'
|
||||||
- '8.1'
|
- '8.1'
|
||||||
|
|||||||
3
.github/workflows/build-linux-x86_64.yml
vendored
3
.github/workflows/build-linux-x86_64.yml
vendored
@@ -6,9 +6,10 @@ on:
|
|||||||
version:
|
version:
|
||||||
required: true
|
required: true
|
||||||
description: php version to compile
|
description: php version to compile
|
||||||
default: '8.2'
|
default: '8.3'
|
||||||
type: choice
|
type: choice
|
||||||
options:
|
options:
|
||||||
|
- '8.4'
|
||||||
- '8.3'
|
- '8.3'
|
||||||
- '8.2'
|
- '8.2'
|
||||||
- '8.1'
|
- '8.1'
|
||||||
|
|||||||
3
.github/workflows/build-macos-aarch64.yml
vendored
3
.github/workflows/build-macos-aarch64.yml
vendored
@@ -6,9 +6,10 @@ on:
|
|||||||
version:
|
version:
|
||||||
required: true
|
required: true
|
||||||
description: php version to compile
|
description: php version to compile
|
||||||
default: '8.2'
|
default: '8.3'
|
||||||
type: choice
|
type: choice
|
||||||
options:
|
options:
|
||||||
|
- '8.4'
|
||||||
- '8.3'
|
- '8.3'
|
||||||
- '8.2'
|
- '8.2'
|
||||||
- '8.1'
|
- '8.1'
|
||||||
|
|||||||
18
.github/workflows/build-macos-x86_64.yml
vendored
18
.github/workflows/build-macos-x86_64.yml
vendored
@@ -6,14 +6,13 @@ on:
|
|||||||
version:
|
version:
|
||||||
required: true
|
required: true
|
||||||
description: php version to compile
|
description: php version to compile
|
||||||
default: '8.2'
|
default: '8.3'
|
||||||
type: choice
|
type: choice
|
||||||
options:
|
options:
|
||||||
|
- '8.4'
|
||||||
- '8.3'
|
- '8.3'
|
||||||
- '8.2'
|
- '8.2'
|
||||||
- '8.1'
|
- '8.1'
|
||||||
- '8.0'
|
|
||||||
- '7.4'
|
|
||||||
build-cli:
|
build-cli:
|
||||||
description: build cli binary
|
description: build cli binary
|
||||||
default: true
|
default: true
|
||||||
@@ -35,6 +34,10 @@ on:
|
|||||||
debug:
|
debug:
|
||||||
description: enable debug logs
|
description: enable debug logs
|
||||||
type: boolean
|
type: boolean
|
||||||
|
no-strip:
|
||||||
|
description: keep debug symbols for debugging
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -80,13 +83,15 @@ jobs:
|
|||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: downloads
|
path: downloads
|
||||||
key: php-${{ env.INPUT_HASH }}
|
key: php-${{ inputs.version }}-macos-x86_64
|
||||||
|
|
||||||
# With or without debug
|
# With or without debug
|
||||||
- if: inputs.debug == true
|
- if: inputs.debug == true
|
||||||
run: echo "SPC_BUILD_DEBUG=--debug" >> $GITHUB_ENV
|
run: echo "SPC_BUILD_DEBUG=--debug" >> $GITHUB_ENV
|
||||||
- if: inputs.prefer-pre-built == true
|
- if: inputs.prefer-pre-built == true
|
||||||
run: echo "SPC_PRE_BUILT=--prefer-pre-built" >> $env:GITHUB_ENV
|
run: echo "SPC_PRE_BUILT=--prefer-pre-built" >> $env:GITHUB_ENV
|
||||||
|
- if: inputs.no-strip == true
|
||||||
|
run: echo "SPC_NO_STRIP=--no-strip" >> $env:GITHUB_ENV
|
||||||
|
|
||||||
# With target select: cli, micro or both
|
# With target select: cli, micro or both
|
||||||
- if: ${{ inputs.build-cli == true }}
|
- if: ${{ inputs.build-cli == true }}
|
||||||
@@ -97,11 +102,10 @@ jobs:
|
|||||||
run: echo "SPC_BUILD_FPM=--build-fpm" >> $GITHUB_ENV
|
run: echo "SPC_BUILD_FPM=--build-fpm" >> $GITHUB_ENV
|
||||||
|
|
||||||
# If there's no dependencies cache, fetch sources, with or without debug
|
# 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=${{ inputs.version }} --for-extensions=${{ inputs.extensions }} ${{ env.SPC_BUILD_DEBUG }} ${{ env.SPC_PRE_BUILT }} --ignore-cache-sources=php-src
|
||||||
run: ./bin/spc download --with-php=${{ inputs.version }} --for-extensions=${{ inputs.extensions }} ${{ env.SPC_BUILD_DEBUG }} ${{ env.SPC_PRE_BUILT }}
|
|
||||||
|
|
||||||
# Run build command
|
# Run build command
|
||||||
- run: ./bin/spc build ${{ inputs.extensions }} ${{ env.SPC_BUILD_DEBUG }} ${{ env.SPC_BUILD_CLI }} ${{ env.SPC_BUILD_MICRO }} ${{ env.SPC_BUILD_FPM }}
|
- run: ./bin/spc build ${{ inputs.extensions }} ${{ env.SPC_BUILD_DEBUG }} ${{ env.SPC_NO_STRIP }} ${{ env.SPC_BUILD_CLI }} ${{ env.SPC_BUILD_MICRO }} ${{ env.SPC_BUILD_FPM }}
|
||||||
|
|
||||||
# Upload cli executable
|
# Upload cli executable
|
||||||
- if: ${{ inputs.build-cli == true }}
|
- if: ${{ inputs.build-cli == true }}
|
||||||
|
|||||||
1
.github/workflows/build-windows-x86_64.yml
vendored
1
.github/workflows/build-windows-x86_64.yml
vendored
@@ -9,6 +9,7 @@ on:
|
|||||||
default: '8.2'
|
default: '8.2'
|
||||||
type: choice
|
type: choice
|
||||||
options:
|
options:
|
||||||
|
- '8.4'
|
||||||
- '8.3'
|
- '8.3'
|
||||||
- '8.2'
|
- '8.2'
|
||||||
- '8.1'
|
- '8.1'
|
||||||
|
|||||||
148
.github/workflows/ext-matrix-tests.yml
vendored
Normal file
148
.github/workflows/ext-matrix-tests.yml
vendored
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
name: "Extension matrix tests"
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
branches: [ "main" ]
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/ext-matrix-tests.yml'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "${{ matrix.extension }} (PHP ${{ matrix.php-version }} on ${{ matrix.operating-system }})"
|
||||||
|
runs-on: ${{ matrix.operating-system }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
extension:
|
||||||
|
- amqp
|
||||||
|
- apcu
|
||||||
|
- bcmath
|
||||||
|
- bz2
|
||||||
|
- calendar
|
||||||
|
- ctype
|
||||||
|
- curl
|
||||||
|
- dba
|
||||||
|
- dom
|
||||||
|
- ds
|
||||||
|
- event
|
||||||
|
- exif
|
||||||
|
- filter
|
||||||
|
- fileinfo
|
||||||
|
- ftp
|
||||||
|
- gd
|
||||||
|
- gettext
|
||||||
|
- gmp
|
||||||
|
- iconv
|
||||||
|
- igbinary
|
||||||
|
- imagick
|
||||||
|
- imap
|
||||||
|
- intl
|
||||||
|
- ldap
|
||||||
|
- mbstring,mbregex
|
||||||
|
- memcache
|
||||||
|
- mysqli,mysqlnd,pdo_mysql
|
||||||
|
- opcache
|
||||||
|
- openssl
|
||||||
|
- pcntl
|
||||||
|
- password-argon2
|
||||||
|
- pcntl
|
||||||
|
- pdo
|
||||||
|
- pgsql,pdo_pgsql
|
||||||
|
- phar
|
||||||
|
- posix
|
||||||
|
- rar
|
||||||
|
- protobuf
|
||||||
|
- readline
|
||||||
|
- redis
|
||||||
|
- session
|
||||||
|
- shmop
|
||||||
|
- simdjson
|
||||||
|
- simplexml,xml
|
||||||
|
- snappy
|
||||||
|
- soap
|
||||||
|
- sockets
|
||||||
|
- sodium
|
||||||
|
- sqlite3,pdo_sqlite
|
||||||
|
- sqlsrv
|
||||||
|
- ssh2
|
||||||
|
- swoole
|
||||||
|
- swoole,swoole-hook-pgsql,swoole-hook-mysql,swoole-hook-sqlite
|
||||||
|
- swow
|
||||||
|
- sysvmsg,sysvsem,sysvshm
|
||||||
|
- tidy
|
||||||
|
- tokenizer
|
||||||
|
- uuid
|
||||||
|
- uv
|
||||||
|
- xhprof
|
||||||
|
- xlswriter
|
||||||
|
- xmlwriter,xmlreader
|
||||||
|
- xsl
|
||||||
|
- yac
|
||||||
|
- yaml
|
||||||
|
- zip
|
||||||
|
- zlib
|
||||||
|
- zstd
|
||||||
|
php-version:
|
||||||
|
- "8.4"
|
||||||
|
operating-system:
|
||||||
|
- "ubuntu-latest"
|
||||||
|
#- "macos-13"
|
||||||
|
#- "debian-arm64-self-hosted"
|
||||||
|
- "macos-14"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: "Checkout"
|
||||||
|
uses: "actions/checkout@v4"
|
||||||
|
|
||||||
|
- name: OS type
|
||||||
|
id: os-type
|
||||||
|
run: |
|
||||||
|
OS=""
|
||||||
|
if [ "${{ matrix.operating-system }}" = "ubuntu-latest" ]; then
|
||||||
|
OS="linux-x86_64"
|
||||||
|
elif [ "${{ matrix.operating-system }}" = "macos-13" ]; then
|
||||||
|
OS="macos-x86_64"
|
||||||
|
elif [ "${{ matrix.operating-system }}" = "debian-arm64-self-hosted" ]; then
|
||||||
|
OS="linux-aarch64"
|
||||||
|
elif [ "${{ matrix.operating-system }}" = "macos-14" ]; then
|
||||||
|
OS="macos-aarch64"
|
||||||
|
fi
|
||||||
|
echo "OS=$OS" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: "Setup PHP"
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: 8.2
|
||||||
|
tools: pecl, composer
|
||||||
|
extensions: curl, openssl, mbstring
|
||||||
|
ini-values: memory_limit=-1
|
||||||
|
env:
|
||||||
|
phpts: nts
|
||||||
|
|
||||||
|
- name: "Install Dependencies"
|
||||||
|
run: composer update -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
|
||||||
|
|
||||||
|
- id: cache-download
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: downloads
|
||||||
|
key: php-${{ matrix.php-version }}-dependencies-for-tests
|
||||||
|
|
||||||
|
# If there's no dependencies cache, fetch sources
|
||||||
|
- name: "Download sources"
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: ./bin/spc download --with-php=${{ matrix.php-version }} --for-extensions=${{ matrix.extension }} --debug --ignore-cache-sources=php-src
|
||||||
|
|
||||||
|
- name: "Build library: ${{ matrix.library }}"
|
||||||
|
run: |
|
||||||
|
SPC_USE_SUDO=yes ./bin/spc doctor --auto-fix
|
||||||
|
if [ "${{ env.OS }}" = "linux-x86_64" ]; then
|
||||||
|
./bin/spc install-pkg upx
|
||||||
|
UPX=--with-upx-pack
|
||||||
|
elif [ "${{ env.OS }}" = "linux-aarch64" ]; then
|
||||||
|
./bin/spc install-pkg upx
|
||||||
|
UPX=--with-upx-pack
|
||||||
|
fi
|
||||||
|
./bin/spc build --build-cli --build-micro --build-fpm ${{ matrix.extension }} --debug $UPX --with-suggested-libs --with-suggested-exts
|
||||||
5
.github/workflows/tests.yml
vendored
5
.github/workflows/tests.yml
vendored
@@ -82,6 +82,7 @@ jobs:
|
|||||||
- php: '8.1'
|
- php: '8.1'
|
||||||
- php: '8.2'
|
- php: '8.2'
|
||||||
- php: '8.3'
|
- php: '8.3'
|
||||||
|
- php: '8.4'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout"
|
- name: "Checkout"
|
||||||
@@ -198,3 +199,7 @@ jobs:
|
|||||||
|
|
||||||
- name: "Run Build Tests (build)"
|
- name: "Run Build Tests (build)"
|
||||||
run: php src/globals/test-extensions.php build_cmd ${{ matrix.os }} ${{ matrix.php }}
|
run: php src/globals/test-extensions.php build_cmd ${{ matrix.os }} ${{ matrix.php }}
|
||||||
|
|
||||||
|
- name: "Run Build Tests (build - embed for non-windows)"
|
||||||
|
if: matrix.os != 'windows-latest'
|
||||||
|
run: php src/globals/test-extensions.php build_embed_cmd ${{ matrix.os }} ${{ matrix.php }}
|
||||||
|
|||||||
22
README-zh.md
22
README-zh.md
@@ -82,16 +82,18 @@ static-php-cli(简称 `spc`)有许多特性:
|
|||||||
>
|
>
|
||||||
> :x: 不支持
|
> :x: 不支持
|
||||||
|
|
||||||
| PHP Version | Status | Comment |
|
| PHP Version | Status | Comment |
|
||||||
|-------------|--------------------|------------------------------|
|
|-------------|--------------------|----------------------------------------------|
|
||||||
| 7.2 | :x: | |
|
| 7.2 | :x: | |
|
||||||
| 7.3 | :warning: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
|
| 7.3 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
|
||||||
| 7.4 | :warning: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
|
| 7.4 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
|
||||||
| 8.0 | :heavy_check_mark: | PHP 官方已停止 8.0 的维护 |
|
| 8.0 | :warning: | PHP 官方已停止 8.0 的维护,我们不再处理 8.0 相关的 backport 支持 |
|
||||||
| 8.1 | :heavy_check_mark: | PHP 官方仅对 8.1 提供安全更新 |
|
| 8.1 | :heavy_check_mark: | PHP 官方仅对 8.1 提供安全更新 |
|
||||||
| 8.2 | :heavy_check_mark: | |
|
| 8.2 | :heavy_check_mark: | |
|
||||||
| 8.3 | :heavy_check_mark: | |
|
| 8.3 | :heavy_check_mark: | |
|
||||||
| 8.4 | :x: | WIP |
|
| 8.4 | :heavy_check_mark: | |
|
||||||
|
|
||||||
|
> 这个表格的支持状态是 static-php-cli 对构建对应版本的支持情况,不是 PHP 官方对该版本的支持情况。
|
||||||
|
|
||||||
### 支持的扩展
|
### 支持的扩展
|
||||||
|
|
||||||
|
|||||||
23
README.md
23
README.md
@@ -89,16 +89,19 @@ Currently supported PHP versions for compilation:
|
|||||||
>
|
>
|
||||||
> :x: not supported
|
> :x: not supported
|
||||||
|
|
||||||
| PHP Version | Status | Comment |
|
| PHP Version | Status | Comment |
|
||||||
|-------------|--------------------|---------------------------------------------------|
|
|-------------|--------------------|----------------------------------------------------------------------------------------------------|
|
||||||
| 7.2 | :x: | |
|
| 7.2 | :x: | |
|
||||||
| 7.3 | :warning: | phpmicro and some extensions not supported on 7.x |
|
| 7.3 | :x: | phpmicro and some extensions not supported on 7.x |
|
||||||
| 7.4 | :warning: | phpmicro and some extensions not supported on 7.x |
|
| 7.4 | :x: | phpmicro and some extensions not supported on 7.x |
|
||||||
| 8.0 | :heavy_check_mark: | PHP official has stopped maintenance of 8.0 |
|
| 8.0 | :warning: | PHP official has stopped maintenance of 8.0, we no longer provide backport support for version 8.0 |
|
||||||
| 8.1 | :heavy_check_mark: | PHP official has security fixes only |
|
| 8.1 | :heavy_check_mark: | PHP official has security fixes only |
|
||||||
| 8.2 | :heavy_check_mark: | |
|
| 8.2 | :heavy_check_mark: | |
|
||||||
| 8.3 | :heavy_check_mark: | |
|
| 8.3 | :heavy_check_mark: | |
|
||||||
| 8.4 | :x: | WIP |
|
| 8.4 | :heavy_check_mark: | |
|
||||||
|
|
||||||
|
> This table shows the support status for static-php-cli in building the corresponding version,
|
||||||
|
> not the official PHP support status for that version.
|
||||||
|
|
||||||
### Supported Extensions
|
### Supported Extensions
|
||||||
|
|
||||||
|
|||||||
28
composer.lock
generated
28
composer.lock
generated
@@ -2529,16 +2529,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "friendsofphp/php-cs-fixer",
|
"name": "friendsofphp/php-cs-fixer",
|
||||||
"version": "v3.64.0",
|
"version": "v3.65.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
||||||
"reference": "58dd9c931c785a79739310aef5178928305ffa67"
|
"reference": "79d4f3e77b250a7d8043d76c6af8f0695e8a469f"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/58dd9c931c785a79739310aef5178928305ffa67",
|
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/79d4f3e77b250a7d8043d76c6af8f0695e8a469f",
|
||||||
"reference": "58dd9c931c785a79739310aef5178928305ffa67",
|
"reference": "79d4f3e77b250a7d8043d76c6af8f0695e8a469f",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -2548,7 +2548,7 @@
|
|||||||
"ext-filter": "*",
|
"ext-filter": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-tokenizer": "*",
|
"ext-tokenizer": "*",
|
||||||
"fidry/cpu-core-counter": "^1.0",
|
"fidry/cpu-core-counter": "^1.2",
|
||||||
"php": "^7.4 || ^8.0",
|
"php": "^7.4 || ^8.0",
|
||||||
"react/child-process": "^0.6.5",
|
"react/child-process": "^0.6.5",
|
||||||
"react/event-loop": "^1.0",
|
"react/event-loop": "^1.0",
|
||||||
@@ -2568,18 +2568,18 @@
|
|||||||
"symfony/stopwatch": "^5.4 || ^6.0 || ^7.0"
|
"symfony/stopwatch": "^5.4 || ^6.0 || ^7.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"facile-it/paraunit": "^1.3 || ^2.3",
|
"facile-it/paraunit": "^1.3.1 || ^2.4",
|
||||||
"infection/infection": "^0.29.5",
|
"infection/infection": "^0.29.8",
|
||||||
"justinrainbow/json-schema": "^5.2",
|
"justinrainbow/json-schema": "^5.3 || ^6.0",
|
||||||
"keradus/cli-executor": "^2.1",
|
"keradus/cli-executor": "^2.1",
|
||||||
"mikey179/vfsstream": "^1.6.11",
|
"mikey179/vfsstream": "^1.6.12",
|
||||||
"php-coveralls/php-coveralls": "^2.7",
|
"php-coveralls/php-coveralls": "^2.7",
|
||||||
"php-cs-fixer/accessible-object": "^1.1",
|
"php-cs-fixer/accessible-object": "^1.1",
|
||||||
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.5",
|
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.5",
|
||||||
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.5",
|
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.5",
|
||||||
"phpunit/phpunit": "^9.6.19 || ^10.5.21 || ^11.2",
|
"phpunit/phpunit": "^9.6.21 || ^10.5.38 || ^11.4.3",
|
||||||
"symfony/var-dumper": "^5.4 || ^6.0 || ^7.0",
|
"symfony/var-dumper": "^5.4.47 || ^6.4.15 || ^7.1.8",
|
||||||
"symfony/yaml": "^5.4 || ^6.0 || ^7.0"
|
"symfony/yaml": "^5.4.45 || ^6.4.13 || ^7.1.6"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-dom": "For handling output formats in XML",
|
"ext-dom": "For handling output formats in XML",
|
||||||
@@ -2620,7 +2620,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
|
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
|
||||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.64.0"
|
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.65.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -2628,7 +2628,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-08-30T23:09:38+00:00"
|
"time": "2024-11-25T00:39:24+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "humbug/box",
|
"name": "humbug/box",
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="${SPC_PHP_DEFAULT_OPTIMIZE_CFLAGS} -fno-ident
|
|||||||
; EXTRA_LIBS for `make` php
|
; EXTRA_LIBS for `make` php
|
||||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS=""
|
SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS=""
|
||||||
; EXTRA_LDFLAGS_PROGRAM for `make` php
|
; EXTRA_LDFLAGS_PROGRAM for `make` php
|
||||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-all-static"
|
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-all-static -Wl,-O1 -pie"
|
||||||
|
|
||||||
[macos]
|
[macos]
|
||||||
; compiler environments
|
; compiler environments
|
||||||
|
|||||||
@@ -199,6 +199,19 @@
|
|||||||
"gmssl"
|
"gmssl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"grpc": {
|
||||||
|
"support": {
|
||||||
|
"Windows": "wip",
|
||||||
|
"BSD": "wip"
|
||||||
|
},
|
||||||
|
"type": "external",
|
||||||
|
"source": "grpc",
|
||||||
|
"arg-type-unix": "custom",
|
||||||
|
"cpp-extension": true,
|
||||||
|
"lib-depends": [
|
||||||
|
"grpc"
|
||||||
|
]
|
||||||
|
},
|
||||||
"iconv": {
|
"iconv": {
|
||||||
"support": {
|
"support": {
|
||||||
"BSD": "wip"
|
"BSD": "wip"
|
||||||
@@ -242,7 +255,8 @@
|
|||||||
"BSD": "wip"
|
"BSD": "wip"
|
||||||
},
|
},
|
||||||
"notes": true,
|
"notes": true,
|
||||||
"type": "builtin",
|
"type": "external",
|
||||||
|
"source": "ext-imap",
|
||||||
"arg-type": "custom",
|
"arg-type": "custom",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"imap"
|
"imap"
|
||||||
@@ -510,7 +524,7 @@
|
|||||||
},
|
},
|
||||||
"notes": true,
|
"notes": true,
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
"arg-type": "with-prefix",
|
"arg-type": "custom",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"postgresql"
|
"postgresql"
|
||||||
]
|
]
|
||||||
@@ -694,6 +708,19 @@
|
|||||||
"zlib"
|
"zlib"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"rdkafka": {
|
||||||
|
"support": {
|
||||||
|
"BSD": "wip",
|
||||||
|
"Windows": "wip"
|
||||||
|
},
|
||||||
|
"type": "external",
|
||||||
|
"source": "ext-rdkafka",
|
||||||
|
"arg-type": "custom",
|
||||||
|
"cpp-extension": true,
|
||||||
|
"lib-depends": [
|
||||||
|
"librdkafka"
|
||||||
|
]
|
||||||
|
},
|
||||||
"swoole": {
|
"swoole": {
|
||||||
"support": {
|
"support": {
|
||||||
"Windows": "no",
|
"Windows": "no",
|
||||||
|
|||||||
@@ -139,6 +139,20 @@
|
|||||||
"Security"
|
"Security"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"grpc": {
|
||||||
|
"source": "grpc",
|
||||||
|
"static-libs-unix": [
|
||||||
|
"libgrpc.a",
|
||||||
|
"libcares.a"
|
||||||
|
],
|
||||||
|
"lib-depends": [
|
||||||
|
"zlib",
|
||||||
|
"openssl"
|
||||||
|
],
|
||||||
|
"frameworks": [
|
||||||
|
"CoreFoundation"
|
||||||
|
]
|
||||||
|
},
|
||||||
"icu": {
|
"icu": {
|
||||||
"source": "icu",
|
"source": "icu",
|
||||||
"cpp-library": true,
|
"cpp-library": true,
|
||||||
@@ -544,6 +558,18 @@
|
|||||||
"pkg-config": {
|
"pkg-config": {
|
||||||
"source": "pkg-config"
|
"source": "pkg-config"
|
||||||
},
|
},
|
||||||
|
"librdkafka": {
|
||||||
|
"source": "librdkafka",
|
||||||
|
"static-libs-unix": [
|
||||||
|
"librdkafka.a",
|
||||||
|
"librdkafka++.a",
|
||||||
|
"librdkafka-static.a"
|
||||||
|
],
|
||||||
|
"cpp-library": true,
|
||||||
|
"lib-suggests": [
|
||||||
|
"zstd"
|
||||||
|
]
|
||||||
|
},
|
||||||
"postgresql": {
|
"postgresql": {
|
||||||
"source": "postgresql",
|
"source": "postgresql",
|
||||||
"static-libs-unix": [
|
"static-libs-unix": [
|
||||||
|
|||||||
@@ -36,9 +36,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bzip2": {
|
"bzip2": {
|
||||||
"type": "filelist",
|
"alt": {
|
||||||
"url": "https://sourceware.org/pub/bzip2/",
|
"type": "filelist",
|
||||||
"regex": "/href=\"(?<file>bzip2-(?<version>[^\"]+)\\.tar\\.gz)\"/",
|
"url": "https://sourceware.org/pub/bzip2/",
|
||||||
|
"regex": "/href=\"(?<file>bzip2-(?<version>[^\"]+)\\.tar\\.gz)\"/"
|
||||||
|
},
|
||||||
|
"type": "url",
|
||||||
|
"url": "https://dl.static-php.dev/static-php-cli/deps/bzip2/bzip2-1.0.8.tar.gz",
|
||||||
"provide-pre-built": true,
|
"provide-pre-built": true,
|
||||||
"license": {
|
"license": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -65,6 +69,23 @@
|
|||||||
"path": "LICENSE"
|
"path": "LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"librdkafka": {
|
||||||
|
"type": "ghtar",
|
||||||
|
"repo": "confluentinc/librdkafka",
|
||||||
|
"license": {
|
||||||
|
"type": "file",
|
||||||
|
"path": "LICENSE"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ext-rdkafka": {
|
||||||
|
"type": "ghtar",
|
||||||
|
"repo": "arnaud-lb/php-rdkafka",
|
||||||
|
"path": "php-src/ext/rdkafka",
|
||||||
|
"license": {
|
||||||
|
"type": "file",
|
||||||
|
"path": "LICENSE"
|
||||||
|
}
|
||||||
|
},
|
||||||
"ext-event": {
|
"ext-event": {
|
||||||
"type": "url",
|
"type": "url",
|
||||||
"url": "https://bitbucket.org/osmanov/pecl-event/get/3.0.8.tar.gz",
|
"url": "https://bitbucket.org/osmanov/pecl-event/get/3.0.8.tar.gz",
|
||||||
@@ -102,6 +123,18 @@
|
|||||||
"path": "LICENSE"
|
"path": "LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ext-imap": {
|
||||||
|
"type": "url",
|
||||||
|
"url": "https://pecl.php.net/get/imap",
|
||||||
|
"path": "php-src/ext/imap",
|
||||||
|
"filename": "imap.tgz",
|
||||||
|
"license": {
|
||||||
|
"type": "file",
|
||||||
|
"path": [
|
||||||
|
"LICENSE"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"ext-memcache": {
|
"ext-memcache": {
|
||||||
"type": "url",
|
"type": "url",
|
||||||
"url": "https://pecl.php.net/get/memcache",
|
"url": "https://pecl.php.net/get/memcache",
|
||||||
@@ -211,6 +244,16 @@
|
|||||||
"path": "LICENSE"
|
"path": "LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"grpc": {
|
||||||
|
"type": "git",
|
||||||
|
"rev": "v1.68.x",
|
||||||
|
"url": "https://github.com/grpc/grpc.git",
|
||||||
|
"provide-pre-built": true,
|
||||||
|
"license": {
|
||||||
|
"type": "file",
|
||||||
|
"path": "LICENSE"
|
||||||
|
}
|
||||||
|
},
|
||||||
"icu": {
|
"icu": {
|
||||||
"type": "ghrel",
|
"type": "ghrel",
|
||||||
"repo": "unicode-org/icu",
|
"repo": "unicode-org/icu",
|
||||||
@@ -513,7 +556,7 @@
|
|||||||
"micro": {
|
"micro": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"path": "php-src/sapi/micro",
|
"path": "php-src/sapi/micro",
|
||||||
"rev": "master",
|
"rev": "84beta",
|
||||||
"url": "https://github.com/static-php/phpmicro",
|
"url": "https://github.com/static-php/phpmicro",
|
||||||
"license": {
|
"license": {
|
||||||
"type": "file",
|
"type": "file",
|
||||||
@@ -726,13 +769,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"swoole": {
|
"swoole": {
|
||||||
"type": "ghtar",
|
|
||||||
"path": "php-src/ext/swoole",
|
"path": "php-src/ext/swoole",
|
||||||
"repo": "swoole/swoole-src",
|
"type": "git",
|
||||||
"prefer-stable": true,
|
"rev": "master",
|
||||||
|
"url": "https://github.com/swoole/swoole-src.git",
|
||||||
"license": {
|
"license": {
|
||||||
"type": "file",
|
"type": "file",
|
||||||
"path": "LICENSE"
|
"path": "LICENSE"
|
||||||
|
},
|
||||||
|
"alt": {
|
||||||
|
"type": "ghtar",
|
||||||
|
"repo": "swoole/swoole-src",
|
||||||
|
"prefer-stable": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"swow": {
|
"swow": {
|
||||||
|
|||||||
@@ -84,3 +84,11 @@ For Linux systems, you can download the [cacert.pem](https://curl.se/docs/caextr
|
|||||||
For the certificate locations of different distros, please refer to [Golang docs](https://go.dev/src/crypto/x509/root_linux.go).
|
For the certificate locations of different distros, please refer to [Golang docs](https://go.dev/src/crypto/x509/root_linux.go).
|
||||||
|
|
||||||
> INI configuration `openssl.cafile` cannot be set dynamically using the `ini_set()` function, because `openssl.cafile` is a `PHP_INI_SYSTEM` type configuration and can only be set in the `php.ini` file.
|
> INI configuration `openssl.cafile` cannot be set dynamically using the `ini_set()` function, because `openssl.cafile` is a `PHP_INI_SYSTEM` type configuration and can only be set in the `php.ini` file.
|
||||||
|
|
||||||
|
## Why don't we support older versions of PHP?
|
||||||
|
|
||||||
|
Because older versions of PHP have many problems, such as security issues, performance issues, and functional issues.
|
||||||
|
In addition, many older versions of PHP are not compatible with the latest dependency libraries,
|
||||||
|
which is one of the reasons why older versions of PHP are not supported.
|
||||||
|
|
||||||
|
You can use older versions compiled earlier by static-php-cli, such as PHP 8.0, but earlier versions will not be explicitly supported.
|
||||||
|
|||||||
@@ -74,6 +74,12 @@ bin/setup-runtime -action add-path
|
|||||||
bin/setup-runtime -action remove-path
|
bin/setup-runtime -action remove-path
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Finally, now that you have PHP and Composer installed, you need to install static-php-cli's Composer dependencies:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
composer install
|
||||||
|
```
|
||||||
|
|
||||||
### Install other Tools (automatic)
|
### Install other Tools (automatic)
|
||||||
|
|
||||||
For `php-sdk-binary-tools`, `strawberry-perl`, and `nasm`,
|
For `php-sdk-binary-tools`, `strawberry-perl`, and `nasm`,
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ This extension contains an implementation of the coroutine environment for `pdo_
|
|||||||
|
|
||||||
## swow
|
## swow
|
||||||
|
|
||||||
1. Only PHP version >= 8.0 is supported.
|
1. Only PHP 8.0 ~ 8.4 is supported.
|
||||||
|
|
||||||
## imap
|
## imap
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ Windows currently only supports the x86_64 architecture, and does not support 32
|
|||||||
|
|
||||||
## Supported PHP Version
|
## Supported PHP Version
|
||||||
|
|
||||||
Currently, static php cli supports PHP versions 8.0 to 8.3, and theoretically supports PHP 7.4 and earlier versions.
|
Currently, static php cli supports PHP versions 8.1 to 8.4, and theoretically supports PHP 8.0 and earlier versions.
|
||||||
Simply select the earlier version when downloading.
|
Simply select the earlier version when downloading.
|
||||||
However, due to some extensions and special components that have stopped supporting earlier versions of PHP,
|
However, due to some extensions and special components that have stopped supporting earlier versions of PHP,
|
||||||
static-php-cli will not explicitly support earlier versions.
|
static-php-cli will not explicitly support earlier versions.
|
||||||
|
|||||||
@@ -142,9 +142,9 @@ including php-src and the source code of various dependent libraries.
|
|||||||
# Download all dependencies
|
# Download all dependencies
|
||||||
bin/spc download --all
|
bin/spc download --all
|
||||||
|
|
||||||
# Download all dependent packages, and specify the main version of PHP to download, optional: 7.3, 7.4, 8.0, 8.1, 8.2, 8.3
|
# Download all dependent packages, and specify the main version of PHP to download, optional: 8.1, 8.2, 8.3, 8.4
|
||||||
# Also supports specific version of php release: 8.3.10, 8.2.22, etc.
|
# Also supports specific version of php release: 8.3.10, 8.2.22, etc.
|
||||||
bin/spc download --all --with-php=8.2
|
bin/spc download --all --with-php=8.3
|
||||||
|
|
||||||
# Show download progress bar while downloading (curl)
|
# Show download progress bar while downloading (curl)
|
||||||
bin/spc download --all --debug
|
bin/spc download --all --debug
|
||||||
@@ -272,12 +272,12 @@ If you want to build multiple versions of PHP and don't want to build other depe
|
|||||||
you can use `switch-php-version` to quickly switch to another version and compile after compiling one version:
|
you can use `switch-php-version` to quickly switch to another version and compile after compiling one version:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# switch to 8.3
|
# switch to 8.4
|
||||||
bin/spc switch-php-version 8.3
|
bin/spc switch-php-version 8.4
|
||||||
# build
|
# build
|
||||||
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
||||||
# switch to 8.0
|
# switch to 8.1
|
||||||
bin/spc switch-php-version 8.0
|
bin/spc switch-php-version 8.1
|
||||||
# build
|
# build
|
||||||
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
||||||
```
|
```
|
||||||
@@ -553,3 +553,76 @@ If you need to build multiple times locally, the following method can save you t
|
|||||||
- If you want to rebuild once, but do not re-download the source code, you can first `rm -rf buildroot source` to delete the compilation directory and source code directory, and then rebuild.
|
- If you want to rebuild once, but do not re-download the source code, you can first `rm -rf buildroot source` to delete the compilation directory and source code directory, and then rebuild.
|
||||||
- If you want to update a version of a dependency, you can use `bin/spc del-download <source-name>` to delete the specified source code, and then use `download <source-name>` to download it again.
|
- If you want to update a version of a dependency, you can use `bin/spc del-download <source-name>` to delete the specified source code, and then use `download <source-name>` to download it again.
|
||||||
- If you want to update all dependent versions, you can use `bin/spc download --clean` to delete all downloaded sources, and then download them again.
|
- If you want to update all dependent versions, you can use `bin/spc download --clean` to delete all downloaded sources, and then download them again.
|
||||||
|
|
||||||
|
## embed usage
|
||||||
|
|
||||||
|
If you want to embed static-php into other C language programs, you can use `--build-embed` to build an embed version of PHP.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bin/spc build {your extensions} --build-embed --debug
|
||||||
|
```
|
||||||
|
|
||||||
|
Under normal circumstances, PHP embed will generate `php-config` after compilation.
|
||||||
|
For static-php, we provide `spc-config` to obtain the parameters during compilation.
|
||||||
|
In addition, when using embed SAPI (libphp.a), you need to use the same compiler as libphp, otherwise there will be a link error.
|
||||||
|
|
||||||
|
Here is the basic usage of spc-config:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# output all flags and options
|
||||||
|
bin/spc spc-config curl,zlib,phar,openssl
|
||||||
|
|
||||||
|
# output libs
|
||||||
|
bin/spc spc-config curl,zlib,phar,openssl --libs
|
||||||
|
|
||||||
|
# output includes
|
||||||
|
bin/spc spc-config curl,zlib,phar,openssl --includes
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, static-php uses the following compilers on different systems:
|
||||||
|
|
||||||
|
- macOS: `clang`
|
||||||
|
- Linux (Alpine Linux): `gcc`
|
||||||
|
- Linux (glibc based distros, x86_64): `/usr/local/musl/bin/x86_64-linux-musl-gcc`
|
||||||
|
- Linux (glibc based distros, aarch64): `/usr/local/musl/bin/aarch64-linux-musl-gcc`
|
||||||
|
- FreeBSD: `clang`
|
||||||
|
|
||||||
|
Here is an example of using embed SAPI:
|
||||||
|
|
||||||
|
```c
|
||||||
|
// embed.c
|
||||||
|
#include <sapi/embed/php_embed.h>
|
||||||
|
|
||||||
|
int main(int argc,char **argv){
|
||||||
|
|
||||||
|
PHP_EMBED_START_BLOCK(argc,argv)
|
||||||
|
|
||||||
|
zend_file_handle file_handle;
|
||||||
|
|
||||||
|
zend_stream_init_filename(&file_handle,"embed.php");
|
||||||
|
|
||||||
|
if(php_execute_script(&file_handle) == FAILURE){
|
||||||
|
php_printf("Failed to execute PHP script.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_EMBED_END_BLOCK()
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
// embed.php
|
||||||
|
echo "Hello world!\n";
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# compile in debian/ubuntu x86_64
|
||||||
|
/usr/local/musl/bin/x86_64-linux-musl-gcc embed.c $(bin/spc spc-config bcmath,zlib) -static -o embed
|
||||||
|
# compile in macOS/FreeBSD
|
||||||
|
clang embed.c $(bin/spc spc-config bcmath,zlib) -o embed
|
||||||
|
|
||||||
|
./embed
|
||||||
|
# out: Hello world!
|
||||||
|
```
|
||||||
|
|||||||
@@ -70,4 +70,10 @@ PHP 代码的编译器是完全不同的项目,因此不会考虑额外的情
|
|||||||
对于 Linux 系统,你可以从 curl 官方网站下载 [cacert.pem](https://curl.se/docs/caextract.html) 文件,也可以使用系统自带的证书文件。
|
对于 Linux 系统,你可以从 curl 官方网站下载 [cacert.pem](https://curl.se/docs/caextract.html) 文件,也可以使用系统自带的证书文件。
|
||||||
有关不同发行版的证书位置,可参考 [Go 标准库](https://go.dev/src/crypto/x509/root_linux.go)。
|
有关不同发行版的证书位置,可参考 [Go 标准库](https://go.dev/src/crypto/x509/root_linux.go)。
|
||||||
|
|
||||||
> INI 配置 `openssl.cafile` 不可以使用 `ini_set()` 函数动态设置,因为 `openssl.cafile` 是一个 `PHP_INI_SYSTEM` 类型的配置,只能在 `php.ini` 文件中设置。
|
> INI 配置 `openssl.cafile` 不可以使用 `ini_set()` 函数动态设置,因为 `openssl.cafile` 是一个 `PHP_INI_SYSTEM` 类型的配置,只能在 `php.ini` 文件中设置。
|
||||||
|
|
||||||
|
## 为什么不支持旧版本 PHP ?
|
||||||
|
|
||||||
|
因为旧版本的 PHP 有很多问题,比如安全问题、性能问题、功能问题等。此外,旧版本的 PHP 很多都无法与最新的依赖库兼容,这也是不支持旧版本 PHP 的原因之一。
|
||||||
|
|
||||||
|
你可以使用 static-php-cli 早期编译好的旧版本,如 PHP 8.0,但是不会明确支持早期版本。
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ swoole-hook-sqlite 与 `pdo_sqlite` 扩展冲突。如需使用 Swoole 和 `pdo_
|
|||||||
|
|
||||||
## swow
|
## swow
|
||||||
|
|
||||||
1. swow 仅支持 PHP >= 8.0 版本。
|
1. swow 仅支持 PHP 8.0 ~ 8.4 版本。
|
||||||
|
|
||||||
## imap
|
## imap
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,6 @@ Windows 目前只支持 x86_64 架构,不支持 32 位 x86、不支持 arm64
|
|||||||
|
|
||||||
## PHP 支持版本
|
## PHP 支持版本
|
||||||
|
|
||||||
目前,static-php-cli 对 PHP 7.4 ~ 8.3 版本是支持的,对于 PHP 7.4 及更早版本理论上支持,只需下载时选择早期版本即可。
|
目前,static-php-cli 对 PHP 8.1 ~ 8.4 版本是支持的,对于 PHP 8.0 及更早版本理论上支持,只需下载时选择早期版本即可。
|
||||||
但由于部分扩展和特殊组件已对早期版本的 PHP 停止了支持,所以 static-php-cli 不会明确支持早期版本。
|
但由于部分扩展和特殊组件已对早期版本的 PHP 停止了支持,所以 static-php-cli 不会明确支持早期版本。
|
||||||
我们推荐你编译尽可能新的 PHP 版本,以获得更好的体验。
|
我们推荐你编译尽可能新的 PHP 版本,以获得更好的体验。
|
||||||
|
|||||||
@@ -141,8 +141,8 @@ bin/spc download --for-extensions="curl,pcntl,xml,mbstring" --prefer-pre-built
|
|||||||
# 下载所有依赖包
|
# 下载所有依赖包
|
||||||
bin/spc download --all
|
bin/spc download --all
|
||||||
|
|
||||||
# 下载所有依赖包,并指定下载的 PHP 主版本,可选:7.3,7.4,8.0,8.1,8.2,8.3,也可以使用特定的版本,如 8.3.10。
|
# 下载所有依赖包,并指定下载的 PHP 主版本,可选:8.1,8.2,8.3,8.4,也可以使用特定的版本,如 8.3.10。
|
||||||
bin/spc download --all --with-php=8.2
|
bin/spc download --all --with-php=8.3
|
||||||
|
|
||||||
# 下载时显示下载进度条(curl)
|
# 下载时显示下载进度条(curl)
|
||||||
bin/spc download --all --debug
|
bin/spc download --all --debug
|
||||||
@@ -236,12 +236,12 @@ bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
|||||||
如果你想构建多个版本的 PHP,且不想每次都重复构建其他依赖库,可以使用 `switch-php-version` 在编译好一个版本后快速切换至另一个版本并编译:
|
如果你想构建多个版本的 PHP,且不想每次都重复构建其他依赖库,可以使用 `switch-php-version` 在编译好一个版本后快速切换至另一个版本并编译:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# switch to 8.3
|
# switch to 8.4
|
||||||
bin/spc switch-php-version 8.3
|
bin/spc switch-php-version 8.4
|
||||||
# build
|
# build
|
||||||
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
||||||
# switch to 8.0
|
# switch to 8.1
|
||||||
bin/spc switch-php-version 8.0
|
bin/spc switch-php-version 8.1
|
||||||
# build
|
# build
|
||||||
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
||||||
```
|
```
|
||||||
@@ -493,3 +493,75 @@ static-php-cli 开放的方法非常多,文档中无法一一列举,但只
|
|||||||
- 如果你想重新构建一次,但不重新下载源码,可以先 `rm -rf buildroot source` 删除编译目录和源码目录,然后重新构建。
|
- 如果你想重新构建一次,但不重新下载源码,可以先 `rm -rf buildroot source` 删除编译目录和源码目录,然后重新构建。
|
||||||
- 如果你想更新某个依赖的版本,可以使用 `bin/spc del-download <source-name>` 删除指定的源码,然后使用 `download <source-name>` 重新下载。
|
- 如果你想更新某个依赖的版本,可以使用 `bin/spc del-download <source-name>` 删除指定的源码,然后使用 `download <source-name>` 重新下载。
|
||||||
- 如果你想更新所有依赖的版本,可以使用 `bin/spc download --clean` 删除所有下载的源码,然后重新下载。
|
- 如果你想更新所有依赖的版本,可以使用 `bin/spc download --clean` 删除所有下载的源码,然后重新下载。
|
||||||
|
|
||||||
|
## embed 使用
|
||||||
|
|
||||||
|
如果你想将 static-php 嵌入到其他 C 语言程序中,可以使用 `--build-embed` 构建一个 embed 版本的 PHP。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bin/spc build {your extensions} --build-embed --debug
|
||||||
|
```
|
||||||
|
|
||||||
|
在通常的情况下,PHP embed 编译后会生成 `php-config`。对于 static-php,我们提供了 `spc-config`,用于获取编译时的参数。
|
||||||
|
另外,在使用 embed SAPI(libphp.a)时,你需要使用和编译 libphp 相同的编译器,否则会出现链接错误。
|
||||||
|
|
||||||
|
下面是 spc-config 的基本用法:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# output all flags and options
|
||||||
|
bin/spc spc-config curl,zlib,phar,openssl
|
||||||
|
|
||||||
|
# output libs
|
||||||
|
bin/spc spc-config curl,zlib,phar,openssl --libs
|
||||||
|
|
||||||
|
# output includes
|
||||||
|
bin/spc spc-config curl,zlib,phar,openssl --includes
|
||||||
|
```
|
||||||
|
|
||||||
|
默认情况下,static-php 在不同系统使用的编译器分别是:
|
||||||
|
|
||||||
|
- macOS: `clang`
|
||||||
|
- Linux (Alpine Linux): `gcc`
|
||||||
|
- Linux (glibc based distros, x86_64): `/usr/local/musl/bin/x86_64-linux-musl-gcc`
|
||||||
|
- Linux (glibc based distros, aarch64): `/usr/local/musl/bin/aarch64-linux-musl-gcc`
|
||||||
|
- FreeBSD: `clang`
|
||||||
|
|
||||||
|
下面是一个使用 embed SAPI 的例子:
|
||||||
|
|
||||||
|
```c
|
||||||
|
// embed.c
|
||||||
|
#include <sapi/embed/php_embed.h>
|
||||||
|
|
||||||
|
int main(int argc,char **argv){
|
||||||
|
|
||||||
|
PHP_EMBED_START_BLOCK(argc,argv)
|
||||||
|
|
||||||
|
zend_file_handle file_handle;
|
||||||
|
|
||||||
|
zend_stream_init_filename(&file_handle,"embed.php");
|
||||||
|
|
||||||
|
if(php_execute_script(&file_handle) == FAILURE){
|
||||||
|
php_printf("Failed to execute PHP script.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_EMBED_END_BLOCK()
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
// embed.php
|
||||||
|
echo "Hello world!\n";
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# compile in debian/ubuntu x86_64
|
||||||
|
/usr/local/musl/bin/x86_64-linux-musl-gcc embed.c $(bin/spc spc-config bcmath,zlib) -static -o embed
|
||||||
|
# compile in macOS/FreeBSD
|
||||||
|
clang embed.c $(bin/spc spc-config bcmath,zlib) -o embed
|
||||||
|
|
||||||
|
./embed
|
||||||
|
# out: Hello world!
|
||||||
|
```
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ use SPC\command\DumpLicenseCommand;
|
|||||||
use SPC\command\ExtractCommand;
|
use SPC\command\ExtractCommand;
|
||||||
use SPC\command\InstallPkgCommand;
|
use SPC\command\InstallPkgCommand;
|
||||||
use SPC\command\MicroCombineCommand;
|
use SPC\command\MicroCombineCommand;
|
||||||
|
use SPC\command\SPCConfigCommand;
|
||||||
use SPC\command\SwitchPhpVersionCommand;
|
use SPC\command\SwitchPhpVersionCommand;
|
||||||
use Symfony\Component\Console\Application;
|
use Symfony\Component\Console\Application;
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ use Symfony\Component\Console\Application;
|
|||||||
*/
|
*/
|
||||||
final class ConsoleApplication extends Application
|
final class ConsoleApplication extends Application
|
||||||
{
|
{
|
||||||
public const VERSION = '2.3.6';
|
public const VERSION = '2.4.2';
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -52,6 +53,7 @@ final class ConsoleApplication extends Application
|
|||||||
new ExtractCommand(),
|
new ExtractCommand(),
|
||||||
new MicroCombineCommand(),
|
new MicroCombineCommand(),
|
||||||
new SwitchPhpVersionCommand(),
|
new SwitchPhpVersionCommand(),
|
||||||
|
new SPCConfigCommand(),
|
||||||
|
|
||||||
// Dev commands
|
// Dev commands
|
||||||
new AllExtCommand(),
|
new AllExtCommand(),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace SPC\builder;
|
|||||||
|
|
||||||
use SPC\exception\ExceptionHandler;
|
use SPC\exception\ExceptionHandler;
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\FileSystemException;
|
||||||
|
use SPC\exception\InterruptException;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\RuntimeException;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\store\Config;
|
use SPC\store\Config;
|
||||||
@@ -24,6 +25,12 @@ abstract class BuilderBase
|
|||||||
/** @var array<string, Extension> extensions */
|
/** @var array<string, Extension> extensions */
|
||||||
protected array $exts = [];
|
protected array $exts = [];
|
||||||
|
|
||||||
|
/** @var array<int, string> extension names */
|
||||||
|
protected array $ext_list = [];
|
||||||
|
|
||||||
|
/** @var array<int, string> library names */
|
||||||
|
protected array $lib_list = [];
|
||||||
|
|
||||||
/** @var bool compile libs only (just mark it) */
|
/** @var bool compile libs only (just mark it) */
|
||||||
protected bool $libs_only = false;
|
protected bool $libs_only = false;
|
||||||
|
|
||||||
@@ -160,7 +167,7 @@ abstract class BuilderBase
|
|||||||
* @throws FileSystemException
|
* @throws FileSystemException
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
* @throws \ReflectionException
|
* @throws \ReflectionException
|
||||||
* @throws WrongUsageException
|
* @throws \Throwable|WrongUsageException
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
public function proveExts(array $extensions, bool $skip_check_deps = false): void
|
public function proveExts(array $extensions, bool $skip_check_deps = false): void
|
||||||
@@ -190,6 +197,7 @@ abstract class BuilderBase
|
|||||||
foreach ($this->exts as $ext) {
|
foreach ($this->exts as $ext) {
|
||||||
$ext->checkDependency();
|
$ext->checkDependency();
|
||||||
}
|
}
|
||||||
|
$this->ext_list = $extensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -276,7 +284,7 @@ abstract class BuilderBase
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (preg_match('/php-(\d+\.\d+\.\d+)/', $file, $match)) {
|
if (preg_match('/php-(\d+\.\d+\.\d+(?:RC\d+)?)\.tar\.(?:gz|bz2|xz)/', $file, $match)) {
|
||||||
return $match[1];
|
return $match[1];
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -407,6 +415,13 @@ abstract class BuilderBase
|
|||||||
}
|
}
|
||||||
logger()->debug('Running additional patch script: ' . $patch);
|
logger()->debug('Running additional patch script: ' . $patch);
|
||||||
require $patch;
|
require $patch;
|
||||||
|
} catch (InterruptException $e) {
|
||||||
|
if ($e->getCode() === 0) {
|
||||||
|
logger()->notice('Patch script ' . $patch . ' interrupted' . ($e->getMessage() ? (': ' . $e->getMessage()) : '.'));
|
||||||
|
} else {
|
||||||
|
logger()->error('Patch script ' . $patch . ' interrupted with error code [' . $e->getCode() . ']' . ($e->getMessage() ? (': ' . $e->getMessage()) : '.'));
|
||||||
|
}
|
||||||
|
exit($e->getCode());
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
logger()->critical('Patch script ' . $patch . ' failed to run.');
|
logger()->critical('Patch script ' . $patch . ' failed to run.');
|
||||||
if ($this->getOption('debug')) {
|
if ($this->getOption('debug')) {
|
||||||
@@ -414,6 +429,7 @@ abstract class BuilderBase
|
|||||||
} else {
|
} else {
|
||||||
logger()->critical('Please check with --debug option to see more details.');
|
logger()->critical('Please check with --debug option to see more details.');
|
||||||
}
|
}
|
||||||
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
45
src/SPC/builder/extension/grpc.php
Normal file
45
src/SPC/builder/extension/grpc.php
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\builder\macos\MacOSBuilder;
|
||||||
|
use SPC\builder\windows\WindowsBuilder;
|
||||||
|
use SPC\store\FileSystem;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
|
use SPC\util\GlobalEnvManager;
|
||||||
|
|
||||||
|
#[CustomExt('grpc')]
|
||||||
|
class grpc extends Extension
|
||||||
|
{
|
||||||
|
public function patchBeforeBuildconf(): bool
|
||||||
|
{
|
||||||
|
// soft link to the grpc source code
|
||||||
|
if ($this->builder instanceof WindowsBuilder) {
|
||||||
|
// not support windows yet
|
||||||
|
throw new \RuntimeException('grpc extension does not support windows yet');
|
||||||
|
}
|
||||||
|
if (!is_link(SOURCE_PATH . '/php-src/ext/grpc')) {
|
||||||
|
shell()->exec('ln -s ' . $this->builder->getLib('grpc')->getSourceDir() . '/src/php/ext/grpc ' . SOURCE_PATH . '/php-src/ext/grpc');
|
||||||
|
$macos = $this->builder instanceof MacOSBuilder ? "\n" . ' LDFLAGS="$LDFLAGS -framework CoreFoundation"' : '';
|
||||||
|
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/ext/grpc/config.m4', '/GRPC_LIBDIR=.*$/m', 'GRPC_LIBDIR=' . BUILD_LIB_PATH . $macos);
|
||||||
|
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/ext/grpc/config.m4', '/SEARCH_PATH=.*$/m', 'SEARCH_PATH="' . BUILD_ROOT_PATH . '"');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function patchBeforeMake(): bool
|
||||||
|
{
|
||||||
|
// add -Wno-strict-prototypes
|
||||||
|
GlobalEnvManager::putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -Wno-strict-prototypes');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUnixConfigureArg(): string
|
||||||
|
{
|
||||||
|
return '--enable-grpc=' . BUILD_ROOT_PATH . '/grpc GRPC_LIB_SUBDIR=' . BUILD_LIB_PATH;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ namespace SPC\builder\extension;
|
|||||||
|
|
||||||
use SPC\builder\Extension;
|
use SPC\builder\Extension;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
|
use SPC\store\FileSystem;
|
||||||
use SPC\util\CustomExt;
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
#[CustomExt('parallel')]
|
#[CustomExt('parallel')]
|
||||||
@@ -17,4 +18,10 @@ class parallel extends Extension
|
|||||||
throw new WrongUsageException('ext-parallel must be built with ZTS builds. Use "--enable-zts" option!');
|
throw new WrongUsageException('ext-parallel must be built with ZTS builds. Use "--enable-zts" option!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function patchBeforeBuildconf(): bool
|
||||||
|
{
|
||||||
|
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/ext/parallel/config.m4', '/PHP_VERSION=.*/m', '');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ namespace SPC\builder\extension;
|
|||||||
|
|
||||||
use SPC\builder\Extension;
|
use SPC\builder\Extension;
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\FileSystemException;
|
||||||
|
use SPC\exception\RuntimeException;
|
||||||
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
use SPC\util\CustomExt;
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
@@ -14,6 +16,8 @@ class pgsql extends Extension
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @throws FileSystemException
|
* @throws FileSystemException
|
||||||
|
* @throws RuntimeException
|
||||||
|
* @throws WrongUsageException
|
||||||
*/
|
*/
|
||||||
public function patchBeforeConfigure(): bool
|
public function patchBeforeConfigure(): bool
|
||||||
{
|
{
|
||||||
@@ -24,4 +28,16 @@ class pgsql extends Extension
|
|||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws WrongUsageException
|
||||||
|
* @throws RuntimeException
|
||||||
|
*/
|
||||||
|
public function getUnixConfigureArg(): string
|
||||||
|
{
|
||||||
|
if ($this->builder->getPHPVersionID() >= 80400) {
|
||||||
|
return '--with-pgsql PGSQL_CFLAGS=-I' . BUILD_INCLUDE_PATH . ' PGSQL_LIBS="-L' . BUILD_LIB_PATH . ' -lpq -lpgport -lpgcommon"';
|
||||||
|
}
|
||||||
|
return '--with-pgsql=' . BUILD_ROOT_PATH;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
36
src/SPC/builder/extension/rdkafka.php
Normal file
36
src/SPC/builder/extension/rdkafka.php
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\store\FileSystem;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
|
#[CustomExt('rdkafka')]
|
||||||
|
class rdkafka extends Extension
|
||||||
|
{
|
||||||
|
public function patchBeforeMake(): bool
|
||||||
|
{
|
||||||
|
// when compiling rdkafka with inline builds, it shows some errors, I don't know why.
|
||||||
|
FileSystem::replaceFileStr(
|
||||||
|
SOURCE_PATH . '/php-src/ext/rdkafka/rdkafka.c',
|
||||||
|
"#ifdef HAS_RD_KAFKA_TRANSACTIONS\n#include \"kafka_error_exception.h\"\n#endif",
|
||||||
|
'#include "kafka_error_exception.h"'
|
||||||
|
);
|
||||||
|
FileSystem::replaceFileStr(
|
||||||
|
SOURCE_PATH . '/php-src/ext/rdkafka/kafka_error_exception.h',
|
||||||
|
['#ifdef HAS_RD_KAFKA_TRANSACTIONS', '#endif'],
|
||||||
|
''
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getConfigureArg(): string
|
||||||
|
{
|
||||||
|
$pkgconf_libs = shell()->execWithResult('pkg-config --libs --static rdkafka')[1];
|
||||||
|
$pkgconf_libs = trim(implode('', $pkgconf_libs));
|
||||||
|
return '--with-rdkafka=' . BUILD_ROOT_PATH . ' LIBS="' . $pkgconf_libs . '"';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace SPC\builder\extension;
|
|
||||||
|
|
||||||
use SPC\builder\Extension;
|
|
||||||
use SPC\util\CustomExt;
|
|
||||||
|
|
||||||
#[CustomExt('sodium')]
|
|
||||||
class sodium extends Extension
|
|
||||||
{
|
|
||||||
public function patchBeforeBuildconf(): bool
|
|
||||||
{
|
|
||||||
// bypass error: unknown warning option '-Wno-logical-op' for macOS
|
|
||||||
return $this->removeLineContainingString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function removeLineContainingString(): bool
|
|
||||||
{
|
|
||||||
$path = SOURCE_PATH . '/php-src/ext/sodium/config.m4';
|
|
||||||
$search = '-Wno-logical-op';
|
|
||||||
if (!file_exists($path)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$content = file_get_contents($path);
|
|
||||||
$lines = preg_split('/\r\n|\n/', $content);
|
|
||||||
$filteredLines = array_filter($lines, function ($line) use ($search) {
|
|
||||||
return strpos($line, $search) === false;
|
|
||||||
});
|
|
||||||
$newContent = implode("\n", $filteredLines);
|
|
||||||
file_put_contents($path, $newContent);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,6 +12,9 @@ class zlib extends Extension
|
|||||||
{
|
{
|
||||||
public function getUnixConfigureArg(): string
|
public function getUnixConfigureArg(): string
|
||||||
{
|
{
|
||||||
|
if ($this->builder->getPHPVersionID() >= 80400) {
|
||||||
|
return '--with-zlib';
|
||||||
|
}
|
||||||
return '--with-zlib --with-zlib-dir="' . BUILD_ROOT_PATH . '"';
|
return '--with-zlib --with-zlib-dir="' . BUILD_ROOT_PATH . '"';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||||
*
|
*
|
||||||
|
|||||||
12
src/SPC/builder/linux/library/grpc.php
Normal file
12
src/SPC/builder/linux/library/grpc.php
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\linux\library;
|
||||||
|
|
||||||
|
class grpc extends LinuxLibraryBase
|
||||||
|
{
|
||||||
|
use \SPC\builder\unix\library\grpc;
|
||||||
|
|
||||||
|
public const NAME = 'grpc';
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||||
*
|
*
|
||||||
|
|||||||
13
src/SPC/builder/linux/library/librdkafka.php
Normal file
13
src/SPC/builder/linux/library/librdkafka.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\linux\library;
|
||||||
|
|
||||||
|
class librdkafka extends LinuxLibraryBase
|
||||||
|
{
|
||||||
|
// TODO: Linux is buggy, see https://github.com/confluentinc/librdkafka/discussions/4495
|
||||||
|
use \SPC\builder\unix\library\librdkafka;
|
||||||
|
|
||||||
|
public const NAME = 'librdkafka';
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||||
*
|
*
|
||||||
|
|||||||
12
src/SPC/builder/macos/library/grpc.php
Normal file
12
src/SPC/builder/macos/library/grpc.php
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\macos\library;
|
||||||
|
|
||||||
|
class grpc extends MacOSLibraryBase
|
||||||
|
{
|
||||||
|
use \SPC\builder\unix\library\grpc;
|
||||||
|
|
||||||
|
public const NAME = 'grpc';
|
||||||
|
}
|
||||||
@@ -56,7 +56,7 @@ class imap extends MacOSLibraryBase
|
|||||||
->exec('chmod +x src/osdep/unix/drivers')
|
->exec('chmod +x src/osdep/unix/drivers')
|
||||||
->exec('chmod +x src/osdep/unix/mkauths')
|
->exec('chmod +x src/osdep/unix/mkauths')
|
||||||
->exec(
|
->exec(
|
||||||
"yes | make osx {$ssl_options} EXTRACFLAGS='-Wimplicit-function-declaration -Wno-incompatible-function-pointer-types {$out}'"
|
"echo y | make osx {$ssl_options} EXTRACFLAGS='-Wno-implicit-function-declaration -Wno-incompatible-function-pointer-types {$out}'"
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
shell()
|
shell()
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||||
*
|
*
|
||||||
|
|||||||
12
src/SPC/builder/macos/library/librdkafka.php
Normal file
12
src/SPC/builder/macos/library/librdkafka.php
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\macos\library;
|
||||||
|
|
||||||
|
class librdkafka extends MacOSLibraryBase
|
||||||
|
{
|
||||||
|
use \SPC\builder\unix\library\librdkafka;
|
||||||
|
|
||||||
|
public const NAME = 'librdkafka';
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use SPC\exception\WrongUsageException;
|
|||||||
use SPC\store\Config;
|
use SPC\store\Config;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
use SPC\util\DependencyUtil;
|
use SPC\util\DependencyUtil;
|
||||||
|
use SPC\util\SPCConfigUtil;
|
||||||
|
|
||||||
abstract class UnixBuilderBase extends BuilderBase
|
abstract class UnixBuilderBase extends BuilderBase
|
||||||
{
|
{
|
||||||
@@ -128,6 +129,7 @@ abstract class UnixBuilderBase extends BuilderBase
|
|||||||
foreach ($this->libs as $lib) {
|
foreach ($this->libs as $lib) {
|
||||||
$lib->calcDependency();
|
$lib->calcDependency();
|
||||||
}
|
}
|
||||||
|
$this->lib_list = $sorted_libraries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -170,6 +172,32 @@ abstract class UnixBuilderBase extends BuilderBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sanity check for embed
|
||||||
|
if (($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED) {
|
||||||
|
logger()->info('running embed sanity check');
|
||||||
|
$sample_file_path = SOURCE_PATH . '/embed-test';
|
||||||
|
if (!is_dir($sample_file_path)) {
|
||||||
|
@mkdir($sample_file_path);
|
||||||
|
}
|
||||||
|
// copy embed test files
|
||||||
|
copy(ROOT_DIR . '/src/globals/common-tests/embed.c', $sample_file_path . '/embed.c');
|
||||||
|
copy(ROOT_DIR . '/src/globals/common-tests/embed.php', $sample_file_path . '/embed.php');
|
||||||
|
$util = new SPCConfigUtil($this);
|
||||||
|
$config = $util->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs'));
|
||||||
|
$lens = "{$config['cflags']} {$config['ldflags']} {$config['libs']}";
|
||||||
|
if (PHP_OS_FAMILY === 'Linux') {
|
||||||
|
$lens .= ' -static';
|
||||||
|
}
|
||||||
|
[$ret, $out] = shell()->cd($sample_file_path)->execWithResult(getenv('CC') . ' -o embed embed.c ' . $lens);
|
||||||
|
if ($ret !== 0) {
|
||||||
|
throw new RuntimeException('embed failed sanity check: build failed. Error message: ' . implode("\n", $out));
|
||||||
|
}
|
||||||
|
[$ret, $output] = shell()->cd($sample_file_path)->execWithResult('./embed');
|
||||||
|
if ($ret !== 0 || trim(implode('', $output)) !== 'hello') {
|
||||||
|
throw new RuntimeException('embed failed sanity check: run failed. Error message: ' . implode("\n", $output));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ trait gettext
|
|||||||
'--disable-java ' .
|
'--disable-java ' .
|
||||||
'--disable-c+ ' .
|
'--disable-c+ ' .
|
||||||
$extra .
|
$extra .
|
||||||
|
'--with-included-gettext ' .
|
||||||
'--with-libiconv-prefix=' . BUILD_ROOT_PATH . ' ' .
|
'--with-libiconv-prefix=' . BUILD_ROOT_PATH . ' ' .
|
||||||
'--prefix=' . BUILD_ROOT_PATH
|
'--prefix=' . BUILD_ROOT_PATH
|
||||||
)
|
)
|
||||||
|
|||||||
24
src/SPC/builder/unix/library/grpc.php
Normal file
24
src/SPC/builder/unix/library/grpc.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\unix\library;
|
||||||
|
|
||||||
|
use SPC\store\FileSystem;
|
||||||
|
|
||||||
|
trait grpc
|
||||||
|
{
|
||||||
|
protected function build(): void
|
||||||
|
{
|
||||||
|
shell()->cd($this->source_dir)
|
||||||
|
->exec('EXTRA_DEFINES=GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK EMBED_OPENSSL=false CXXFLAGS="-L' . BUILD_LIB_PATH . ' -I' . BUILD_INCLUDE_PATH . '" make static -j' . $this->builder->concurrency);
|
||||||
|
copy($this->source_dir . '/libs/opt/libgrpc.a', BUILD_LIB_PATH . '/libgrpc.a');
|
||||||
|
copy($this->source_dir . '/libs/opt/libboringssl.a', BUILD_LIB_PATH . '/libboringssl.a');
|
||||||
|
if (!file_exists(BUILD_LIB_PATH . '/libcares.a')) {
|
||||||
|
copy($this->source_dir . '/libs/opt/libcares.a', BUILD_LIB_PATH . '/libcares.a');
|
||||||
|
}
|
||||||
|
FileSystem::copyDir($this->source_dir . '/include/grpc', BUILD_INCLUDE_PATH . '/grpc');
|
||||||
|
FileSystem::copyDir($this->source_dir . '/include/grpc++', BUILD_INCLUDE_PATH . '/grpc++');
|
||||||
|
FileSystem::copyDir($this->source_dir . '/include/grpcpp', BUILD_INCLUDE_PATH . '/grpcpp');
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/SPC/builder/unix/library/librdkafka.php
Normal file
39
src/SPC/builder/unix/library/librdkafka.php
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\unix\library;
|
||||||
|
|
||||||
|
use SPC\exception\FileSystemException;
|
||||||
|
use SPC\exception\RuntimeException;
|
||||||
|
|
||||||
|
trait librdkafka
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @throws FileSystemException
|
||||||
|
* @throws RuntimeException
|
||||||
|
*/
|
||||||
|
protected function build(): void
|
||||||
|
{
|
||||||
|
$builddir = BUILD_ROOT_PATH;
|
||||||
|
|
||||||
|
$zstd_option = $this->builder->getLib('zstd') ? ("STATIC_LIB_libzstd={$builddir}/lib/libzstd.a ") : '';
|
||||||
|
shell()->cd($this->source_dir)
|
||||||
|
->exec(
|
||||||
|
$zstd_option .
|
||||||
|
'./configure ' .
|
||||||
|
'--enable-static --disable-shared --disable-curl --disable-sasl --disable-valgrind --disable-zlib --disable-ssl ' .
|
||||||
|
($zstd_option == '' ? '--disable-zstd ' : '') .
|
||||||
|
'--prefix='
|
||||||
|
)
|
||||||
|
->exec('make clean')
|
||||||
|
->exec("make -j{$this->builder->concurrency}")
|
||||||
|
->exec("make install DESTDIR={$builddir}");
|
||||||
|
$this->patchPkgconfPrefix(['rdkafka.pc', 'rdkafka-static.pc', 'rdkafka++.pc', 'rdkafka++-static.pc']);
|
||||||
|
// remove dynamic libs
|
||||||
|
shell()
|
||||||
|
->exec("rm -rf {$builddir}/lib/*.so.*")
|
||||||
|
->exec("rm -rf {$builddir}/lib/*.so")
|
||||||
|
->exec("rm -rf {$builddir}/lib/*.dylib");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -248,6 +248,7 @@ class WindowsBuilder extends BuilderBase
|
|||||||
foreach ($this->libs as $lib) {
|
foreach ($this->libs as $lib) {
|
||||||
$lib->calcDependency();
|
$lib->calcDependency();
|
||||||
}
|
}
|
||||||
|
$this->lib_list = $sorted_libraries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -181,7 +181,9 @@ class BuildCliCommand extends BuildCommand
|
|||||||
|
|
||||||
// compile stopwatch :P
|
// compile stopwatch :P
|
||||||
$time = round(microtime(true) - START_TIME, 3);
|
$time = round(microtime(true) - START_TIME, 3);
|
||||||
logger()->info('Build complete, used ' . $time . ' s !');
|
logger()->info('');
|
||||||
|
logger()->info(' Build complete, used ' . $time . ' s !');
|
||||||
|
logger()->info('');
|
||||||
|
|
||||||
// ---------- When using bin/spc-alpine-docker, the build root path is different from the host system ----------
|
// ---------- When using bin/spc-alpine-docker, the build root path is different from the host system ----------
|
||||||
$build_root_path = BUILD_ROOT_PATH;
|
$build_root_path = BUILD_ROOT_PATH;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class DownloadCommand extends BaseCommand
|
|||||||
$this->addArgument('sources', InputArgument::REQUIRED, 'The sources will be compiled, comma separated');
|
$this->addArgument('sources', InputArgument::REQUIRED, 'The sources will be compiled, comma separated');
|
||||||
$this->addOption('shallow-clone', null, null, 'Clone shallow');
|
$this->addOption('shallow-clone', null, null, 'Clone shallow');
|
||||||
$this->addOption('with-openssl11', null, null, 'Use openssl 1.1');
|
$this->addOption('with-openssl11', null, null, 'Use openssl 1.1');
|
||||||
$this->addOption('with-php', null, InputOption::VALUE_REQUIRED, 'version in major.minor format (default 8.2)', '8.2');
|
$this->addOption('with-php', null, InputOption::VALUE_REQUIRED, 'version in major.minor format (default 8.3)', '8.3');
|
||||||
$this->addOption('clean', null, null, 'Clean old download cache and source before fetch');
|
$this->addOption('clean', null, null, 'Clean old download cache and source before fetch');
|
||||||
$this->addOption('all', 'A', null, 'Fetch all sources that static-php-cli needed');
|
$this->addOption('all', 'A', null, 'Fetch all sources that static-php-cli needed');
|
||||||
$this->addOption('custom-url', 'U', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Specify custom source download url, e.g "php-src:https://downloads.php.net/~eric/php-8.3.0beta1.tar.gz"');
|
$this->addOption('custom-url', 'U', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Specify custom source download url, e.g "php-src:https://downloads.php.net/~eric/php-8.3.0beta1.tar.gz"');
|
||||||
|
|||||||
53
src/SPC/command/SPCConfigCommand.php
Normal file
53
src/SPC/command/SPCConfigCommand.php
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\command;
|
||||||
|
|
||||||
|
use SPC\exception\RuntimeException;
|
||||||
|
use SPC\util\SPCConfigUtil;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
|
||||||
|
#[AsCommand('spc-config', 'Build dependencies')]
|
||||||
|
class SPCConfigCommand extends BuildCommand
|
||||||
|
{
|
||||||
|
protected bool $no_motd = true;
|
||||||
|
|
||||||
|
public function configure(): void
|
||||||
|
{
|
||||||
|
$this->addArgument('extensions', InputArgument::OPTIONAL, 'The extensions will be compiled, comma separated');
|
||||||
|
$this->addOption('with-libs', null, InputOption::VALUE_REQUIRED, 'add additional libraries, comma separated', '');
|
||||||
|
$this->addOption('with-suggested-libs', 'L', null, 'Build with suggested libs for selected exts and libs');
|
||||||
|
$this->addOption('with-suggested-exts', 'E', null, 'Build with suggested extensions for selected exts');
|
||||||
|
$this->addOption('includes', null, null, 'Add additional include path');
|
||||||
|
$this->addOption('libs', null, null, 'Add additional libs path');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws RuntimeException
|
||||||
|
*/
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
// transform string to array
|
||||||
|
$libraries = array_map('trim', array_filter(explode(',', $this->getOption('with-libs'))));
|
||||||
|
// transform string to array
|
||||||
|
$extensions = $this->getArgument('extensions') ? $this->parseExtensionList($this->getArgument('extensions')) : [];
|
||||||
|
$include_suggest_ext = $this->getOption('with-suggested-exts');
|
||||||
|
$include_suggest_lib = $this->getOption('with-suggested-libs');
|
||||||
|
|
||||||
|
$util = new SPCConfigUtil(null, $this->input);
|
||||||
|
$config = $util->config($extensions, $libraries, $include_suggest_ext, $include_suggest_lib);
|
||||||
|
|
||||||
|
if ($this->getOption('includes')) {
|
||||||
|
$this->output->writeln($config['cflags']);
|
||||||
|
} elseif ($this->getOption('libs')) {
|
||||||
|
$this->output->writeln("{$config['ldflags']} {$config['libs']}");
|
||||||
|
} else {
|
||||||
|
$this->output->writeln("{$config['cflags']} {$config['ldflags']} {$config['libs']}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,9 +19,9 @@ class SwitchPhpVersionCommand extends BaseCommand
|
|||||||
$this->addArgument(
|
$this->addArgument(
|
||||||
'php-major-version',
|
'php-major-version',
|
||||||
InputArgument::REQUIRED,
|
InputArgument::REQUIRED,
|
||||||
'PHP major version (supported: 7.4, 8.0, 8.1, 8.2, 8.3)',
|
'PHP major version (supported: 7.4, 8.0, 8.1, 8.2, 8.3, 8.4)',
|
||||||
null,
|
null,
|
||||||
fn () => ['7.4', '8.0', '8.1', '8.2', '8.3']
|
fn () => ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
|
||||||
);
|
);
|
||||||
$this->no_motd = true;
|
$this->no_motd = true;
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ class SwitchPhpVersionCommand extends BaseCommand
|
|||||||
public function handle(): int
|
public function handle(): int
|
||||||
{
|
{
|
||||||
$php_ver = $this->input->getArgument('php-major-version');
|
$php_ver = $this->input->getArgument('php-major-version');
|
||||||
if (!in_array($php_ver, ['7.4', '8.0', '8.1', '8.2', '8.3'])) {
|
if (!in_array($php_ver, ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4'])) {
|
||||||
// match x.y.z
|
// match x.y.z
|
||||||
preg_match('/^\d+\.\d+\.\d+$/', $php_ver, $matches);
|
preg_match('/^\d+\.\d+\.\d+$/', $php_ver, $matches);
|
||||||
if (!$matches) {
|
if (!$matches) {
|
||||||
|
|||||||
7
src/SPC/exception/InterruptException.php
Normal file
7
src/SPC/exception/InterruptException.php
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\exception;
|
||||||
|
|
||||||
|
class InterruptException extends \Exception {}
|
||||||
@@ -28,7 +28,7 @@ class Downloader
|
|||||||
logger()->debug("finding {$name} source from bitbucket tag");
|
logger()->debug("finding {$name} source from bitbucket tag");
|
||||||
$data = json_decode(self::curlExec(
|
$data = json_decode(self::curlExec(
|
||||||
url: "https://api.bitbucket.org/2.0/repositories/{$source['repo']}/refs/tags",
|
url: "https://api.bitbucket.org/2.0/repositories/{$source['repo']}/refs/tags",
|
||||||
retry: intval(getenv('SPC_RETRY_TIME') ? getenv('SPC_RETRY_TIME') : 0)
|
retry: self::getRetryTime()
|
||||||
), true);
|
), true);
|
||||||
$ver = $data['values'][0]['name'];
|
$ver = $data['values'][0]['name'];
|
||||||
if (!$ver) {
|
if (!$ver) {
|
||||||
@@ -38,7 +38,7 @@ class Downloader
|
|||||||
$headers = self::curlExec(
|
$headers = self::curlExec(
|
||||||
url: $url,
|
url: $url,
|
||||||
method: 'HEAD',
|
method: 'HEAD',
|
||||||
retry: intval(getenv('SPC_RETRY_TIME') ? getenv('SPC_RETRY_TIME') : 0)
|
retry: self::getRetryTime()
|
||||||
);
|
);
|
||||||
preg_match('/^content-disposition:\s+attachment;\s*filename=("?)(?<filename>.+\.tar\.gz)\1/im', $headers, $matches);
|
preg_match('/^content-disposition:\s+attachment;\s*filename=("?)(?<filename>.+\.tar\.gz)\1/im', $headers, $matches);
|
||||||
if ($matches) {
|
if ($matches) {
|
||||||
@@ -66,7 +66,7 @@ class Downloader
|
|||||||
$data = json_decode(self::curlExec(
|
$data = json_decode(self::curlExec(
|
||||||
url: "https://api.github.com/repos/{$source['repo']}/{$type}",
|
url: "https://api.github.com/repos/{$source['repo']}/{$type}",
|
||||||
hooks: [[CurlHook::class, 'setupGithubToken']],
|
hooks: [[CurlHook::class, 'setupGithubToken']],
|
||||||
retry: intval(getenv('SPC_RETRY_TIME') ? getenv('SPC_RETRY_TIME') : 0)
|
retry: self::getRetryTime()
|
||||||
), true);
|
), true);
|
||||||
|
|
||||||
if (($source['prefer-stable'] ?? false) === false) {
|
if (($source['prefer-stable'] ?? false) === false) {
|
||||||
@@ -85,7 +85,7 @@ class Downloader
|
|||||||
url: $url,
|
url: $url,
|
||||||
method: 'HEAD',
|
method: 'HEAD',
|
||||||
hooks: [[CurlHook::class, 'setupGithubToken']],
|
hooks: [[CurlHook::class, 'setupGithubToken']],
|
||||||
retry: intval(getenv('SPC_RETRY_TIME') ? getenv('SPC_RETRY_TIME') : 0)
|
retry: self::getRetryTime()
|
||||||
);
|
);
|
||||||
preg_match('/^content-disposition:\s+attachment;\s*filename=("?)(?<filename>.+\.tar\.gz)\1/im', $headers, $matches);
|
preg_match('/^content-disposition:\s+attachment;\s*filename=("?)(?<filename>.+\.tar\.gz)\1/im', $headers, $matches);
|
||||||
if ($matches) {
|
if ($matches) {
|
||||||
@@ -108,11 +108,11 @@ class Downloader
|
|||||||
*/
|
*/
|
||||||
public static function getLatestGithubRelease(string $name, array $source, bool $match_result = true): array
|
public static function getLatestGithubRelease(string $name, array $source, bool $match_result = true): array
|
||||||
{
|
{
|
||||||
logger()->debug("finding {$name} from github releases assests");
|
logger()->debug("finding {$name} from github releases assets");
|
||||||
$data = json_decode(self::curlExec(
|
$data = json_decode(self::curlExec(
|
||||||
url: "https://api.github.com/repos/{$source['repo']}/releases",
|
url: "https://api.github.com/repos/{$source['repo']}/releases",
|
||||||
hooks: [[CurlHook::class, 'setupGithubToken']],
|
hooks: [[CurlHook::class, 'setupGithubToken']],
|
||||||
retry: intval(getenv('SPC_RETRY_TIME') ? getenv('SPC_RETRY_TIME') : 0)
|
retry: self::getRetryTime()
|
||||||
), true);
|
), true);
|
||||||
$url = null;
|
$url = null;
|
||||||
foreach ($data as $release) {
|
foreach ($data as $release) {
|
||||||
@@ -149,7 +149,7 @@ class Downloader
|
|||||||
public static function getFromFileList(string $name, array $source): array
|
public static function getFromFileList(string $name, array $source): array
|
||||||
{
|
{
|
||||||
logger()->debug("finding {$name} source from file list");
|
logger()->debug("finding {$name} source from file list");
|
||||||
$page = self::curlExec($source['url'], retry: intval(getenv('SPC_RETRY_TIME') ? getenv('SPC_RETRY_TIME') : 0));
|
$page = self::curlExec($source['url'], retry: self::getRetryTime());
|
||||||
preg_match_all($source['regex'], $page, $matches);
|
preg_match_all($source['regex'], $page, $matches);
|
||||||
if (!$matches) {
|
if (!$matches) {
|
||||||
throw new DownloaderException("Failed to get {$name} version");
|
throw new DownloaderException("Failed to get {$name} version");
|
||||||
@@ -194,7 +194,7 @@ class Downloader
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
self::registerCancelEvent($cancel_func);
|
self::registerCancelEvent($cancel_func);
|
||||||
self::curlDown(url: $url, path: FileSystem::convertPath(DOWNLOAD_PATH . "/{$filename}"), retry: intval(getenv('SPC_RETRY_TIME') ? getenv('SPC_RETRY_TIME') : 0));
|
self::curlDown(url: $url, path: FileSystem::convertPath(DOWNLOAD_PATH . "/{$filename}"), retry: self::getRetryTime());
|
||||||
self::unregisterCancelEvent();
|
self::unregisterCancelEvent();
|
||||||
logger()->debug("Locking {$filename}");
|
logger()->debug("Locking {$filename}");
|
||||||
self::lockSource($name, ['source_type' => 'archive', 'filename' => $filename, 'move_path' => $move_path, 'lock_as' => $lock_as]);
|
self::lockSource($name, ['source_type' => 'archive', 'filename' => $filename, 'move_path' => $move_path, 'lock_as' => $lock_as]);
|
||||||
@@ -347,7 +347,7 @@ class Downloader
|
|||||||
$pkg['url'],
|
$pkg['url'],
|
||||||
$pkg['rev'],
|
$pkg['rev'],
|
||||||
$pkg['extract'] ?? null,
|
$pkg['extract'] ?? null,
|
||||||
intval(getenv('SPC_RETRY_TIME') ? getenv('SPC_RETRY_TIME') : 0),
|
self::getRetryTime(),
|
||||||
SPC_LOCK_PRE_BUILT
|
SPC_LOCK_PRE_BUILT
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@@ -451,7 +451,7 @@ class Downloader
|
|||||||
$source['url'],
|
$source['url'],
|
||||||
$source['rev'],
|
$source['rev'],
|
||||||
$source['path'] ?? null,
|
$source['path'] ?? null,
|
||||||
intval(getenv('SPC_RETRY_TIME') ? getenv('SPC_RETRY_TIME') : 0),
|
self::getRetryTime(),
|
||||||
$lock_as
|
$lock_as
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@@ -567,7 +567,7 @@ class Downloader
|
|||||||
}
|
}
|
||||||
if ($retry > 0) {
|
if ($retry > 0) {
|
||||||
logger()->notice('Retrying curl download ...');
|
logger()->notice('Retrying curl download ...');
|
||||||
self::curlDown($url, $path, $method, $used_headers, retry: intval(getenv('SPC_RETRY_TIME') ? getenv('SPC_RETRY_TIME') : 0));
|
self::curlDown($url, $path, $method, $used_headers, retry: $retry - 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw $e;
|
throw $e;
|
||||||
@@ -601,4 +601,9 @@ class Downloader
|
|||||||
pcntl_signal(2, SIG_IGN);
|
pcntl_signal(2, SIG_IGN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function getRetryTime(): int
|
||||||
|
{
|
||||||
|
return intval(getenv('SPC_RETRY_TIME') ? getenv('SPC_RETRY_TIME') : 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -367,6 +367,9 @@ class FileSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (is_link($dir)) {
|
||||||
|
return unlink($dir);
|
||||||
|
}
|
||||||
return rmdir($dir);
|
return rmdir($dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ class SourcePatcher
|
|||||||
FileSystem::addSourceExtractHook('pdo_sqlsrv', [SourcePatcher::class, 'patchSQLSRVWin32']);
|
FileSystem::addSourceExtractHook('pdo_sqlsrv', [SourcePatcher::class, 'patchSQLSRVWin32']);
|
||||||
FileSystem::addSourceExtractHook('yaml', [SourcePatcher::class, 'patchYamlWin32']);
|
FileSystem::addSourceExtractHook('yaml', [SourcePatcher::class, 'patchYamlWin32']);
|
||||||
FileSystem::addSourceExtractHook('libyaml', [SourcePatcher::class, 'patchLibYaml']);
|
FileSystem::addSourceExtractHook('libyaml', [SourcePatcher::class, 'patchLibYaml']);
|
||||||
|
FileSystem::addSourceExtractHook('php-src', [SourcePatcher::class, 'patchImapLicense']);
|
||||||
|
FileSystem::addSourceExtractHook('ext-imagick', [SourcePatcher::class, 'patchImagickWith84']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -370,6 +372,27 @@ class SourcePatcher
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Patch imap license file for PHP < 8.4
|
||||||
|
*/
|
||||||
|
public static function patchImapLicense(): bool
|
||||||
|
{
|
||||||
|
if (!file_exists(SOURCE_PATH . '/php-src/ext/imap/LICENSE') && is_dir(SOURCE_PATH . '/php-src/ext/imap')) {
|
||||||
|
file_put_contents(SOURCE_PATH . '/php-src/ext/imap/LICENSE', file_get_contents(ROOT_DIR . '/src/globals/extra/Apache_LICENSE'));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Patch imagick for PHP 8.4
|
||||||
|
*/
|
||||||
|
public static function patchImagickWith84(): bool
|
||||||
|
{
|
||||||
|
SourcePatcher::patchFile('imagick_php84.patch', SOURCE_PATH . '/php-src/ext/imagick');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Patch cli SAPI Makefile for Windows.
|
* Patch cli SAPI Makefile for Windows.
|
||||||
*
|
*
|
||||||
@@ -416,7 +439,7 @@ class SourcePatcher
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ($ver_id < 80200) {
|
if ($ver_id < 80200) {
|
||||||
self::patchFile('spc_fix_libxml2_12_php81.patch', SOURCE_PATH . '/php-src');
|
// self::patchFile('spc_fix_libxml2_12_php81.patch', SOURCE_PATH . '/php-src');
|
||||||
self::patchFile('spc_fix_alpine_build_php80.patch', SOURCE_PATH . '/php-src');
|
self::patchFile('spc_fix_alpine_build_php80.patch', SOURCE_PATH . '/php-src');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,8 @@ class PhpSource extends CustomSourceBase
|
|||||||
*/
|
*/
|
||||||
public function fetch(bool $force = false, ?array $config = null, int $lock_as = SPC_LOCK_SOURCE): void
|
public function fetch(bool $force = false, ?array $config = null, int $lock_as = SPC_LOCK_SOURCE): void
|
||||||
{
|
{
|
||||||
$major = defined('SPC_BUILD_PHP_VERSION') ? SPC_BUILD_PHP_VERSION : '8.1';
|
$major = defined('SPC_BUILD_PHP_VERSION') ? SPC_BUILD_PHP_VERSION : '8.3';
|
||||||
if ($major === '8.4') {
|
Downloader::downloadSource('php-src', self::getLatestPHPInfo($major), $force);
|
||||||
Downloader::downloadSource('php-src', ['type' => 'url', 'url' => 'https://downloads.php.net/~saki/php-8.4.0RC1.tar.xz'], $force);
|
|
||||||
} else {
|
|
||||||
Downloader::downloadSource('php-src', self::getLatestPHPInfo($major), $force);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class GlobalEnvManager
|
|||||||
self::putenv('PKG_CONFIG=' . BUILD_BIN_PATH . '/pkg-config');
|
self::putenv('PKG_CONFIG=' . BUILD_BIN_PATH . '/pkg-config');
|
||||||
self::putenv('PKG_CONFIG_PATH=' . BUILD_ROOT_PATH . '/lib/pkgconfig');
|
self::putenv('PKG_CONFIG_PATH=' . BUILD_ROOT_PATH . '/lib/pkgconfig');
|
||||||
if ($builder instanceof BuilderBase) {
|
if ($builder instanceof BuilderBase) {
|
||||||
self::putenv('SPC_PHP_DEFAULT_OPTIMIZE_CFLAGS=' . ($builder->getOption('no-strip') ? '-g -O0' : '-g -Os'));
|
self::putenv('SPC_PHP_DEFAULT_OPTIMIZE_CFLAGS=' . ($builder->getOption('no-strip') ? '-g -O0' : '-g -fstack-protector-strong -fpic -fpie -Os -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
104
src/SPC/util/SPCConfigUtil.php
Normal file
104
src/SPC/util/SPCConfigUtil.php
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\util;
|
||||||
|
|
||||||
|
use SPC\builder\BuilderBase;
|
||||||
|
use SPC\builder\BuilderProvider;
|
||||||
|
use SPC\builder\macos\MacOSBuilder;
|
||||||
|
use SPC\store\Config;
|
||||||
|
use Symfony\Component\Console\Input\ArgvInput;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
|
||||||
|
class SPCConfigUtil
|
||||||
|
{
|
||||||
|
public function __construct(private ?BuilderBase $builder = null, ?InputInterface $input = null)
|
||||||
|
{
|
||||||
|
if ($builder === null) {
|
||||||
|
$this->builder = BuilderProvider::makeBuilderByInput($input ?? new ArgvInput());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function config(array $extensions = [], array $libraries = [], bool $include_suggest_ext = false, bool $include_suggest_lib = false): array
|
||||||
|
{
|
||||||
|
[$extensions, $libraries] = DependencyUtil::getExtsAndLibs($extensions, $libraries, $include_suggest_ext, $include_suggest_lib);
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
$this->builder->proveLibs($libraries);
|
||||||
|
$this->builder->proveExts($extensions);
|
||||||
|
ob_get_clean();
|
||||||
|
$ldflags = $this->getLdflagsString();
|
||||||
|
$libs = $this->getLibsString($libraries);
|
||||||
|
$cflags = $this->getIncludesString();
|
||||||
|
|
||||||
|
// embed
|
||||||
|
$libs = '-lphp -lc ' . $libs;
|
||||||
|
$extra_env = getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS');
|
||||||
|
if (is_string($extra_env)) {
|
||||||
|
$libs .= ' ' . $extra_env;
|
||||||
|
}
|
||||||
|
// c++
|
||||||
|
if ($this->builder->hasCpp()) {
|
||||||
|
$libs .= $this->builder instanceof MacOSBuilder ? ' -lc++' : ' -lstdc++';
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
'cflags' => $cflags,
|
||||||
|
'ldflags' => $ldflags,
|
||||||
|
'libs' => $libs,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getIncludesString(): string
|
||||||
|
{
|
||||||
|
$base = BUILD_INCLUDE_PATH;
|
||||||
|
$php_embed_includes = [
|
||||||
|
"-I{$base}",
|
||||||
|
"-I{$base}/php",
|
||||||
|
"-I{$base}/php/main",
|
||||||
|
"-I{$base}/php/TSRM",
|
||||||
|
"-I{$base}/php/Zend",
|
||||||
|
"-I{$base}/php/ext",
|
||||||
|
];
|
||||||
|
return implode(' ', $php_embed_includes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getLdflagsString(): string
|
||||||
|
{
|
||||||
|
return '-L' . BUILD_LIB_PATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getLibsString(array $libraries): string
|
||||||
|
{
|
||||||
|
$short_name = [];
|
||||||
|
foreach (array_reverse($libraries) as $library) {
|
||||||
|
$libs = Config::getLib($library, 'static-libs', []);
|
||||||
|
foreach ($libs as $lib) {
|
||||||
|
$short_name[] = $this->getShortLibName($lib);
|
||||||
|
}
|
||||||
|
if (PHP_OS_FAMILY !== 'Darwin') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach (Config::getLib($library, 'frameworks', []) as $fw) {
|
||||||
|
$ks = '-framework ' . $fw;
|
||||||
|
if (!in_array($ks, $short_name)) {
|
||||||
|
$short_name[] = $ks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// patch: imagick (imagemagick wrapper) for linux needs -lgomp
|
||||||
|
if (in_array('imagemagick', $libraries) && PHP_OS_FAMILY === 'Linux') {
|
||||||
|
$short_name[] = '-lgomp';
|
||||||
|
}
|
||||||
|
return implode(' ', $short_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getShortLibName(string $lib): string
|
||||||
|
{
|
||||||
|
if (!str_starts_with($lib, 'lib') || !str_ends_with($lib, '.a')) {
|
||||||
|
return BUILD_LIB_PATH . '/' . $lib;
|
||||||
|
}
|
||||||
|
// get short name
|
||||||
|
return '-l' . substr($lib, 3, -2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,6 +62,9 @@ class UnixShell
|
|||||||
logger()->debug(ConsoleColor::blue('[EXEC] ') . ConsoleColor::gray($cmd));
|
logger()->debug(ConsoleColor::blue('[EXEC] ') . ConsoleColor::gray($cmd));
|
||||||
}
|
}
|
||||||
logger()->debug('Executed at: ' . debug_backtrace()[0]['file'] . ':' . debug_backtrace()[0]['line']);
|
logger()->debug('Executed at: ' . debug_backtrace()[0]['file'] . ':' . debug_backtrace()[0]['line']);
|
||||||
|
if ($this->cd !== null) {
|
||||||
|
$cmd = 'cd ' . escapeshellarg($this->cd) . ' && ' . $cmd;
|
||||||
|
}
|
||||||
exec($cmd, $out, $code);
|
exec($cmd, $out, $code);
|
||||||
return [$code, $out];
|
return [$code, $out];
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/globals/common-tests/embed.c
Normal file
17
src/globals/common-tests/embed.c
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#include <sapi/embed/php_embed.h>
|
||||||
|
|
||||||
|
int main(int argc,char **argv){
|
||||||
|
|
||||||
|
PHP_EMBED_START_BLOCK(argc,argv)
|
||||||
|
|
||||||
|
zend_file_handle file_handle;
|
||||||
|
|
||||||
|
zend_stream_init_filename(&file_handle,"embed.php");
|
||||||
|
|
||||||
|
if(php_execute_script(&file_handle) == FAILURE){
|
||||||
|
php_printf("Failed to execute PHP script.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_EMBED_END_BLOCK()
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
4
src/globals/common-tests/embed.php
Normal file
4
src/globals/common-tests/embed.php
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
echo 'hello' . PHP_EOL;
|
||||||
@@ -5,7 +5,6 @@ declare(strict_types=1);
|
|||||||
assert(function_exists('gettext'));
|
assert(function_exists('gettext'));
|
||||||
assert(function_exists('bindtextdomain'));
|
assert(function_exists('bindtextdomain'));
|
||||||
assert(function_exists('textdomain'));
|
assert(function_exists('textdomain'));
|
||||||
assert(function_exists('bind_textdomain_codeset'));
|
|
||||||
|
|
||||||
if (!is_dir('locale/en_US/LC_MESSAGES/')) {
|
if (!is_dir('locale/en_US/LC_MESSAGES/')) {
|
||||||
mkdir('locale/en_US/LC_MESSAGES/', 0755, true);
|
mkdir('locale/en_US/LC_MESSAGES/', 0755, true);
|
||||||
@@ -19,7 +18,6 @@ setlocale(LC_ALL, 'en_US');
|
|||||||
|
|
||||||
$domain = 'test';
|
$domain = 'test';
|
||||||
bindtextdomain($domain, 'locale/');
|
bindtextdomain($domain, 'locale/');
|
||||||
bind_textdomain_codeset($domain, 'UTF-8');
|
|
||||||
textdomain($domain);
|
textdomain($domain);
|
||||||
|
|
||||||
assert(gettext(json_decode('"\u793a\u4f8b"', true)) === 'Example');
|
assert(gettext(json_decode('"\u793a\u4f8b"', true)) === 'Example');
|
||||||
|
|||||||
5
src/globals/ext-tests/grpc.php
Normal file
5
src/globals/ext-tests/grpc.php
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
assert(class_exists('Grpc\ChannelCredentials'));
|
||||||
@@ -6,7 +6,6 @@ assert(function_exists('swoole_cpu_num'));
|
|||||||
assert(function_exists('swoole_string'));
|
assert(function_exists('swoole_string'));
|
||||||
assert(class_exists('Swoole\Coroutine'));
|
assert(class_exists('Swoole\Coroutine'));
|
||||||
assert(class_exists('Swoole\Coroutine\Http2\Client'));
|
assert(class_exists('Swoole\Coroutine\Http2\Client'));
|
||||||
assert(class_exists('Swoole\Coroutine\Redis'));
|
|
||||||
assert(class_exists('Swoole\Coroutine\WaitGroup'));
|
assert(class_exists('Swoole\Coroutine\WaitGroup'));
|
||||||
assert(class_exists('Swoole\Http2\Request'));
|
assert(class_exists('Swoole\Http2\Request'));
|
||||||
assert(constant('SWOOLE_VERSION'));
|
assert(constant('SWOOLE_VERSION'));
|
||||||
|
|||||||
201
src/globals/extra/Apache_LICENSE
Normal file
201
src/globals/extra/Apache_LICENSE
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use SPC\builder\BuilderBase;
|
use SPC\builder\BuilderBase;
|
||||||
use SPC\builder\BuilderProvider;
|
use SPC\builder\BuilderProvider;
|
||||||
|
use SPC\exception\InterruptException;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\RuntimeException;
|
||||||
use SPC\exception\WrongUsageException;
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\util\UnixShell;
|
use SPC\util\UnixShell;
|
||||||
@@ -125,6 +126,11 @@ function patch_point(): string
|
|||||||
return BuilderProvider::getBuilder()->getPatchPoint();
|
return BuilderProvider::getBuilder()->getPatchPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function patch_point_interrupt(int $retcode, string $msg = ''): InterruptException
|
||||||
|
{
|
||||||
|
return new InterruptException(message: $msg, code: $retcode);
|
||||||
|
}
|
||||||
|
|
||||||
// ------- function f_* part -------
|
// ------- function f_* part -------
|
||||||
// f_ means standard function wrapper
|
// f_ means standard function wrapper
|
||||||
|
|
||||||
|
|||||||
40
src/globals/patch/imagick_php84.patch
Normal file
40
src/globals/patch/imagick_php84.patch
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
From 65e27f2bc02e7e8f1bf64e26e359e42a1331fca1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= <mvorisek@mvorisek.cz>
|
||||||
|
Date: Wed, 25 Sep 2024 10:56:28 +0200
|
||||||
|
Subject: [PATCH] Fix removed "php_strtolower" for PHP 8.4
|
||||||
|
|
||||||
|
---
|
||||||
|
imagick.c | 6 +++---
|
||||||
|
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/imagick.c b/imagick.c
|
||||||
|
index 1b765389..ebab7ae7 100644
|
||||||
|
--- a/imagick.c
|
||||||
|
+++ b/imagick.c
|
||||||
|
@@ -610,7 +610,7 @@ static zval *php_imagick_read_property(zend_object *object, zend_string *member,
|
||||||
|
if (format) {
|
||||||
|
retval = rv;
|
||||||
|
ZVAL_STRING(retval, format);
|
||||||
|
- php_strtolower(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
|
||||||
|
+ zend_str_tolower(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
|
||||||
|
IMAGICK_FREE_MAGICK_MEMORY(format);
|
||||||
|
} else {
|
||||||
|
retval = rv;
|
||||||
|
@@ -683,7 +683,7 @@ static zval *php_imagick_read_property(zval *object, zval *member, int type, voi
|
||||||
|
if (format) {
|
||||||
|
retval = rv;
|
||||||
|
ZVAL_STRING(retval, format);
|
||||||
|
- php_strtolower(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
|
||||||
|
+ zend_str_tolower(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
|
||||||
|
IMAGICK_FREE_MAGICK_MEMORY(format);
|
||||||
|
} else {
|
||||||
|
retval = rv;
|
||||||
|
@@ -766,7 +766,7 @@ static zval *php_imagick_read_property(zval *object, zval *member, int type, con
|
||||||
|
|
||||||
|
if (format) {
|
||||||
|
ZVAL_STRING(retval, format, 1);
|
||||||
|
- php_strtolower(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
|
||||||
|
+ zend_str_tolower(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
|
||||||
|
IMAGICK_FREE_MAGICK_MEMORY(format);
|
||||||
|
} else {
|
||||||
|
ZVAL_STRING(retval, "", 1);
|
||||||
@@ -13,18 +13,17 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
// test php version
|
// test php version
|
||||||
$test_php_version = [
|
$test_php_version = [
|
||||||
'8.0',
|
|
||||||
'8.1',
|
'8.1',
|
||||||
'8.2',
|
'8.2',
|
||||||
'8.3',
|
'8.3',
|
||||||
|
'8.4',
|
||||||
];
|
];
|
||||||
|
|
||||||
// test os (macos-13, macos-14, ubuntu-latest, windows-latest are available)
|
// test os (macos-13, macos-14, ubuntu-latest, windows-latest are available)
|
||||||
$test_os = [
|
$test_os = [
|
||||||
'macos-14',
|
// 'macos-14',
|
||||||
'ubuntu-latest',
|
|
||||||
'macos-13',
|
'macos-13',
|
||||||
'windows-latest',
|
// 'ubuntu-latest',
|
||||||
];
|
];
|
||||||
|
|
||||||
// whether enable thread safe
|
// whether enable thread safe
|
||||||
@@ -40,8 +39,8 @@ $prefer_pre_built = true;
|
|||||||
|
|
||||||
// If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`).
|
// If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`).
|
||||||
$extensions = match (PHP_OS_FAMILY) {
|
$extensions = match (PHP_OS_FAMILY) {
|
||||||
'Linux', 'Darwin' => '',
|
'Linux', 'Darwin' => 'rdkafka',
|
||||||
'Windows' => 'amqp,apcu,bcmath,bz2,calendar,ctype,curl,dba,dom,ds,exif,ffi,fileinfo,filter,ftp,gd,iconv,igbinary,libxml,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pdo,pdo_mysql,pdo_sqlite,pdo_sqlsrv,phar,rar,redis,session,shmop,simdjson,simplexml,soap,sockets,sqlite3,sqlsrv,ssh2,swow,sysvshm,tokenizer,xml,xmlreader,xmlwriter,yac,yaml,zip,zlib',
|
'Windows' => 'zlib',
|
||||||
};
|
};
|
||||||
|
|
||||||
// If you want to test lib-suggests feature with extension, add them below (comma separated, example `libwebp,libavif`).
|
// If you want to test lib-suggests feature with extension, add them below (comma separated, example `libwebp,libavif`).
|
||||||
@@ -116,14 +115,13 @@ if ($argv[1] === 'download_cmd') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// generate build command
|
// generate build command
|
||||||
if ($argv[1] === 'build_cmd') {
|
if ($argv[1] === 'build_cmd' || $argv[1] === 'build_embed_cmd') {
|
||||||
$build_cmd = 'build ';
|
$build_cmd = 'build ';
|
||||||
$build_cmd .= quote2($final_extensions) . ' ';
|
$build_cmd .= quote2($final_extensions) . ' ';
|
||||||
$build_cmd .= $zts ? '--enable-zts ' : '';
|
$build_cmd .= $zts ? '--enable-zts ' : '';
|
||||||
$build_cmd .= $no_strip ? '--no-strip ' : '';
|
$build_cmd .= $no_strip ? '--no-strip ' : '';
|
||||||
$build_cmd .= $upx ? '--with-upx-pack ' : '';
|
$build_cmd .= $upx ? '--with-upx-pack ' : '';
|
||||||
$build_cmd .= $final_libs === '' ? '' : ('--with-libs=' . quote2($final_libs) . ' ');
|
$build_cmd .= $final_libs === '' ? '' : ('--with-libs=' . quote2($final_libs) . ' ');
|
||||||
$build_cmd .= '--build-cli --build-micro ';
|
|
||||||
$build_cmd .= str_starts_with($argv[2], 'windows-') ? '' : '--build-fpm ';
|
$build_cmd .= str_starts_with($argv[2], 'windows-') ? '' : '--build-fpm ';
|
||||||
$build_cmd .= '--debug ';
|
$build_cmd .= '--debug ';
|
||||||
}
|
}
|
||||||
@@ -141,6 +139,7 @@ echo match ($argv[1]) {
|
|||||||
'prefer_pre_built' => $prefer_pre_built ? '--prefer-pre-built' : '',
|
'prefer_pre_built' => $prefer_pre_built ? '--prefer-pre-built' : '',
|
||||||
'download_cmd' => $down_cmd,
|
'download_cmd' => $down_cmd,
|
||||||
'build_cmd' => $build_cmd,
|
'build_cmd' => $build_cmd,
|
||||||
|
'build_embed_cmd' => $build_cmd,
|
||||||
default => '',
|
default => '',
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -152,9 +151,16 @@ if ($argv[1] === 'download_cmd') {
|
|||||||
}
|
}
|
||||||
} elseif ($argv[1] === 'build_cmd') {
|
} elseif ($argv[1] === 'build_cmd') {
|
||||||
if (str_starts_with($argv[2], 'windows-')) {
|
if (str_starts_with($argv[2], 'windows-')) {
|
||||||
passthru('powershell.exe -file .\bin\spc.ps1 ' . $build_cmd, $retcode);
|
passthru('powershell.exe -file .\bin\spc.ps1 ' . $build_cmd . ' --build-cli --build-micro', $retcode);
|
||||||
} else {
|
} else {
|
||||||
passthru('./bin/spc ' . $build_cmd, $retcode);
|
passthru('./bin/spc ' . $build_cmd . ' --build-cli --build-micro', $retcode);
|
||||||
|
}
|
||||||
|
} elseif ($argv[1] === 'build_embed_cmd') {
|
||||||
|
if (str_starts_with($argv[2], 'windows-')) {
|
||||||
|
// windows does not accept embed SAPI
|
||||||
|
passthru('powershell.exe -file .\bin\spc.ps1 ' . $build_cmd . ' --build-cli', $retcode);
|
||||||
|
} else {
|
||||||
|
passthru('./bin/spc ' . $build_cmd . ' --build-embed', $retcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -246,6 +246,7 @@ class BuilderTest extends TestCase
|
|||||||
public function testEmitPatchPointNotExists()
|
public function testEmitPatchPointNotExists()
|
||||||
{
|
{
|
||||||
$this->expectOutputRegex('/failed to run/');
|
$this->expectOutputRegex('/failed to run/');
|
||||||
|
$this->expectException(RuntimeException::class);
|
||||||
$this->builder->setOption('with-added-patch', ['/tmp/patch-point.not_exsssists.php']);
|
$this->builder->setOption('with-added-patch', ['/tmp/patch-point.not_exsssists.php']);
|
||||||
$this->builder->emitPatchPoint('not-exists');
|
$this->builder->emitPatchPoint('not-exists');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user