mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-03-19 13:24:51 +08:00
Merge branch 'main' into ext/rdkafka
# Conflicts: # src/globals/test-extensions.php
This commit is contained in:
commit
d0fbc5ab2d
3
.github/workflows/build-linux-arm.yml
vendored
3
.github/workflows/build-linux-arm.yml
vendored
@ -12,9 +12,10 @@ on:
|
||||
version:
|
||||
required: true
|
||||
description: php version to compile
|
||||
default: '8.2'
|
||||
default: '8.3'
|
||||
type: choice
|
||||
options:
|
||||
- '8.4'
|
||||
- '8.3'
|
||||
- '8.2'
|
||||
- '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:
|
||||
required: true
|
||||
description: php version to compile
|
||||
default: '8.2'
|
||||
default: '8.3'
|
||||
type: choice
|
||||
options:
|
||||
- '8.4'
|
||||
- '8.3'
|
||||
- '8.2'
|
||||
- '8.1'
|
||||
|
||||
3
.github/workflows/build-macos-aarch64.yml
vendored
3
.github/workflows/build-macos-aarch64.yml
vendored
@ -6,9 +6,10 @@ on:
|
||||
version:
|
||||
required: true
|
||||
description: php version to compile
|
||||
default: '8.2'
|
||||
default: '8.3'
|
||||
type: choice
|
||||
options:
|
||||
- '8.4'
|
||||
- '8.3'
|
||||
- '8.2'
|
||||
- '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:
|
||||
required: true
|
||||
description: php version to compile
|
||||
default: '8.2'
|
||||
default: '8.3'
|
||||
type: choice
|
||||
options:
|
||||
- '8.4'
|
||||
- '8.3'
|
||||
- '8.2'
|
||||
- '8.1'
|
||||
- '8.0'
|
||||
- '7.4'
|
||||
build-cli:
|
||||
description: build cli binary
|
||||
default: true
|
||||
@ -35,6 +34,10 @@ on:
|
||||
debug:
|
||||
description: enable debug logs
|
||||
type: boolean
|
||||
no-strip:
|
||||
description: keep debug symbols for debugging
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@ -80,13 +83,15 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: downloads
|
||||
key: php-${{ env.INPUT_HASH }}
|
||||
key: php-${{ inputs.version }}-macos-x86_64
|
||||
|
||||
# With or without debug
|
||||
- if: inputs.debug == true
|
||||
run: echo "SPC_BUILD_DEBUG=--debug" >> $GITHUB_ENV
|
||||
- if: inputs.prefer-pre-built == true
|
||||
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
|
||||
- if: ${{ inputs.build-cli == true }}
|
||||
@ -97,11 +102,10 @@ jobs:
|
||||
run: echo "SPC_BUILD_FPM=--build-fpm" >> $GITHUB_ENV
|
||||
|
||||
# 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 }}
|
||||
- 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 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
|
||||
- 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'
|
||||
type: choice
|
||||
options:
|
||||
- '8.4'
|
||||
- '8.3'
|
||||
- '8.2'
|
||||
- '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
|
||||
66
.github/workflows/tests.yml
vendored
66
.github/workflows/tests.yml
vendored
@ -82,6 +82,7 @@ jobs:
|
||||
- php: '8.1'
|
||||
- php: '8.2'
|
||||
- php: '8.3'
|
||||
- php: '8.4'
|
||||
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
@ -109,24 +110,41 @@ jobs:
|
||||
|
||||
- name: "Run PHPUnit Tests"
|
||||
run: |
|
||||
vendor/bin/phpunit tests/ --no-coverage
|
||||
SPC_NO_MUSL_PATH=yes vendor/bin/phpunit tests/ --no-coverage
|
||||
|
||||
define-matrix:
|
||||
name: "Define Matrix"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
php: ${{ steps.gendef.outputs.php }}
|
||||
os: ${{ steps.gendef.outputs.os }}
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: "Setup PHP"
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 8.2
|
||||
|
||||
- name: Define
|
||||
id: gendef
|
||||
run: |
|
||||
PHP_VERSIONS=$(php src/globals/test-extensions.php php)
|
||||
OS_VERSIONS=$(php src/globals/test-extensions.php os)
|
||||
echo 'php='"$PHP_VERSIONS" >> "$GITHUB_OUTPUT"
|
||||
echo 'os='"$OS_VERSIONS" >> "$GITHUB_OUTPUT"
|
||||
|
||||
|
||||
build:
|
||||
name: "Build PHP Test (PHP ${{ matrix.php }} ${{ matrix.os }})"
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: define-matrix
|
||||
timeout-minutes: 120
|
||||
strategy:
|
||||
matrix:
|
||||
php:
|
||||
- "8.0"
|
||||
- "8.1"
|
||||
- "8.2"
|
||||
- "8.3"
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- macos-13
|
||||
- windows-latest
|
||||
- macos-14
|
||||
php: ${{ fromJSON(needs.define-matrix.outputs.php) }}
|
||||
os: ${{ fromJSON(needs.define-matrix.outputs.os) }}
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
@ -139,6 +157,8 @@ jobs:
|
||||
tools: pecl, composer
|
||||
extensions: curl, openssl, mbstring
|
||||
ini-values: memory_limit=-1
|
||||
env:
|
||||
phpts: nts
|
||||
|
||||
- name: "Cache composer packages"
|
||||
id: composer-cache
|
||||
@ -154,13 +174,13 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: downloads
|
||||
key: php-${{ matrix.php }}-dependencies
|
||||
key: php-dependencies-${{ matrix.os }}
|
||||
|
||||
- name: "Install Dependencies"
|
||||
run: composer update -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
|
||||
|
||||
- name: "Run Build Tests (doctor)"
|
||||
run: bin/spc doctor --auto-fix
|
||||
run: bin/spc doctor --auto-fix --debug
|
||||
|
||||
- name: "Prepare UPX for Windows"
|
||||
if: matrix.os == 'windows-latest'
|
||||
@ -175,19 +195,11 @@ jobs:
|
||||
echo "UPX_CMD=$(php src/globals/test-extensions.php upx)" >> $GITHUB_ENV
|
||||
|
||||
- name: "Run Build Tests (download)"
|
||||
run: |
|
||||
bin/spc download --for-extensions="$(php src/globals/test-extensions.php extensions)" --for-libs="$(php src/globals/test-extensions.php libs)" --with-php=${{ matrix.php }} --ignore-cache-sources=php-src --debug --retry=5 --shallow-clone
|
||||
run: php src/globals/test-extensions.php download_cmd ${{ matrix.os }} ${{ matrix.php }}
|
||||
|
||||
- name: "Download pre-built libraries for pkg-config"
|
||||
- name: "Run Build Tests (build)"
|
||||
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: |
|
||||
bin/spc del-download pkg-config
|
||||
bin/spc download pkg-config --prefer-pre-built --debug
|
||||
|
||||
- name: "Run Build Tests (build, *nix)"
|
||||
if: matrix.os != 'windows-latest'
|
||||
run: bin/spc build "$(php src/globals/test-extensions.php extensions)" $(php src/globals/test-extensions.php zts) $(php src/globals/test-extensions.php no_strip) $UPX_CMD --with-libs="$(php src/globals/test-extensions.php libs)" --build-cli --build-micro --build-fpm --debug
|
||||
|
||||
- name: "Run Build Tests (build, windows)"
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: bin/spc build "$(php src/globals/test-extensions.php extensions)" $(php src/globals/test-extensions.php zts) $(php src/globals/test-extensions.php no_strip) $env:UPX_CMD --with-libs="$(php src/globals/test-extensions.php libs)" --build-cli --build-micro --debug
|
||||
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: 不支持
|
||||
|
||||
| PHP Version | Status | Comment |
|
||||
|-------------|--------------------|------------------------------|
|
||||
| 7.2 | :x: | |
|
||||
| 7.3 | :warning: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
|
||||
| 7.4 | :warning: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
|
||||
| 8.0 | :heavy_check_mark: | PHP 官方已停止 8.0 的维护 |
|
||||
| 8.1 | :heavy_check_mark: | PHP 官方仅对 8.1 提供安全更新 |
|
||||
| 8.2 | :heavy_check_mark: | |
|
||||
| 8.3 | :heavy_check_mark: | |
|
||||
| 8.4 | :x: | WIP |
|
||||
| PHP Version | Status | Comment |
|
||||
|-------------|--------------------|----------------------------------------------|
|
||||
| 7.2 | :x: | |
|
||||
| 7.3 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
|
||||
| 7.4 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
|
||||
| 8.0 | :warning: | PHP 官方已停止 8.0 的维护,我们不再处理 8.0 相关的 backport 支持 |
|
||||
| 8.1 | :heavy_check_mark: | PHP 官方仅对 8.1 提供安全更新 |
|
||||
| 8.2 | :heavy_check_mark: | |
|
||||
| 8.3 | :heavy_check_mark: | |
|
||||
| 8.4 | :heavy_check_mark: | |
|
||||
|
||||
> 这个表格的支持状态是 static-php-cli 对构建对应版本的支持情况,不是 PHP 官方对该版本的支持情况。
|
||||
|
||||
### 支持的扩展
|
||||
|
||||
|
||||
25
README.md
25
README.md
@ -89,16 +89,19 @@ Currently supported PHP versions for compilation:
|
||||
>
|
||||
> :x: not supported
|
||||
|
||||
| PHP Version | Status | Comment |
|
||||
|-------------|--------------------|---------------------------------------------------|
|
||||
| 7.2 | :x: | |
|
||||
| 7.3 | :warning: | phpmicro and some extensions not supported on 7.x |
|
||||
| 7.4 | :warning: | phpmicro and some extensions not supported on 7.x |
|
||||
| 8.0 | :heavy_check_mark: | PHP official has stopped maintenance of 8.0 |
|
||||
| 8.1 | :heavy_check_mark: | PHP official has security fixes only |
|
||||
| 8.2 | :heavy_check_mark: | |
|
||||
| 8.3 | :heavy_check_mark: | |
|
||||
| 8.4 | :x: | WIP |
|
||||
| PHP Version | Status | Comment |
|
||||
|-------------|--------------------|----------------------------------------------------------------------------------------------------|
|
||||
| 7.2 | :x: | |
|
||||
| 7.3 | :x: | phpmicro and some extensions not supported on 7.x |
|
||||
| 7.4 | :x: | phpmicro and some extensions not supported on 7.x |
|
||||
| 8.0 | :warning: | PHP official has stopped maintenance of 8.0, we no longer provide backport support for version 8.0 |
|
||||
| 8.1 | :heavy_check_mark: | PHP official has security fixes only |
|
||||
| 8.2 | :heavy_check_mark: | |
|
||||
| 8.3 | :heavy_check_mark: | |
|
||||
| 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
|
||||
|
||||
@ -142,7 +145,7 @@ curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-m
|
||||
# macOS aarch64 (Apple)
|
||||
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-aarch64
|
||||
# Windows (x86_64, win10 build 17063 or later)
|
||||
curl.exe -fsSL -o spc.exehttps://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe
|
||||
curl.exe -fsSL -o spc.exe https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe
|
||||
|
||||
# Add execute perm (Linux and macOS only)
|
||||
chmod +x ./spc
|
||||
|
||||
@ -51,10 +51,10 @@ if ($action -eq 'add-path') {
|
||||
}
|
||||
|
||||
# get php 8.1 specific version
|
||||
$API = (Invoke-WebRequest -Uri "https://www.php.net/releases/index.php?json&version=8.1") | ConvertFrom-Json
|
||||
$API = (Invoke-WebRequest -Uri "https://www.php.net/releases/index.php?json&version=8.3") | ConvertFrom-Json
|
||||
|
||||
# php windows download
|
||||
$PHPRuntimeUrl = "https://windows.php.net/downloads/releases/php-" + $API.version + "-Win32-vs16-x64.zip"
|
||||
$PHPRuntimeUrl = "https://windows.php.net/downloads/releases/php-" + $API.version + "-nts-Win32-vs16-x64.zip"
|
||||
$ComposerUrl = "https://getcomposer.org/download/latest-stable/composer.phar"
|
||||
|
||||
# create dir
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
"require": {
|
||||
"php": ">= 8.1",
|
||||
"ext-mbstring": "*",
|
||||
"ext-zlib": "*",
|
||||
"laravel/prompts": "^0.1.12",
|
||||
"symfony/console": "^5.4 || ^6 || ^7",
|
||||
"zhamao/logger": "^1.0"
|
||||
@ -19,10 +20,10 @@
|
||||
"captainhook/captainhook-phar": "^5.23",
|
||||
"captainhook/hook-installer": "^1.0",
|
||||
"friendsofphp/php-cs-fixer": "^3.25",
|
||||
"humbug/box": "^4.5",
|
||||
"humbug/box": "^4.5.0 || ^4.6.0",
|
||||
"nunomaduro/collision": "^7.8",
|
||||
"phpstan/phpstan": "^1.10",
|
||||
"phpunit/phpunit": "^10.3 || ^9"
|
||||
"phpunit/phpunit": "^10.3 || ^9.5"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
||||
491
composer.lock
generated
491
composer.lock
generated
File diff suppressed because it is too large
Load Diff
134
config/env.ini
Normal file
134
config/env.ini
Normal file
@ -0,0 +1,134 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; static-php-cli (spc) env configuration
|
||||
;
|
||||
; This file is used to set default env vars for static-php-cli build.
|
||||
; As dynamic build process, some of these vars can be overwritten by CLI options.
|
||||
; And you can also overwrite these vars by setting them in your shell environment.
|
||||
;
|
||||
; We need to use some pre-defined internal env vars, like `BUILD_ROOT_PATH`, `DOWNLOAD_PATH`, etc.
|
||||
; Please note that these vars cannot be defined in this file, they are only be defined before static-php-cli running.
|
||||
; Here's a list of these pre-defined internal env vars, these vars are only be defined in the static-php-cli build process if not set in the shell environment:
|
||||
;
|
||||
; BUILD_ROOT_PATH: the root path of the build process. (default: `$(pwd)/buildroot`)
|
||||
; BUILD_INCLUDE_PATH: the path of the include files. (default: `$BUILD_ROOT_PATH/include`)
|
||||
; BUILD_LIB_PATH: the path of the lib files. (default: `$BUILD_ROOT_PATH/lib`)
|
||||
; BUILD_BIN_PATH: the path of the bin files. (default: `$BUILD_ROOT_PATH/bin`)
|
||||
; PKG_ROOT_PATH: the root path of the package files. (default: `$(pwd)/pkgroot`)
|
||||
; SOURCE_PATH: the path of the source files. (default: `$(pwd)/source`)
|
||||
; DOWNLOAD_PATH: the path of the download files. (default: `$(pwd)/downloads`)
|
||||
; CPU_COUNT: the count of the CPU cores. (default: `$(nproc)`)
|
||||
; GNU_ARCH: the GNU arch of the current system. (default: `$(uname -m)`, e.g. `x86_64`, `aarch64`)
|
||||
; MAC_ARCH: the MAC arch of the current system. (default: `$(uname -m)`, e.g. `x86_64`, `arm64`)
|
||||
;
|
||||
; Here's a list of env vars, these value cannot be changed anywhere:
|
||||
;
|
||||
; WORKING_DIR: the working directory of the build process. (default: `$(pwd)`)
|
||||
; ROOT_DIR: the root directory of static-php-cli. (default: `/path/to/static-php-cli`, when running in phar or micro mode: `phar://path/to/spc.phar`)
|
||||
;
|
||||
; * These vars are only be defined in Unix (macOS, Linux, FreeBSD)Builder *
|
||||
; PATH: static-php-cli will add `$BUILD_BIN_PATH` to PATH.
|
||||
; PKG_CONFIG: static-php-cli will set `$BUILD_BIN_PATH/pkg-config` to PKG_CONFIG.
|
||||
; PKG_CONFIG_PATH: static-php-cli will set `$BUILD_LIB_PATH/pkgconfig` to PKG_CONFIG_PATH.
|
||||
; SPC_PHP_DEFAULT_OPTIMIZE_CFLAGS: the default optimization CFLAGS for compiling php. (if --no-strip option is set: `-g -O0`, else: `-g -Os`)
|
||||
;
|
||||
; * These vars are only be defined in LinuxBuilder *
|
||||
; SPC_LINUX_DEFAULT_CC: the default compiler for linux. (For alpine linux: `gcc`, default: `$GNU_ARCH-linux-musl-gcc`)
|
||||
; SPC_LINUX_DEFAULT_CXX: the default c++ compiler for linux. (For alpine linux: `g++`, default: `$GNU_ARCH-linux-musl-g++`)
|
||||
; SPC_LINUX_DEFAULT_AR: the default archiver for linux. (For alpine linux: `ar`, default: `$GNU_ARCH-linux-musl-ar`)
|
||||
; SPC_PHP_DEFAULT_LD_LIBRARY_PATH_CMD: the default LD_LIBRARY_PATH for php. (linux: `LD_LIBRARY_PATH=/usr/local/musl/$GNU_ARCH-linux-musl/lib`, default: empty)
|
||||
|
||||
|
||||
[global]
|
||||
; Build concurrency for make -jN, default is CPU_COUNT, this value are used in every libs.
|
||||
SPC_CONCURRENCY=${CPU_COUNT}
|
||||
; Ignore PHP version check before building some extensions
|
||||
SPC_SKIP_PHP_VERSION_CHECK="no"
|
||||
; Ignore some check item for bin/spc doctor command, comma separated (e.g. SPC_SKIP_DOCTOR_CHECK_ITEMS="if homebrew has installed")
|
||||
SPC_SKIP_DOCTOR_CHECK_ITEMS=""
|
||||
|
||||
[windows]
|
||||
; php-sdk-binary-tools path
|
||||
PHP_SDK_PATH="${WORKING_DIR}\php-sdk-binary-tools"
|
||||
; upx executable path
|
||||
UPX_EXEC="${PKG_ROOT_PATH}\bin\upx.exe"
|
||||
; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches
|
||||
SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,cli_static
|
||||
|
||||
[linux]
|
||||
; include PATH for musl libc.
|
||||
SPC_NO_MUSL_PATH=no
|
||||
; compiler environments
|
||||
CC=${SPC_LINUX_DEFAULT_CC}
|
||||
CXX=${SPC_LINUX_DEFAULT_CXX}
|
||||
AR=${SPC_LINUX_DEFAULT_AR}
|
||||
LD=ld.gold
|
||||
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
|
||||
SPC_DEFAULT_C_FLAGS=
|
||||
SPC_DEFAULT_CXX_FLAGS=
|
||||
; extra libs for building php executable, used in `make` command for building php (this value may changed by extension build process, space separated)
|
||||
SPC_EXTRA_LIBS=
|
||||
; upx executable path
|
||||
UPX_EXEC=${PKG_ROOT_PATH}/bin/upx
|
||||
; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches
|
||||
SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream
|
||||
|
||||
; *** default build command for building php ***
|
||||
; buildconf command
|
||||
SPC_CMD_PREFIX_PHP_BUILDCONF="./buildconf --force"
|
||||
; configure command
|
||||
SPC_CMD_PREFIX_PHP_CONFIGURE="${SPC_PHP_DEFAULT_LD_LIBRARY_PATH_CMD} ./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-cgi --disable-phpdbg"
|
||||
; make command
|
||||
SPC_CMD_PREFIX_PHP_MAKE="make -j${CPU_COUNT}"
|
||||
|
||||
; *** default build vars for building php ***
|
||||
; CFLAGS for configuring php
|
||||
SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS="${SPC_DEFAULT_C_FLAGS}"
|
||||
; CPPFLAGS for configuring php
|
||||
SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS="-I${BUILD_INCLUDE_PATH}"
|
||||
; LDFLAGS for configuring php
|
||||
SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS="-L${BUILD_LIB_PATH}"
|
||||
; LIBS for configuring php
|
||||
SPC_CMD_VAR_PHP_CONFIGURE_LIBS="-ldl -lpthread -lm"
|
||||
; EXTRA_CFLAGS for `make` php
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="${SPC_PHP_DEFAULT_OPTIMIZE_CFLAGS} -fno-ident -fPIE"
|
||||
; EXTRA_LIBS for `make` php
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS=""
|
||||
; EXTRA_LDFLAGS_PROGRAM for `make` php
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-all-static -Wl,-O1 -pie"
|
||||
|
||||
[macos]
|
||||
; compiler environments
|
||||
CC=clang
|
||||
CXX=clang++
|
||||
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
|
||||
SPC_DEFAULT_C_FLAGS="--target=${MAC_ARCH}-apple-darwin"
|
||||
SPC_DEFAULT_CXX_FLAGS="--target=${MAC_ARCH}-apple-darwin"
|
||||
; extra libs for building php executable, used in `make` command for building php (this value may changed by extension build process, space separated)
|
||||
SPC_EXTRA_LIBS=
|
||||
; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches
|
||||
SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,macos_iconv
|
||||
|
||||
; *** default build command for building php ***
|
||||
; buildconf command
|
||||
SPC_CMD_PREFIX_PHP_BUILDCONF="./buildconf --force"
|
||||
; configure command
|
||||
SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-cgi --disable-phpdbg"
|
||||
; make command
|
||||
SPC_CMD_PREFIX_PHP_MAKE="make -j${CPU_COUNT}"
|
||||
|
||||
; *** default build vars for building php ***
|
||||
; CFLAGS for configuring php
|
||||
SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS="${SPC_DEFAULT_C_FLAGS} -Werror=unknown-warning-option"
|
||||
; CPPFLAGS for configuring php
|
||||
SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS="-I${BUILD_INCLUDE_PATH}"
|
||||
; LDFLAGS for configuring php
|
||||
SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS="-L${BUILD_LIB_PATH}"
|
||||
; EXTRA_CFLAGS for `make` php
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="${SPC_PHP_DEFAULT_OPTIMIZE_CFLAGS}"
|
||||
; EXTRA_LIBS for `make` php
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-lresolv"
|
||||
|
||||
[freebsd]
|
||||
; compiler environments
|
||||
CC=clang
|
||||
CXX=clang++
|
||||
@ -199,6 +199,19 @@
|
||||
"gmssl"
|
||||
]
|
||||
},
|
||||
"grpc": {
|
||||
"support": {
|
||||
"Windows": "wip",
|
||||
"BSD": "wip"
|
||||
},
|
||||
"type": "external",
|
||||
"source": "grpc",
|
||||
"arg-type-unix": "custom",
|
||||
"cpp-extension": true,
|
||||
"lib-depends": [
|
||||
"grpc"
|
||||
]
|
||||
},
|
||||
"iconv": {
|
||||
"support": {
|
||||
"BSD": "wip"
|
||||
@ -242,7 +255,8 @@
|
||||
"BSD": "wip"
|
||||
},
|
||||
"notes": true,
|
||||
"type": "builtin",
|
||||
"type": "external",
|
||||
"source": "ext-imap",
|
||||
"arg-type": "custom",
|
||||
"lib-depends": [
|
||||
"imap"
|
||||
@ -510,7 +524,7 @@
|
||||
},
|
||||
"notes": true,
|
||||
"type": "builtin",
|
||||
"arg-type": "with-prefix",
|
||||
"arg-type": "custom",
|
||||
"lib-depends": [
|
||||
"postgresql"
|
||||
]
|
||||
|
||||
@ -139,6 +139,20 @@
|
||||
"Security"
|
||||
]
|
||||
},
|
||||
"grpc": {
|
||||
"source": "grpc",
|
||||
"static-libs-unix": [
|
||||
"libgrpc.a",
|
||||
"libcares.a"
|
||||
],
|
||||
"lib-depends": [
|
||||
"zlib",
|
||||
"openssl"
|
||||
],
|
||||
"frameworks": [
|
||||
"CoreFoundation"
|
||||
]
|
||||
},
|
||||
"icu": {
|
||||
"source": "icu",
|
||||
"cpp-library": true,
|
||||
@ -654,7 +668,7 @@
|
||||
"liblzma.a"
|
||||
],
|
||||
"static-libs-windows": [
|
||||
"liblzma.lib",
|
||||
"lzma.lib",
|
||||
"liblzma_a.lib"
|
||||
],
|
||||
"headers-unix": [
|
||||
|
||||
@ -36,9 +36,13 @@
|
||||
}
|
||||
},
|
||||
"bzip2": {
|
||||
"type": "filelist",
|
||||
"url": "https://sourceware.org/pub/bzip2/",
|
||||
"regex": "/href=\"(?<file>bzip2-(?<version>[^\"]+)\\.tar\\.gz)\"/",
|
||||
"alt": {
|
||||
"type": "filelist",
|
||||
"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,
|
||||
"license": {
|
||||
"type": "text",
|
||||
@ -119,6 +123,18 @@
|
||||
"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": {
|
||||
"type": "url",
|
||||
"url": "https://pecl.php.net/get/memcache",
|
||||
@ -228,6 +244,16 @@
|
||||
"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": {
|
||||
"type": "ghrel",
|
||||
"repo": "unicode-org/icu",
|
||||
@ -530,7 +556,7 @@
|
||||
"micro": {
|
||||
"type": "git",
|
||||
"path": "php-src/sapi/micro",
|
||||
"rev": "master",
|
||||
"rev": "84beta",
|
||||
"url": "https://github.com/static-php/phpmicro",
|
||||
"license": {
|
||||
"type": "file",
|
||||
@ -691,10 +717,10 @@
|
||||
}
|
||||
},
|
||||
"redis": {
|
||||
"type": "git",
|
||||
"type": "url",
|
||||
"url": "https://pecl.php.net/get/redis",
|
||||
"path": "php-src/ext/redis",
|
||||
"rev": "release/6.0.2",
|
||||
"url": "https://github.com/phpredis/phpredis",
|
||||
"filename": "redis.tgz",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": [
|
||||
@ -743,13 +769,18 @@
|
||||
}
|
||||
},
|
||||
"swoole": {
|
||||
"type": "ghtar",
|
||||
"path": "php-src/ext/swoole",
|
||||
"repo": "swoole/swoole-src",
|
||||
"prefer-stable": true,
|
||||
"type": "git",
|
||||
"rev": "master",
|
||||
"url": "https://github.com/swoole/swoole-src.git",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
},
|
||||
"alt": {
|
||||
"type": "ghtar",
|
||||
"repo": "swoole/swoole-src",
|
||||
"prefer-stable": true
|
||||
}
|
||||
},
|
||||
"swow": {
|
||||
|
||||
@ -2,17 +2,29 @@
|
||||
<div>
|
||||
<h2>{{ I18N[lang].selectedSystem }}</h2>
|
||||
<div class="option-line">
|
||||
<span v-for="(item, index) in osList" :key="index" style="margin-right: 4px">
|
||||
<span v-for="(item, index) in osList" :key="index" style="margin-right: 8px">
|
||||
<input type="radio" :id="'os-' + item.os" :value="item.os" :disabled="item.disabled === true" v-model="selectedSystem" />
|
||||
<label :for="'os-' + item.os">{{ item.label }}</label>
|
||||
</span>
|
||||
</div>
|
||||
<div class="option-line">
|
||||
<select v-model="selectedArch">
|
||||
<option value="x86_64">x86_64</option>
|
||||
<option value="aarch64" :disabled="selectedSystem === 'windows'">aarch64</option>
|
||||
</select>
|
||||
</div>
|
||||
<h2>{{ I18N[lang].selectExt }}{{ checkedExts.length > 0 ? (' (' + checkedExts.length + ')') : '' }}</h2>
|
||||
<div class="box">
|
||||
<div v-for="(item, index) in ext" class="ext-item">
|
||||
<span v-if="isSupported(index, selectedSystem)">
|
||||
<input type="checkbox" :id="index" :value="index" v-model="checkedExts" :disabled="extDisableList.indexOf(index) !== -1">
|
||||
<label :for="index">{{ index }}</label>
|
||||
<input class="input" v-model="filterText" placeholder="Highlight search..." />
|
||||
<br>
|
||||
<div v-for="item in extFilter" class="ext-item">
|
||||
<span>
|
||||
<input type="checkbox" :id="item" :value="item" v-model="checkedExts" :disabled="extDisableList.indexOf(item) !== -1">
|
||||
<label :for="item">
|
||||
<span>{{ highlightItem(item, 0) }}</span>
|
||||
<span style="color: orangered; font-weight: bolder">{{ highlightItem(item, 1) }}</span>
|
||||
<span>{{ highlightItem(item, 2) }}</span>
|
||||
</label>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
@ -20,7 +32,7 @@
|
||||
<div class="my-btn" v-if="selectedSystem !== 'windows'" @click="selectCommon">{{ I18N[lang].selectCommon }}</div>
|
||||
<div class="my-btn" @click="checkedExts = []">{{ I18N[lang].selectNone }}</div>
|
||||
|
||||
<details class="details custom-block">
|
||||
<details class="details custom-block" open>
|
||||
<summary>{{ I18N[lang].buildLibs }}{{ checkedLibs.length > 0 ? (' (' + checkedLibs.length + ')') : '' }}</summary>
|
||||
<div class="box">
|
||||
<div v-for="(item, index) in libContain" class="ext-item">
|
||||
@ -135,24 +147,33 @@
|
||||
<div class="warning custom-block">
|
||||
<p class="custom-block-title">WARNING</p>
|
||||
<p>{{ I18N[lang].windowsDownSPCWarning }}</p>
|
||||
<a href="https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe" target="_blank">https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="downloadByExt" class="command-container">
|
||||
<b>{{ I18N[lang].downloadExtOnlyCommand }}</b>
|
||||
<div class="command-preview">{{ spcCommand }} download --with-php={{ selectedPhpVersion }} --for-extensions "{{ extList }}"{{ preBuilt ? ' --prefer-pre-built' : '' }}{{ debug ? ' --debug' : '' }}</div>
|
||||
<div id="download-ext-cmd" class="command-preview">
|
||||
{{ downloadExtCommand }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="command-container">
|
||||
<b>{{ I18N[lang].downloadAllCommand }}</b>
|
||||
<div class="command-preview">{{ spcCommand }} download --all --with-php={{ selectedPhpVersion }}{{ preBuilt ? ' --prefer-pre-built' : '' }}{{ debug ? ' --debug' : '' }}</div>
|
||||
<div id="download-all-cmd" class="command-preview">
|
||||
{{ downloadAllCommand }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="command-container" v-if="enableUPX">
|
||||
<b>{{ I18N[lang].downloadUPXCommand }}</b>
|
||||
<div class="command-preview">{{ spcCommand }} install-pkg upx{{ debug ? ' --debug' : '' }}</div>
|
||||
<div id="download-pkg-cmd" class="command-preview">
|
||||
{{ downloadPkgCommand }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="command-container">
|
||||
<b>{{ I18N[lang].compileCommand }}</b>
|
||||
<div class="command-preview">{{ spcCommand }} build {{ buildCommand }} "{{ extList }}"{{ additionalLibs }}{{ debug ? ' --debug' : '' }}{{ zts ? ' --enable-zts' : '' }}{{ enableUPX ? ' --with-upx-pack' : '' }}{{ displayINI }}</div>
|
||||
<div id="build-cmd" class="command-preview">
|
||||
{{ buildCommandString }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -170,6 +191,15 @@ import libData from '../config/lib.json';
|
||||
import { getAllExtLibsByDeps } from './DependencyUtil.js';
|
||||
|
||||
const ext = ref(extData);
|
||||
const extFilter = computed(() => {
|
||||
const ls = [];
|
||||
for (const [name, item] of Object.entries(ext.value)) {
|
||||
if (isSupported(name, selectedSystem.value)) {
|
||||
ls.push(name);
|
||||
}
|
||||
}
|
||||
return ls;
|
||||
});
|
||||
const lib = ref(libData);
|
||||
const libContain = ref([]);
|
||||
|
||||
@ -234,7 +264,7 @@ const I18N = {
|
||||
microUnavailable: 'micro 不支持 PHP 7.4 及更早版本!',
|
||||
windowsSAPIUnavailable: 'Windows 目前不支持 fpm、embed 构建!',
|
||||
useUPX: '是否开启 UPX 压缩(减小二进制体积)',
|
||||
windowsDownSPCWarning: 'Windows 下请手动下载 spc.exe 二进制文件并解压到当前目录!',
|
||||
windowsDownSPCWarning: 'Windows 下请手动下载 spc.exe 二进制文件,解压到当前目录并重命名为 spc.exe!',
|
||||
usePreBuilt: '如果可能,下载预编译的依赖库(减少编译时间)',
|
||||
},
|
||||
en: {
|
||||
@ -268,7 +298,7 @@ const I18N = {
|
||||
microUnavailable: 'Micro does not support PHP 7.4 and earlier versions!',
|
||||
windowsSAPIUnavailable: 'Windows does not support fpm and embed build!',
|
||||
useUPX: 'Enable UPX compression (reduce binary size)',
|
||||
windowsDownSPCWarning: 'Please download the spc.exe binary file manually and extract it to the current directory on Windows!',
|
||||
windowsDownSPCWarning: 'Please download the binary file manually, extract it to the current directory and rename to spc.exe on Windows!',
|
||||
usePreBuilt: 'Download pre-built dependencies if possible (reduce compile time)',
|
||||
}
|
||||
};
|
||||
@ -325,7 +355,7 @@ const libDisableList = ref([]);
|
||||
const checkedTargets = ref(['cli']);
|
||||
|
||||
// chosen env
|
||||
const selectedEnv = ref('native');
|
||||
const selectedEnv = ref('spc');
|
||||
|
||||
// chosen php version
|
||||
const selectedPhpVersion = ref('8.2');
|
||||
@ -348,6 +378,13 @@ const enableUPX = ref(0);
|
||||
const hardcodedINIData = ref('');
|
||||
|
||||
const selectedSystem = ref('linux');
|
||||
|
||||
watch(selectedSystem, () => {
|
||||
if (selectedSystem.value === 'windows') {
|
||||
selectedArch.value = 'x86_64';
|
||||
}
|
||||
});
|
||||
|
||||
const selectedArch = ref('x86_64');
|
||||
|
||||
// spc command string, alt: spc-alpine-docker, spc
|
||||
@ -381,6 +418,25 @@ const displayINI = computed(() => {
|
||||
return ' ' + str.map((x) => '-I "' + x + '"').join(' ');
|
||||
});
|
||||
|
||||
const filterText = ref('');
|
||||
|
||||
const highlightItem = (item, step) => {
|
||||
if (item.includes(filterText.value)) {
|
||||
if (step === 0) {
|
||||
return item.substring(0, item.indexOf(filterText.value));
|
||||
} else if (step === 1) {
|
||||
return filterText.value;
|
||||
} else {
|
||||
return item.substring(item.indexOf(filterText.value) + filterText.value.length);
|
||||
}
|
||||
} else {
|
||||
if (step === 0) {
|
||||
return item;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
const onTargetChange = (event) => {
|
||||
let id;
|
||||
if (checkedTargets.value.indexOf('all') !== -1 && event.target.value === 'all') {
|
||||
@ -427,6 +483,22 @@ const calculateExtDepends = (input) => {
|
||||
return Array.from(result);
|
||||
};
|
||||
|
||||
const downloadAllCommand = computed(() => {
|
||||
return `${spcCommand.value} download --all --with-php=${selectedPhpVersion.value}${preBuilt.value ? ' --prefer-pre-built' : ''}${debug.value ? ' --debug' : ''}`;
|
||||
});
|
||||
|
||||
const downloadExtCommand = computed(() => {
|
||||
return `${spcCommand.value} download --with-php=${selectedPhpVersion.value} --for-extensions "${extList.value}"${preBuilt.value ? ' --prefer-pre-built' : ''}${debug.value ? ' --debug' : ''}`;
|
||||
});
|
||||
|
||||
const downloadPkgCommand = computed(() => {
|
||||
return `${spcCommand.value} install-pkg upx${debug.value ? ' --debug' : ''}`;
|
||||
});
|
||||
|
||||
const buildCommandString = computed(() => {
|
||||
return `${spcCommand.value} build ${buildCommand.value} "${extList.value}"${additionalLibs.value}${debug.value ? ' --debug' : ''}${zts.value ? ' --enable-zts' : ''}${enableUPX.value ? ' --with-upx-pack' : ''}${displayINI.value}`;
|
||||
});
|
||||
|
||||
const calculateExtLibDepends = (input) => {
|
||||
const result = new Set();
|
||||
|
||||
@ -539,9 +611,12 @@ h2 {
|
||||
.command-preview {
|
||||
padding: 1.2rem;
|
||||
background: var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
word-break: break-all;
|
||||
font-family: monospace;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.option-line {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
@ -582,12 +657,38 @@ select {
|
||||
background-color: var(--vp-button-alt-active-bg);
|
||||
}
|
||||
.textarea {
|
||||
border: 1px solid var(--vp-button-alt-border);
|
||||
padding: 0 4px;
|
||||
min-width: 300px;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 4px;
|
||||
width: calc(100% - 12px);
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.input {
|
||||
display: block;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 4px;
|
||||
width: 100%;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.command-container {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.modal-button {
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
border-color: var(--vp-button-alt-border);
|
||||
color: var(--vp-button-alt-text);
|
||||
background-color: var(--vp-button-alt-bg);
|
||||
}
|
||||
.modal-button:hover {
|
||||
border-color: var(--vp-button-alt-hover-border);
|
||||
color: var(--vp-button-alt-hover-text);
|
||||
background-color: var(--vp-button-alt-hover-bg)
|
||||
}
|
||||
.modal-button:active {
|
||||
border-color: var(--vp-button-alt-active-border);
|
||||
color: var(--vp-button-alt-active-text);
|
||||
background-color: var(--vp-button-alt-active-bg)
|
||||
}
|
||||
</style>
|
||||
|
||||
79
docs/.vitepress/components/SearchTable.vue
Normal file
79
docs/.vitepress/components/SearchTable.vue
Normal file
@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<div>
|
||||
<header class="DocSearch-SearchBar" style="padding: 0">
|
||||
<form class="DocSearch-Form searchinput">
|
||||
<input class="DocSearch-Input" v-model="filterText" placeholder="Filter name..." @input="doFilter" />
|
||||
</form>
|
||||
</header>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Extension Name</th>
|
||||
<th>Linux</th>
|
||||
<th>macOS</th>
|
||||
<th>FreeBSD</th>
|
||||
<th>Windows</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="item in filterData">
|
||||
<td v-if="!item.notes">{{ item.name }}</td>
|
||||
<td v-else>
|
||||
<a :href="'./extension-notes.html#' + item.name">{{ item.name }}</a>
|
||||
</td>
|
||||
<td>{{ item.linux }}</td>
|
||||
<td>{{ item.macos }}</td>
|
||||
<td>{{ item.freebsd }}</td>
|
||||
<td>{{ item.windows }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div v-if="filterData.length === 0" style="margin: 0 4px 20px 4px; color: var(--vp-c-text-2); font-size: 14px">
|
||||
No result, please try another keyword.
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "SearchTable"
|
||||
}
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import {ref} from "vue";
|
||||
import ext from '../../../config/ext.json';
|
||||
|
||||
// 将 ext 转换为列表,方便后续操作
|
||||
const data = ref([]);
|
||||
for (const [name, item] of Object.entries(ext)) {
|
||||
data.value.push({
|
||||
name,
|
||||
linux: item.support?.Linux === undefined ? 'yes' : (item.support?.Linux === 'wip' ? '' : item.support?.Linux),
|
||||
macos: item.support?.Darwin === undefined ? 'yes' : (item.support?.Darwin === 'wip' ? '' : item.support?.Darwin),
|
||||
freebsd: item.support?.BSD === undefined ? 'yes' : (item.support?.BSD === 'wip' ? '' : item.support?.BSD),
|
||||
windows: item.support?.Windows === undefined ? 'yes' : (item.support?.Windows === 'wip' ? '' : item.support?.Windows),
|
||||
notes: item.notes === true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const filterData = ref(data.value);
|
||||
const filterText = ref('');
|
||||
|
||||
const doFilter = () => {
|
||||
if (filterText.value === '') {
|
||||
filterData.value = data.value;
|
||||
return;
|
||||
}
|
||||
filterData.value = data.value.filter(item => {
|
||||
return item.name.toLowerCase().includes(filterText.value.toLowerCase());
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.searchinput {
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
</style>
|
||||
@ -2,7 +2,19 @@
|
||||
|
||||
Here will be some questions that you may encounter easily. There are currently many, but I need to take time to organize them.
|
||||
|
||||
## Can statically compiled PHP install extensions?
|
||||
## What is the path of php.ini ?
|
||||
|
||||
On Linux, macOS and FreeBSD, the path of `php.ini` is `/usr/local/etc/php/php.ini`.
|
||||
On Windows, the path is `C:\windows\php.ini` or the current directory of `php.exe`.
|
||||
The directory where to look for `php.ini` can be changed on *nix using the manual build option `--with-config-file-path`.
|
||||
|
||||
In addition, on Linux, macOS and FreeBSD, `.ini` files present in the `/usr/local/etc/php/conf.d` directory will also be loaded.
|
||||
On Windows, this path is empty by default.
|
||||
The directory can be changed using the manual build option `--with-config-file-scan-dir`.
|
||||
|
||||
`php.ini` will also be searched for in [the other standard locations](https://www.php.net/manual/configuration.file.php).
|
||||
|
||||
## Can statically-compiled PHP install extensions?
|
||||
|
||||
Because the principle of installing extensions in PHP under the traditional architecture is to install new extensions using `.so` type dynamic link libraries,
|
||||
and statically linked PHP compiled using this project cannot **directly** install new extensions using dynamic link libraries.
|
||||
@ -72,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).
|
||||
|
||||
> 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
|
||||
```
|
||||
|
||||
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)
|
||||
|
||||
For `php-sdk-binary-tools`, `strawberry-perl`, and `nasm`,
|
||||
@ -159,7 +165,8 @@ You can try to use the following commands:
|
||||
|
||||
- `--with-clean`: clean up old make files before compiling PHP
|
||||
- `--enable-zts`: Make compiled PHP thread-safe version (default is NTS version)
|
||||
- `--with-libs=XXX,YYY`: Compile the specified dependent library before compiling PHP, and activate some extension optional functions
|
||||
- `--with-libs=XXX,YYY`: Compile the specified dependent library before compiling PHP, and activate some extension optional functions
|
||||
- `--with-config-file-scan-dir=XXX`: Set the directory to scan for `.ini` files after reading `php.ini` (Check [here](../faq/index.html#what-is-the-path-of-php-ini) for default paths)
|
||||
- `-I xxx=yyy`: Hard compile INI options into PHP before compiling (support multiple options, alias is `--with-hardcoded-ini`)
|
||||
- `--with-micro-fake-cli`: When compiling micro, let micro's `PHP_SAPI` pretend to be `cli` (for compatibility with some programs that check `PHP_SAPI`)
|
||||
- `--disable-opcache-jit`: Disable opcache jit (enabled by default)
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
---
|
||||
aside: false
|
||||
---
|
||||
|
||||
<script setup lang="ts">
|
||||
import CliGenerator from "../../.vitepress/components/CliGenerator.vue";
|
||||
</script>
|
||||
|
||||
@ -1,12 +1,23 @@
|
||||
---
|
||||
aside: false
|
||||
---
|
||||
|
||||
# Environment variables
|
||||
|
||||
All environment variables mentioned in the list on this page have default values unless otherwise noted.
|
||||
You can override the default values by setting these environment variables.
|
||||
|
||||
## Environment variables list
|
||||
|
||||
Starting from version 2.3.5, we have centralized the environment variables in the `config/env.ini` file.
|
||||
You can set environment variables by modifying this file.
|
||||
|
||||
We divide the environment variables supported by static-php-cli into three types:
|
||||
|
||||
- Global internal environment variables: declared after static-php-cli starts, you can use `getenv()` to get them internally in static-php-cli, and you can override them before starting static-php-cli.
|
||||
- Fixed environment variables: declared after static-php-cli starts, you can only use `getenv()` to get them, but you cannot override them through shell scripts.
|
||||
- Config file environment variables: declared before static-php-cli build, you can set these environment variables by modifying the `config/env.ini` file or through shell scripts.
|
||||
|
||||
You can read the comments for each parameter in [config/env.ini](https://github.com/crazywhalecc/static-php-cli/blob/main/config/env.ini) to understand its purpose.
|
||||
|
||||
## Custom environment variables
|
||||
|
||||
Generally, you don't need to modify any of the following environment variables as they are already set to optimal values.
|
||||
However, if you have special needs, you can set these environment variables to meet your needs
|
||||
(for example, you need to debug PHP performance under different compilation parameters).
|
||||
@ -22,94 +33,13 @@ bin/spc build mbstring,pcntl --build-cli
|
||||
SPC_CONCURRENCY=4 bin/spc build mbstring,pcntl --build-cli
|
||||
```
|
||||
|
||||
## General environment variables
|
||||
Or, if you need to modify an environment variable for a long time, you can modify the `config/env.ini` file.
|
||||
|
||||
General environment variables can be used by all build targets.
|
||||
`config/env.ini` is divided into three sections, `[global]` is globally effective, `[windows]`, `[macos]`, `[linux]` are only effective for the corresponding operating system.
|
||||
|
||||
| var name | default value | comment |
|
||||
|------------------------------|---------------------------|-------------------------------------------------|
|
||||
| `BUILD_ROOT_PATH` | `{pwd}/buildroot` | The root directory of the build target |
|
||||
| `BUILD_LIB_PATH` | `{pwd}/buildroot/lib` | The root directory of compilation libraries |
|
||||
| `BUILD_INCLUDE_PATH` | `{pwd}/buildroot/include` | Header file directory for compiling libraries |
|
||||
| `BUILD_BIN_PATH` | `{pwd}/buildroot/bin` | Compiled binary file directory |
|
||||
| `PKG_ROOT_PATH` | `{pwd}/pkgroot` | Directory where precompiled tools are installed |
|
||||
| `SOURCE_PATH` | `{pwd}/source` | The source code extract directory |
|
||||
| `DOWNLOAD_PATH` | `{pwd}/downloads` | Downloaded file directory |
|
||||
| `SPC_CONCURRENCY` | Depends on CPU cores | Number of parallel compilations |
|
||||
| `SPC_SKIP_PHP_VERSION_CHECK` | empty | Skip PHP version check when set to `yes` |
|
||||
For example, if you need to modify the `./configure` command for compiling PHP, you can find the `SPC_CMD_PREFIX_PHP_CONFIGURE` environment variable in the `config/env.ini` file, and then modify its value.
|
||||
|
||||
## OS specific variables
|
||||
|
||||
These environment variables are system-specific and will only take effect on a specific OS.
|
||||
|
||||
### Windows
|
||||
|
||||
| var name | default value | comment |
|
||||
|---------------------|-----------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|
|
||||
| `PHP_SDK_PATH` | `{pwd}\php-sdk-binary-tools` | PHP SDK tools path |
|
||||
| `UPX_EXEC` | `$PKG_ROOT_PATH\bin\upx.exe` | UPX compression tool path |
|
||||
| `SPC_MICRO_PATCHES` | `static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,cli_static` | Used phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) |
|
||||
|
||||
### macOS
|
||||
|
||||
| var name | default value | comment |
|
||||
|--------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|
|
||||
| `CC` | `clang` | C Compiler |
|
||||
| `CXX` | `clang++` | C++ Compiler |
|
||||
| `SPC_DEFAULT_C_FLAGS` | `--target=arm64-apple-darwin` or `--target=x86_64-apple-darwin` | Default C flags (not the same as `CFLAGS`) |
|
||||
| `SPC_DEFAULT_CXX_FLAGS` | `--target=arm64-apple-darwin` or `--target=x86_64-apple-darwin` | Default C flags (not the same as `CPPFLAGS`) |
|
||||
| `SPC_CMD_PREFIX_PHP_BUILDCONF` | `./buildconf --force` | PHP `buildconf` command prefix |
|
||||
| `SPC_CMD_PREFIX_PHP_CONFIGURE` | `./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-cgi --disable-phpdbg` | PHP `configure` command prefix |
|
||||
| `SPC_CMD_PREFIX_PHP_MAKE` | `make -j$SPC_CONCURRENCY` | PHP `make` command prefix |
|
||||
| `SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS` | `$SPC_DEFAULT_C_FLAGS -Werror=unknown-warning-option` | `CFLAGS` variable of PHP `configure` command |
|
||||
| `SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS` | `-I$BUILD_INCLUDE_PATH` | `CPPFLAGS` variable of PHP `configure` command |
|
||||
| `SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS` | `-L$BUILD_LIB_PATH` | `LDFLAGS` variable of PHP `configure` command |
|
||||
| `SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS` | `-g0 -Os` or `-g -O0` (the latter when using `--no-strip`) | `EXTRA_CFLAGS` variable of PHP `make` command |
|
||||
| `SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS` | `-lresolv` | Extra `EXTRA_LIBS` variables for PHP `make` command |
|
||||
| `SPC_MICRO_PATCHES` | `static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,macos_iconv` | Used phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) |
|
||||
|
||||
### Linux
|
||||
|
||||
| var name | default value | comment |
|
||||
|----------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|
|
||||
| `UPX_EXEC` | `$PKG_ROOT_PATH/bin/upx` | UPX compression tool path |
|
||||
| `GNU_ARCH` | `x86_64` or `aarch64` | CPU architecture |
|
||||
| `CC` | Alpine: `gcc`, Other: `$GNU_ARCH-linux-musl-gcc` | C Compiler |
|
||||
| `CXX` | Alpine: `g++`, Other: `$GNU_ARCH-linux-musl-g++` | C++ Compiler |
|
||||
| `AR` | Alpine: `ar`, Other: `$GNU_ARCH-linux-musl-ar` | Static library tools |
|
||||
| `LD` | `ld.gold` | Linker |
|
||||
| `PATH` | `/usr/local/musl/bin:/usr/local/musl/$GNU_ARCH-linux-musl/bin:$PATH` | System PATH |
|
||||
| `SPC_DEFAULT_C_FLAGS` | empty | Default C flags |
|
||||
| `SPC_DEFAULT_CXX_FLAGS` | empty | Default C++ flags |
|
||||
| `SPC_CMD_PREFIX_PHP_BUILDCONF` | `./buildconf --force` | PHP `buildconf` command prefix |
|
||||
| `SPC_CMD_PREFIX_PHP_CONFIGURE` | `LD_LIBRARY_PATH={ld_lib_path} ./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-cgi --disable-phpdbg` | PHP `configure` command prefix |
|
||||
| `SPC_CMD_PREFIX_PHP_MAKE` | `make -j$SPC_CONCURRENCY` | PHP `make` command prefix |
|
||||
| `SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS` | `$SPC_DEFAULT_C_FLAGS` | `CFLAGS` variable of PHP `configure` command |
|
||||
| `SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS` | `-I$BUILD_INCLUDE_PATH` | `CPPFLAGS` variable of PHP `configure` command |
|
||||
| `SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS` | `-L$BUILD_LIB_PATH` | `LDFLAGS` variable of PHP `configure` command |
|
||||
| `SPC_CMD_VAR_PHP_CONFIGURE_LIBS` | `-ldl -lpthread` | `LIBS` variable of PHP `configure` command |
|
||||
| `SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS` | `-g0 -Os -fno-ident -fPIE` or `-g -O0 -fno-ident -fPIE` (the latter when using `--no-strip`) | `EXTRA_CFLAGS` variable of PHP `make` command |
|
||||
| `SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS` | empty | Extra `EXTRA_LIBS` variables for PHP `make` command |
|
||||
| `SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM` | `-all-static` (when using `clang`: `-Xcompiler -fuse-ld=lld -all-static`) | Additional `LDFLAGS` variable for `make` command |
|
||||
| `SPC_NO_MUSL_PATH` | empty | Whether to not insert the PATH of the musl toolchain (not inserted when the value is `yes`) |
|
||||
| `SPC_MICRO_PATCHES` | `static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream` | Used phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) |
|
||||
> `{ld_lib_path}` value is `/usr/local/musl/$GNU_ARCH-linux-musl/lib`。
|
||||
|
||||
### FreeBSD
|
||||
|
||||
Due to the small number of users of the FreeBSD system, we do not provide environment variables for the FreeBSD system for the time being.
|
||||
|
||||
### Unix
|
||||
|
||||
For Unix systems such as macOS, Linux, FreeBSD, etc., the following environment variables are common.
|
||||
|
||||
| var name | default value | comment |
|
||||
|-------------------|------------------------------|----------------------------|
|
||||
| `PATH` | `$BUILD_BIN_PATH:$PATH` | System PATH |
|
||||
| `PKG_CONFIG_PATH` | `$BUILD_LIB_PATH/pkgconfig` | pkg-config search path |
|
||||
| `PKG_CONFIG` | `$BUILD_BIN_PATH/pkg-config` | pkg-config executable path |
|
||||
|
||||
## Library Environment variables (Unix only)
|
||||
## Library environment variables (Unix only)
|
||||
|
||||
Starting from 2.2.0, static-php-cli supports custom environment variables for all compilation dependent library commands of macOS, Linux, FreeBSD and other Unix systems.
|
||||
|
||||
|
||||
@ -46,7 +46,7 @@ This extension contains an implementation of the coroutine environment for `pdo_
|
||||
|
||||
## swow
|
||||
|
||||
1. Only PHP version >= 8.0 is supported.
|
||||
1. Only PHP 8.0 ~ 8.4 is supported.
|
||||
|
||||
## imap
|
||||
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
<script setup>
|
||||
import SearchTable from "../../.vitepress/components/SearchTable.vue";
|
||||
</script>
|
||||
|
||||
# Extensions
|
||||
|
||||
> - `yes`: supported
|
||||
@ -5,7 +9,7 @@
|
||||
> - `no` with issue link: confirmed to be unavailable due to issue
|
||||
> - `partial` with issue link: supported but not perfect due to issue
|
||||
|
||||
<!--@include: ../../extensions.md-->
|
||||
<search-table />
|
||||
|
||||
::: tip
|
||||
If an extension you need is missing, you can create a [Feature Request](https://github.com/crazywhalecc/static-php-cli/issues).
|
||||
|
||||
@ -36,7 +36,7 @@ Windows currently only supports the x86_64 architecture, and does not support 32
|
||||
|
||||
## 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.
|
||||
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.
|
||||
|
||||
@ -142,9 +142,9 @@ including php-src and the source code of various dependent libraries.
|
||||
# Download all dependencies
|
||||
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.
|
||||
bin/spc download --all --with-php=8.2
|
||||
bin/spc download --all --with-php=8.3
|
||||
|
||||
# Show download progress bar while downloading (curl)
|
||||
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:
|
||||
|
||||
```shell
|
||||
# switch to 8.3
|
||||
bin/spc switch-php-version 8.3
|
||||
# switch to 8.4
|
||||
bin/spc switch-php-version 8.4
|
||||
# build
|
||||
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
||||
# switch to 8.0
|
||||
bin/spc switch-php-version 8.0
|
||||
# switch to 8.1
|
||||
bin/spc switch-php-version 8.1
|
||||
# build
|
||||
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
||||
```
|
||||
@ -304,6 +304,8 @@ You can try to use the following commands:
|
||||
- `--enable-zts`: Make compiled PHP thread-safe version (default is NTS version)
|
||||
- `--no-strip`: Do not run `strip` after compiling the PHP library to trim the binary file to reduce its size (the macOS binary file without trim can use dynamically linked third-party extensions)
|
||||
- `--with-libs=XXX,YYY`: Compile the specified dependent library before compiling PHP, and activate some extended optional functions (such as libavif of the gd library, etc.)
|
||||
- `--with-config-file-path=XXX`: Set the path in which to look for `php.ini` (Check [here](../faq/index.html#what-is-the-path-of-php-ini) for default paths)
|
||||
- `--with-config-file-scan-dir=XXX`: Set the directory to scan for `.ini` files after reading `php.ini` (Check [here](../faq/index.html#what-is-the-path-of-php-ini) for default paths)
|
||||
- `-I xxx=yyy`: Hard compile INI options into PHP before compiling (support multiple options, alias is `--with-hardcoded-ini`)
|
||||
- `--with-micro-fake-cli`: When compiling micro, let micro's `PHP_SAPI` pretend to be `cli` (for compatibility with some programs that check `PHP_SAPI`)
|
||||
- `--disable-opcache-jit`: Disable opcache jit (enabled by default)
|
||||
@ -551,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 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.
|
||||
|
||||
## 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!
|
||||
```
|
||||
|
||||
@ -2,6 +2,18 @@
|
||||
|
||||
这里将会编写一些你容易遇到的问题。目前有很多,但是我需要花时间来整理一下。
|
||||
|
||||
## php.ini 的路径是什么?
|
||||
|
||||
在 Linux、macOS 和 FreeBSD 上,`php.ini` 的默认路径是 `/usr/local/etc/php/php.ini`。
|
||||
在 Windows 中,路径是 `C:\windows\php.ini` 或 `php.exe` 所在的当前目录。
|
||||
可以在 *nix 系统中使用手动构建选项 `--with-config-file-path` 来更改查找 `php.ini` 的目录。
|
||||
|
||||
此外,在 Linux、macOS 和 FreeBSD 上,`/usr/local/etc/php/conf.d` 目录中的 `*.ini` 文件也会被加载。
|
||||
在 Windows 中,该路径默认为空。
|
||||
可以使用手动构建选项 `--with-config-file-scan-dir` 更改该目录。
|
||||
|
||||
PHP 默认也会从 [其他标准位置](https://www.php.net/manual/zh/configuration.file.php) 中搜索 `php.ini`。
|
||||
|
||||
## 静态编译的 PHP 可以安装扩展吗
|
||||
|
||||
因为传统架构下的 PHP 安装扩展的原理是使用 `.so` 类型的动态链接的库方式安装新扩展,而使用本项目编译的静态链接的 PHP 无法**直接**使用动态链接库安装新扩展。
|
||||
@ -58,4 +70,10 @@ PHP 代码的编译器是完全不同的项目,因此不会考虑额外的情
|
||||
对于 Linux 系统,你可以从 curl 官方网站下载 [cacert.pem](https://curl.se/docs/caextract.html) 文件,也可以使用系统自带的证书文件。
|
||||
有关不同发行版的证书位置,可参考 [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,但是不会明确支持早期版本。
|
||||
|
||||
@ -146,6 +146,7 @@ bin/spc build "openssl" --build-cli --debug
|
||||
- `--with-clean`: 编译 PHP 前先清理旧的 make 产生的文件
|
||||
- `--enable-zts`: 让编译的 PHP 为线程安全版本(默认为 NTS 版本)
|
||||
- `--with-libs=XXX,YYY`: 编译 PHP 前先编译指定的依赖库,激活部分扩展的可选功能
|
||||
- `--with-config-file-scan-dir=XXX`: 读取 `php.ini` 后扫描 `.ini` 文件的目录(在 [这里](../faq/index.html#php-ini-的路径是什么) 查看默认路径)
|
||||
- `-I xxx=yyy`: 编译前将 INI 选项硬编译到 PHP 内(支持多个选项,别名是 `--with-hardcoded-ini`)
|
||||
- `--with-micro-fake-cli`: 在编译 micro 时,让 micro 的 SAPI 伪装为 `cli`(用于兼容一些检查 `PHP_SAPI` 的程序)
|
||||
- `--disable-opcache-jit`: 禁用 opcache jit(默认启用)
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
---
|
||||
aside: false
|
||||
---
|
||||
|
||||
<script setup lang="ts">
|
||||
import CliGenerator from "../../.vitepress/components/CliGenerator.vue";
|
||||
</script>
|
||||
|
||||
@ -1,11 +1,21 @@
|
||||
---
|
||||
aside: false
|
||||
---
|
||||
|
||||
# 环境变量列表
|
||||
# 环境变量
|
||||
|
||||
本页面的环境变量列表中所提到的所有环境变量都具有默认值,除非另有说明。你可以通过设置这些环境变量来覆盖默认值。
|
||||
|
||||
## 环境变量列表
|
||||
|
||||
在 2.3.5 版本之后,我们将环境变量集中到了 `config/env.ini` 文件中,你可以通过修改这个文件来设置环境变量。
|
||||
|
||||
我们将 static-php-cli 支持的环境变量分为三种:
|
||||
|
||||
- 全局内部环境变量:在 static-php-cli 启动后即声明,你可以在 static-php-cli 的内部使用 `getenv()` 来获取他们,也可以在启动 static-php-cli 前覆盖。
|
||||
- 固定环境变量:在 static-php-cli 启动后声明,你仅可使用 `getenv()` 获取,但无法通过 shell 脚本对其覆盖。
|
||||
- 配置文件环境变量:在 static-php-cli 构建前声明,你可以通过修改 `config/env.ini` 文件或通过 shell 脚本来设置这些环境变量。
|
||||
|
||||
你可以阅读 [config/env.ini](https://github.com/crazywhalecc/static-php-cli/blob/main/config/env.ini) 中每项参数的注释来了解其作用(仅限英文版)。
|
||||
|
||||
## 自定义环境变量
|
||||
|
||||
一般情况下,你不需要修改任何以下环境变量,因为它们已经被设置为最佳值。
|
||||
但是,如果你有特殊需求,你可以通过设置这些环境变量来满足你的需求(比如你需要调试不同编译参数下的 PHP 性能表现)。
|
||||
|
||||
@ -20,93 +30,11 @@ bin/spc build mbstring,pcntl --build-cli
|
||||
SPC_CONCURRENCY=4 bin/spc build mbstring,pcntl --build-cli
|
||||
```
|
||||
|
||||
## 通用环境变量
|
||||
或者,如果你需要长期修改某个环境变量,你可以通过修改 `config/env.ini` 文件来实现。
|
||||
|
||||
通用环境变量是所有构建目标都可以使用的环境变量。
|
||||
`config/env.ini` 分为三段,其中 `[global]` 全局有效,`[windows]`、`[macos]`、`[linux]` 仅对应的操作系统有效。
|
||||
|
||||
| var name | default value | comment |
|
||||
|------------------------------|---------------------------|-----------------------------|
|
||||
| `BUILD_ROOT_PATH` | `{pwd}/buildroot` | 编译目标的根目录 |
|
||||
| `BUILD_LIB_PATH` | `{pwd}/buildroot/lib` | 编译依赖库的根目录 |
|
||||
| `BUILD_INCLUDE_PATH` | `{pwd}/buildroot/include` | 编译依赖库的头文件目录 |
|
||||
| `BUILD_BIN_PATH` | `{pwd}/buildroot/bin` | 编译依赖库的二进制文件目录 |
|
||||
| `PKG_ROOT_PATH` | `{pwd}/pkgroot` | 闭源或预编译工具下载后安装的目录 |
|
||||
| `SOURCE_PATH` | `{pwd}/source` | 编译项目的源码解压缩目录 |
|
||||
| `DOWNLOAD_PATH` | `{pwd}/downloads` | 下载的文件存放目录 |
|
||||
| `SPC_CONCURRENCY` | 取决于当前 CPU 核心数量 | 并行编译的数量 |
|
||||
| `SPC_SKIP_PHP_VERSION_CHECK` | 空 | 设置为 `yes` 时,跳过扩展对 PHP 版本的检查 |
|
||||
|
||||
## 系统特定变量
|
||||
|
||||
这些环境变量是特定于系统的,它们只在特定的系统上才会生效。
|
||||
|
||||
### Windows
|
||||
|
||||
| var name | default value | comment |
|
||||
|---------------------|-----------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|
|
||||
| `PHP_SDK_PATH` | `{pwd}\php-sdk-binary-tools` | PHP SDK 工具的安装目录 |
|
||||
| `UPX_EXEC` | `$PKG_ROOT_PATH\bin\upx.exe` | UPX 压缩工具的路径 |
|
||||
| `SPC_MICRO_PATCHES` | `static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,cli_static` | 使用的 phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) |
|
||||
|
||||
### macOS
|
||||
|
||||
| var name | default value | comment |
|
||||
|--------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|
|
||||
| `CC` | `clang` | C 编译器 |
|
||||
| `CXX` | `clang++` | C++ 编译器 |
|
||||
| `SPC_DEFAULT_C_FLAGS` | `--target=arm64-apple-darwin` 或 `--target=x86_64-apple-darwin` | 默认 C 编译标志(与 `CFLAGS` 不同) |
|
||||
| `SPC_DEFAULT_CXX_FLAGS` | `--target=arm64-apple-darwin` 或 `--target=x86_64-apple-darwin` | 默认 C++ 编译标志(与 `CXXFLAGS` 不同) |
|
||||
| `SPC_CMD_PREFIX_PHP_BUILDCONF` | `./buildconf --force` | 编译 PHP `buildconf` 命令前缀 |
|
||||
| `SPC_CMD_PREFIX_PHP_CONFIGURE` | `./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-cgi --disable-phpdbg` | 编译 PHP `configure` 命令前缀 |
|
||||
| `SPC_CMD_PREFIX_PHP_MAKE` | `make -j$SPC_CONCURRENCY` | 编译 PHP `make` 命令前缀 |
|
||||
| `SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS` | `$SPC_DEFAULT_C_FLAGS -Werror=unknown-warning-option` | PHP `configure` 命令的 `CFLAGS` 变量 |
|
||||
| `SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS` | `-I$BUILD_INCLUDE_PATH` | PHP `configure` 命令的 `CPPFLAGS` 变量 |
|
||||
| `SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS` | `-L$BUILD_LIB_PATH` | PHP `configure` 命令的 `LDFLAGS` 变量 |
|
||||
| `SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS` | `-g0 -Os` 或 `-g -O0`(当使用 `--no-strip` 时为后者) | PHP `make` 命令的 `EXTRA_CFLAGS` 变量 |
|
||||
| `SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS` | `-lresolv` | PHP `make` 命令的额外 `EXTRA_LIBS` 变量 |
|
||||
| `SPC_MICRO_PATCHES` | `static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,macos_iconv` | 使用的 phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) |
|
||||
|
||||
### Linux
|
||||
|
||||
| var name | default value | comment |
|
||||
|----------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|
|
||||
| `UPX_EXEC` | `$PKG_ROOT_PATH/bin/upx` | UPX 压缩工具的路径 |
|
||||
| `GNU_ARCH` | `x86_64` 或 `aarch64` | 当前环境的 CPU 架构 |
|
||||
| `CC` | Alpine: `gcc`, Other: `$GNU_ARCH-linux-musl-gcc` | C 编译器 |
|
||||
| `CXX` | Alpine: `g++`, Other: `$GNU_ARCH-linux-musl-g++` | C++ 编译器 |
|
||||
| `AR` | Alpine: `ar`, Other: `$GNU_ARCH-linux-musl-ar` | 静态库工具 |
|
||||
| `LD` | `ld.gold` | 链接器 |
|
||||
| `PATH` | `/usr/local/musl/bin:/usr/local/musl/$GNU_ARCH-linux-musl/bin:$PATH` | 系统 PATH |
|
||||
| `SPC_DEFAULT_C_FLAGS` | empty | 默认 C 编译标志 |
|
||||
| `SPC_DEFAULT_CXX_FLAGS` | empty | 默认 C++ 编译标志 |
|
||||
| `SPC_CMD_PREFIX_PHP_BUILDCONF` | `./buildconf --force` | 编译 PHP `buildconf` 命令前缀 |
|
||||
| `SPC_CMD_PREFIX_PHP_CONFIGURE` | `LD_LIBRARY_PATH={ld_lib_path} ./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-cgi --disable-phpdbg` | 编译 PHP `configure` 命令前缀 |
|
||||
| `SPC_CMD_PREFIX_PHP_MAKE` | `make -j$SPC_CONCURRENCY` | 编译 PHP `make` 命令前缀 |
|
||||
| `SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS` | `$SPC_DEFAULT_C_FLAGS` | PHP `configure` 命令的 `CFLAGS` 变量 |
|
||||
| `SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS` | `-I$BUILD_INCLUDE_PATH` | PHP `configure` 命令的 `CPPFLAGS` 变量 |
|
||||
| `SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS` | `-L$BUILD_LIB_PATH` | PHP `configure` 命令的 `LDFLAGS` 变量 |
|
||||
| `SPC_CMD_VAR_PHP_CONFIGURE_LIBS` | `-ldl -lpthread` | PHP `configure` 命令的 `LIBS` 变量 |
|
||||
| `SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS` | `-g0 -Os -fno-ident -fPIE` 或 `-g -O0 -fno-ident -fPIE`(当使用 `--no-strip` 时为后者) | PHP `make` 命令的 `EXTRA_CFLAGS` 变量 |
|
||||
| `SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS` | empty | PHP `make` 命令的额外 `EXTRA_LIBS` 变量 |
|
||||
| `SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM` | `-all-static`(当使用 `clang` 时:`-Xcompiler -fuse-ld=lld -all-static`) | `make` 命令的额外 `LDFLAGS` 变量(用于编译程序) |
|
||||
| `SPC_NO_MUSL_PATH` | empty | 是否不插入 musl 工具链的 PATH(值为 `yes` 时不插入) |
|
||||
| `SPC_MICRO_PATCHES` | `static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream` | 使用的 phpmicro [patches](https://github.com/easysoft/phpmicro/blob/master/patches/Readme.md) |
|
||||
|
||||
> `{ld_lib_path}` 值为 `/usr/local/musl/$GNU_ARCH-linux-musl/lib`。
|
||||
|
||||
### FreeBSD
|
||||
|
||||
因 FreeBSD 系统的用户较少,我们暂时不提供 FreeBSD 系统的环境变量。
|
||||
|
||||
### Unix
|
||||
|
||||
对于 macOS、Linux、FreeBSD 等 Unix 系统,以下环境变量是通用的。
|
||||
|
||||
| var name | default value | comment |
|
||||
|-------------------|------------------------------|------------------|
|
||||
| `PATH` | `$BUILD_BIN_PATH:$PATH` | 系统 PATH |
|
||||
| `PKG_CONFIG_PATH` | `$BUILD_LIB_PATH/pkgconfig` | pkg-config 的搜索路径 |
|
||||
| `PKG_CONFIG` | `$BUILD_BIN_PATH/pkg-config` | pkg-config 命令路径 |
|
||||
例如,你需要修改编译 PHP 的 `./configure` 命令,你可以在 `config/env.ini` 文件中找到 `SPC_CMD_PREFIX_PHP_CONFIGURE` 环境变量,然后修改其值即可。
|
||||
|
||||
## 编译依赖库的环境变量(仅限 Unix 系统)
|
||||
|
||||
@ -142,6 +70,7 @@ openssl_CFLAGS="-O0"
|
||||
| `ldap_LDFLAGS` | `-L$BUILD_LIB_PATH` |
|
||||
| `openssl_CFLAGS` | Linux: `$SPC_DEFAULT_C_FLAGS`, Other: empty |
|
||||
| others... | empty |
|
||||
|
||||
:::
|
||||
|
||||
下表是支持自定义以上三种变量的依赖库名称列表:
|
||||
@ -165,5 +94,6 @@ openssl_CFLAGS="-O0"
|
||||
::: tip
|
||||
因为给每个库适配自定义环境变量是一项特别繁琐的工作,且大部分情况下你都不需要这些库的自定义环境变量,所以我们目前只支持了部分库的自定义环境变量。
|
||||
|
||||
如果你需要自定义环境变量的库不在上方列表,可以通过 [GitHub Issue](https://github.com/crazywhalecc/static-php-cli/issues) 来提出需求。
|
||||
如果你需要自定义环境变量的库不在上方列表,可以通过 [GitHub Issue](https://github.com/crazywhalecc/static-php-cli/issues)
|
||||
来提出需求。
|
||||
:::
|
||||
|
||||
@ -43,7 +43,7 @@ swoole-hook-sqlite 与 `pdo_sqlite` 扩展冲突。如需使用 Swoole 和 `pdo_
|
||||
|
||||
## swow
|
||||
|
||||
1. swow 仅支持 PHP >= 8.0 版本。
|
||||
1. swow 仅支持 PHP 8.0 ~ 8.4 版本。
|
||||
|
||||
## imap
|
||||
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
<script setup>
|
||||
import SearchTable from "../../.vitepress/components/SearchTable.vue";
|
||||
</script>
|
||||
|
||||
# 扩展列表
|
||||
|
||||
> - `yes`: 已支持
|
||||
@ -5,7 +9,8 @@
|
||||
> - `no` with issue link: 确定不支持或无法支持
|
||||
> - `partial` with issue link: 已支持,但是无法完美工作
|
||||
|
||||
<!--@include: ../../extensions.md-->
|
||||
|
||||
<search-table />
|
||||
|
||||
::: tip
|
||||
如果缺少您需要的扩展,您可以创建 [功能请求](https://github.com/crazywhalecc/static-php-cli/issues)。
|
||||
|
||||
@ -29,6 +29,6 @@ Windows 目前只支持 x86_64 架构,不支持 32 位 x86、不支持 arm64
|
||||
|
||||
## 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 版本,以获得更好的体验。
|
||||
|
||||
@ -141,8 +141,8 @@ bin/spc download --for-extensions="curl,pcntl,xml,mbstring" --prefer-pre-built
|
||||
# 下载所有依赖包
|
||||
bin/spc download --all
|
||||
|
||||
# 下载所有依赖包,并指定下载的 PHP 主版本,可选:7.3,7.4,8.0,8.1,8.2,8.3,也可以使用特定的版本,如 8.3.10。
|
||||
bin/spc download --all --with-php=8.2
|
||||
# 下载所有依赖包,并指定下载的 PHP 主版本,可选:8.1,8.2,8.3,8.4,也可以使用特定的版本,如 8.3.10。
|
||||
bin/spc download --all --with-php=8.3
|
||||
|
||||
# 下载时显示下载进度条(curl)
|
||||
bin/spc download --all --debug
|
||||
@ -236,12 +236,12 @@ bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
||||
如果你想构建多个版本的 PHP,且不想每次都重复构建其他依赖库,可以使用 `switch-php-version` 在编译好一个版本后快速切换至另一个版本并编译:
|
||||
|
||||
```shell
|
||||
# switch to 8.3
|
||||
bin/spc switch-php-version 8.3
|
||||
# switch to 8.4
|
||||
bin/spc switch-php-version 8.4
|
||||
# build
|
||||
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
||||
# switch to 8.0
|
||||
bin/spc switch-php-version 8.0
|
||||
# switch to 8.1
|
||||
bin/spc switch-php-version 8.1
|
||||
# build
|
||||
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
||||
```
|
||||
@ -265,6 +265,8 @@ bin/spc build mysqlnd,pdo_mysql --build-all --debug
|
||||
- `--enable-zts`: 让编译的 PHP 为线程安全版本(默认为 NTS 版本)
|
||||
- `--no-strip`: 编译 PHP 库后不运行 `strip` 裁剪二进制文件缩小体积(不裁剪的 macOS 二进制文件可使用动态链接的第三方扩展)
|
||||
- `--with-libs=XXX,YYY`: 编译 PHP 前先编译指定的依赖库,激活部分扩展的可选功能(例如 gd 库的 libavif 等)
|
||||
- `--with-config-file-path=XXX`: 查找 `php.ini` 的路径(在 [这里](../faq/index.html#php-ini-的路径是什么) 查看默认路径)
|
||||
- `--with-config-file-scan-dir=XXX`: 读取 `php.ini` 后扫描 `.ini` 文件的目录(在 [这里](../faq/index.html#php-ini-的路径是什么) 查看默认路径)
|
||||
- `-I xxx=yyy`: 编译前将 INI 选项硬编译到 PHP 内(支持多个选项,别名是 `--with-hardcoded-ini`)
|
||||
- `--with-micro-fake-cli`: 在编译 micro 时,让 micro 的 SAPI 伪装为 `cli`(用于兼容一些检查 `PHP_SAPI` 的程序)
|
||||
- `--disable-opcache-jit`: 禁用 opcache jit(默认启用)
|
||||
@ -491,3 +493,75 @@ static-php-cli 开放的方法非常多,文档中无法一一列举,但只
|
||||
- 如果你想重新构建一次,但不重新下载源码,可以先 `rm -rf buildroot source` 删除编译目录和源码目录,然后重新构建。
|
||||
- 如果你想更新某个依赖的版本,可以使用 `bin/spc del-download <source-name>` 删除指定的源码,然后使用 `download <source-name>` 重新下载。
|
||||
- 如果你想更新所有依赖的版本,可以使用 `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!
|
||||
```
|
||||
|
||||
@ -4,7 +4,6 @@ parameters:
|
||||
paths:
|
||||
- ./src/
|
||||
ignoreErrors:
|
||||
- '#Constant .* not found#'
|
||||
- '#Unsafe usage of new static#'
|
||||
- '#class Fiber#'
|
||||
- '#Attribute class JetBrains\\PhpStorm\\ArrayShape does not exist#'
|
||||
@ -15,4 +14,4 @@ parameters:
|
||||
analyseAndScan:
|
||||
- ./src/globals/ext-tests/swoole.php
|
||||
- ./src/globals/ext-tests/swoole.phpt
|
||||
- ./src/globals/test-extensions.php
|
||||
- ./src/globals/test-extensions.php
|
||||
|
||||
5
phpunit.xml.dist
Normal file
5
phpunit.xml.dist
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<phpunit
|
||||
bootstrap="tests/bootstrap.php"
|
||||
>
|
||||
</phpunit>
|
||||
@ -22,6 +22,7 @@ use SPC\command\DumpLicenseCommand;
|
||||
use SPC\command\ExtractCommand;
|
||||
use SPC\command\InstallPkgCommand;
|
||||
use SPC\command\MicroCombineCommand;
|
||||
use SPC\command\SPCConfigCommand;
|
||||
use SPC\command\SwitchPhpVersionCommand;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
@ -30,12 +31,15 @@ use Symfony\Component\Console\Application;
|
||||
*/
|
||||
final class ConsoleApplication extends Application
|
||||
{
|
||||
public const VERSION = '2.3.4';
|
||||
public const VERSION = '2.4.2';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('static-php-cli', self::VERSION);
|
||||
|
||||
// Define internal env vars and constants
|
||||
require_once ROOT_DIR . '/src/globals/internal-env.php';
|
||||
|
||||
$this->addCommands(
|
||||
[
|
||||
// Common commands
|
||||
@ -49,6 +53,7 @@ final class ConsoleApplication extends Application
|
||||
new ExtractCommand(),
|
||||
new MicroCombineCommand(),
|
||||
new SwitchPhpVersionCommand(),
|
||||
new SPCConfigCommand(),
|
||||
|
||||
// Dev commands
|
||||
new AllExtCommand(),
|
||||
|
||||
@ -6,6 +6,7 @@ namespace SPC\builder;
|
||||
|
||||
use SPC\exception\ExceptionHandler;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\InterruptException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
@ -24,6 +25,12 @@ abstract class BuilderBase
|
||||
/** @var array<string, Extension> extensions */
|
||||
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) */
|
||||
protected bool $libs_only = false;
|
||||
|
||||
@ -160,7 +167,7 @@ abstract class BuilderBase
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws \ReflectionException
|
||||
* @throws WrongUsageException
|
||||
* @throws \Throwable|WrongUsageException
|
||||
* @internal
|
||||
*/
|
||||
public function proveExts(array $extensions, bool $skip_check_deps = false): void
|
||||
@ -190,6 +197,7 @@ abstract class BuilderBase
|
||||
foreach ($this->exts as $ext) {
|
||||
$ext->checkDependency();
|
||||
}
|
||||
$this->ext_list = $extensions;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -276,7 +284,7 @@ abstract class BuilderBase
|
||||
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 false;
|
||||
@ -407,6 +415,13 @@ abstract class BuilderBase
|
||||
}
|
||||
logger()->debug('Running additional patch script: ' . $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) {
|
||||
logger()->critical('Patch script ' . $patch . ' failed to run.');
|
||||
if ($this->getOption('debug')) {
|
||||
@ -414,34 +429,11 @@ abstract class BuilderBase
|
||||
} else {
|
||||
logger()->critical('Please check with --debug option to see more details.');
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if all libs are downloaded.
|
||||
* If not, throw exception.
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
protected function checkLibsSource(): void
|
||||
{
|
||||
$not_downloaded = [];
|
||||
foreach ($this->libs as $lib) {
|
||||
if (!file_exists($lib->getSourceDir())) {
|
||||
$not_downloaded[] = $lib::NAME;
|
||||
}
|
||||
}
|
||||
if ($not_downloaded !== []) {
|
||||
throw new RuntimeException(
|
||||
'"' . implode(', ', $not_downloaded) .
|
||||
'" totally ' . count($not_downloaded) .
|
||||
' source' . (count($not_downloaded) === 1 ? '' : 's') .
|
||||
' not downloaded, maybe you need to "fetch" ' . (count($not_downloaded) === 1 ? 'it' : 'them') . ' first?'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate micro extension test php code.
|
||||
*/
|
||||
|
||||
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\exception\WrongUsageException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[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!');
|
||||
}
|
||||
}
|
||||
|
||||
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\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
@ -14,6 +16,8 @@ class pgsql extends Extension
|
||||
{
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function patchBeforeConfigure(): bool
|
||||
{
|
||||
@ -24,4 +28,16 @@ class pgsql extends Extension
|
||||
);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
{
|
||||
if ($this->builder->getPHPVersionID() >= 80400) {
|
||||
return '--with-zlib';
|
||||
}
|
||||
return '--with-zlib --with-zlib-dir="' . BUILD_ROOT_PATH . '"';
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,6 +89,11 @@ class BSDBuilder extends UnixBuilderBase
|
||||
$zts_enable = $this->getPHPVersionID() < 80000 ? '--enable-maintainer-zts --disable-zend-signals' : '--enable-zts --disable-zend-signals';
|
||||
$zts = $this->getOption('enable-zts', false) ? $zts_enable : '';
|
||||
|
||||
$config_file_path = $this->getOption('with-config-file-path', false) ?
|
||||
('--with-config-file-path=' . $this->getOption('with-config-file-path') . ' ') : '';
|
||||
$config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ?
|
||||
('--with-config-file-scan-dir=' . $this->getOption('with-config-file-scan-dir') . ' ') : '';
|
||||
|
||||
$enableCli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI;
|
||||
$enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
|
||||
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
|
||||
@ -109,6 +114,8 @@ class BSDBuilder extends UnixBuilderBase
|
||||
($enableFpm ? '--enable-fpm ' : '--disable-fpm ') .
|
||||
($enableEmbed ? '--enable-embed=static ' : '--disable-embed ') .
|
||||
($enableMicro ? '--enable-micro ' : '--disable-micro ') .
|
||||
$config_file_path .
|
||||
$config_file_scan_dir .
|
||||
$json_74 .
|
||||
$zts .
|
||||
$this->makeExtensionArgs()
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||
*
|
||||
|
||||
@ -35,7 +35,7 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
|
||||
GlobalEnvManager::init($this);
|
||||
|
||||
if (str_ends_with(getenv('CC'), 'linux-musl-gcc') && !file_exists("/usr/local/musl/bin/{$arch}-linux-musl-gcc")) {
|
||||
if (str_ends_with(getenv('CC'), 'linux-musl-gcc') && !file_exists("/usr/local/musl/bin/{$arch}-linux-musl-gcc") && (getenv('SPC_NO_MUSL_PATH') !== 'yes')) {
|
||||
throw new WrongUsageException('musl-cross-make not installed, please install it first. (You can use `doctor` command to install it)');
|
||||
}
|
||||
|
||||
@ -134,6 +134,11 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
}
|
||||
$disable_jit = $this->getOption('disable-opcache-jit', false) ? '--disable-opcache-jit ' : '';
|
||||
|
||||
$config_file_path = $this->getOption('with-config-file-path', false) ?
|
||||
('--with-config-file-path=' . $this->getOption('with-config-file-path') . ' ') : '';
|
||||
$config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ?
|
||||
('--with-config-file-scan-dir=' . $this->getOption('with-config-file-scan-dir') . ' ') : '';
|
||||
|
||||
$enable_cli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI;
|
||||
$enable_fpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
|
||||
$enable_micro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
|
||||
@ -163,6 +168,8 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
($enable_fpm ? '--enable-fpm ' : '--disable-fpm ') .
|
||||
($enable_embed ? '--enable-embed=static ' : '--disable-embed ') .
|
||||
($enable_micro ? '--enable-micro=all-static ' : '--disable-micro ') .
|
||||
$config_file_path .
|
||||
$config_file_scan_dir .
|
||||
$disable_jit .
|
||||
$json_74 .
|
||||
$zts .
|
||||
|
||||
@ -6,7 +6,6 @@ namespace SPC\builder\linux;
|
||||
|
||||
use SPC\builder\traits\UnixSystemUtilTrait;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
|
||||
class SystemUtil
|
||||
{
|
||||
@ -83,52 +82,6 @@ class SystemUtil
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public static function getArchCFlags(string $cc, string $arch): string
|
||||
{
|
||||
if (php_uname('m') === $arch) {
|
||||
return '';
|
||||
}
|
||||
return match (static::getCCType($cc)) {
|
||||
'clang' => match ($arch) {
|
||||
'x86_64' => '--target=x86_64-unknown-linux',
|
||||
'arm64', 'aarch64' => '--target=arm64-unknown-linux',
|
||||
default => throw new WrongUsageException('unsupported arch: ' . $arch),
|
||||
},
|
||||
'gcc' => '',
|
||||
default => throw new WrongUsageException('cc compiler ' . $cc . ' is not supported'),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public static function getTuneCFlags(string $arch): array
|
||||
{
|
||||
return match ($arch) {
|
||||
'x86_64', 'arm64', 'aarch64' => [],
|
||||
default => throw new RuntimeException('unsupported arch: ' . $arch),
|
||||
};
|
||||
}
|
||||
|
||||
public static function checkCCFlags(array $flags, string $cc): array
|
||||
{
|
||||
return array_filter($flags, fn ($flag) => static::checkCCFlag($flag, $cc));
|
||||
}
|
||||
|
||||
public static function checkCCFlag(string $flag, string $cc): string
|
||||
{
|
||||
[$ret] = shell()->execWithResult("echo | {$cc} -E -x c - {$flag} 2>/dev/null");
|
||||
if ($ret != 0) {
|
||||
return '';
|
||||
}
|
||||
return $flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* @noinspection PhpUnused
|
||||
|
||||
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
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||
*
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||
*
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||
*
|
||||
|
||||
@ -137,6 +137,11 @@ class MacOSBuilder extends UnixBuilderBase
|
||||
$json_74 = $this->getPHPVersionID() < 80000 ? '--enable-json ' : '';
|
||||
$zts = $this->getOption('enable-zts', false) ? '--enable-zts --disable-zend-signals ' : '';
|
||||
|
||||
$config_file_path = $this->getOption('with-config-file-path', false) ?
|
||||
('--with-config-file-path=' . $this->getOption('with-config-file-path') . ' ') : '';
|
||||
$config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ?
|
||||
('--with-config-file-scan-dir=' . $this->getOption('with-config-file-scan-dir') . ' ') : '';
|
||||
|
||||
$enableCli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI;
|
||||
$enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
|
||||
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
|
||||
@ -164,6 +169,8 @@ class MacOSBuilder extends UnixBuilderBase
|
||||
($enableFpm ? '--enable-fpm ' : '--disable-fpm ') .
|
||||
($enableEmbed ? '--enable-embed=static ' : '--disable-embed ') .
|
||||
($enableMicro ? '--enable-micro ' : '--disable-micro ') .
|
||||
$config_file_path .
|
||||
$config_file_scan_dir .
|
||||
$json_74 .
|
||||
$zts .
|
||||
$this->makeExtensionArgs() . ' ' .
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||
*
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||
*
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 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/mkauths')
|
||||
->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 {
|
||||
shell()
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||
*
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||
*
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||
*
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||
*
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||
*
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||
*
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||
*
|
||||
|
||||
@ -12,6 +12,7 @@ use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\DependencyUtil;
|
||||
use SPC\util\SPCConfigUtil;
|
||||
|
||||
abstract class UnixBuilderBase extends BuilderBase
|
||||
{
|
||||
@ -128,6 +129,7 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
foreach ($this->libs as $lib) {
|
||||
$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-c+ ' .
|
||||
$extra .
|
||||
'--with-included-gettext ' .
|
||||
'--with-libiconv-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');
|
||||
}
|
||||
}
|
||||
@ -21,7 +21,7 @@ class SystemUtil
|
||||
if (!$paths) {
|
||||
$paths = explode(PATH_SEPARATOR, getenv('Path'));
|
||||
if ($include_sdk_bin) {
|
||||
$paths[] = PHP_SDK_PATH . '\bin';
|
||||
$paths[] = getenv('PHP_SDK_PATH') . '\bin';
|
||||
}
|
||||
}
|
||||
foreach ($paths as $path) {
|
||||
|
||||
@ -38,7 +38,7 @@ class WindowsBuilder extends BuilderBase
|
||||
// ---------- set necessary options ----------
|
||||
// set sdk (require visual studio 16 or 17)
|
||||
$vs = SystemUtil::findVisualStudio()['version'];
|
||||
$this->sdk_prefix = PHP_SDK_PATH . "\\phpsdk-{$vs}-x64.bat -t";
|
||||
$this->sdk_prefix = getenv('PHP_SDK_PATH') . "\\phpsdk-{$vs}-x64.bat -t";
|
||||
|
||||
// set zts
|
||||
$this->zts = $this->getOption('enable-zts', false);
|
||||
@ -103,6 +103,9 @@ class WindowsBuilder extends BuilderBase
|
||||
|
||||
$micro_w32 = $this->getOption('enable-micro-win32') ? ' --enable-micro-win32=yes' : '';
|
||||
|
||||
$config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ?
|
||||
('--with-config-file-scan-dir=' . $this->getOption('with-config-file-scan-dir') . ' ') : '';
|
||||
|
||||
cmd()->cd(SOURCE_PATH . '\php-src')
|
||||
->exec(
|
||||
"{$this->sdk_prefix} configure.bat --task-args \"" .
|
||||
@ -114,6 +117,7 @@ class WindowsBuilder extends BuilderBase
|
||||
($enableCli ? '--enable-cli=yes ' : '--enable-cli=no ') .
|
||||
($enableMicro ? ('--enable-micro=yes ' . $micro_logo . $micro_w32) : '--enable-micro=no ') .
|
||||
($enableEmbed ? '--enable-embed=yes ' : '--enable-embed=no ') .
|
||||
$config_file_scan_dir .
|
||||
"{$this->makeExtensionArgs()} " .
|
||||
$zts .
|
||||
'"'
|
||||
@ -244,6 +248,7 @@ class WindowsBuilder extends BuilderBase
|
||||
foreach ($this->libs as $lib) {
|
||||
$lib->calcDependency();
|
||||
}
|
||||
$this->lib_list = $sorted_libraries;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -32,7 +32,7 @@ class xz extends WindowsLibraryBase
|
||||
);
|
||||
|
||||
// copy liblzma.lib to liblzma_a.lib
|
||||
copy(BUILD_LIB_PATH . '/liblzma.lib', BUILD_LIB_PATH . '/liblzma_a.lib');
|
||||
copy(BUILD_LIB_PATH . '/lzma.lib', BUILD_LIB_PATH . '/liblzma_a.lib');
|
||||
// patch lzma.h
|
||||
FileSystem::replaceFileStr(BUILD_INCLUDE_PATH . '/lzma.h', 'defined(LZMA_API_STATIC)', 'defined(_WIN32)');
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ use Psr\Log\LogLevel;
|
||||
use SPC\ConsoleApplication;
|
||||
use SPC\exception\ExceptionHandler;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
@ -94,6 +95,11 @@ abstract class BaseCommand extends Command
|
||||
$question = new ConfirmationQuestion($prompt->label . $case, $prompt->default);
|
||||
return $helper->ask($input, $output, $question);
|
||||
});
|
||||
|
||||
// init GlobalEnv
|
||||
if (!$this instanceof BuildCommand) {
|
||||
GlobalEnvManager::init();
|
||||
}
|
||||
if ($this->shouldExecute()) {
|
||||
try {
|
||||
// show raw argv list for logger()->debug
|
||||
|
||||
@ -22,6 +22,8 @@ class BuildCliCommand extends BuildCommand
|
||||
{
|
||||
public function configure(): void
|
||||
{
|
||||
$isWindows = PHP_OS_FAMILY === 'Windows';
|
||||
|
||||
$this->addArgument('extensions', InputArgument::REQUIRED, 'The extensions will be compiled, comma separated');
|
||||
$this->addOption('with-libs', null, InputOption::VALUE_REQUIRED, 'add additional libraries, comma separated', '');
|
||||
$this->addOption('build-micro', null, null, 'Build micro SAPI');
|
||||
@ -32,6 +34,8 @@ class BuildCliCommand extends BuildCommand
|
||||
$this->addOption('no-strip', null, null, 'build without strip, in order to debug and load external extensions');
|
||||
$this->addOption('enable-zts', null, null, 'enable ZTS support');
|
||||
$this->addOption('disable-opcache-jit', null, null, 'disable opcache jit');
|
||||
$this->addOption('with-config-file-path', null, InputOption::VALUE_REQUIRED, 'Set the path in which to look for php.ini', $isWindows ? null : '/usr/local/etc/php');
|
||||
$this->addOption('with-config-file-scan-dir', null, InputOption::VALUE_REQUIRED, 'Set the directory to scan for .ini files after reading php.ini', $isWindows ? null : '/usr/local/etc/php/conf.d');
|
||||
$this->addOption('with-hardcoded-ini', 'I', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Patch PHP source code, inject hardcoded INI');
|
||||
$this->addOption('with-micro-fake-cli', null, null, 'Let phpmicro\'s PHP_SAPI use "cli" instead of "micro"');
|
||||
$this->addOption('with-suggested-libs', 'L', null, 'Build with suggested libs for selected exts and libs');
|
||||
@ -114,6 +118,9 @@ class BuildCliCommand extends BuildCommand
|
||||
'Strip Binaries' => $builder->getOption('no-strip') ? 'no' : 'yes',
|
||||
'Enable ZTS' => $builder->getOption('enable-zts') ? 'yes' : 'no',
|
||||
];
|
||||
if (!empty($this->input->getOption('with-config-file-path'))) {
|
||||
$indent_texts['Config File Path'] = $this->input->getOption('with-config-file-path');
|
||||
}
|
||||
if (!empty($this->input->getOption('with-hardcoded-ini'))) {
|
||||
$indent_texts['Hardcoded INI'] = $this->input->getOption('with-hardcoded-ini');
|
||||
}
|
||||
@ -174,7 +181,9 @@ class BuildCliCommand extends BuildCommand
|
||||
|
||||
// compile stopwatch :P
|
||||
$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 ----------
|
||||
$build_root_path = BUILD_ROOT_PATH;
|
||||
|
||||
@ -23,6 +23,8 @@ class DoctorCommand extends BaseCommand
|
||||
{
|
||||
try {
|
||||
$checker = new CheckListHandler();
|
||||
// skipped items
|
||||
$skip_items = array_filter(explode(',', getenv('SPC_SKIP_DOCTOR_CHECK_ITEMS') ?: ''));
|
||||
|
||||
$fix_policy = $this->input->getOption('auto-fix') ? FIX_POLICY_AUTOFIX : FIX_POLICY_PROMPT;
|
||||
foreach ($checker->runChecks() as $check) {
|
||||
@ -32,13 +34,12 @@ class DoctorCommand extends BaseCommand
|
||||
|
||||
$this->output->write('Checking <comment>' . $check->item_name . '</comment> ... ');
|
||||
|
||||
$result = call_user_func($check->callback);
|
||||
if ($result === null) {
|
||||
// check if this item is skipped
|
||||
if (in_array($check->item_name, $skip_items) || ($result = call_user_func($check->callback)) === null) {
|
||||
$this->output->writeln('skipped');
|
||||
} elseif ($result instanceof CheckResult) {
|
||||
if ($result->isOK()) {
|
||||
$this->output->writeln($result->getMessage() ?? 'ok');
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@ class DownloadCommand extends BaseCommand
|
||||
$this->addArgument('sources', InputArgument::REQUIRED, 'The sources will be compiled, comma separated');
|
||||
$this->addOption('shallow-clone', null, null, 'Clone shallow');
|
||||
$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('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"');
|
||||
|
||||
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(
|
||||
'php-major-version',
|
||||
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,
|
||||
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;
|
||||
|
||||
@ -31,7 +31,7 @@ class SwitchPhpVersionCommand extends BaseCommand
|
||||
public function handle(): int
|
||||
{
|
||||
$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
|
||||
preg_match('/^\d+\.\d+\.\d+$/', $php_ver, $matches);
|
||||
if (!$matches) {
|
||||
|
||||
@ -5,8 +5,12 @@ declare(strict_types=1);
|
||||
namespace SPC\command\dev;
|
||||
|
||||
use SPC\builder\BuilderProvider;
|
||||
use SPC\builder\LibraryBase;
|
||||
use SPC\command\BuildCommand;
|
||||
use SPC\exception\ExceptionHandler;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\DependencyUtil;
|
||||
@ -53,6 +57,8 @@ class PackLibCommand extends BuildCommand
|
||||
$lib->tryBuild(true);
|
||||
// do something like patching pkg-conf files.
|
||||
$lib->beforePack();
|
||||
// sanity check for libs (check if the libraries are built correctly)
|
||||
$this->sanityCheckLib($lib);
|
||||
// After build: load buildroot/ directory, and calculate increase files
|
||||
$after_buildroot = FileSystem::scanDirFiles(BUILD_ROOT_PATH, relative: true);
|
||||
$increase_files = array_diff($after_buildroot, $before_buildroot);
|
||||
@ -82,4 +88,20 @@ class PackLibCommand extends BuildCommand
|
||||
return static::FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws WrongUsageException
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
private function sanityCheckLib(LibraryBase $lib): void
|
||||
{
|
||||
logger()->info('Sanity check for library ' . $lib->getName());
|
||||
// config
|
||||
foreach ($lib->getStaticLibs() as $static_lib) {
|
||||
if (!file_exists(FileSystem::convertPath(BUILD_LIB_PATH . '/' . $static_lib))) {
|
||||
throw new RuntimeException('Static library ' . $static_lib . ' not found in ' . BUILD_LIB_PATH);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,9 +73,9 @@ class LinuxMuslCheck
|
||||
FileSystem::extractSource($musl_version_name, DOWNLOAD_PATH . "/{$musl_version_name}.tar.gz");
|
||||
logger()->info('Installing musl wrapper');
|
||||
shell()->cd(SOURCE_PATH . "/{$musl_version_name}")
|
||||
->exec('./configure --disable-gcc-wrapper')
|
||||
->exec('make -j')
|
||||
->exec("{$prefix}make install");
|
||||
->exec('CC=gcc CXX=g++ AR=ar LD=ld ./configure --disable-gcc-wrapper')
|
||||
->exec('CC=gcc CXX=g++ AR=ar LD=ld make -j')
|
||||
->exec("CC=gcc CXX=g++ AR=ar LD=ld {$prefix}make install");
|
||||
// TODO: add path using putenv instead of editing /etc/profile
|
||||
return true;
|
||||
} catch (RuntimeException) {
|
||||
|
||||
@ -37,10 +37,10 @@ class WindowsToolCheckList
|
||||
#[AsCheckItem('if php-sdk-binary-tools are downloaded', limit_os: 'Windows', level: 997)]
|
||||
public function checkSDK(): ?CheckResult
|
||||
{
|
||||
if (!file_exists(PHP_SDK_PATH . DIRECTORY_SEPARATOR . 'phpsdk-starter.bat')) {
|
||||
if (!file_exists(getenv('PHP_SDK_PATH') . DIRECTORY_SEPARATOR . 'phpsdk-starter.bat')) {
|
||||
return CheckResult::fail('php-sdk-binary-tools not downloaded', 'install-php-sdk');
|
||||
}
|
||||
return CheckResult::ok(PHP_SDK_PATH);
|
||||
return CheckResult::ok(getenv('PHP_SDK_PATH'));
|
||||
}
|
||||
|
||||
#[AsCheckItem('if git associated command exists', limit_os: 'Windows', level: 996)]
|
||||
@ -81,8 +81,8 @@ class WindowsToolCheckList
|
||||
public function installPhpSdk(): bool
|
||||
{
|
||||
try {
|
||||
FileSystem::removeDir(PHP_SDK_PATH);
|
||||
cmd(true)->exec('git.exe clone --depth 1 https://github.com/php/php-sdk-binary-tools.git ' . PHP_SDK_PATH);
|
||||
FileSystem::removeDir(getenv('PHP_SDK_PATH'));
|
||||
cmd(true)->exec('git.exe clone --depth 1 https://github.com/php/php-sdk-binary-tools.git ' . getenv('PHP_SDK_PATH'));
|
||||
} catch (RuntimeException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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 {}
|
||||
@ -20,11 +20,17 @@ class CurlHook
|
||||
}
|
||||
if (getenv('GITHUB_USER')) {
|
||||
$auth = base64_encode(getenv('GITHUB_USER') . ':' . getenv('GITHUB_TOKEN'));
|
||||
$headers[] = "Authorization: Basic {$auth}";
|
||||
$he = "Authorization: Basic {$auth}";
|
||||
if (!in_array($he, $headers)) {
|
||||
$headers[] = $he;
|
||||
}
|
||||
logger()->info("using basic github token for {$method} {$url}");
|
||||
} else {
|
||||
$auth = getenv('GITHUB_TOKEN');
|
||||
$headers[] = "Authorization: Bearer {$auth}";
|
||||
$he = "Authorization: Bearer {$auth}";
|
||||
if (!in_array($he, $headers)) {
|
||||
$headers[] = $he;
|
||||
}
|
||||
logger()->info("using bearer github token for {$method} {$url}");
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ class Downloader
|
||||
logger()->debug("finding {$name} source from bitbucket tag");
|
||||
$data = json_decode(self::curlExec(
|
||||
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);
|
||||
$ver = $data['values'][0]['name'];
|
||||
if (!$ver) {
|
||||
@ -38,7 +38,7 @@ class Downloader
|
||||
$headers = self::curlExec(
|
||||
url: $url,
|
||||
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);
|
||||
if ($matches) {
|
||||
@ -66,7 +66,7 @@ class Downloader
|
||||
$data = json_decode(self::curlExec(
|
||||
url: "https://api.github.com/repos/{$source['repo']}/{$type}",
|
||||
hooks: [[CurlHook::class, 'setupGithubToken']],
|
||||
retry: intval(getenv('SPC_RETRY_TIME') ? getenv('SPC_RETRY_TIME') : 0)
|
||||
retry: self::getRetryTime()
|
||||
), true);
|
||||
|
||||
if (($source['prefer-stable'] ?? false) === false) {
|
||||
@ -85,7 +85,7 @@ class Downloader
|
||||
url: $url,
|
||||
method: 'HEAD',
|
||||
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);
|
||||
if ($matches) {
|
||||
@ -108,11 +108,11 @@ class Downloader
|
||||
*/
|
||||
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(
|
||||
url: "https://api.github.com/repos/{$source['repo']}/releases",
|
||||
hooks: [[CurlHook::class, 'setupGithubToken']],
|
||||
retry: intval(getenv('SPC_RETRY_TIME') ? getenv('SPC_RETRY_TIME') : 0)
|
||||
retry: self::getRetryTime()
|
||||
), true);
|
||||
$url = null;
|
||||
foreach ($data as $release) {
|
||||
@ -149,7 +149,7 @@ class Downloader
|
||||
public static function getFromFileList(string $name, array $source): array
|
||||
{
|
||||
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);
|
||||
if (!$matches) {
|
||||
throw new DownloaderException("Failed to get {$name} version");
|
||||
@ -182,6 +182,7 @@ class Downloader
|
||||
*
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public static function downloadFile(string $name, string $url, string $filename, ?string $move_path = null, int $lock_as = SPC_LOCK_SOURCE): void
|
||||
{
|
||||
@ -193,7 +194,7 @@ class Downloader
|
||||
}
|
||||
};
|
||||
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();
|
||||
logger()->debug("Locking {$filename}");
|
||||
self::lockSource($name, ['source_type' => 'archive', 'filename' => $filename, 'move_path' => $move_path, 'lock_as' => $lock_as]);
|
||||
@ -220,6 +221,7 @@ class Downloader
|
||||
*
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public static function downloadGit(string $name, string $url, string $branch, ?string $move_path = null, int $retry = 0, int $lock_as = SPC_LOCK_SOURCE): void
|
||||
{
|
||||
@ -345,7 +347,7 @@ class Downloader
|
||||
$pkg['url'],
|
||||
$pkg['rev'],
|
||||
$pkg['extract'] ?? null,
|
||||
intval(getenv('SPC_RETRY_TIME') ? getenv('SPC_RETRY_TIME') : 0),
|
||||
self::getRetryTime(),
|
||||
SPC_LOCK_PRE_BUILT
|
||||
);
|
||||
break;
|
||||
@ -381,6 +383,7 @@ class Downloader
|
||||
* @param int $lock_as Lock source type (default: SPC_LOCK_SOURCE)
|
||||
* @throws DownloaderException
|
||||
* @throws FileSystemException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public static function downloadSource(string $name, ?array $source = null, bool $force = false, int $lock_as = SPC_LOCK_SOURCE): void
|
||||
{
|
||||
@ -448,7 +451,7 @@ class Downloader
|
||||
$source['url'],
|
||||
$source['rev'],
|
||||
$source['path'] ?? null,
|
||||
intval(getenv('SPC_RETRY_TIME') ? getenv('SPC_RETRY_TIME') : 0),
|
||||
self::getRetryTime(),
|
||||
$lock_as
|
||||
);
|
||||
break;
|
||||
@ -539,6 +542,7 @@ class Downloader
|
||||
* Use curl to download sources from url
|
||||
*
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public static function curlDown(string $url, string $path, string $method = 'GET', array $headers = [], array $hooks = [], int $retry = 0): void
|
||||
{
|
||||
@ -563,7 +567,7 @@ class Downloader
|
||||
}
|
||||
if ($retry > 0) {
|
||||
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;
|
||||
}
|
||||
throw $e;
|
||||
@ -597,4 +601,9 @@ class Downloader
|
||||
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);
|
||||
}
|
||||
|
||||
@ -428,7 +431,7 @@ class FileSystem
|
||||
{
|
||||
$replacement = [
|
||||
'{pkg_root_path}' => PKG_ROOT_PATH,
|
||||
'{php_sdk_path}' => defined('PHP_SDK_PATH') ? PHP_SDK_PATH : WORKING_DIR . '/php-sdk-binary-tools',
|
||||
'{php_sdk_path}' => getenv('PHP_SDK_PATH') ? getenv('PHP_SDK_PATH') : WORKING_DIR . '/php-sdk-binary-tools',
|
||||
'{working_dir}' => WORKING_DIR,
|
||||
'{download_path}' => DOWNLOAD_PATH,
|
||||
'{source_path}' => SOURCE_PATH,
|
||||
@ -480,7 +483,7 @@ class FileSystem
|
||||
};
|
||||
} elseif (PHP_OS_FAMILY === 'Windows') {
|
||||
// use php-sdk-binary-tools/bin/7za.exe
|
||||
$_7z = self::convertPath(PHP_SDK_PATH . '/bin/7za.exe');
|
||||
$_7z = self::convertPath(getenv('PHP_SDK_PATH') . '/bin/7za.exe');
|
||||
|
||||
// Windows notes: I hate windows tar.......
|
||||
// When extracting .tar.gz like libxml2, it shows a symlink error and returns code[1].
|
||||
|
||||
@ -25,6 +25,8 @@ class SourcePatcher
|
||||
FileSystem::addSourceExtractHook('pdo_sqlsrv', [SourcePatcher::class, 'patchSQLSRVWin32']);
|
||||
FileSystem::addSourceExtractHook('yaml', [SourcePatcher::class, 'patchYamlWin32']);
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@ -416,7 +439,7 @@ class SourcePatcher
|
||||
return true;
|
||||
}
|
||||
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');
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ class PhpSource extends CustomSourceBase
|
||||
*/
|
||||
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';
|
||||
Downloader::downloadSource('php-src', self::getLatestPHPInfo($major), $force);
|
||||
}
|
||||
|
||||
|
||||
@ -5,11 +5,9 @@ declare(strict_types=1);
|
||||
namespace SPC\util;
|
||||
|
||||
use SPC\builder\BuilderBase;
|
||||
use SPC\builder\freebsd\SystemUtil as BSDSystemUtil;
|
||||
use SPC\builder\linux\SystemUtil as LinuxSystemUtil;
|
||||
use SPC\builder\macos\SystemUtil as MacOSSystemUtil;
|
||||
use SPC\builder\windows\SystemUtil as WindowsSystemUtil;
|
||||
use SPC\builder\linux\SystemUtil;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
|
||||
/**
|
||||
* Environment variable manager
|
||||
@ -26,171 +24,87 @@ class GlobalEnvManager
|
||||
/**
|
||||
* Initialize the environment variables
|
||||
*
|
||||
* @param BuilderBase $builder Builder
|
||||
* @param null|BuilderBase $builder Builder
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public static function init(BuilderBase $builder): void
|
||||
public static function init(?BuilderBase $builder = null): void
|
||||
{
|
||||
// Init global env, build related path
|
||||
self::putenv('BUILD_ROOT_PATH=' . BUILD_ROOT_PATH);
|
||||
self::putenv('BUILD_INCLUDE_PATH=' . BUILD_INCLUDE_PATH);
|
||||
self::putenv('BUILD_LIB_PATH=' . BUILD_LIB_PATH);
|
||||
self::putenv('BUILD_BIN_PATH=' . BUILD_BIN_PATH);
|
||||
self::putenv('PKG_ROOT_PATH=' . PKG_ROOT_PATH);
|
||||
self::putenv('SOURCE_PATH=' . SOURCE_PATH);
|
||||
self::putenv('DOWNLOAD_PATH=' . DOWNLOAD_PATH);
|
||||
// Check pre-defined env vars exists
|
||||
if (getenv('BUILD_ROOT_PATH') === false) {
|
||||
throw new RuntimeException('You must include src/globals/internal-env.php before using GlobalEnvManager');
|
||||
}
|
||||
|
||||
// Init SPC env
|
||||
self::initIfNotExists('SPC_CONCURRENCY', match (PHP_OS_FAMILY) {
|
||||
'Windows' => (string) WindowsSystemUtil::getCpuCount(),
|
||||
'Darwin' => (string) MacOSSystemUtil::getCpuCount(),
|
||||
'Linux' => (string) LinuxSystemUtil::getCpuCount(),
|
||||
'BSD' => (string) BSDSystemUtil::getCpuCount(),
|
||||
default => '1',
|
||||
});
|
||||
// Define env vars for unix
|
||||
if (is_unix()) {
|
||||
self::putenv('PATH=' . BUILD_ROOT_PATH . '/bin:' . getenv('PATH'));
|
||||
self::putenv('PKG_CONFIG=' . BUILD_BIN_PATH . '/pkg-config');
|
||||
self::putenv('PKG_CONFIG_PATH=' . BUILD_ROOT_PATH . '/lib/pkgconfig');
|
||||
if ($builder instanceof BuilderBase) {
|
||||
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'));
|
||||
}
|
||||
}
|
||||
|
||||
// Init system-specific env
|
||||
match (PHP_OS_FAMILY) {
|
||||
'Windows' => self::initWindowsEnv(),
|
||||
'Darwin' => self::initDarwinEnv($builder),
|
||||
'Linux' => self::initLinuxEnv($builder),
|
||||
'BSD' => 'TODO',
|
||||
default => logger()->warning('Unknown OS: ' . PHP_OS_FAMILY),
|
||||
};
|
||||
}
|
||||
|
||||
private static function initWindowsEnv(): void
|
||||
{
|
||||
// Windows need php-sdk binary tools
|
||||
self::initIfNotExists('PHP_SDK_PATH', WORKING_DIR . DIRECTORY_SEPARATOR . 'php-sdk-binary-tools');
|
||||
self::initIfNotExists('UPX_EXEC', PKG_ROOT_PATH . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'upx.exe');
|
||||
self::initIfNotExists('SPC_MICRO_PATCHES', 'static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,cli_static');
|
||||
}
|
||||
|
||||
private static function initLinuxEnv(BuilderBase $builder): void
|
||||
{
|
||||
// Init C Compiler and C++ Compiler (alpine)
|
||||
if (LinuxSystemUtil::isMuslDist()) {
|
||||
self::initIfNotExists('CC', 'gcc');
|
||||
self::initIfNotExists('CXX', 'g++');
|
||||
self::initIfNotExists('AR', 'ar');
|
||||
self::initIfNotExists('LD', 'ld.gold');
|
||||
} else {
|
||||
// Define env vars for linux
|
||||
if (PHP_OS_FAMILY === 'Linux') {
|
||||
$arch = arch2gnu(php_uname('m'));
|
||||
self::initIfNotExists('CC', "{$arch}-linux-musl-gcc");
|
||||
self::initIfNotExists('CXX', "{$arch}-linux-musl-g++");
|
||||
self::initIfNotExists('AR', "{$arch}-linux-musl-ar");
|
||||
self::initIfNotExists('LD', 'ld.gold');
|
||||
if (SystemUtil::isMuslDist()) {
|
||||
self::putenv('SPC_LINUX_DEFAULT_CC=gcc');
|
||||
self::putenv('SPC_LINUX_DEFAULT_CXX=g++');
|
||||
self::putenv('SPC_LINUX_DEFAULT_AR=ar');
|
||||
} else {
|
||||
self::putenv("SPC_LINUX_DEFAULT_CC={$arch}-linux-musl-gcc");
|
||||
self::putenv("SPC_LINUX_DEFAULT_CXX={$arch}-linux-musl-g++");
|
||||
self::putenv("SPC_LINUX_DEFAULT_AR={$arch}-linux-musl-ar");
|
||||
}
|
||||
self::putenv("SPC_PHP_DEFAULT_LD_LIBRARY_PATH_CMD=LD_LIBRARY_PATH=/usr/local/musl/{$arch}-linux-musl/lib");
|
||||
if (getenv('SPC_NO_MUSL_PATH') !== 'yes') {
|
||||
self::putenv("PATH=/usr/local/musl/bin:/usr/local/musl/{$arch}-linux-musl/bin:" . getenv('PATH'));
|
||||
}
|
||||
}
|
||||
|
||||
// Init arch-specific cflags
|
||||
self::initIfNotExists('SPC_DEFAULT_C_FLAGS', '');
|
||||
self::initIfNotExists('SPC_DEFAULT_CXX_FLAGS', '');
|
||||
self::initIfNotExists('SPC_EXTRA_LIBS', '');
|
||||
|
||||
// SPC_MICRO_PATCHES for linux
|
||||
self::initIfNotExists('SPC_MICRO_PATCHES', 'static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream');
|
||||
|
||||
// Init linux-only env
|
||||
self::initIfNotExists('UPX_EXEC', PKG_ROOT_PATH . '/bin/upx');
|
||||
self::initIfNotExists('GNU_ARCH', arch2gnu(php_uname('m')));
|
||||
|
||||
// optimization flags with different strip option
|
||||
$php_extra_cflags_optimize = $builder->getOption('no-strip') ? '-g -O0' : '-g -Os';
|
||||
// optimization flags with different c compiler
|
||||
$clang_use_lld = str_ends_with(getenv('CC'), 'clang') && LinuxSystemUtil::findCommand('lld') ? '-Xcompiler -fuse-ld=lld ' : '';
|
||||
|
||||
$init_spc_cmd_maps = [
|
||||
// Init default build command prefix
|
||||
'SPC_CMD_PREFIX_PHP_BUILDCONF' => './buildconf --force',
|
||||
'SPC_CMD_PREFIX_PHP_CONFIGURE' => $builder->getOption('ld_library_path') . ' ./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-cgi --disable-phpdbg',
|
||||
'SPC_CMD_PREFIX_PHP_MAKE' => 'make -j' . getenv('SPC_CONCURRENCY'),
|
||||
// Init default build vars for build command
|
||||
'SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS' => getenv('SPC_DEFAULT_C_FLAGS'),
|
||||
'SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH,
|
||||
'SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS' => '-L' . BUILD_LIB_PATH,
|
||||
'SPC_CMD_VAR_PHP_CONFIGURE_LIBS' => '-ldl -lpthread -lm',
|
||||
'SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS' => $php_extra_cflags_optimize . ' -fno-ident -fPIE',
|
||||
'SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS' => '',
|
||||
'SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM' => $clang_use_lld . '-all-static',
|
||||
// Init env.ini file, read order:
|
||||
// WORKING_DIR/config/env.ini
|
||||
// ROOT_DIR/config/env.ini
|
||||
$ini_files = [
|
||||
WORKING_DIR . '/config/env.ini',
|
||||
ROOT_DIR . '/config/env.ini',
|
||||
];
|
||||
foreach ($init_spc_cmd_maps as $name => $value) {
|
||||
self::initIfNotExists($name, $value);
|
||||
$ini = null;
|
||||
foreach ($ini_files as $ini_file) {
|
||||
if (file_exists($ini_file)) {
|
||||
$ini = parse_ini_file($ini_file, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self::initUnixEnv($builder);
|
||||
}
|
||||
|
||||
private static function initDarwinEnv(BuilderBase $builder): void
|
||||
{
|
||||
// Init C Compiler and C++ Compiler
|
||||
self::initIfNotExists('CC', 'clang');
|
||||
self::initIfNotExists('CXX', 'clang++');
|
||||
|
||||
// Init arch-specific cflags
|
||||
self::initIfNotExists('SPC_DEFAULT_C_FLAGS', match (php_uname('m')) {
|
||||
'arm64', 'aarch64' => '--target=arm64-apple-darwin',
|
||||
default => '--target=x86_64-apple-darwin',
|
||||
});
|
||||
// Init arch-specific cxxflags
|
||||
self::initIfNotExists('SPC_DEFAULT_CXX_FLAGS', match (php_uname('m')) {
|
||||
'arm64', 'aarch64' => '--target=arm64-apple-darwin',
|
||||
default => '--target=x86_64-apple-darwin',
|
||||
});
|
||||
|
||||
// Init extra libs (will be appended before `before-php-buildconf` event point)
|
||||
self::initIfNotExists('SPC_EXTRA_LIBS', '');
|
||||
|
||||
// SPC_MICRO_PATCHES for macOS
|
||||
self::initIfNotExists('SPC_MICRO_PATCHES', 'static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,macos_iconv');
|
||||
|
||||
$init_spc_cmd_maps = [
|
||||
// Init default build command prefix
|
||||
'SPC_CMD_PREFIX_PHP_BUILDCONF' => './buildconf --force',
|
||||
'SPC_CMD_PREFIX_PHP_CONFIGURE' => './configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-cgi --disable-phpdbg',
|
||||
'SPC_CMD_PREFIX_PHP_MAKE' => 'make -j' . getenv('SPC_CONCURRENCY'),
|
||||
// Init default build vars for build command
|
||||
'SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS' => getenv('SPC_DEFAULT_C_FLAGS') . ' -Werror=unknown-warning-option',
|
||||
'SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH,
|
||||
'SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS' => '-L' . BUILD_LIB_PATH,
|
||||
'SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS' => $builder->getOption('no-strip') ? '-g -O0' : '-g -Os',
|
||||
'SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS' => '-lresolv',
|
||||
];
|
||||
foreach ($init_spc_cmd_maps as $name => $value) {
|
||||
self::initIfNotExists($name, $value);
|
||||
if ($ini === null) {
|
||||
throw new WrongUsageException('env.ini not found');
|
||||
}
|
||||
|
||||
self::initUnixEnv($builder);
|
||||
}
|
||||
|
||||
private static function initUnixEnv(BuilderBase $builder): void
|
||||
{
|
||||
self::putenv('PATH=' . BUILD_ROOT_PATH . '/bin:' . getenv('PATH'));
|
||||
self::putenv('PKG_CONFIG=' . BUILD_BIN_PATH . '/pkg-config');
|
||||
self::putenv('PKG_CONFIG_PATH=' . BUILD_ROOT_PATH . '/lib/pkgconfig');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the environment variable if it does not exist
|
||||
*
|
||||
* @param string $name Environment variable name
|
||||
* @param string $value Environment variable value
|
||||
*/
|
||||
private static function initIfNotExists(string $name, string $value): void
|
||||
{
|
||||
if (($val = getenv($name)) === false) {
|
||||
self::putenv($name . '=' . $value);
|
||||
} else {
|
||||
logger()->debug("env [{$name}] existing: {$val}");
|
||||
if ($ini === false || !isset($ini['global'])) {
|
||||
throw new WrongUsageException('Failed to parse ' . $ini_file);
|
||||
}
|
||||
self::applyConfig($ini['global']);
|
||||
match (PHP_OS_FAMILY) {
|
||||
'Windows' => self::applyConfig($ini['windows']),
|
||||
'Darwin' => self::applyConfig($ini['macos']),
|
||||
'Linux' => self::applyConfig($ini['linux']),
|
||||
'BSD' => self::applyConfig($ini['freebsd']),
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
|
||||
private static function putenv(string $val): void
|
||||
public static function putenv(string $val): void
|
||||
{
|
||||
f_putenv($val);
|
||||
self::$env_cache[] = $val;
|
||||
}
|
||||
|
||||
private static function applyConfig(array $ini): void
|
||||
{
|
||||
foreach ($ini as $k => $v) {
|
||||
if (getenv($k) === false) {
|
||||
self::putenv($k . '=' . $v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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('Executed at: ' . debug_backtrace()[0]['file'] . ':' . debug_backtrace()[0]['line']);
|
||||
if ($this->cd !== null) {
|
||||
$cmd = 'cd ' . escapeshellarg($this->cd) . ' && ' . $cmd;
|
||||
}
|
||||
exec($cmd, $out, $code);
|
||||
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;
|
||||
@ -2,32 +2,16 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use SPC\store\FileSystem;
|
||||
use ZM\Logger\ConsoleLogger;
|
||||
|
||||
define('WORKING_DIR', getcwd());
|
||||
define('ROOT_DIR', dirname(__DIR__, 2));
|
||||
putenv('WORKING_DIR=' . WORKING_DIR);
|
||||
putenv('ROOT_DIR=' . ROOT_DIR);
|
||||
|
||||
// CLI start time
|
||||
define('START_TIME', microtime(true));
|
||||
|
||||
define('BUILD_ROOT_PATH', FileSystem::convertPath(is_string($a = getenv('BUILD_ROOT_PATH')) ? $a : (WORKING_DIR . '/buildroot')));
|
||||
define('SOURCE_PATH', FileSystem::convertPath(is_string($a = getenv('SOURCE_PATH')) ? $a : (WORKING_DIR . '/source')));
|
||||
define('DOWNLOAD_PATH', FileSystem::convertPath(is_string($a = getenv('DOWNLOAD_PATH')) ? $a : (WORKING_DIR . '/downloads')));
|
||||
define('PKG_ROOT_PATH', FileSystem::convertPath(is_string($a = getenv('PKG_ROOT_PATH')) ? $a : (WORKING_DIR . '/pkgroot')));
|
||||
define('BUILD_BIN_PATH', FileSystem::convertPath(is_string($a = getenv('INSTALL_BIN_PATH')) ? $a : (BUILD_ROOT_PATH . '/bin')));
|
||||
define('BUILD_LIB_PATH', FileSystem::convertPath(is_string($a = getenv('INSTALL_LIB_PATH')) ? $a : (BUILD_ROOT_PATH . '/lib')));
|
||||
define('BUILD_INCLUDE_PATH', FileSystem::convertPath(is_string($a = getenv('INSTALL_INCLUDE_PATH')) ? $a : (BUILD_ROOT_PATH . '/include')));
|
||||
define('SEPARATED_PATH', [
|
||||
'/' . pathinfo(BUILD_LIB_PATH)['basename'], // lib
|
||||
'/' . pathinfo(BUILD_INCLUDE_PATH)['basename'], // include
|
||||
BUILD_ROOT_PATH,
|
||||
]);
|
||||
|
||||
if (PHP_OS_FAMILY === 'Windows') {
|
||||
define('PHP_SDK_PATH', is_string($a = getenv('PHP_SDK_PATH')) ? $a : (WORKING_DIR . DIRECTORY_SEPARATOR . 'php-sdk-binary-tools'));
|
||||
}
|
||||
|
||||
// for windows, prevent calling Invoke-WebRequest and wsl command
|
||||
const SPC_CURL_EXEC = PHP_OS_FAMILY === 'Windows' ? 'curl.exe' : 'curl';
|
||||
const SPC_GIT_EXEC = PHP_OS_FAMILY === 'Windows' ? 'git.exe' : 'git';
|
||||
|
||||
@ -5,7 +5,6 @@ declare(strict_types=1);
|
||||
assert(function_exists('gettext'));
|
||||
assert(function_exists('bindtextdomain'));
|
||||
assert(function_exists('textdomain'));
|
||||
assert(function_exists('bind_textdomain_codeset'));
|
||||
|
||||
if (!is_dir('locale/en_US/LC_MESSAGES/')) {
|
||||
mkdir('locale/en_US/LC_MESSAGES/', 0755, true);
|
||||
@ -19,7 +18,6 @@ setlocale(LC_ALL, 'en_US');
|
||||
|
||||
$domain = 'test';
|
||||
bindtextdomain($domain, 'locale/');
|
||||
bind_textdomain_codeset($domain, 'UTF-8');
|
||||
textdomain($domain);
|
||||
|
||||
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(class_exists('Swoole\Coroutine'));
|
||||
assert(class_exists('Swoole\Coroutine\Http2\Client'));
|
||||
assert(class_exists('Swoole\Coroutine\Redis'));
|
||||
assert(class_exists('Swoole\Coroutine\WaitGroup'));
|
||||
assert(class_exists('Swoole\Http2\Request'));
|
||||
assert(constant('SWOOLE_VERSION'));
|
||||
|
||||
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 SPC\builder\BuilderBase;
|
||||
use SPC\builder\BuilderProvider;
|
||||
use SPC\exception\InterruptException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\util\UnixShell;
|
||||
@ -31,6 +32,11 @@ function logger(): LoggerInterface
|
||||
return $ob_logger;
|
||||
}
|
||||
|
||||
function is_unix(): bool
|
||||
{
|
||||
return in_array(PHP_OS_FAMILY, ['Linux', 'Darwin', 'BSD']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer architecture name to gnu triplet
|
||||
*
|
||||
@ -120,6 +126,11 @@ function patch_point(): string
|
||||
return BuilderProvider::getBuilder()->getPatchPoint();
|
||||
}
|
||||
|
||||
function patch_point_interrupt(int $retcode, string $msg = ''): InterruptException
|
||||
{
|
||||
return new InterruptException(message: $msg, code: $retcode);
|
||||
}
|
||||
|
||||
// ------- function f_* part -------
|
||||
// f_ means standard function wrapper
|
||||
|
||||
|
||||
49
src/globals/internal-env.php
Normal file
49
src/globals/internal-env.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use SPC\builder\freebsd\SystemUtil as BSDSystemUtil;
|
||||
use SPC\builder\linux\SystemUtil as LinuxSystemUtil;
|
||||
use SPC\builder\macos\SystemUtil as MacOSSystemUtil;
|
||||
use SPC\builder\windows\SystemUtil as WindowsSystemUtil;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
|
||||
define('BUILD_ROOT_PATH', FileSystem::convertPath(is_string($a = getenv('BUILD_ROOT_PATH')) ? $a : (WORKING_DIR . '/buildroot')));
|
||||
define('BUILD_INCLUDE_PATH', FileSystem::convertPath(is_string($a = getenv('BUILD_INCLUDE_PATH')) ? $a : (BUILD_ROOT_PATH . '/include')));
|
||||
define('BUILD_LIB_PATH', FileSystem::convertPath(is_string($a = getenv('BUILD_LIB_PATH')) ? $a : (BUILD_ROOT_PATH . '/lib')));
|
||||
define('BUILD_BIN_PATH', FileSystem::convertPath(is_string($a = getenv('BUILD_BIN_PATH')) ? $a : (BUILD_ROOT_PATH . '/bin')));
|
||||
define('PKG_ROOT_PATH', FileSystem::convertPath(is_string($a = getenv('PKG_ROOT_PATH')) ? $a : (WORKING_DIR . '/pkgroot')));
|
||||
define('SOURCE_PATH', FileSystem::convertPath(is_string($a = getenv('SOURCE_PATH')) ? $a : (WORKING_DIR . '/source')));
|
||||
define('DOWNLOAD_PATH', FileSystem::convertPath(is_string($a = getenv('DOWNLOAD_PATH')) ? $a : (WORKING_DIR . '/downloads')));
|
||||
define('CPU_COUNT', match (PHP_OS_FAMILY) {
|
||||
'Windows' => (string) WindowsSystemUtil::getCpuCount(),
|
||||
'Darwin' => (string) MacOSSystemUtil::getCpuCount(),
|
||||
'Linux' => (string) LinuxSystemUtil::getCpuCount(),
|
||||
'BSD' => (string) BSDSystemUtil::getCpuCount(),
|
||||
default => 1,
|
||||
});
|
||||
define('GNU_ARCH', arch2gnu(php_uname('m')));
|
||||
define('MAC_ARCH', match ($_im8a = arch2gnu(php_uname('m'))) {
|
||||
'aarch64' => 'arm64',
|
||||
default => $_im8a
|
||||
});
|
||||
|
||||
// deprecated variables
|
||||
define('SEPARATED_PATH', [
|
||||
'/' . pathinfo(BUILD_LIB_PATH)['basename'], // lib
|
||||
'/' . pathinfo(BUILD_INCLUDE_PATH)['basename'], // include
|
||||
BUILD_ROOT_PATH,
|
||||
]);
|
||||
|
||||
// add these to env vars with same name
|
||||
GlobalEnvManager::putenv('BUILD_ROOT_PATH=' . BUILD_ROOT_PATH);
|
||||
GlobalEnvManager::putenv('BUILD_INCLUDE_PATH=' . BUILD_INCLUDE_PATH);
|
||||
GlobalEnvManager::putenv('BUILD_LIB_PATH=' . BUILD_LIB_PATH);
|
||||
GlobalEnvManager::putenv('BUILD_BIN_PATH=' . BUILD_BIN_PATH);
|
||||
GlobalEnvManager::putenv('PKG_ROOT_PATH=' . PKG_ROOT_PATH);
|
||||
GlobalEnvManager::putenv('SOURCE_PATH=' . SOURCE_PATH);
|
||||
GlobalEnvManager::putenv('DOWNLOAD_PATH=' . DOWNLOAD_PATH);
|
||||
GlobalEnvManager::putenv('CPU_COUNT=' . CPU_COUNT);
|
||||
GlobalEnvManager::putenv('GNU_ARCH=' . GNU_ARCH);
|
||||
GlobalEnvManager::putenv('MAC_ARCH=' . MAC_ARCH);
|
||||
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);
|
||||
@ -11,16 +11,35 @@ declare(strict_types=1);
|
||||
|
||||
// --------------------------------- edit area ---------------------------------
|
||||
|
||||
$zts = false;
|
||||
// test php version
|
||||
$test_php_version = [
|
||||
'8.1',
|
||||
'8.2',
|
||||
'8.3',
|
||||
'8.4',
|
||||
];
|
||||
|
||||
// test os (macos-13, macos-14, ubuntu-latest, windows-latest are available)
|
||||
$test_os = [
|
||||
'macos-14',
|
||||
'ubuntu-latest',
|
||||
];
|
||||
|
||||
// whether enable thread safe
|
||||
$zts = true;
|
||||
|
||||
$no_strip = false;
|
||||
|
||||
$upx = true;
|
||||
// compress with upx
|
||||
$upx = false;
|
||||
|
||||
// prefer downloading pre-built packages to speed up the build process
|
||||
$prefer_pre_built = true;
|
||||
|
||||
// If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`).
|
||||
$extensions = match (PHP_OS_FAMILY) {
|
||||
'Linux', 'Darwin' => 'rdkafka',
|
||||
'Windows' => 'rdkafka',
|
||||
'Linux', 'Darwin' => 'apcu,bcmath,bz2,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,ftp,gd,gmp,gettext,iconv,igbinary,imagick,intl,ldap,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,parallel,pcntl,pdo,pdo_mysql,pdo_pgsql,pdo_sqlite,pgsql,phar,posix,protobuf,readline,redis,session,shmop,simplexml,soap,sockets,sodium,sqlite3,ssh2,sysvmsg,sysvsem,sysvshm,tidy,tokenizer,xlswriter,xml,xmlreader,xmlwriter,zip,zlib,yaml,zstd',
|
||||
'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',
|
||||
};
|
||||
|
||||
// If you want to test lib-suggests feature with extension, add them below (comma separated, example `libwebp,libavif`).
|
||||
@ -58,7 +77,7 @@ function _getCombination(string $type = 'common'): string
|
||||
}
|
||||
|
||||
if (!isset($argv[1])) {
|
||||
exit("Please use 'extensions', 'cmd' or 'libs' as output type");
|
||||
exit("Please use 'extensions', 'cmd', 'os', 'php' or 'libs' as output type");
|
||||
}
|
||||
|
||||
$trim_value = "\r\n \t,";
|
||||
@ -72,7 +91,43 @@ if (PHP_OS_FAMILY === 'Windows') {
|
||||
$final_extensions_cmd = $final_extensions;
|
||||
}
|
||||
|
||||
function quote2(string $param): string
|
||||
{
|
||||
global $argv;
|
||||
if (str_starts_with($argv[2], 'windows-')) {
|
||||
return '"' . $param . '"';
|
||||
}
|
||||
return $param;
|
||||
}
|
||||
|
||||
// generate download command
|
||||
if ($argv[1] === 'download_cmd') {
|
||||
$down_cmd = 'download ';
|
||||
$down_cmd .= '--for-extensions=' . quote2($final_extensions) . ' ';
|
||||
$down_cmd .= '--for-libs=' . quote2($final_libs) . ' ';
|
||||
$down_cmd .= '--with-php=' . quote2($argv[3]) . ' ';
|
||||
$down_cmd .= '--ignore-cache-sources=php-src ';
|
||||
$down_cmd .= '--debug ';
|
||||
$down_cmd .= '--retry=5 ';
|
||||
$down_cmd .= '--shallow-clone ';
|
||||
$down_cmd .= $prefer_pre_built ? '--prefer-pre-built ' : '';
|
||||
}
|
||||
|
||||
// generate build command
|
||||
if ($argv[1] === 'build_cmd' || $argv[1] === 'build_embed_cmd') {
|
||||
$build_cmd = 'build ';
|
||||
$build_cmd .= quote2($final_extensions) . ' ';
|
||||
$build_cmd .= $zts ? '--enable-zts ' : '';
|
||||
$build_cmd .= $no_strip ? '--no-strip ' : '';
|
||||
$build_cmd .= $upx ? '--with-upx-pack ' : '';
|
||||
$build_cmd .= $final_libs === '' ? '' : ('--with-libs=' . quote2($final_libs) . ' ');
|
||||
$build_cmd .= str_starts_with($argv[2], 'windows-') ? '' : '--build-fpm ';
|
||||
$build_cmd .= '--debug ';
|
||||
}
|
||||
|
||||
echo match ($argv[1]) {
|
||||
'os' => json_encode($test_os),
|
||||
'php' => json_encode($test_php_version),
|
||||
'extensions' => $final_extensions,
|
||||
'libs' => $final_libs,
|
||||
'libs_cmd' => ($final_libs === '' ? '' : (' --with-libs=' . $final_libs)),
|
||||
@ -80,5 +135,32 @@ echo match ($argv[1]) {
|
||||
'zts' => $zts ? '--enable-zts' : '',
|
||||
'no_strip' => $no_strip ? '--no-strip' : '',
|
||||
'upx' => $upx ? '--with-upx-pack' : '',
|
||||
'prefer_pre_built' => $prefer_pre_built ? '--prefer-pre-built' : '',
|
||||
'download_cmd' => $down_cmd,
|
||||
'build_cmd' => $build_cmd,
|
||||
'build_embed_cmd' => $build_cmd,
|
||||
default => '',
|
||||
};
|
||||
|
||||
if ($argv[1] === 'download_cmd') {
|
||||
if (str_starts_with($argv[2], 'windows-')) {
|
||||
passthru('powershell.exe -file .\bin\spc.ps1 ' . $down_cmd, $retcode);
|
||||
} else {
|
||||
passthru('./bin/spc ' . $down_cmd, $retcode);
|
||||
}
|
||||
} elseif ($argv[1] === 'build_cmd') {
|
||||
if (str_starts_with($argv[2], 'windows-')) {
|
||||
passthru('powershell.exe -file .\bin\spc.ps1 ' . $build_cmd . ' --build-cli --build-micro', $retcode);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
exit($retcode);
|
||||
|
||||
253
tests/SPC/builder/BuilderTest.php
Normal file
253
tests/SPC/builder/BuilderTest.php
Normal file
@ -0,0 +1,253 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\Tests\builder;
|
||||
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use SPC\builder\BuilderBase;
|
||||
use SPC\builder\BuilderProvider;
|
||||
use SPC\builder\Extension;
|
||||
use SPC\builder\LibraryBase;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
use SPC\util\DependencyUtil;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class BuilderTest extends TestCase
|
||||
{
|
||||
private BuilderBase $builder;
|
||||
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
BuilderProvider::makeBuilderByInput(new ArgvInput());
|
||||
BuilderProvider::getBuilder();
|
||||
}
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->builder = BuilderProvider::makeBuilderByInput(new ArgvInput());
|
||||
[$extensions, $libs] = DependencyUtil::getExtsAndLibs(['mbregex']);
|
||||
$this->builder->proveLibs($libs);
|
||||
CustomExt::loadCustomExt();
|
||||
foreach ($extensions as $extension) {
|
||||
$class = CustomExt::getExtClass($extension);
|
||||
$ext = new $class($extension, $this->builder);
|
||||
$this->builder->addExt($ext);
|
||||
}
|
||||
foreach ($this->builder->getExts() as $ext) {
|
||||
$ext->checkDependency();
|
||||
}
|
||||
}
|
||||
|
||||
public function testMakeBuilderByInput(): void
|
||||
{
|
||||
$this->assertInstanceOf(BuilderBase::class, BuilderProvider::makeBuilderByInput(new ArgvInput()));
|
||||
$this->assertInstanceOf(BuilderBase::class, BuilderProvider::getBuilder());
|
||||
}
|
||||
|
||||
public function testGetLibAndGetLibs()
|
||||
{
|
||||
$this->assertIsArray($this->builder->getLibs());
|
||||
$this->assertInstanceOf(LibraryBase::class, $this->builder->getLib('onig'));
|
||||
}
|
||||
|
||||
public function testGetExtAndGetExts()
|
||||
{
|
||||
$this->assertIsArray($this->builder->getExts());
|
||||
$this->assertInstanceOf(Extension::class, $this->builder->getExt('mbregex'));
|
||||
}
|
||||
|
||||
public function testHasCpp()
|
||||
{
|
||||
// mbregex doesn't have cpp
|
||||
$this->assertFalse($this->builder->hasCpp());
|
||||
}
|
||||
|
||||
public function testMakeExtensionArgs()
|
||||
{
|
||||
$this->assertStringContainsString('--enable-mbstring', $this->builder->makeExtensionArgs());
|
||||
}
|
||||
|
||||
public function testIsLibsOnly()
|
||||
{
|
||||
// mbregex is not libs only
|
||||
$this->assertFalse($this->builder->isLibsOnly());
|
||||
}
|
||||
|
||||
public function testGetPHPVersionID()
|
||||
{
|
||||
if (file_exists(SOURCE_PATH . '/php-src/main/php_version.h')) {
|
||||
$file = SOURCE_PATH . '/php-src/main/php_version.h';
|
||||
$cnt = preg_match('/PHP_VERSION_ID (\d+)/m', file_get_contents($file), $match);
|
||||
if ($cnt !== 0) {
|
||||
$this->assertEquals(intval($match[1]), $this->builder->getPHPVersionID());
|
||||
} else {
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->builder->getPHPVersionID();
|
||||
}
|
||||
} else {
|
||||
$this->expectException(WrongUsageException::class);
|
||||
$this->builder->getPHPVersionID();
|
||||
}
|
||||
}
|
||||
|
||||
public function testGetPHPVersion()
|
||||
{
|
||||
if (file_exists(SOURCE_PATH . '/php-src/main/php_version.h')) {
|
||||
$file = SOURCE_PATH . '/php-src/main/php_version.h';
|
||||
$cnt = preg_match('/PHP_VERSION "(\d+\.\d+\.\d+)"/', file_get_contents($file), $match);
|
||||
if ($cnt !== 0) {
|
||||
$this->assertEquals($match[1], $this->builder->getPHPVersion());
|
||||
} else {
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->builder->getPHPVersion();
|
||||
}
|
||||
} else {
|
||||
$this->expectException(WrongUsageException::class);
|
||||
$this->builder->getPHPVersion();
|
||||
}
|
||||
}
|
||||
|
||||
public function testGetPHPVersionFromArchive()
|
||||
{
|
||||
$lock = file_exists(DOWNLOAD_PATH . '/.lock.json') ? file_get_contents(DOWNLOAD_PATH . '/.lock.json') : false;
|
||||
if ($lock === false) {
|
||||
$this->assertFalse($this->builder->getPHPVersionFromArchive());
|
||||
} else {
|
||||
$lock = json_decode($lock, true);
|
||||
$file = $lock['php-src']['filename'] ?? null;
|
||||
if ($file === null) {
|
||||
$this->assertFalse($this->builder->getPHPVersionFromArchive());
|
||||
} else {
|
||||
$cnt = preg_match('/php-(\d+\.\d+\.\d+)/', $file, $match);
|
||||
if ($cnt !== 0) {
|
||||
$this->assertEquals($match[1], $this->builder->getPHPVersionFromArchive());
|
||||
} else {
|
||||
$this->assertFalse($this->builder->getPHPVersionFromArchive());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function testGetMicroVersion()
|
||||
{
|
||||
$file = FileSystem::convertPath(SOURCE_PATH . '/php-src/sapi/micro/php_micro.h');
|
||||
if (!file_exists($file)) {
|
||||
$this->assertFalse($this->builder->getMicroVersion());
|
||||
} else {
|
||||
$content = file_get_contents($file);
|
||||
$ver = '';
|
||||
preg_match('/#define PHP_MICRO_VER_MAJ (\d)/m', $content, $match);
|
||||
$ver .= $match[1] . '.';
|
||||
preg_match('/#define PHP_MICRO_VER_MIN (\d)/m', $content, $match);
|
||||
$ver .= $match[1] . '.';
|
||||
preg_match('/#define PHP_MICRO_VER_PAT (\d)/m', $content, $match);
|
||||
$ver .= $match[1];
|
||||
$this->assertEquals($ver, $this->builder->getMicroVersion());
|
||||
}
|
||||
}
|
||||
|
||||
public static function providerGetBuildTypeName(): array
|
||||
{
|
||||
return [
|
||||
[BUILD_TARGET_CLI, 'cli'],
|
||||
[BUILD_TARGET_FPM, 'fpm'],
|
||||
[BUILD_TARGET_MICRO, 'micro'],
|
||||
[BUILD_TARGET_EMBED, 'embed'],
|
||||
[BUILD_TARGET_ALL, 'cli, micro, fpm, embed'],
|
||||
[BUILD_TARGET_CLI | BUILD_TARGET_EMBED, 'cli, embed'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerGetBuildTypeName
|
||||
*/
|
||||
public function testGetBuildTypeName(int $target, string $name): void
|
||||
{
|
||||
$this->assertEquals($name, $this->builder->getBuildTypeName($target));
|
||||
}
|
||||
|
||||
public function testGetOption()
|
||||
{
|
||||
// we cannot assure the option exists, so just tests default value
|
||||
$this->assertEquals('foo', $this->builder->getOption('bar', 'foo'));
|
||||
}
|
||||
|
||||
public function testGetOptions()
|
||||
{
|
||||
$this->assertIsArray($this->builder->getOptions());
|
||||
}
|
||||
|
||||
public function testSetOptionIfNotExist()
|
||||
{
|
||||
$this->assertEquals(null, $this->builder->getOption('bar'));
|
||||
$this->builder->setOptionIfNotExist('bar', 'foo');
|
||||
$this->assertEquals('foo', $this->builder->getOption('bar'));
|
||||
}
|
||||
|
||||
public function testSetOption()
|
||||
{
|
||||
$this->assertEquals(null, $this->builder->getOption('bar'));
|
||||
$this->builder->setOption('bar', 'foo');
|
||||
$this->assertEquals('foo', $this->builder->getOption('bar'));
|
||||
}
|
||||
|
||||
public function testGetEnvString()
|
||||
{
|
||||
$this->assertIsString($this->builder->getEnvString());
|
||||
putenv('TEST_SPC_BUILDER=foo');
|
||||
$this->assertStringContainsString('TEST_SPC_BUILDER=foo', $this->builder->getEnvString(['TEST_SPC_BUILDER']));
|
||||
}
|
||||
|
||||
public function testValidateLibsAndExts()
|
||||
{
|
||||
$this->builder->validateLibsAndExts();
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public static function providerEmitPatchPoint(): array
|
||||
{
|
||||
return [
|
||||
['before-libs-extract'],
|
||||
['after-libs-extract'],
|
||||
['before-php-extract'],
|
||||
['after-php-extract'],
|
||||
['before-micro-extract'],
|
||||
['after-micro-extract'],
|
||||
['before-exts-extract'],
|
||||
['after-exts-extract'],
|
||||
['before-php-buildconf'],
|
||||
['before-php-configure'],
|
||||
['before-php-make'],
|
||||
['before-sanity-check'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerEmitPatchPoint
|
||||
*/
|
||||
public function testEmitPatchPoint(string $point)
|
||||
{
|
||||
$code = '<?php if (patch_point() === "' . $point . '") echo "GOOD:' . $point . '";';
|
||||
// emulate patch point
|
||||
$this->builder->setOption('with-added-patch', ['/tmp/patch-point.' . $point . '.php']);
|
||||
FileSystem::writeFile('/tmp/patch-point.' . $point . '.php', $code);
|
||||
$this->expectOutputString('GOOD:' . $point);
|
||||
$this->builder->emitPatchPoint($point);
|
||||
}
|
||||
|
||||
public function testEmitPatchPointNotExists()
|
||||
{
|
||||
$this->expectOutputRegex('/failed to run/');
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->builder->setOption('with-added-patch', ['/tmp/patch-point.not_exsssists.php']);
|
||||
$this->builder->emitPatchPoint('not-exists');
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user