mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-09 18:05:36 +08:00
Compare commits
83 Commits
d31e1b00e8
...
2.0.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6c9112575 | ||
|
|
f0a987ba3a | ||
|
|
42b2d36319 | ||
|
|
5d5ffe8866 | ||
|
|
8cd45e3f3f | ||
|
|
baf513bd56 | ||
|
|
5333da35cb | ||
|
|
fe85f138df | ||
|
|
684149eb50 | ||
|
|
8018f2c570 | ||
|
|
2fdbe6ba8c | ||
|
|
018c76ba41 | ||
|
|
48f40b4304 | ||
|
|
528ad1199a | ||
|
|
4c0d35c723 | ||
|
|
1540af266b | ||
|
|
8fb8b34239 | ||
|
|
4b7c2fe84f | ||
|
|
61a76dc0c9 | ||
|
|
e4de37708b | ||
|
|
ea40d25125 | ||
|
|
eacb24a482 | ||
|
|
65a32a977f | ||
|
|
40d09bc82e | ||
|
|
fa437644f5 | ||
|
|
762f6043c5 | ||
|
|
ab1109df90 | ||
|
|
c40da1a71a | ||
|
|
05490c1785 | ||
|
|
103f76e190 | ||
|
|
01bf2ae63b | ||
|
|
03b987c78e | ||
|
|
960addc8f2 | ||
|
|
5b09e95e51 | ||
|
|
2bbb66f844 | ||
|
|
4777f86f7e | ||
|
|
f95b3bcd4b | ||
|
|
6de0d81ea3 | ||
|
|
31fee5645d | ||
|
|
651bb747f1 | ||
|
|
52d787c903 | ||
|
|
0b4253090d | ||
|
|
50a1fcfc20 | ||
|
|
e2aa21fbea | ||
|
|
62aeb6dc7b | ||
|
|
a7d500422d | ||
|
|
76e95b8c55 | ||
|
|
9970986a52 | ||
|
|
abfc60511d | ||
|
|
663d0c05c7 | ||
|
|
76c39ef08a | ||
|
|
bcd45e87c8 | ||
|
|
5c54434300 | ||
|
|
feb20fad83 | ||
|
|
bb52b87d2f | ||
|
|
40b6980cdc | ||
|
|
bbeb399004 | ||
|
|
bdf99ba9f1 | ||
|
|
9161aff942 | ||
|
|
298a758166 | ||
|
|
000ebef28b | ||
|
|
54efec60b8 | ||
|
|
7f5f15a41d | ||
|
|
2766450696 | ||
|
|
24c6a3a637 | ||
|
|
d3b8baa5e7 | ||
|
|
fd57d40ca9 | ||
|
|
feae9b59f5 | ||
|
|
24ce235ed4 | ||
|
|
31a02082de | ||
|
|
f4ebca927b | ||
|
|
84daa9b151 | ||
|
|
213a6680dc | ||
|
|
978b59c0dc | ||
|
|
4063b8454b | ||
|
|
29e0269588 | ||
|
|
1731cc1202 | ||
|
|
09e5c16570 | ||
|
|
3709bcc5e4 | ||
|
|
b9b686b9cf | ||
|
|
b0ac50941f | ||
|
|
b8a58b270c | ||
|
|
a20cc5bd26 |
129
.github/workflows/build.yml
vendored
Normal file
129
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
operating-system:
|
||||||
|
required: true
|
||||||
|
description: Compile target OS
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- ubuntu-latest
|
||||||
|
- macos-latest
|
||||||
|
version:
|
||||||
|
required: true
|
||||||
|
description: php version to compile
|
||||||
|
default: '8.2'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- '8.2'
|
||||||
|
- '8.1'
|
||||||
|
- '8.0'
|
||||||
|
- '7.4'
|
||||||
|
build-cli:
|
||||||
|
description: build cli binary
|
||||||
|
default: true
|
||||||
|
type: boolean
|
||||||
|
build-micro:
|
||||||
|
description: build phpmicro binary
|
||||||
|
type: boolean
|
||||||
|
build-fpm:
|
||||||
|
description: build fpm binary
|
||||||
|
type: boolean
|
||||||
|
extensions:
|
||||||
|
description: extensions to compile (comma separated)
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
debug:
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: build ${{ inputs.version }} on ${{ inputs.operating-system }}
|
||||||
|
runs-on: ${{ inputs.operating-system }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
# Install macOS missing packages and mark os suffix
|
||||||
|
- if: ${{ inputs.operating-system == 'macos-latest' }}
|
||||||
|
run: |
|
||||||
|
brew install automake gzip
|
||||||
|
echo "SPC_BUILD_OS=macos" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# Install Ubuntu missing packages and mark os suffix
|
||||||
|
- if: ${{ inputs.operating-system == 'ubuntu-latest' }}
|
||||||
|
run: |
|
||||||
|
sudo apt install musl-tools -y
|
||||||
|
echo "SPC_BUILD_OS=linux" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# Cache composer dependencies
|
||||||
|
- id: cache-composer-deps
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: vendor
|
||||||
|
key: composer-dependencies
|
||||||
|
|
||||||
|
# If there's no Composer cache, install dependencies
|
||||||
|
- if: steps.cache-composer-deps.outputs.cache-hit != 'true'
|
||||||
|
run: composer update --no-dev
|
||||||
|
|
||||||
|
# Cache downloaded source
|
||||||
|
- id: cache-download
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: downloads
|
||||||
|
key: php-${{ inputs.version }}-dependencies
|
||||||
|
|
||||||
|
# With or without debug
|
||||||
|
- if: inputs.debug == true
|
||||||
|
run: echo "SPC_BUILD_DEBUG=--debug" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# With target select: cli, micro or both
|
||||||
|
- if: ${{ inputs.build-cli == true }}
|
||||||
|
run: echo "SPC_BUILD_CLI=--build-cli" >> $GITHUB_ENV
|
||||||
|
- if: ${{ inputs.build-micro == true }}
|
||||||
|
run: echo "SPC_BUILD_MICRO=--build-micro" >> $GITHUB_ENV
|
||||||
|
- if: ${{ inputs.build-fpm == true }}
|
||||||
|
run: echo "SPC_BUILD_FPM=--build-fpm" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# If there's no dependencies cache, fetch sources, with or without debug
|
||||||
|
- run: CACHE_API_EXEC=yes ./bin/spc fetch --with-php=${{ inputs.version }} --all ${{ env.SPC_BUILD_DEBUG }}
|
||||||
|
|
||||||
|
# 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 }}
|
||||||
|
|
||||||
|
# Upload cli executable
|
||||||
|
- if: ${{ inputs.build-cli == true }}
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: php-${{ inputs.version }}-${{ env.SPC_BUILD_OS }}
|
||||||
|
path: buildroot/bin/php
|
||||||
|
|
||||||
|
# Upload micro self-extracted executable
|
||||||
|
- if: ${{ inputs.build-micro == true }}
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: micro-${{ inputs.version }}-${{ env.SPC_BUILD_OS }}
|
||||||
|
path: buildroot/bin/micro.sfx
|
||||||
|
|
||||||
|
# Upload fpm executable
|
||||||
|
- if: ${{ inputs.build-fpm == true }}
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: php-fpm-${{ inputs.version }}-${{ env.SPC_BUILD_OS }}
|
||||||
|
path: buildroot/bin/php-fpm
|
||||||
|
|
||||||
|
# Upload extensions metadata
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: license-files
|
||||||
|
path: buildroot/license/
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: build-meta
|
||||||
|
path: |
|
||||||
|
buildroot/build-extensions.json
|
||||||
|
buildroot/build-libraries.json
|
||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -19,3 +19,8 @@ composer.lock
|
|||||||
|
|
||||||
# php cs fixer cache file
|
# php cs fixer cache file
|
||||||
.php-cs-fixer.cache
|
.php-cs-fixer.cache
|
||||||
|
|
||||||
|
# exclude self-runtime
|
||||||
|
/bin/*
|
||||||
|
!/bin/spc
|
||||||
|
!/bin/setup-runtime
|
||||||
|
|||||||
161
README-en.md
161
README-en.md
@@ -5,62 +5,144 @@ Compile A Statically Linked PHP With Swoole and other Extensions.
|
|||||||
Compile a purely static PHP binary file with various extensions to make PHP-cli applications more portable!
|
Compile a purely static PHP binary file with various extensions to make PHP-cli applications more portable!
|
||||||
|
|
||||||
You can also use the micro binary file to package PHP source code and binary files into one for distribution!
|
You can also use the micro binary file to package PHP source code and binary files into one for distribution!
|
||||||
|
This function is provided by [dixyes/phpmicro](https://github.com/dixyes/phpmicro).
|
||||||
|
|
||||||
Note: only support cli SAPI, not support fpm, cgi.
|
> This branch is new version, if you are looking for old bash version of static-php-cli, see [bash-version](https://github.com/crazywhalecc/static-php-cli/tree/bash-version).
|
||||||
|
|
||||||
|
[]()
|
||||||
|
[]()
|
||||||
|
[](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml)
|
||||||
|
[]()
|
||||||
|
|
||||||
## Compilation Requirements
|
## Compilation Requirements
|
||||||
|
|
||||||
Yes, this project is written in PHP, pretty funny.
|
Yes, this project is written in PHP, pretty funny.
|
||||||
But php-static-cli only requires an environment above PHP 8.0.
|
But static-php-cli runtime only requires an environment above PHP 8.0 and `tokenizer`, `iconv` extension.
|
||||||
|
|
||||||
- Linux
|
Here is the architecture support status, where `CI` represents support for GitHub Action builds,
|
||||||
- Supported arch: aarch64, amd64
|
`Local` represents support for local builds, and blank represents not currently supported.
|
||||||
- Supported distributions: alpine, ubuntu, centos
|
|
||||||
- Requirements: make, bison, flex, pkg-config, git, autoconf, automake, tar, unzip, gzip, bzip2, cmake
|
| | x86_64 | aarch64 |
|
||||||
- macOS
|
|---------|-----------|---------|
|
||||||
- Supported arch: arm64, x86_64
|
| macOS | CI, Local | Local |
|
||||||
- Requirements: make, bison, flex, pkg-config, git, autoconf, automake, tar, unzip, xz, gzip, bzip2, cmake
|
| Linux | CI, Local | Local |
|
||||||
- Windows
|
| Windows | | |
|
||||||
- Supported arch: x86_64
|
|
||||||
- Requirements: (TODO)
|
> linux-aarch64 and macOS-arm64 is not supported for GitHub Actions, if you are going to build on arm, you can build it manually on your own machine.
|
||||||
- PHP
|
|
||||||
- Supported version: 7.4, 8.0, 8.1, 8.2
|
Currently supported PHP versions for compilation are: `7.4`, `8.0`, `8.1`, `8.2`.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
After stable release for this project, a single phar and single binary for this tool will be published.
|
Please first select the extension you want to compile based on the extension list below.
|
||||||
|
|
||||||
And currently you may need to clone this branch and edit GitHub Action to build.
|
### Supported Extensions
|
||||||
|
|
||||||
### Compilation
|
[Supported Extension List](/ext-support.md)
|
||||||
|
|
||||||
|
> If there is no extension you need here, you can submit an issue.
|
||||||
|
|
||||||
|
### GitHub Actions Build
|
||||||
|
|
||||||
|
Use GitHub Action to easily build a statically compiled PHP and phpmicro,
|
||||||
|
and at the same time define the extensions to be compiled by yourself.
|
||||||
|
|
||||||
|
1. Fork me.
|
||||||
|
2. Go to the Actions of the project and select `CI`.
|
||||||
|
3. Select `Run workflow`, fill in the PHP version you want to compile, the target type, and the list of extensions. (extensions comma separated, e.g. `bcmath,curl,mbstring`)
|
||||||
|
4. After waiting for about a period of time, enter the corresponding task and get `Artifacts`.
|
||||||
|
|
||||||
|
If you enable `debug`, all logs will be output at build time, including compiled logs, for troubleshooting.
|
||||||
|
|
||||||
|
- When using ubuntu-latest, it will build linux-x86_64 binary.
|
||||||
|
- When using macos-latest, it will build macOS-x86_64 binary.
|
||||||
|
|
||||||
|
### Manual Build
|
||||||
|
|
||||||
|
Clone repo first:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
chmod +x spc
|
git clone https://github.com/crazywhalecc/static-php-cli.git
|
||||||
|
```
|
||||||
|
|
||||||
|
If you have not installed php on your system, you can download single-file php binary and composer first.
|
||||||
|
|
||||||
|
The PHP runtime for static-php-cli itself will be downloaded at `bin/php`, and composer is at `bin/composer`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd static-php-cli
|
||||||
|
chmod +x bin/setup-runtime
|
||||||
|
./bin/setup-runtime
|
||||||
|
|
||||||
|
# Use this php runtime to run static-php-cli compiler
|
||||||
|
./bin/php bin/spc
|
||||||
|
|
||||||
|
# Use composer
|
||||||
|
./bin/php bin/composer
|
||||||
|
```
|
||||||
|
|
||||||
|
Basic usage for building php and micro with some extensions:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd static-php-cli
|
||||||
|
composer update
|
||||||
|
chmod +x bin/spc
|
||||||
|
# Check system tool dependencies, fix them automatically (only support macOS) (TODO: Linux distro support)
|
||||||
|
./bin/spc doctor
|
||||||
# fetch all libraries
|
# fetch all libraries
|
||||||
./spc fetch --all
|
./bin/spc fetch --all
|
||||||
# with bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl extension, build both CLI and phpmicro SAPI
|
# with bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl extension, build both CLI and phpmicro SAPI
|
||||||
./spc build bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl --build-all
|
./bin/spc build bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl --build-cli --build-micro
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use the parameter `--with-php=x.y` to specify the downloaded PHP version, currently supports 7.4 ~ 8.2:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Using PHP >= 8.0 is recommended, because 7.4 cannot use phpmicro
|
||||||
|
./bin/spc fetch --with-php=8.2 --all
|
||||||
|
```
|
||||||
|
|
||||||
|
Now we support `cli`, `micro`, `fpm`, you can use one or more of the following parameters to specify the compiled SAPI:
|
||||||
|
|
||||||
|
- `--build-cli`: build static cli executable
|
||||||
|
- `--build-micro`: build static phpmicro self-extracted executable
|
||||||
|
- `--build-fpm`: build static fpm binary
|
||||||
|
- `--build-all`: build all
|
||||||
|
|
||||||
|
If anything goes wrong, use `--debug` option to display full terminal output:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./bin/spc build openssl,pcntl,mbstring --debug --build-all
|
||||||
|
./bin/spc fetch --all --debug
|
||||||
```
|
```
|
||||||
|
|
||||||
### php-cli Usage
|
### php-cli Usage
|
||||||
|
|
||||||
When using the parameter `--build-all` or not adding the `--build-micro` parameter,
|
> php-cli is a single static binary, you can use it like normal php installed on your system.
|
||||||
|
|
||||||
|
When using the parameter `--build-cli` or `--build-all`,
|
||||||
the final compilation result will output a binary file named `./php`,
|
the final compilation result will output a binary file named `./php`,
|
||||||
which can be distributed and used directly.
|
which can be distributed and used directly.
|
||||||
This file will be located in the directory `source/php-src/sapi/cli/`, simply copy it out for use.
|
This file will be located in the directory `buildroot/bin/`, copy it out for use.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./php -v
|
cd buildroot/bin/
|
||||||
./php -m
|
./php -v # check version
|
||||||
./php your_code.php
|
./php -m # check extensions
|
||||||
|
./php your_code.php # run your php code
|
||||||
|
./php your_project.phar # run your phar (project archive)
|
||||||
```
|
```
|
||||||
|
|
||||||
### micro.sfx Usage
|
### micro.sfx Usage
|
||||||
|
|
||||||
|
> phpmicro is a Self-Extracted Executable SAPI module,
|
||||||
|
> provided by [dixyes/phpmicro](https://github.com/dixyes/phpmicro).
|
||||||
|
> It can put php runtime and your source code together.
|
||||||
|
|
||||||
When using the parameter `--build-all` or `--build-micro`,
|
When using the parameter `--build-all` or `--build-micro`,
|
||||||
the final compilation result will output a file named `./micro.sfx`,
|
the final compilation result will output a file named `./micro.sfx`,
|
||||||
which needs to be used with your PHP source code like `code.php`.
|
which needs to be used with your PHP source code like `code.php`.
|
||||||
This file will be located in the directory `source/php-src/sapi/micro/`, simply copy it out for use.
|
This file will be located in the path `buildroot/bin/micro.sfx`, simply copy it out for use.
|
||||||
|
|
||||||
Prepare your project source code, which can be a single PHP file or a Phar file, for use.
|
Prepare your project source code, which can be a single PHP file or a Phar file, for use.
|
||||||
|
|
||||||
@@ -69,11 +151,22 @@ echo "<?php echo 'Hello world' . PHP_EOL;" > code.php
|
|||||||
cat micro.sfx code.php > single-app && chmod +x single-app
|
cat micro.sfx code.php > single-app && chmod +x single-app
|
||||||
./single-app
|
./single-app
|
||||||
|
|
||||||
# If packing a PHAR file, simply replace code.php with the Phar file path.
|
# If packing a PHAR file, replace code.php with the Phar file path.
|
||||||
```
|
```
|
||||||
|
|
||||||
> In some cases, PHAR files may not run in a micro environment.
|
> In some cases, PHAR files may not run in a micro environment.
|
||||||
|
|
||||||
|
### php-fpm Usage
|
||||||
|
|
||||||
|
When using the parameter `--build-all` or `--build-fpm`,
|
||||||
|
the final compilation result will output a file named `./php-fpm`,
|
||||||
|
This file will be located in the path `buildroot/bin/`, simply copy it out for use.
|
||||||
|
|
||||||
|
In normal Linux distributions and macOS systems, the package manager will automatically generate a default fpm configuration file after installing php-fpm.
|
||||||
|
Because php-fpm must specify a configuration file before running, the php-fpm compiled by this project will not have any configuration files, so you need to write `php-fpm.conf` and `pool.conf` configuration files yourself.
|
||||||
|
|
||||||
|
Specifying `php-fpm.conf` can use the command parameter `-y`, for example: `./php-fpm -y php-fpm.conf`.
|
||||||
|
|
||||||
## Current Status
|
## Current Status
|
||||||
|
|
||||||
- [X] Basic CLI framework (by `symfony/console`)
|
- [X] Basic CLI framework (by `symfony/console`)
|
||||||
@@ -82,10 +175,9 @@ cat micro.sfx code.php > single-app && chmod +x single-app
|
|||||||
- [X] Exception handler
|
- [X] Exception handler
|
||||||
- [ ] Windows support
|
- [ ] Windows support
|
||||||
- [X] PHP 7.4 support
|
- [X] PHP 7.4 support
|
||||||
|
- [X] fpm support
|
||||||
|
|
||||||
## Supported Extensions
|
More functions and features are coming soon, Bugs and TODOs: https://github.com/crazywhalecc/static-php-cli/issues/32
|
||||||
|
|
||||||
[Support Extension List](/ext-support.md)
|
|
||||||
|
|
||||||
## Contribution
|
## Contribution
|
||||||
|
|
||||||
@@ -107,8 +199,7 @@ The basic principles for contributing are as follows:
|
|||||||
## Open-Source License
|
## Open-Source License
|
||||||
|
|
||||||
This project is based on the tradition of using the MIT License for old versions,
|
This project is based on the tradition of using the MIT License for old versions,
|
||||||
while the new version references source code from some other projects.
|
while the new version references source code from some other projects:
|
||||||
Special thanks to:
|
|
||||||
|
|
||||||
- [dixyes/lwmbs](https://github.com/dixyes/lwmbs) (Mulun Permissive License)
|
- [dixyes/lwmbs](https://github.com/dixyes/lwmbs) (Mulun Permissive License)
|
||||||
- [swoole/swoole-cli](https://github.com/swoole/swoole-cli) (Apache 2.0 LICENSE+SWOOLE-CLI LICENSE)
|
- [swoole/swoole-cli](https://github.com/swoole/swoole-cli) (Apache 2.0 LICENSE+SWOOLE-CLI LICENSE)
|
||||||
@@ -119,3 +210,9 @@ and they all have their own open source licenses.
|
|||||||
|
|
||||||
Please use the `dump-license`(TODO) command to export the open source licenses used in the project after compilation,
|
Please use the `dump-license`(TODO) command to export the open source licenses used in the project after compilation,
|
||||||
and comply with the corresponding project's LICENSE.
|
and comply with the corresponding project's LICENSE.
|
||||||
|
|
||||||
|
## Advanced
|
||||||
|
|
||||||
|
This project is pure open source project, and some modules are separated for developing.
|
||||||
|
|
||||||
|
This section will be improved after refactor version released.
|
||||||
|
|||||||
163
README.md
163
README.md
@@ -1,65 +1,139 @@
|
|||||||
# static-php-cli
|
# static-php-cli
|
||||||
|
|
||||||
Compile A Statically Linked PHP With Swoole and other Extensions. [English README](README-en.md)
|
Compile A Statically Linked PHP With Swoole and other Extensions.
|
||||||
|
|
||||||
|
If you are using English, see [English README](README-en.md).
|
||||||
|
|
||||||
编译纯静态的 PHP Binary 二进制文件,带有各种扩展,让 PHP-cli 应用变得更便携!
|
编译纯静态的 PHP Binary 二进制文件,带有各种扩展,让 PHP-cli 应用变得更便携!
|
||||||
|
|
||||||
同时可以使用 micro 二进制文件,将 PHP 源码和 PHP 二进制构建为一个文件分发!
|
同时可以使用 micro 二进制文件,将 PHP 源码和 PHP 二进制构建为一个文件分发!(由 [dixyes/phpmicro](https://github.com/dixyes/phpmicro) 提供支持)
|
||||||
|
|
||||||
注:只能编译 CLI 模式,暂不支持 CGI 和 FPM 模式。
|
> 此分支为重构的新版,如果你在找纯 Bash 编写的旧版本,请到 [bash-version 分支](https://github.com/crazywhalecc/static-php-cli/tree/bash-version)。
|
||||||
|
|
||||||
[]()
|
[]()
|
||||||
|
[]()
|
||||||
|
[](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml)
|
||||||
|
[]()
|
||||||
|
|
||||||
## 编译环境需求
|
## 编译环境需求
|
||||||
|
|
||||||
是的,本项目采用 PHP 编写,编译前需要一个 PHP 环境,比较滑稽。
|
是的,本项目采用 PHP 编写,编译前需要一个 PHP 环境,比较滑稽。
|
||||||
但本项目默认可通过自身构建的 micro 和 static-php 二进制运行,其他只需要包含 tokenizer 扩展和 PHP 版本大于等于 8.0 即可。
|
但本项目默认可通过自身构建的 micro 和 static-php 二进制运行,其他只需要包含 tokenizer 扩展和 PHP 版本大于等于 8.0 即可。
|
||||||
|
|
||||||
- Linux
|
下面是架构支持情况,`CI` 代表支持 GitHub Action 构建,`Local` 代表支持本地构建,空 代表暂不支持。
|
||||||
- 支持架构: aarch64, amd64
|
|
||||||
- 支持发行版: alpine, ubuntu, centos
|
|
||||||
- 依赖工具: make, bison, flex, pkg-config, git, autoconf, automake, tar, unzip, gzip, bzip2, cmake
|
|
||||||
- macOS
|
|
||||||
- 支持架构: arm64, x86_64
|
|
||||||
- 依赖工具: make, bison, flex, pkg-config, git, autoconf, automake, tar, unzip, xz, gzip, bzip2, cmake
|
|
||||||
- Windows
|
|
||||||
- 支持架构: x86_64
|
|
||||||
- 依赖工具: (TODO)
|
|
||||||
- PHP
|
|
||||||
- 支持版本: 7.4, 8.0, 8.1, 8.2
|
|
||||||
|
|
||||||
## 使用(WIP)
|
| | x86_64 | aarch64 |
|
||||||
|
|---------|-----------|---------|
|
||||||
|
| macOS | CI, Local | Local |
|
||||||
|
| Linux | CI, Local | Local |
|
||||||
|
| Windows | | |
|
||||||
|
|
||||||
> 你正在看的是重构后的 static-php-cli 编译项目,新项目还未完全重构,所以还有大量的扩展没有完成。
|
> linux-aarch64 and macOS-arm64 因 GitHub 暂未提供 arm runner,如果要构建 arm 二进制,可以使用手动构建。
|
||||||
> 你可以阅读使用 bash 编写的仅为 Linux 系统使用的静态编译脚本和 Docker,详见 bash-version 分支。 旧版本未来将会切换为次要版本,提供有限支持。
|
|
||||||
|
|
||||||
未来会提供一个直接可使用的 phar 包和一个 phpmicro 打包的二进制文件,你可以直接从 Release 中获取并使用:
|
目前支持编译的 PHP 版本为:`7.4`,`8.0`,`8.1`,`8.2`。
|
||||||
|
|
||||||
### 编译
|
## 使用
|
||||||
|
|
||||||
|
请先根据下方扩展列表选择你要编译的扩展。
|
||||||
|
|
||||||
|
### 支持的扩展情况
|
||||||
|
|
||||||
|
[扩展支持列表](/ext-support.md)
|
||||||
|
|
||||||
|
> 如果这里没有你需要的扩展,可以提交 Issue。
|
||||||
|
|
||||||
|
### 使用 Actions 构建
|
||||||
|
|
||||||
|
使用 GitHub Action 可以方便地构建一个静态编译的 PHP 和 phpmicro,同时可以自行定义要编译的扩展。
|
||||||
|
|
||||||
|
1. Fork 本项目。
|
||||||
|
2. 进入项目的 Actions,选择 CI。
|
||||||
|
3. 选择 `Run workflow`,填入你要编译的 PHP 版本、目标类型、扩展列表。(扩展列表使用英文逗号分割,例如 `bcmath,curl,mbstring`)
|
||||||
|
4. 等待大约一段时间后,进入对应的任务中,获取 `Artifacts`。
|
||||||
|
|
||||||
|
如果你选择了 `debug`,则会在构建时输出所有日志,包括编译的日志,以供排查错误。
|
||||||
|
|
||||||
|
### 手动构建
|
||||||
|
|
||||||
|
先克隆本项目:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
chmod +x spc
|
git clone https://github.com/crazywhalecc/static-php-cli.git
|
||||||
|
```
|
||||||
|
|
||||||
|
如果你本机没有安装 PHP,你可以通过命令下载静态编译好的 php-cli 和 Composer。
|
||||||
|
|
||||||
|
下载的 php 和 Composer 将保存为 `bin/php` 和 `bin/composer`。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd static-php-cli
|
||||||
|
chmod +x bin/setup-runtime
|
||||||
|
./bin/setup-runtime
|
||||||
|
|
||||||
|
# 使用独立的 php 运行 static-php-cli
|
||||||
|
./bin/php bin/spc
|
||||||
|
|
||||||
|
# 使用 composer
|
||||||
|
./bin/php bin/composer
|
||||||
|
```
|
||||||
|
|
||||||
|
下面是使用 static-php-cli 编译静态 php 和 micro 的基础用法:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 克隆本项目
|
||||||
|
cd static-php-cli
|
||||||
|
composer update
|
||||||
|
chmod +x bin/spc
|
||||||
|
# 检查环境依赖,并根据提示的命令安装缺失的编译工具(目前仅支持 macOS,Linux 后续会支持)
|
||||||
|
./bin/spc doctor
|
||||||
# 拉取所有依赖库
|
# 拉取所有依赖库
|
||||||
./spc fetch --all
|
./bin/spc fetch --all
|
||||||
# 构建包含 bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl 扩展的 php-cli 和 micro.sfx
|
# 构建包含 bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl 扩展的 php-cli 和 micro.sfx
|
||||||
./spc build "bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl" --build-all
|
./bin/spc build "bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl" --build-cli --build-micro
|
||||||
|
```
|
||||||
|
|
||||||
|
你也可以使用参数 `--with-php=x.y` 来指定下载的 PHP 版本,目前支持 7.4 ~ 8.2:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 优先考虑使用 >= 8.0 的 PHP 版本
|
||||||
|
./bin/spc fetch --with-php=8.2 --all
|
||||||
|
```
|
||||||
|
|
||||||
|
其中,目前支持构建 cli,micro,fpm 三种静态二进制,使用以下参数的一个或多个来指定编译的 SAPI:
|
||||||
|
|
||||||
|
- `--build-cli`:构建 cli 二进制
|
||||||
|
- `--build-micro`:构建 phpmicro 自执行二进制
|
||||||
|
- `--build-fpm`:构建 fpm
|
||||||
|
- `--build-all`:构建所有
|
||||||
|
|
||||||
|
如果出现了任何错误,可以使用 `--debug` 参数来展示完整的输出日志,以供排查错误:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./bin/spc build openssl,pcntl,mbstring --debug --build-all
|
||||||
|
./bin/spc fetch --all --debug
|
||||||
```
|
```
|
||||||
|
|
||||||
### 使用 php-cli
|
### 使用 php-cli
|
||||||
|
|
||||||
采用参数 `--build-all` 或不添加 `--build-micro` 参数时,最后编译结果会输出一个 `./php` 的二进制文件,此文件可分发、可直接使用。
|
> php-cli 是一个静态的二进制文件,类似 Go、Rust 语言编译后的单个可移植的二进制文件。
|
||||||
该文件编译后会存放在 `source/php-src/sapi/cli/` 目录中,拷贝出来即可。
|
|
||||||
|
采用参数 `--build-cli` 或`--build-all` 参数时,最后编译结果会输出一个 `./php` 的二进制文件,此文件可分发、可直接使用。
|
||||||
|
该文件编译后会存放在 `buildroot/bin/` 目录中,名称为 `php`,拷贝出来即可。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./php -v
|
cd buildroot/bin/
|
||||||
./php -m
|
./php -v # 检查版本
|
||||||
./php your_code.php
|
./php -m # 检查编译的扩展
|
||||||
|
./php your_code.php # 运行代码
|
||||||
|
./php your_project.phar # 运行打包为 phar 单文件的项目
|
||||||
```
|
```
|
||||||
|
|
||||||
### 使用 micro.sfx
|
### 使用 micro.sfx
|
||||||
|
|
||||||
采用项目参数 `--build-all` 或 `--build-micro` 时,最后编译结果会输出一个 `./micro.sfx` 的文件,此文件需要配合你的 PHP 源码使用。
|
> phpmicro 是一个提供自执行二进制 PHP 的项目,本项目依赖 phpmicro 进行编译自执行二进制。详见 [dixyes/phpmicro](https://github.com/dixyes/phpmicro)。
|
||||||
该文件编译后会存放在 `source/php-src/sapi/micro/` 目录中,拷贝出来即可。
|
|
||||||
|
采用项目参数 `--build-micro` 或 `--build-all` 时,最后编译结果会输出一个 `./micro.sfx` 的文件,此文件需要配合你的 PHP 源码使用。
|
||||||
|
该文件编译后会存放在 `buildroot/bin/` 目录中,拷贝出来即可。
|
||||||
|
|
||||||
使用时应准备好你的项目源码文件,可以是单个 PHP 文件,也可以是 Phar 文件。
|
使用时应准备好你的项目源码文件,可以是单个 PHP 文件,也可以是 Phar 文件。
|
||||||
|
|
||||||
@@ -73,6 +147,16 @@ cat micro.sfx code.php > single-app && chmod +x single-app
|
|||||||
|
|
||||||
> 有些情况下的 phar 文件可能无法在 micro 环境下运行。
|
> 有些情况下的 phar 文件可能无法在 micro 环境下运行。
|
||||||
|
|
||||||
|
### 使用 php-fpm
|
||||||
|
|
||||||
|
采用项目参数 `--build-fpm` 或 `--build-all` 时,最后编译结果会输出一个 `./php-fpm` 的文件。
|
||||||
|
该文件存放在 `buildroot/bin/` 目录,拷贝出来即可使用。
|
||||||
|
|
||||||
|
在正常的 Linux 发行版和 macOS 系统中,安装 php-fpm 后包管理会自动生成默认的 fpm 配置文件。
|
||||||
|
因为 php-fpm 必须指定配置文件才可启动,本项目编译的 php-fpm 不会带任何配置文件,所以需自行编写 `php-fpm.conf` 和 `pool.conf` 配置文件。
|
||||||
|
|
||||||
|
指定 `php-fpm.conf` 可以使用命令参数 `-y`,例如:`./php-fpm -y php-fpm.conf`。
|
||||||
|
|
||||||
## 项目支持情况
|
## 项目支持情况
|
||||||
|
|
||||||
- [X] 基础结构编写(采用 `symfony/console`)
|
- [X] 基础结构编写(采用 `symfony/console`)
|
||||||
@@ -81,10 +165,9 @@ cat micro.sfx code.php > single-app && chmod +x single-app
|
|||||||
- [ ] Windows 支持
|
- [ ] Windows 支持
|
||||||
- [X] Linux 支持
|
- [X] Linux 支持
|
||||||
- [X] PHP 7.4 支持
|
- [X] PHP 7.4 支持
|
||||||
|
- [X] fpm 支持
|
||||||
|
|
||||||
## 支持的扩展情况
|
更多功能和特性正在陆续支持中,详见:https://github.com/crazywhalecc/static-php-cli/issues/32
|
||||||
|
|
||||||
[扩展支持列表](/ext-support.md)
|
|
||||||
|
|
||||||
## 贡献
|
## 贡献
|
||||||
|
|
||||||
@@ -97,12 +180,20 @@ cat micro.sfx code.php > single-app && chmod +x single-app
|
|||||||
- 应遵循命名规范,例如扩展名称应采取 PHP 内注册的扩展名本身,外部库名应遵循项目本身的名称,内部逻辑的函数、类名、变量等应遵循驼峰、下划线等格式,禁止同一模块混用。
|
- 应遵循命名规范,例如扩展名称应采取 PHP 内注册的扩展名本身,外部库名应遵循项目本身的名称,内部逻辑的函数、类名、变量等应遵循驼峰、下划线等格式,禁止同一模块混用。
|
||||||
- 涉及编译外部库的命令和 Patch 时应注意兼容不同操作系统。
|
- 涉及编译外部库的命令和 Patch 时应注意兼容不同操作系统。
|
||||||
|
|
||||||
|
另外,添加新扩展的贡献方式,可以参考下方 `进阶`。
|
||||||
|
|
||||||
## 开源协议
|
## 开源协议
|
||||||
|
|
||||||
本项目依据旧版本惯例采用 MIT License 开源,新版本采用了部分项目的源代码做参考,特别感谢:
|
本项目依据旧版本惯例采用 MIT License 开源,自身的部分代码引用或修改自以下项目:
|
||||||
|
|
||||||
- [dixyes/lwmbs](https://github.com/dixyes/lwmbs)(木兰宽松许可证)
|
- [dixyes/lwmbs](https://github.com/dixyes/lwmbs)(木兰宽松许可证)
|
||||||
- [swoole/swoole-cli](https://github.com/swoole/swoole-cli)(Apache 2.0 LICENSE+SWOOLE-CLI LICENSE)
|
- [swoole/swoole-cli](https://github.com/swoole/swoole-cli)(Apache 2.0 LICENSE、SWOOLE-CLI LICENSE)
|
||||||
|
|
||||||
因本项目的特殊性,使用项目编译过程中会使用很多其他开源项目,例如 curl、protobuf 等,它们都有各自的开源协议。
|
因本项目的特殊性,使用项目编译过程中会使用很多其他开源项目,例如 curl、protobuf 等,它们都有各自的开源协议。
|
||||||
请在编译完成后,使用命令 `dump-license`(TODO) 导出项目使用项目的开源协议,并遵守对应项目的 LICENSE。
|
请在编译完成后,使用命令 `dump-license`(TODO) 导出项目使用项目的开源协议,并遵守对应项目的 LICENSE。
|
||||||
|
|
||||||
|
## 进阶
|
||||||
|
|
||||||
|
本项目重构分支为模块化编写。
|
||||||
|
|
||||||
|
TODO:这部分将在基础功能完成后编写完成。
|
||||||
|
|||||||
48
bin/setup-runtime
Executable file
48
bin/setup-runtime
Executable file
@@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# set error-quit, verbose, non-variable-quit
|
||||||
|
set -eu
|
||||||
|
# see what system used
|
||||||
|
__OS__=$(uname -s)
|
||||||
|
# see what arch used
|
||||||
|
__ARCH__=$(uname -m)
|
||||||
|
# format arch name
|
||||||
|
case $__ARCH__ in
|
||||||
|
arm64 | aarch64) __ARCH__=arm64 ;;
|
||||||
|
x86_64|x64) __ARCH__=x64 ;;
|
||||||
|
*) ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# format uname
|
||||||
|
case $__OS__ in
|
||||||
|
Darwin) __OS_FIXED__=macos ;;
|
||||||
|
Linux) __OS_FIXED__=linux ;;
|
||||||
|
*) echo "Current OS is not supported" && exit 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# set project dir
|
||||||
|
__DIR__=$(cd "$(dirname "$0")" && pwd)
|
||||||
|
__PROJECT__=$(cd ${__DIR__}/../ && pwd)
|
||||||
|
|
||||||
|
# set download dir
|
||||||
|
__PHP_RUNTIME_URL__="https://github.com/swoole/swoole-src/releases/download/v4.8.13/swoole-cli-v4.8.13-${__OS_FIXED__}-${__ARCH__}.tar.xz"
|
||||||
|
__COMPOSER_URL__="https://getcomposer.org/download/latest-stable/composer.phar"
|
||||||
|
|
||||||
|
# download static-php binary (currently using swoole-cli temporarily)
|
||||||
|
test -d ${__PROJECT__}/downloads || mkdir ${__PROJECT__}/downloads
|
||||||
|
# download static php binary
|
||||||
|
test -f ${__PROJECT__}/downloads/runtime.tar.xz || { echo "Downloading $__PHP_RUNTIME_URL__ ..." && curl -#fSL -o ${__PROJECT__}/downloads/runtime.tar.xz "$__PHP_RUNTIME_URL__" ; }
|
||||||
|
test -f ${__DIR__}/php || { tar -xf ${__PROJECT__}/downloads/runtime.tar.xz -C ${__DIR__}/ && mv ${__DIR__}/swoole-cli ${__DIR__}/php && rm ${__DIR__}/LICENSE ; } # (TODO: temporarily use swoole-cli as php)
|
||||||
|
chmod +x ${__DIR__}/php
|
||||||
|
# download composer
|
||||||
|
test -f ${__DIR__}/composer || curl -#fSL -o ${__DIR__}/composer "$__COMPOSER_URL__"
|
||||||
|
chmod +x ${__DIR__}/composer
|
||||||
|
# sanity check for php and composer
|
||||||
|
${__DIR__}/php -v >/dev/null || { echo "Failed to run php" && exit 1; }
|
||||||
|
${__DIR__}/php ${__DIR__}/composer --version >/dev/null || { echo "Failed to run composer" && exit 1; }
|
||||||
|
|
||||||
|
echo "Setup runtime OK!"
|
||||||
|
echo "runtime bin path needs to add manually by command below:"
|
||||||
|
echo ""
|
||||||
|
echo " export PATH=\"${__DIR__}:\$PATH\""
|
||||||
|
echo ""
|
||||||
2
bin/spc
2
bin/spc
@@ -1,4 +1,4 @@
|
|||||||
#!php
|
#!/usr/bin/env php
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
require_once __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
},
|
},
|
||||||
"bz2": {
|
"bz2": {
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
"arg-type": "custom",
|
"arg-type": "with-prefix",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"bzip2"
|
"bzip2"
|
||||||
]
|
]
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
},
|
},
|
||||||
"curl": {
|
"curl": {
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
"arg-type": "with",
|
"arg-type": "custom",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"curl"
|
"curl"
|
||||||
]
|
]
|
||||||
@@ -28,24 +28,18 @@
|
|||||||
},
|
},
|
||||||
"dom": {
|
"dom": {
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
|
"arg-type": "custom",
|
||||||
"arg-type-windows": "with",
|
"arg-type-windows": "with",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"libxml2",
|
"libxml2",
|
||||||
"zlib"
|
"zlib"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"enchant": {
|
|
||||||
"type": "builtin",
|
|
||||||
"arg-type": "with",
|
|
||||||
"lib-depends": [
|
|
||||||
"enchant2"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"exif": {
|
"exif": {
|
||||||
"type": "builtin"
|
"type": "builtin"
|
||||||
},
|
},
|
||||||
"ffi": {
|
"ffi": {
|
||||||
"arg-type": "with",
|
"arg-type": "custom",
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"libffi"
|
"libffi"
|
||||||
@@ -65,6 +59,7 @@
|
|||||||
},
|
},
|
||||||
"gd": {
|
"gd": {
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
|
"arg-type": "custom",
|
||||||
"arg-type-windows": "with",
|
"arg-type-windows": "with",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"zlib",
|
"zlib",
|
||||||
@@ -104,14 +99,14 @@
|
|||||||
},
|
},
|
||||||
"gmp": {
|
"gmp": {
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
"arg-type": "none",
|
"arg-type": "with-prefix",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"gmp"
|
"gmp"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"iconv": {
|
"iconv": {
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
"arg-type": "with",
|
"arg-type": "with-prefix",
|
||||||
"lib-depends-windows": [
|
"lib-depends-windows": [
|
||||||
"libiconv"
|
"libiconv"
|
||||||
]
|
]
|
||||||
@@ -147,6 +142,7 @@
|
|||||||
},
|
},
|
||||||
"mbstring": {
|
"mbstring": {
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
|
"arg-type": "custom",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"onig"
|
"onig"
|
||||||
]
|
]
|
||||||
@@ -171,7 +167,7 @@
|
|||||||
},
|
},
|
||||||
"openssl": {
|
"openssl": {
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
"arg-type": "with",
|
"arg-type": "custom",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"openssl"
|
"openssl"
|
||||||
]
|
]
|
||||||
@@ -214,7 +210,7 @@
|
|||||||
},
|
},
|
||||||
"phar": {
|
"phar": {
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
"lib-suggests": [
|
"ext-depends": [
|
||||||
"zlib"
|
"zlib"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -222,6 +218,10 @@
|
|||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
"unix-only": true
|
"unix-only": true
|
||||||
},
|
},
|
||||||
|
"protobuf": {
|
||||||
|
"type": "external",
|
||||||
|
"source": "protobuf"
|
||||||
|
},
|
||||||
"pspell": {
|
"pspell": {
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
"arg-type": "with",
|
"arg-type": "with",
|
||||||
@@ -242,7 +242,8 @@
|
|||||||
},
|
},
|
||||||
"redis": {
|
"redis": {
|
||||||
"type": "external",
|
"type": "external",
|
||||||
"source": "redis"
|
"source": "redis",
|
||||||
|
"arg-type": "custom"
|
||||||
},
|
},
|
||||||
"session": {
|
"session": {
|
||||||
"type": "builtin"
|
"type": "builtin"
|
||||||
@@ -252,6 +253,7 @@
|
|||||||
},
|
},
|
||||||
"simplexml": {
|
"simplexml": {
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
|
"arg-type": "custom",
|
||||||
"arg-type-windows": "with",
|
"arg-type-windows": "with",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"libxml2"
|
"libxml2"
|
||||||
@@ -266,6 +268,7 @@
|
|||||||
},
|
},
|
||||||
"soap": {
|
"soap": {
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
|
"arg-type": "custom",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"libxml2"
|
"libxml2"
|
||||||
]
|
]
|
||||||
@@ -282,7 +285,7 @@
|
|||||||
},
|
},
|
||||||
"sqlite3": {
|
"sqlite3": {
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
"arg-type": "with",
|
"arg-type": "custom",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"sqlite"
|
"sqlite"
|
||||||
]
|
]
|
||||||
@@ -290,6 +293,7 @@
|
|||||||
"swoole": {
|
"swoole": {
|
||||||
"type": "external",
|
"type": "external",
|
||||||
"source": "swoole",
|
"source": "swoole",
|
||||||
|
"arg-type": "custom",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"openssl"
|
"openssl"
|
||||||
],
|
],
|
||||||
@@ -301,17 +305,20 @@
|
|||||||
],
|
],
|
||||||
"unix-only": true
|
"unix-only": true
|
||||||
},
|
},
|
||||||
|
"inotify": {
|
||||||
|
"type": "external",
|
||||||
|
"source": "inotify"
|
||||||
|
},
|
||||||
"swow": {
|
"swow": {
|
||||||
"type": "external",
|
"type": "external",
|
||||||
"source": "swow",
|
"source": "swow",
|
||||||
"lib-depends": [
|
"arg-type": "custom",
|
||||||
"libuv"
|
|
||||||
],
|
|
||||||
"lib-suggests": [
|
"lib-suggests": [
|
||||||
"openssl",
|
"openssl",
|
||||||
"curl"
|
"curl"
|
||||||
],
|
],
|
||||||
"ext-suggests": [
|
"ext-suggests": [
|
||||||
|
"openssl",
|
||||||
"curl"
|
"curl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -339,6 +346,7 @@
|
|||||||
},
|
},
|
||||||
"xml": {
|
"xml": {
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
|
"arg-type": "custom",
|
||||||
"arg-type-windows": "with",
|
"arg-type-windows": "with",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"libxml2"
|
"libxml2"
|
||||||
@@ -346,12 +354,14 @@
|
|||||||
},
|
},
|
||||||
"xmlreader": {
|
"xmlreader": {
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
|
"arg-type": "custom",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"libxml2"
|
"libxml2"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"xmlwriter": {
|
"xmlwriter": {
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
|
"arg-type": "custom",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"libxml2"
|
"libxml2"
|
||||||
]
|
]
|
||||||
@@ -363,21 +373,17 @@
|
|||||||
"libxslt"
|
"libxslt"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"protobuf": {
|
|
||||||
"type": "external",
|
|
||||||
"source": "protobuf"
|
|
||||||
},
|
|
||||||
"yaml": {
|
"yaml": {
|
||||||
"type": "external",
|
"type": "external",
|
||||||
"source": "yaml",
|
"source": "yaml",
|
||||||
"arg-type": "with",
|
"arg-type": "with-prefix",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"libyaml"
|
"libyaml"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"zip": {
|
"zip": {
|
||||||
"type": "builtin",
|
"type": "builtin",
|
||||||
"arg-type": "with",
|
"arg-type": "custom",
|
||||||
"arg-type-windows": "enable",
|
"arg-type-windows": "enable",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"libzip"
|
"libzip"
|
||||||
@@ -394,6 +400,7 @@
|
|||||||
"zstd": {
|
"zstd": {
|
||||||
"type": "external",
|
"type": "external",
|
||||||
"source": "ext-zstd",
|
"source": "ext-zstd",
|
||||||
|
"arg-type": "custom",
|
||||||
"lib-depends": [
|
"lib-depends": [
|
||||||
"zstd"
|
"zstd"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -49,9 +49,7 @@
|
|||||||
"brotli",
|
"brotli",
|
||||||
"nghttp2",
|
"nghttp2",
|
||||||
"zstd",
|
"zstd",
|
||||||
"openssl",
|
"openssl"
|
||||||
"idn2",
|
|
||||||
"psl"
|
|
||||||
],
|
],
|
||||||
"lib-suggests-windows": [
|
"lib-suggests-windows": [
|
||||||
"zlib",
|
"zlib",
|
||||||
@@ -68,6 +66,22 @@
|
|||||||
"SystemConfiguration"
|
"SystemConfiguration"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"postgresql": {
|
||||||
|
"source": "postgresql",
|
||||||
|
"static-libs-unix": [
|
||||||
|
"libpg.a"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"freetype": {
|
||||||
|
"source": "freetype",
|
||||||
|
"static-libs-unix": [
|
||||||
|
"libfreetype.a"
|
||||||
|
],
|
||||||
|
"headers-unix": [
|
||||||
|
"freetype2/freetype/freetype.h",
|
||||||
|
"freetype2/ft2build.h"
|
||||||
|
]
|
||||||
|
},
|
||||||
"gmp": {
|
"gmp": {
|
||||||
"source": "gmp",
|
"source": "gmp",
|
||||||
"static-libs-unix": [
|
"static-libs-unix": [
|
||||||
@@ -98,7 +112,23 @@
|
|||||||
"ffitarget.h"
|
"ffitarget.h"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"libiconv": {
|
||||||
|
"source": "libiconv",
|
||||||
|
"static-libs-unix": [
|
||||||
|
"libiconv.a"
|
||||||
|
],
|
||||||
|
"headers": [
|
||||||
|
"iconv.h",
|
||||||
|
"libcharset.h",
|
||||||
|
"localcharset.h"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"libmcrypt": {
|
||||||
|
"source": "libmcrypt",
|
||||||
|
"static-libs-unix": [
|
||||||
|
"libmcrypt.a"
|
||||||
|
]
|
||||||
|
},
|
||||||
"libpng": {
|
"libpng": {
|
||||||
"source": "libpng",
|
"source": "libpng",
|
||||||
"static-libs-unix": [
|
"static-libs-unix": [
|
||||||
@@ -158,7 +188,6 @@
|
|||||||
"libiconv"
|
"libiconv"
|
||||||
],
|
],
|
||||||
"lib-suggests": [
|
"lib-suggests": [
|
||||||
"icu",
|
|
||||||
"xz",
|
"xz",
|
||||||
"zlib"
|
"zlib"
|
||||||
],
|
],
|
||||||
@@ -169,17 +198,6 @@
|
|||||||
"pthreads4w"
|
"pthreads4w"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"libiconv": {
|
|
||||||
"source": "libiconv",
|
|
||||||
"static-libs-unix": [
|
|
||||||
"libiconv.a"
|
|
||||||
],
|
|
||||||
"headers": [
|
|
||||||
"iconv.h",
|
|
||||||
"libcharset.h",
|
|
||||||
"localcharset.h"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"libyaml": {
|
"libyaml": {
|
||||||
"source": "libyaml",
|
"source": "libyaml",
|
||||||
"static-libs-unix": [
|
"static-libs-unix": [
|
||||||
@@ -217,28 +235,12 @@
|
|||||||
"openssl"
|
"openssl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"libmcrypt": {
|
|
||||||
"source": "libmcrypt",
|
|
||||||
"static-libs-unix": [
|
|
||||||
"libmcrypt.a"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"mcrypt": {
|
"mcrypt": {
|
||||||
"source": "mcrypt",
|
"source": "mcrypt",
|
||||||
"static-libs-unix": [
|
"static-libs-unix": [
|
||||||
"libmcrypt.a"
|
"libmcrypt.a"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"freetype": {
|
|
||||||
"source": "freetype",
|
|
||||||
"static-libs-unix": [
|
|
||||||
"libfreetype.a"
|
|
||||||
],
|
|
||||||
"headers-unix": [
|
|
||||||
"freetype2/freetype/freetype.h",
|
|
||||||
"freetype2/ft2build.h"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nghttp2": {
|
"nghttp2": {
|
||||||
"source": "nghttp2",
|
"source": "nghttp2",
|
||||||
"static-libs-unix": [
|
"static-libs-unix": [
|
||||||
@@ -268,15 +270,6 @@
|
|||||||
"cunit"
|
"cunit"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"libuv": {
|
|
||||||
"source": "libuv",
|
|
||||||
"static-libs-unix": [
|
|
||||||
"libuv.a"
|
|
||||||
],
|
|
||||||
"headers": [
|
|
||||||
"uv.h"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"onig": {
|
"onig": {
|
||||||
"source": "onig",
|
"source": "onig",
|
||||||
"static-libs-unix": [
|
"static-libs-unix": [
|
||||||
@@ -306,7 +299,7 @@
|
|||||||
"headers": [
|
"headers": [
|
||||||
"openssl"
|
"openssl"
|
||||||
],
|
],
|
||||||
"lib-suggests": [
|
"lib-depends": [
|
||||||
"zlib"
|
"zlib"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -37,13 +37,20 @@
|
|||||||
},
|
},
|
||||||
"freetype": {
|
"freetype": {
|
||||||
"type": "filelist",
|
"type": "filelist",
|
||||||
"url": "https://download.savannah.gnu.org/releases/freetype/",
|
"url": "https://download-mirror.savannah.gnu.org/releases/freetype/",
|
||||||
"regex": "/href=\"(?<file>freetype-(?<version>[^\"]+)\\.tar\\.xz)\"/",
|
"regex": "/href=\"(?<file>freetype-(?<version>[^\"]+)\\.tar\\.xz)\"/",
|
||||||
"license": {
|
"license": {
|
||||||
"type": "file",
|
"type": "file",
|
||||||
"path": "LICENSE.TXT"
|
"path": "LICENSE.TXT"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"postgresql": {
|
||||||
|
"type": "custom",
|
||||||
|
"license": {
|
||||||
|
"type": "file",
|
||||||
|
"path": "COPYRIGHT"
|
||||||
|
}
|
||||||
|
},
|
||||||
"gmp": {
|
"gmp": {
|
||||||
"type": "filelist",
|
"type": "filelist",
|
||||||
"url": "https://gmplib.org/download/gmp/",
|
"url": "https://gmplib.org/download/gmp/",
|
||||||
@@ -62,9 +69,10 @@
|
|||||||
"path": "LICENSE"
|
"path": "LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mcrypt": {
|
"libiconv": {
|
||||||
"type": "url",
|
"type": "filelist",
|
||||||
"url": "https://jaist.dl.sourceforge.net/project/mcrypt/MCrypt/2.6.8/mcrypt-2.6.8.tar.gz",
|
"url": "https://ftp.gnu.org/gnu/libiconv/",
|
||||||
|
"regex": "/href=\"(?<file>libiconv-(?<version>[^\"]+)\\.tar\\.gz)\"/",
|
||||||
"license": {
|
"license": {
|
||||||
"type": "file",
|
"type": "file",
|
||||||
"path": "COPYING"
|
"path": "COPYING"
|
||||||
@@ -105,6 +113,14 @@
|
|||||||
"path": "COPYING"
|
"path": "COPYING"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"libuv": {
|
||||||
|
"type": "ghtar",
|
||||||
|
"repo": "libuv/libuv",
|
||||||
|
"license": {
|
||||||
|
"type": "file",
|
||||||
|
"path": "LICENSE"
|
||||||
|
}
|
||||||
|
},
|
||||||
"libxml2": {
|
"libxml2": {
|
||||||
"type": "url",
|
"type": "url",
|
||||||
"url": "https://gitlab.gnome.org/GNOME/libxml2/-/archive/v2.9.14/libxml2-v2.9.14.tar.gz",
|
"url": "https://gitlab.gnome.org/GNOME/libxml2/-/archive/v2.9.14/libxml2-v2.9.14.tar.gz",
|
||||||
@@ -131,6 +147,14 @@
|
|||||||
"path": "LICENSE"
|
"path": "LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mcrypt": {
|
||||||
|
"type": "url",
|
||||||
|
"url": "https://jaist.dl.sourceforge.net/project/mcrypt/MCrypt/2.6.8/mcrypt-2.6.8.tar.gz",
|
||||||
|
"license": {
|
||||||
|
"type": "file",
|
||||||
|
"path": "COPYING"
|
||||||
|
}
|
||||||
|
},
|
||||||
"micro": {
|
"micro": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"path": "php-src/sapi/micro",
|
"path": "php-src/sapi/micro",
|
||||||
@@ -160,24 +184,6 @@
|
|||||||
"path": "COPYING"
|
"path": "COPYING"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"libuv": {
|
|
||||||
"type": "ghtar",
|
|
||||||
"repo": "libuv/libuv",
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"protobuf": {
|
|
||||||
"type": "url",
|
|
||||||
"url": "http://pecl.php.net/get/protobuf",
|
|
||||||
"path": "php-src/ext/protobuf",
|
|
||||||
"filename": "protobuf.tgz",
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"onig": {
|
"onig": {
|
||||||
"type": "ghrel",
|
"type": "ghrel",
|
||||||
"repo": "kkos/oniguruma",
|
"repo": "kkos/oniguruma",
|
||||||
@@ -196,6 +202,26 @@
|
|||||||
"path": "LICENSE.txt"
|
"path": "LICENSE.txt"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"protobuf": {
|
||||||
|
"type": "url",
|
||||||
|
"url": "http://pecl.php.net/get/protobuf",
|
||||||
|
"path": "php-src/ext/protobuf",
|
||||||
|
"filename": "protobuf.tgz",
|
||||||
|
"license": {
|
||||||
|
"type": "file",
|
||||||
|
"path": "LICENSE"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inotify": {
|
||||||
|
"type": "url",
|
||||||
|
"url": "http://pecl.php.net/get/inotify",
|
||||||
|
"path": "php-src/ext/inotify",
|
||||||
|
"filename": "inotify.tgz",
|
||||||
|
"license": {
|
||||||
|
"type": "file",
|
||||||
|
"path": "LICENSE"
|
||||||
|
}
|
||||||
|
},
|
||||||
"pthreads4w": {
|
"pthreads4w": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"rev": "master",
|
"rev": "master",
|
||||||
@@ -205,6 +231,13 @@
|
|||||||
"path": "LICENSE"
|
"path": "LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"php-src": {
|
||||||
|
"type": "custom",
|
||||||
|
"license": {
|
||||||
|
"type": "file",
|
||||||
|
"path": "LICENSE"
|
||||||
|
}
|
||||||
|
},
|
||||||
"redis": {
|
"redis": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"path": "php-src/ext/redis",
|
"path": "php-src/ext/redis",
|
||||||
@@ -220,7 +253,7 @@
|
|||||||
"url": "https://www.sqlite.org/2023/sqlite-autoconf-3410100.tar.gz",
|
"url": "https://www.sqlite.org/2023/sqlite-autoconf-3410100.tar.gz",
|
||||||
"license": {
|
"license": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"path": "The author disclaims copyright to this source code. In place of\na legal notice, here is a blessing:\n\n * May you do good and not evil.\n * May you find forgiveness for yourself and forgive others.\n * May you share freely, never taking more than you give."
|
"text": "The author disclaims copyright to this source code. In place of\na legal notice, here is a blessing:\n\n * May you do good and not evil.\n * May you find forgiveness for yourself and forgive others.\n * May you share freely, never taking more than you give."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"swoole": {
|
"swoole": {
|
||||||
@@ -243,15 +276,6 @@
|
|||||||
"path": "LICENSE"
|
"path": "LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"libiconv":{
|
|
||||||
"type": "filelist",
|
|
||||||
"url": "https://ftp.gnu.org/gnu/libiconv/",
|
|
||||||
"regex": "/href=\"(?<file>libiconv-(?<version>[^\"]+)\\.tar\\.gz)\"/",
|
|
||||||
"license": {
|
|
||||||
"type": "text",
|
|
||||||
"text": "TODO"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"xz": {
|
"xz": {
|
||||||
"type": "filelist",
|
"type": "filelist",
|
||||||
"url": "https://tukaani.org/xz/",
|
"url": "https://tukaani.org/xz/",
|
||||||
@@ -272,9 +296,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zlib": {
|
"zlib": {
|
||||||
"type": "filelist",
|
"type": "ghrel",
|
||||||
"url": "https://zlib.net/",
|
"repo": "madler/zlib",
|
||||||
"regex": "/href=\"(?<file>zlib-(?<version>[^\"]+)\\.tar\\.gz)\"/i",
|
"match": "zlib.+\\.tar\\.gz",
|
||||||
"license": {
|
"license": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"text": "(C) 1995-2022 Jean-loup Gailly and Mark Adler\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must not\n claim that you wrote the original software. If you use this software\n in a product, an acknowledgment in the product documentation would be\n appreciated but is not required.\n2. Altered source versions must be plainly marked as such, and must not be\n misrepresented as being the original software.\n3. This notice may not be removed or altered from any source distribution.\n\nJean-loup Gailly Mark Adler\njloup@gzip.org madler@alumni.caltech.edu"
|
"text": "(C) 1995-2022 Jean-loup Gailly and Mark Adler\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must not\n claim that you wrote the original software. If you use this software\n in a product, an acknowledgment in the product documentation would be\n appreciated but is not required.\n2. Altered source versions must be plainly marked as such, and must not be\n misrepresented as being the original software.\n3. This notice may not be removed or altered from any source distribution.\n\nJean-loup Gailly Mark Adler\njloup@gzip.org madler@alumni.caltech.edu"
|
||||||
|
|||||||
111
ext-support.md
111
ext-support.md
@@ -3,60 +3,60 @@
|
|||||||
> - yes: supported and tested
|
> - yes: supported and tested
|
||||||
> - untested: supported, but not tested
|
> - untested: supported, but not tested
|
||||||
> - empty: not supported yet
|
> - empty: not supported yet
|
||||||
> - faulty with issue link: not supported yet due to issue
|
> - no with issue link: not supported yet due to issue
|
||||||
|
> - partial with issue link: supported but not perfect due to issue
|
||||||
|
|
||||||
| | Linux | macOS | Windows |
|
| | Linux | macOS | Windows |
|
||||||
|------------|--------------------------------------------------------------------|--------------------------------------------------------------------|---------|
|
|------------|--------------------------------------------------------------------|---------------------------------------------------------------------|---------|
|
||||||
| bcmath | yes | yes | |
|
| bcmath | yes | yes | |
|
||||||
| bz2 | yes | untested | |
|
| bz2 | yes | yes | |
|
||||||
| calendar | yes | yes | |
|
| calendar | yes | yes | |
|
||||||
| ctype | yes | yes | |
|
| ctype | yes | yes | |
|
||||||
| curl | untested | yes | |
|
| curl | yes | yes | |
|
||||||
| date | yes | yes | |
|
| date | yes | yes | |
|
||||||
| dba | yes | yes | |
|
| dba | yes | yes | |
|
||||||
| dom | untested | untested | |
|
| dom | yes | yes | |
|
||||||
| enchant | | | |
|
| enchant | | | |
|
||||||
| event | | | |
|
| event | | | |
|
||||||
| exif | yes | yes | |
|
| exif | yes | yes | |
|
||||||
| filter | yes | yes | |
|
| filter | yes | yes | |
|
||||||
| fileinfo | yes | | |
|
| fileinfo | yes | | |
|
||||||
| ftp | yes | yes | |
|
| ftp | yes | yes | |
|
||||||
| gd | untested | untested | |
|
| gd | yes, untested | yes | |
|
||||||
| gettext | | | |
|
| gettext | | | |
|
||||||
| gmp | untested | untested | |
|
| gmp | yes, untested | yes, untested | |
|
||||||
| hash | yes | yes | |
|
| iconv | yes | | |
|
||||||
| iconv | untested | | |
|
| inotify | yes | yes | |
|
||||||
| inotify | | | |
|
| mbstring | yes | yes | |
|
||||||
| mbstring | yes | yes | |
|
| mcrypt | | [faulty](https://github.com/crazywhalecc/static-php-cli/issues/32) | |
|
||||||
| mcrypt | | [faulty](https://github.com/crazywhalecc/static-php-cli/issues/32) | |
|
| mongodb | yes, untested | | |
|
||||||
| mongodb | untested | | |
|
| mysqli | | | |
|
||||||
| mysqli | | | |
|
| mysqlnd | yes | yes | |
|
||||||
| mysqlnd | yes | yes | |
|
| openssl | yes | yes | |
|
||||||
| openssl | untested | yes | |
|
| pcntl | yes, untested | yes | |
|
||||||
| pcntl | untested | untested | |
|
| pdo | yes | yes | |
|
||||||
| pdo | yes | yes | |
|
| pdo_mysql | yes | yes | |
|
||||||
| pdo_mysql | yes | yes | |
|
| pdo_sqlite | yes | yes | |
|
||||||
| pdo_sqlite | yes | yes | |
|
| pdo_pgsql | | | |
|
||||||
| pdo_pgsql | | | |
|
| phar | yes | yes | |
|
||||||
| phar | yes | yes | |
|
| posix | yes | yes | |
|
||||||
| posix | yes | yes | |
|
| protobuf | yes, untested | | |
|
||||||
| protobuf | untested | | |
|
| readline | | | |
|
||||||
| readline | | | |
|
| redis | yes | yes | |
|
||||||
| redis | yes | yes | |
|
| session | yes | yes | |
|
||||||
| session | yes | yes | |
|
| shmop | yes, untested | | |
|
||||||
| shmop | untested | | |
|
| simplexml | yes, untested | yes, untested | |
|
||||||
| simplexml | untested | untested | |
|
| soap | yes, untested | | |
|
||||||
| soap | untested | | |
|
| sockets | yes | yes | |
|
||||||
| sockets | untested | | |
|
| sqlite3 | yes, untested | yes, untested | |
|
||||||
| sqlite3 | untested | untested | |
|
| swow | yes | [faulty](https://github.com/crazywhalecc/static-php-cli/issues/32) | |
|
||||||
| swow | | | |
|
| swoole | [faulty](https://github.com/crazywhalecc/static-php-cli/issues/32) | [partial](https://github.com/crazywhalecc/static-php-cli/issues/32) | |
|
||||||
| swoole | [faulty](https://github.com/crazywhalecc/static-php-cli/issues/32) | [faulty](https://github.com/crazywhalecc/static-php-cli/issues/32) | |
|
| tokenizer | yes | yes | |
|
||||||
| tokenizer | yes | yes | |
|
| xml | yes | yes | |
|
||||||
| xml | yes | yes | |
|
| xmlreader | yes, untested | yes, untested | |
|
||||||
| xmlreader | untested | untested | |
|
| xmlwriter | yes, untested | yes, untested | |
|
||||||
| xmlwriter | untested | untested | |
|
| zip | yes, untested | yes | |
|
||||||
| zip | untested | yes | |
|
| zlib | yes | yes | |
|
||||||
| zlib | yes | yes | |
|
|
||||||
|
|
||||||
## Additional Requirements
|
## Additional Requirements
|
||||||
|
|
||||||
@@ -64,6 +64,11 @@
|
|||||||
- swoole >= 5.0 requires PHP >= 8.0
|
- swoole >= 5.0 requires PHP >= 8.0
|
||||||
- swow requires PHP >= 8.0
|
- swow requires PHP >= 8.0
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
- swow and swoole cannot be compiled at the same time.
|
||||||
|
- openssl needs manual configuration for ssl certificate. (TODO: I will write a wiki about it)
|
||||||
|
|
||||||
## Bugs
|
## Bugs
|
||||||
|
|
||||||
See [#32](https://github.com/crazywhalecc/static-php-cli/issues/32).
|
See [#32](https://github.com/crazywhalecc/static-php-cli/issues/32).
|
||||||
|
|||||||
34
quickstart/linux/x86_64/README.md
Normal file
34
quickstart/linux/x86_64/README.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# 快速启动容器环境
|
||||||
|
|
||||||
|
> 提供了 debian 11 构建 和 alpine 构建环境
|
||||||
|
> 任意选一个就可以
|
||||||
|
|
||||||
|
## debian 11 构建环境
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
# 启动 debian 11 容器环境
|
||||||
|
sh quickstart/linux/x86_64/run-debian-11-container.sh
|
||||||
|
|
||||||
|
# 进入容器
|
||||||
|
sh quickstart/linux/x86_64/connection-static-php-cli.sh
|
||||||
|
|
||||||
|
# 准备构建基础软件
|
||||||
|
sh quickstart/linux/x86_64/debian-11-init.sh
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## aline 构建环境
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
# 启动 alpine 容器环境
|
||||||
|
sh quickstart/linux/x86_64/run-alpine-3.16-container.sh
|
||||||
|
|
||||||
|
# 进入容器
|
||||||
|
sh sh quickstart/linux/x86_64/connection-static-php-cli.sh
|
||||||
|
|
||||||
|
# 准备构建基础软件
|
||||||
|
sh quickstart/linux/x86_64/alpine-3.16-init.sh
|
||||||
|
|
||||||
|
```
|
||||||
14
quickstart/linux/x86_64/alpine-3.16-init.sh
Normal file
14
quickstart/linux/x86_64/alpine-3.16-init.sh
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -exu
|
||||||
|
__DIR__=$(
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
pwd
|
||||||
|
)
|
||||||
|
|
||||||
|
test -f /etc/apk/repositories.save || cp /etc/apk/repositories /etc/apk/repositories.save
|
||||||
|
sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories
|
||||||
|
|
||||||
|
apk update
|
||||||
|
|
||||||
|
apk add vim alpine-sdk xz autoconf automake linux-headers clang-dev clang lld libtool cmake bison re2c gettext coreutils
|
||||||
11
quickstart/linux/x86_64/connection-static-php-cli.sh
Normal file
11
quickstart/linux/x86_64/connection-static-php-cli.sh
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -exu
|
||||||
|
__DIR__=$(
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
pwd
|
||||||
|
)
|
||||||
|
|
||||||
|
cd ${__DIR__}
|
||||||
|
|
||||||
|
docker exec -it static-php-cli-dev-1 bash
|
||||||
18
quickstart/linux/x86_64/debian-11-init.sh
Normal file
18
quickstart/linux/x86_64/debian-11-init.sh
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -exu
|
||||||
|
__DIR__=$(
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
pwd
|
||||||
|
)
|
||||||
|
|
||||||
|
sed -i "s@deb.debian.org@mirrors.ustc.edu.cn@g" /etc/apt/sources.list && \
|
||||||
|
sed -i "s@security.debian.org@mirrors.ustc.edu.cn@g" /etc/apt/sources.list
|
||||||
|
|
||||||
|
apt update -y
|
||||||
|
apt install -y git curl wget ca-certificates
|
||||||
|
apt install -y xz-utils autoconf automake libclang-13-dev clang lld libtool cmake bison re2c gettext coreutils lzip zip unzip
|
||||||
|
apt install -y pkg-config bzip2 flex
|
||||||
|
|
||||||
|
|
||||||
|
# apt install build-essential linux-headers-$(uname -r)
|
||||||
25
quickstart/linux/x86_64/prepare.sh
Normal file
25
quickstart/linux/x86_64/prepare.sh
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -exu
|
||||||
|
__DIR__=$(
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
pwd
|
||||||
|
)
|
||||||
|
__PROJECT__=$(
|
||||||
|
cd ${__DIR__}/../../../
|
||||||
|
pwd
|
||||||
|
)
|
||||||
|
cd ${__PROJECT__}
|
||||||
|
|
||||||
|
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
|
||||||
|
|
||||||
|
chmod +x bin/spc
|
||||||
|
|
||||||
|
./bin/spc fetch --all --debug
|
||||||
|
|
||||||
|
./bin/spc list-ext
|
||||||
|
|
||||||
|
|
||||||
|
#./bin/spc build "bcmath,openssl,tokenizer,sqlite3,pdo,pdo_sqlite,ftp,curl" --cc=gcc --cxx=g++ --debug
|
||||||
|
|
||||||
|
./bin/spc build "bcmath,openssl,tokenizer,sqlite3,pdo,pdo_sqlite,ftp,curl" --cc=clang --cxx=clang++ --debug
|
||||||
25
quickstart/linux/x86_64/run-alpine-3.16-container.sh
Normal file
25
quickstart/linux/x86_64/run-alpine-3.16-container.sh
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -exu
|
||||||
|
__DIR__=$(
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
pwd
|
||||||
|
)
|
||||||
|
__PROJECT__=$(
|
||||||
|
cd ${__DIR__}/../../../
|
||||||
|
pwd
|
||||||
|
)
|
||||||
|
cd ${__DIR__}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
docker stop static-php-cli-dev-1
|
||||||
|
} || {
|
||||||
|
echo $?
|
||||||
|
}
|
||||||
|
cd ${__DIR__}
|
||||||
|
IMAGE=alpine:3.16
|
||||||
|
|
||||||
|
cd ${__DIR__}
|
||||||
|
docker run --rm --name static-php-cli-dev-1 -d -v ${__PROJECT__}:/work -w /work $IMAGE tail -f /dev/null
|
||||||
|
|
||||||
25
quickstart/linux/x86_64/run-debian-11-container.sh
Normal file
25
quickstart/linux/x86_64/run-debian-11-container.sh
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -exu
|
||||||
|
__DIR__=$(
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
pwd
|
||||||
|
)
|
||||||
|
__PROJECT__=$(
|
||||||
|
cd ${__DIR__}/../../../
|
||||||
|
pwd
|
||||||
|
)
|
||||||
|
cd ${__DIR__}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
docker stop static-php-cli-dev-1
|
||||||
|
} || {
|
||||||
|
echo $?
|
||||||
|
}
|
||||||
|
cd ${__DIR__}
|
||||||
|
IMAGE=debian:11
|
||||||
|
|
||||||
|
cd ${__DIR__}
|
||||||
|
docker run --rm --name static-php-cli-dev-1 -d -v ${__PROJECT__}:/work -w /work $IMAGE tail -f /dev/null
|
||||||
|
|
||||||
24
quickstart/macOS/x86_64/prepare.sh
Normal file
24
quickstart/macOS/x86_64/prepare.sh
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -exu
|
||||||
|
__DIR__=$(
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
pwd
|
||||||
|
)
|
||||||
|
__PROJECT__=$(
|
||||||
|
cd ${__DIR__}/../../../
|
||||||
|
pwd
|
||||||
|
)
|
||||||
|
cd ${__PROJECT__}
|
||||||
|
|
||||||
|
export PATH=${__PROJECT__}/bin/runtime:$PATH
|
||||||
|
|
||||||
|
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
|
||||||
|
|
||||||
|
chmod +x bin/spc
|
||||||
|
|
||||||
|
./bin/spc fetch --all --debug
|
||||||
|
|
||||||
|
./bin/spc list-ext
|
||||||
|
|
||||||
|
./bin/spc build "bcmath,openssl,tokenizer,sqlite3,pdo,pdo_sqlite,ftp,curl" --cc=clang --cxx=clang++ --debug
|
||||||
@@ -16,7 +16,7 @@ use Symfony\Component\Console\Command\ListCommand;
|
|||||||
*/
|
*/
|
||||||
class ConsoleApplication extends Application
|
class ConsoleApplication extends Application
|
||||||
{
|
{
|
||||||
public const VERSION = '2.0-alpha2';
|
public const VERSION = '2.0-beta2';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws \ReflectionException
|
* @throws \ReflectionException
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use SPC\exception\FileSystemException;
|
|||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\RuntimeException;
|
||||||
use SPC\store\Config;
|
use SPC\store\Config;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
use SPC\util\DependencyUtil;
|
use SPC\util\DependencyUtil;
|
||||||
|
|
||||||
abstract class BuilderBase
|
abstract class BuilderBase
|
||||||
@@ -152,8 +153,10 @@ abstract class BuilderBase
|
|||||||
*/
|
*/
|
||||||
public function proveExts(array $extensions): void
|
public function proveExts(array $extensions): void
|
||||||
{
|
{
|
||||||
|
CustomExt::loadCustomExt();
|
||||||
foreach ($extensions as $extension) {
|
foreach ($extensions as $extension) {
|
||||||
$ext = new Extension($extension, $this);
|
$class = CustomExt::getExtClass($extension);
|
||||||
|
$ext = new $class($extension, $this);
|
||||||
$this->addExt($ext);
|
$this->addExt($ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,15 +170,11 @@ abstract class BuilderBase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始构建 PHP
|
* 开始构建 PHP
|
||||||
* 构建 micro 的规则:
|
|
||||||
* - BUILD_MICRO_NONE(默认):只编译 cli
|
|
||||||
* - BUILD_MICRO_ONLY:只编译 micro
|
|
||||||
* - BUILD_MICRO_BOTH:同时编译 micro 和 cli
|
|
||||||
*
|
*
|
||||||
* @param int $build_micro_rule 规则
|
* @param int $build_target 规则
|
||||||
* @param bool $bloat 保留
|
* @param bool $bloat 保留
|
||||||
*/
|
*/
|
||||||
abstract public function buildPHP(int $build_micro_rule = BUILD_MICRO_NONE, bool $bloat = false);
|
abstract public function buildPHP(int $build_target = BUILD_TARGET_NONE, bool $bloat = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成依赖的扩展编译启用参数
|
* 生成依赖的扩展编译启用参数
|
||||||
@@ -188,7 +187,7 @@ abstract class BuilderBase
|
|||||||
{
|
{
|
||||||
$ret = [];
|
$ret = [];
|
||||||
foreach ($this->exts as $ext) {
|
foreach ($this->exts as $ext) {
|
||||||
$ret[] = $ext->getConfigureArg();
|
$ret[] = trim($ext->getConfigureArg());
|
||||||
}
|
}
|
||||||
logger()->info('Using configure: ' . implode(' ', $ret));
|
logger()->info('Using configure: ' . implode(' ', $ret));
|
||||||
return implode(' ', $ret);
|
return implode(' ', $ret);
|
||||||
@@ -202,6 +201,31 @@ abstract class BuilderBase
|
|||||||
return $this->libs_only;
|
return $this->libs_only;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前即将编译的 PHP 的版本 ID,五位数那个
|
||||||
|
*/
|
||||||
|
public function getPHPVersionID(): int
|
||||||
|
{
|
||||||
|
$file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h');
|
||||||
|
preg_match('/PHP_VERSION_ID (\d+)/', $file, $match);
|
||||||
|
return intval($match[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBuildTypeName(int $type): string
|
||||||
|
{
|
||||||
|
$ls = [];
|
||||||
|
if (($type & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) {
|
||||||
|
$ls[] = 'cli';
|
||||||
|
}
|
||||||
|
if (($type & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO) {
|
||||||
|
$ls[] = 'micro';
|
||||||
|
}
|
||||||
|
if (($type & BUILD_TARGET_FPM) === BUILD_TARGET_FPM) {
|
||||||
|
$ls[] = 'fpm';
|
||||||
|
}
|
||||||
|
return implode(', ', $ls);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查是否存在 lib 库对应的源码,如果不存在,则抛出异常
|
* 检查是否存在 lib 库对应的源码,如果不存在,则抛出异常
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use SPC\builder\linux\LinuxBuilder;
|
|||||||
use SPC\builder\macos\MacOSBuilder;
|
use SPC\builder\macos\MacOSBuilder;
|
||||||
use SPC\builder\windows\WindowsBuilder;
|
use SPC\builder\windows\WindowsBuilder;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\RuntimeException;
|
||||||
|
use SPC\exception\WrongUsageException;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,7 +37,7 @@ class BuilderProvider
|
|||||||
cxx: $input->getOption('cxx'),
|
cxx: $input->getOption('cxx'),
|
||||||
arch: $input->getOption('arch'),
|
arch: $input->getOption('arch'),
|
||||||
),
|
),
|
||||||
default => throw new RuntimeException('Current OS "' . PHP_OS_FAMILY . '" is not supported yet'),
|
default => throw new WrongUsageException('Current OS "' . PHP_OS_FAMILY . '" is not supported yet'),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace SPC\builder;
|
|||||||
|
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\FileSystemException;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\RuntimeException;
|
||||||
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\store\Config;
|
use SPC\store\Config;
|
||||||
|
|
||||||
class Extension
|
class Extension
|
||||||
@@ -13,8 +14,9 @@ class Extension
|
|||||||
protected array $dependencies = [];
|
protected array $dependencies = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws RuntimeException
|
|
||||||
* @throws FileSystemException
|
* @throws FileSystemException
|
||||||
|
* @throws RuntimeException
|
||||||
|
* @throws WrongUsageException
|
||||||
*/
|
*/
|
||||||
public function __construct(protected string $name, protected BuilderBase $builder)
|
public function __construct(protected string $name, protected BuilderBase $builder)
|
||||||
{
|
{
|
||||||
@@ -33,13 +35,14 @@ class Extension
|
|||||||
* 获取开启该扩展的 PHP 编译添加的参数
|
* 获取开启该扩展的 PHP 编译添加的参数
|
||||||
*
|
*
|
||||||
* @throws FileSystemException|RuntimeException
|
* @throws FileSystemException|RuntimeException
|
||||||
|
* @throws WrongUsageException
|
||||||
*/
|
*/
|
||||||
public function getConfigureArg(): string
|
public function getConfigureArg(): string
|
||||||
{
|
{
|
||||||
$arg = $this->getEnableArg();
|
$arg = $this->getEnableArg();
|
||||||
switch (PHP_OS_FAMILY) {
|
switch (PHP_OS_FAMILY) {
|
||||||
case 'Windows':
|
case 'Windows':
|
||||||
$arg .= $this->getWindowsConfigureArg();
|
$arg = $this->getWindowsConfigureArg();
|
||||||
break;
|
break;
|
||||||
case 'Darwin':
|
case 'Darwin':
|
||||||
case 'Linux':
|
case 'Linux':
|
||||||
@@ -54,15 +57,17 @@ class Extension
|
|||||||
*
|
*
|
||||||
* @throws FileSystemException
|
* @throws FileSystemException
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
|
* @throws WrongUsageException
|
||||||
*/
|
*/
|
||||||
public function getEnableArg(): string
|
public function getEnableArg(): string
|
||||||
{
|
{
|
||||||
$_name = str_replace('_', '-', $this->name);
|
$_name = str_replace('_', '-', $this->name);
|
||||||
return match ($arg_type = Config::getExt($this->name, 'arg-type', 'enable')) {
|
return match ($arg_type = Config::getExt($this->name, 'arg-type', 'enable')) {
|
||||||
'enable' => '--enable-' . $_name,
|
'enable' => '--enable-' . $_name . ' ',
|
||||||
'with' => '--with-' . $_name,
|
'with' => '--with-' . $_name . ' ',
|
||||||
|
'with-prefix' => '--with-' . $_name . '="' . BUILD_ROOT_PATH . '" ',
|
||||||
'none', 'custom' => '',
|
'none', 'custom' => '',
|
||||||
default => throw new RuntimeException("argType does not accept {$arg_type}, use [enable/with] ."),
|
default => throw new WrongUsageException("argType does not accept {$arg_type}, use [enable/with/with-prefix] ."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,6 +88,7 @@ class Extension
|
|||||||
*
|
*
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
* @throws FileSystemException
|
* @throws FileSystemException
|
||||||
|
* @throws WrongUsageException
|
||||||
*/
|
*/
|
||||||
public function checkDependency(): static
|
public function checkDependency(): static
|
||||||
{
|
{
|
||||||
@@ -111,6 +117,25 @@ class Extension
|
|||||||
return $this->name;
|
return $this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns extension dist name
|
||||||
|
*/
|
||||||
|
public function getDistName(): string
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getWindowsConfigureArg(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
// Windows is not supported yet
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUnixConfigureArg(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
*/
|
*/
|
||||||
@@ -143,147 +168,6 @@ class Extension
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getWindowsConfigureArg(): string
|
|
||||||
{
|
|
||||||
$arg = '';
|
|
||||||
switch ($this->name) {
|
|
||||||
case 'redis':
|
|
||||||
// $arg = '--enable-redis';
|
|
||||||
// if ($this->builder->getLib('zstd')) {
|
|
||||||
// $arg .= ' --enable-redis-zstd --with-libzstd ';
|
|
||||||
// }
|
|
||||||
break;
|
|
||||||
case 'xml':
|
|
||||||
case 'soap':
|
|
||||||
case 'xmlreader':
|
|
||||||
case 'xmlwriter':
|
|
||||||
case 'dom':
|
|
||||||
$arg .= ' --with-libxml ';
|
|
||||||
break;
|
|
||||||
case 'swow':
|
|
||||||
if ($this->builder->getLib('openssl')) {
|
|
||||||
$arg .= ' --enable-swow-ssl';
|
|
||||||
}
|
|
||||||
if ($this->builder->getLib('curl')) {
|
|
||||||
$arg .= ' --enable-swow-curl';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return $arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getUnixConfigureArg(): string
|
|
||||||
{
|
|
||||||
$arg = '';
|
|
||||||
switch ($this->name) {
|
|
||||||
/*case 'event':
|
|
||||||
$arg = ' --with-event-core --with-event-libevent-dir="' . BUILD_ROOT_PATH . '"';
|
|
||||||
if ($this->builder->getLib('openssl')) {
|
|
||||||
$arg .= ' --with-event-openssl --with-openssl-dir="' . BUILD_ROOT_PATH . '"';
|
|
||||||
}
|
|
||||||
break;*/
|
|
||||||
case 'mbstring':
|
|
||||||
$arg = ' --disable-mbregex ONIG_CFLAGS=-I"' . BUILD_ROOT_PATH . '" ' .
|
|
||||||
'ONIG_LIBS="' . $this->getLibFilesString() . '" ';
|
|
||||||
break;
|
|
||||||
case 'gmp':
|
|
||||||
$arg = ' --with-gmp="' . BUILD_ROOT_PATH . '" ';
|
|
||||||
break;
|
|
||||||
case 'sqlite3':
|
|
||||||
$arg = ' --with-sqlite3="' . BUILD_ROOT_PATH . '" ' .
|
|
||||||
'SQLITE_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ' .
|
|
||||||
'SQLITE_LIBS="' . $this->getLibFilesString() . '" ';
|
|
||||||
break;
|
|
||||||
case 'redis':
|
|
||||||
$arg = ' --enable-redis --disable-redis-session';
|
|
||||||
if ($this->builder->getLib('zstd')) {
|
|
||||||
$arg .= ' --enable-redis-zstd --with-libzstd="' . BUILD_ROOT_PATH . '" ';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'yaml':
|
|
||||||
$arg .= ' --with-yaml="' . BUILD_ROOT_PATH . '" ';
|
|
||||||
break;
|
|
||||||
case 'zstd':
|
|
||||||
$arg .= ' --with-libzstd';
|
|
||||||
break;
|
|
||||||
case 'bz2':
|
|
||||||
$arg = ' --with-bz2="' . BUILD_ROOT_PATH . '" ';
|
|
||||||
break;
|
|
||||||
case 'openssl':
|
|
||||||
$arg .= ' ' .
|
|
||||||
'OPENSSL_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ' .
|
|
||||||
'OPENSSL_LIBS="' . $this->getLibFilesString() . '" ';
|
|
||||||
break;
|
|
||||||
case 'curl':
|
|
||||||
$arg .= ' ' .
|
|
||||||
'CURL_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ' .
|
|
||||||
'CURL_LIBS="' . $this->getLibFilesString() . '" ';
|
|
||||||
break;
|
|
||||||
case 'gd':
|
|
||||||
if ($this->builder->getLib('freetype')) {
|
|
||||||
$arg .= ' --with-freetype ' .
|
|
||||||
'FREETYPE2_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '/freetype2" ' .
|
|
||||||
'FREETYPE2_LIBS="' . $this->getLibFilesString() . '" ';
|
|
||||||
}
|
|
||||||
$arg .= ' ' .
|
|
||||||
'PNG_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ' .
|
|
||||||
'PNG_LIBS="' . $this->getLibFilesString() . '" ';
|
|
||||||
break;
|
|
||||||
// TODO: other libraries
|
|
||||||
case 'phar':
|
|
||||||
case 'zlib':
|
|
||||||
$arg .= ' ' .
|
|
||||||
'ZLIB_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ' .
|
|
||||||
'ZLIB_LIBS="' . $this->getLibFilesString() . '" ';
|
|
||||||
break;
|
|
||||||
case 'xml': // xml may use expat
|
|
||||||
if ($this->getLibraryDependencies()['expat'] ?? null) {
|
|
||||||
$arg .= ' --with-expat="' . BUILD_ROOT_PATH . '" ' .
|
|
||||||
'EXPAT_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ' .
|
|
||||||
'EXPAT_LIBS="' . $this->getLibFilesString() . '" ';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// no break
|
|
||||||
case 'soap':
|
|
||||||
case 'xmlreader':
|
|
||||||
case 'xmlwriter':
|
|
||||||
case 'dom':
|
|
||||||
$arg .= ' --with-libxml="' . BUILD_ROOT_PATH . '" ' .
|
|
||||||
'LIBXML_CFLAGS=-I"' . realpath('include/libxml2') . '" ' .
|
|
||||||
'LIBXML_LIBS="' . $this->getLibFilesString() . '" ';
|
|
||||||
break;
|
|
||||||
case 'ffi':
|
|
||||||
$arg .= ' ' .
|
|
||||||
'FFI_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ' .
|
|
||||||
'FFI_LIBS="' . $this->getLibFilesString() . '" ';
|
|
||||||
break;
|
|
||||||
case 'zip':
|
|
||||||
$arg .= ' ' .
|
|
||||||
'LIBZIP_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ' .
|
|
||||||
'LIBZIP_LIBS="' . $this->getLibFilesString() . '" ';
|
|
||||||
break;
|
|
||||||
case 'mbregex':
|
|
||||||
$arg .= ' ' .
|
|
||||||
'ONIG_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ' .
|
|
||||||
'ONIG_LIBS="' . $this->getLibFilesString() . '" ';
|
|
||||||
break;
|
|
||||||
case 'swow':
|
|
||||||
$arg .= $this->builder->getLib('openssl') ? ' --enable-swow-ssl' : ' --disable-swow-ssl';
|
|
||||||
$arg .= $this->builder->getLib('curl') ? ' --enable-swow-curl' : ' --disable-swow-curl';
|
|
||||||
$arg .= ' SWOW_UV_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ';
|
|
||||||
break;
|
|
||||||
case 'swoole':
|
|
||||||
if ($this->builder->getLib('openssl')) {
|
|
||||||
$arg .= ' --enable-openssl';
|
|
||||||
} else {
|
|
||||||
$arg .= ' --disable-openssl --without-openssl';
|
|
||||||
}
|
|
||||||
// curl hook is buggy for static php
|
|
||||||
$arg .= ' --disable-swoole-curl';
|
|
||||||
}
|
|
||||||
return $arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getLibraryDependencies(bool $recursive = false): array
|
private function getLibraryDependencies(bool $recursive = false): array
|
||||||
{
|
{
|
||||||
$ret = array_filter($this->dependencies, fn ($x) => $x instanceof LibraryBase);
|
$ret = array_filter($this->dependencies, fn ($x) => $x instanceof LibraryBase);
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ abstract class LibraryBase
|
|||||||
{
|
{
|
||||||
// 传入 true,表明直接编译
|
// 传入 true,表明直接编译
|
||||||
if ($force_build) {
|
if ($force_build) {
|
||||||
logger()->info('Building required library ' . static::NAME);
|
logger()->info('Building required library [' . static::NAME . ']');
|
||||||
$this->build();
|
$this->build();
|
||||||
return BUILD_STATUS_OK;
|
return BUILD_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/SPC/builder/extension/curl.php
Normal file
18
src/SPC/builder/extension/curl.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
|
#[CustomExt('curl')]
|
||||||
|
class curl extends Extension
|
||||||
|
{
|
||||||
|
public function getUnixConfigureArg(): string
|
||||||
|
{
|
||||||
|
return '--with-curl CURL_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ' .
|
||||||
|
'CURL_LIBS="' . $this->getLibFilesString() . '"';
|
||||||
|
}
|
||||||
|
}
|
||||||
30
src/SPC/builder/extension/enchant.php
Normal file
30
src/SPC/builder/extension/enchant.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
|
#[CustomExt('enchant')]
|
||||||
|
class enchant extends Extension
|
||||||
|
{
|
||||||
|
public function getUnixConfigureArg(): string
|
||||||
|
{
|
||||||
|
$glibs = [
|
||||||
|
'/Users/jerry/project/git-project/static-php-cli/buildroot/lib/libgio-2.0.a',
|
||||||
|
'/Users/jerry/project/git-project/static-php-cli/buildroot/lib/libglib-2.0.a',
|
||||||
|
'/Users/jerry/project/git-project/static-php-cli/buildroot/lib/libgmodule-2.0.a',
|
||||||
|
'/Users/jerry/project/git-project/static-php-cli/buildroot/lib/libgobject-2.0.a',
|
||||||
|
'/Users/jerry/project/git-project/static-php-cli/buildroot/lib/libgthread-2.0.a',
|
||||||
|
'/Users/jerry/project/git-project/static-php-cli/buildroot/lib/libintl.a',
|
||||||
|
];
|
||||||
|
$arg = '--with-enchant="' . BUILD_ROOT_PATH . '"';
|
||||||
|
$arg .= ' ENCHANT2_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '/enchant-2"';
|
||||||
|
$arg .= ' ENCHANT2_LIBS="' . $this->getLibFilesString() . '"';
|
||||||
|
$arg .= ' GLIB_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '"';
|
||||||
|
$arg .= ' GLIB_LIBS="' . implode(' ', $glibs) . '"';
|
||||||
|
return $arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/SPC/builder/extension/ffi.php
Normal file
18
src/SPC/builder/extension/ffi.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
|
#[CustomExt('ffi')]
|
||||||
|
class ffi extends Extension
|
||||||
|
{
|
||||||
|
public function getUnixConfigureArg(): string
|
||||||
|
{
|
||||||
|
return '--with-ffi FFI_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ' .
|
||||||
|
'FFI_LIBS="' . $this->getLibFilesString() . '"';
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/SPC/builder/extension/gd.php
Normal file
25
src/SPC/builder/extension/gd.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
|
#[CustomExt('gd')]
|
||||||
|
class gd extends Extension
|
||||||
|
{
|
||||||
|
public function getUnixConfigureArg(): string
|
||||||
|
{
|
||||||
|
$arg = '--enable-gd';
|
||||||
|
if ($this->builder->getLib('freetype')) {
|
||||||
|
$arg .= ' --with-freetype ' .
|
||||||
|
'FREETYPE2_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '/freetype2" ' .
|
||||||
|
'FREETYPE2_LIBS="' . $this->getLibFilesString() . '"';
|
||||||
|
}
|
||||||
|
$arg .= ' PNG_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ' .
|
||||||
|
'PNG_LIBS="' . $this->getLibFilesString() . '"';
|
||||||
|
return $arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/SPC/builder/extension/mbregex.php
Normal file
17
src/SPC/builder/extension/mbregex.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
|
#[CustomExt('mbregex')]
|
||||||
|
class mbregex extends Extension
|
||||||
|
{
|
||||||
|
public function getDistName(): string
|
||||||
|
{
|
||||||
|
return 'mbstring';
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/SPC/builder/extension/mbstring.php
Normal file
21
src/SPC/builder/extension/mbstring.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
|
#[CustomExt('mbstring')]
|
||||||
|
class mbstring extends Extension
|
||||||
|
{
|
||||||
|
public function getUnixConfigureArg(): string
|
||||||
|
{
|
||||||
|
$arg = '--enable-mbstring';
|
||||||
|
if ($this->builder->getExt('mbregex') === null) {
|
||||||
|
$arg .= ' --disable-mbregex';
|
||||||
|
}
|
||||||
|
return $arg . ' ONIG_CFLAGS=-I"' . BUILD_ROOT_PATH . '" ONIG_LIBS="' . $this->getLibFilesString() . '"';
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/SPC/builder/extension/openssl.php
Normal file
18
src/SPC/builder/extension/openssl.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
|
#[CustomExt('openssl')]
|
||||||
|
class openssl extends Extension
|
||||||
|
{
|
||||||
|
public function getUnixConfigureArg(): string
|
||||||
|
{
|
||||||
|
return '--with-openssl OPENSSL_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ' .
|
||||||
|
'OPENSSL_LIBS="' . $this->getLibFilesString() . '" ';
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/SPC/builder/extension/redis.php
Normal file
21
src/SPC/builder/extension/redis.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
|
#[CustomExt('redis')]
|
||||||
|
class redis extends Extension
|
||||||
|
{
|
||||||
|
public function getUnixConfigureArg(): string
|
||||||
|
{
|
||||||
|
$arg = '--enable-redis --disable-redis-session';
|
||||||
|
if ($this->builder->getLib('zstd')) {
|
||||||
|
$arg .= ' --enable-redis-zstd --with-libzstd="' . BUILD_ROOT_PATH . '"';
|
||||||
|
}
|
||||||
|
return $arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/SPC/builder/extension/sqlite3.php
Normal file
19
src/SPC/builder/extension/sqlite3.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
|
#[CustomExt('sqlite3')]
|
||||||
|
class sqlite3 extends Extension
|
||||||
|
{
|
||||||
|
public function getUnixConfigureArg(): string
|
||||||
|
{
|
||||||
|
return '--with-sqlite3="' . BUILD_ROOT_PATH . '" ' .
|
||||||
|
'SQLITE_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ' .
|
||||||
|
'SQLITE_LIBS="' . $this->getLibFilesString() . '"';
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/SPC/builder/extension/swoole.php
Normal file
25
src/SPC/builder/extension/swoole.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
|
#[CustomExt('swoole')]
|
||||||
|
class swoole extends Extension
|
||||||
|
{
|
||||||
|
public function getUnixConfigureArg(): string
|
||||||
|
{
|
||||||
|
$arg = '--enable-swoole';
|
||||||
|
if ($this->builder->getLib('openssl')) {
|
||||||
|
$arg .= ' --enable-openssl';
|
||||||
|
} else {
|
||||||
|
$arg .= ' --disable-openssl --without-openssl';
|
||||||
|
}
|
||||||
|
// curl hook is buggy for static php
|
||||||
|
$arg .= ' --disable-swoole-curl';
|
||||||
|
return $arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/SPC/builder/extension/swow.php
Normal file
20
src/SPC/builder/extension/swow.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
|
#[CustomExt('swow')]
|
||||||
|
class swow extends Extension
|
||||||
|
{
|
||||||
|
public function getUnixConfigureArg(): string
|
||||||
|
{
|
||||||
|
$arg = '--enable-swow';
|
||||||
|
$arg .= $this->builder->getLib('openssl') ? ' --enable-swow-ssl' : ' --disable-swow-ssl';
|
||||||
|
$arg .= $this->builder->getLib('curl') ? ' --enable-swow-curl' : ' --disable-swow-curl';
|
||||||
|
return $arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/SPC/builder/extension/xml.php
Normal file
38
src/SPC/builder/extension/xml.php
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\exception\RuntimeException;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
|
#[CustomExt('xml')]
|
||||||
|
#[CustomExt('soap')]
|
||||||
|
#[CustomExt('xmlreader')]
|
||||||
|
#[CustomExt('xmlwriter')]
|
||||||
|
#[CustomExt('dom')]
|
||||||
|
#[CustomExt('simplexml')]
|
||||||
|
class xml extends Extension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @throws RuntimeException
|
||||||
|
*/
|
||||||
|
public function getUnixConfigureArg(): string
|
||||||
|
{
|
||||||
|
$arg = match ($this->name) {
|
||||||
|
'xml' => '--enable-xml',
|
||||||
|
'soap' => '--enable-soap',
|
||||||
|
'xmlreader' => '--enable-xmlreader',
|
||||||
|
'xmlwriter' => '--enable-xmlwriter',
|
||||||
|
'dom' => '--enable-dom',
|
||||||
|
'simplexml' => '--enable-simplexml',
|
||||||
|
default => throw new RuntimeException('Not accept non-xml extension'),
|
||||||
|
};
|
||||||
|
$arg .= ' --with-libxml="' . BUILD_ROOT_PATH . '" ' .
|
||||||
|
'LIBXML_CFLAGS=-I"' . realpath('include/libxml2') . '" ' .
|
||||||
|
'LIBXML_LIBS="' . $this->getLibFilesString() . '" ';
|
||||||
|
return $arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/SPC/builder/extension/zip.php
Normal file
18
src/SPC/builder/extension/zip.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
|
#[CustomExt('zip')]
|
||||||
|
class zip extends Extension
|
||||||
|
{
|
||||||
|
public function getUnixConfigureArg(): string
|
||||||
|
{
|
||||||
|
return '--with-zip LIBZIP_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ' .
|
||||||
|
'LIBZIP_LIBS="' . $this->getLibFilesString() . '"';
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/SPC/builder/extension/zlib.php
Normal file
18
src/SPC/builder/extension/zlib.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
|
#[CustomExt('zlib')]
|
||||||
|
class zlib extends Extension
|
||||||
|
{
|
||||||
|
public function getUnixConfigureArg(): string
|
||||||
|
{
|
||||||
|
return '--with-zlib ZLIB_CFLAGS=-I"' . BUILD_INCLUDE_PATH . '" ' .
|
||||||
|
'ZLIB_LIBS="' . $this->getLibFilesString() . '"';
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/SPC/builder/extension/zstd.php
Normal file
17
src/SPC/builder/extension/zstd.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\extension;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\util\CustomExt;
|
||||||
|
|
||||||
|
#[CustomExt('zstd')]
|
||||||
|
class zstd extends Extension
|
||||||
|
{
|
||||||
|
public function getUnixConfigureArg(): string
|
||||||
|
{
|
||||||
|
return '--with-libzstd';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ use SPC\builder\linux\library\LinuxLibraryBase;
|
|||||||
use SPC\builder\traits\UnixBuilderTrait;
|
use SPC\builder\traits\UnixBuilderTrait;
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\FileSystemException;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\RuntimeException;
|
||||||
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\util\Patcher;
|
use SPC\util\Patcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,6 +41,7 @@ class LinuxBuilder extends BuilderBase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
|
* @throws WrongUsageException
|
||||||
*/
|
*/
|
||||||
public function __construct(?string $cc = null, ?string $cxx = null, ?string $arch = null)
|
public function __construct(?string $cc = null, ?string $cxx = null, ?string $arch = null)
|
||||||
{
|
{
|
||||||
@@ -86,7 +88,7 @@ class LinuxBuilder extends BuilderBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!empty($missing)) {
|
if (!empty($missing)) {
|
||||||
throw new RuntimeException('missing system commands: ' . implode(', ', $missing));
|
throw new WrongUsageException('missing system commands: ' . implode(', ', $missing));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创立 pkg-config 和放头文件的目录
|
// 创立 pkg-config 和放头文件的目录
|
||||||
@@ -119,7 +121,7 @@ class LinuxBuilder extends BuilderBase
|
|||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
* @throws FileSystemException
|
* @throws FileSystemException
|
||||||
*/
|
*/
|
||||||
public function buildPHP(int $build_micro_rule = BUILD_MICRO_NONE, bool $with_clean = false, bool $bloat = false)
|
public function buildPHP(int $build_target = BUILD_TARGET_NONE, bool $with_clean = false, bool $bloat = false)
|
||||||
{
|
{
|
||||||
if (!$bloat) {
|
if (!$bloat) {
|
||||||
$extra_libs = implode(' ', $this->getAllStaticLibFiles());
|
$extra_libs = implode(' ', $this->getAllStaticLibFiles());
|
||||||
@@ -151,7 +153,7 @@ class LinuxBuilder extends BuilderBase
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException('libc ' . $this->libc . ' is not implemented yet');
|
throw new WrongUsageException('libc ' . $this->libc . ' is not implemented yet');
|
||||||
}
|
}
|
||||||
|
|
||||||
$envs = "{$envs} CFLAGS='{$cflags}' LIBS='-ldl -lpthread'";
|
$envs = "{$envs} CFLAGS='{$cflags}' LIBS='-ldl -lpthread'";
|
||||||
@@ -174,6 +176,7 @@ class LinuxBuilder extends BuilderBase
|
|||||||
'--disable-cgi ' .
|
'--disable-cgi ' .
|
||||||
'--disable-phpdbg ' .
|
'--disable-phpdbg ' .
|
||||||
'--enable-cli ' .
|
'--enable-cli ' .
|
||||||
|
'--enable-fpm ' .
|
||||||
'--enable-micro=all-static ' .
|
'--enable-micro=all-static ' .
|
||||||
($this->zts ? '--enable-zts' : '') . ' ' .
|
($this->zts ? '--enable-zts' : '') . ' ' .
|
||||||
$this->makeExtensionArgs() . ' ' .
|
$this->makeExtensionArgs() . ' ' .
|
||||||
@@ -192,31 +195,26 @@ class LinuxBuilder extends BuilderBase
|
|||||||
$extra_libs = "-Wl,--whole-archive {$extra_libs} -Wl,--no-whole-archive";
|
$extra_libs = "-Wl,--whole-archive {$extra_libs} -Wl,--no-whole-archive";
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($build_micro_rule) {
|
if (($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) {
|
||||||
case BUILD_MICRO_NONE:
|
logger()->info('building cli');
|
||||||
logger()->info('building cli');
|
$this->buildCli($extra_libs, $use_lld);
|
||||||
$this->buildCli($extra_libs, $use_lld);
|
}
|
||||||
break;
|
if (($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM) {
|
||||||
case BUILD_MICRO_ONLY:
|
logger()->info('building fpm');
|
||||||
logger()->info('building micro');
|
$this->buildFpm($extra_libs, $use_lld);
|
||||||
$this->buildMicro($extra_libs, $use_lld, $cflags);
|
}
|
||||||
break;
|
if (($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO) {
|
||||||
case BUILD_MICRO_BOTH:
|
logger()->info('building micro');
|
||||||
logger()->info('building cli and micro');
|
$this->buildMicro($extra_libs, $use_lld, $cflags);
|
||||||
$this->buildCli($extra_libs, $use_lld);
|
|
||||||
$this->buildMicro($extra_libs, $use_lld, $cflags);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (php_uname('m') === $this->arch) {
|
if (php_uname('m') === $this->arch) {
|
||||||
$this->sanityCheck($build_micro_rule);
|
$this->sanityCheck($build_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->phar_patched) {
|
if ($this->phar_patched) {
|
||||||
shell()->cd(SOURCE_PATH . '/php-src')->exec('patch -p1 -R < sapi/micro/patches/phar.patch');
|
shell()->cd(SOURCE_PATH . '/php-src')->exec('patch -p1 -R < sapi/micro/patches/phar.patch');
|
||||||
}
|
}
|
||||||
|
|
||||||
file_put_contents(SOURCE_PATH . '/php-src/.extensions.json', json_encode($this->plain_extensions, JSON_PRETTY_PRINT));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -239,7 +237,7 @@ class LinuxBuilder extends BuilderBase
|
|||||||
->exec('elfedit --output-osabi linux php')
|
->exec('elfedit --output-osabi linux php')
|
||||||
->exec("{$this->cross_compile_prefix}strip --strip-all php")
|
->exec("{$this->cross_compile_prefix}strip --strip-all php")
|
||||||
->exec("{$this->cross_compile_prefix}objcopy --update-section .comment=/tmp/comment --add-gnu-debuglink=php.debug --remove-section=.note php");
|
->exec("{$this->cross_compile_prefix}objcopy --update-section .comment=/tmp/comment --add-gnu-debuglink=php.debug --remove-section=.note php");
|
||||||
$this->deployBinary(BUILD_TYPE_CLI);
|
$this->deployBinary(BUILD_TARGET_CLI);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -247,6 +245,9 @@ class LinuxBuilder extends BuilderBase
|
|||||||
*/
|
*/
|
||||||
public function buildMicro(string $extra_libs, string $use_lld, string $cflags): void
|
public function buildMicro(string $extra_libs, string $use_lld, string $cflags): void
|
||||||
{
|
{
|
||||||
|
if ($this->getPHPVersionID() < 80000) {
|
||||||
|
throw new RuntimeException('phpmicro only support PHP >= 8.0!');
|
||||||
|
}
|
||||||
if ($this->getExt('phar')) {
|
if ($this->getExt('phar')) {
|
||||||
$this->phar_patched = true;
|
$this->phar_patched = true;
|
||||||
try {
|
try {
|
||||||
@@ -269,7 +270,30 @@ class LinuxBuilder extends BuilderBase
|
|||||||
|
|
||||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/micro')->exec("{$this->cross_compile_prefix}strip --strip-all micro.sfx");
|
shell()->cd(SOURCE_PATH . '/php-src/sapi/micro')->exec("{$this->cross_compile_prefix}strip --strip-all micro.sfx");
|
||||||
|
|
||||||
$this->deployBinary(BUILD_TYPE_MICRO);
|
$this->deployBinary(BUILD_TARGET_MICRO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws RuntimeException
|
||||||
|
*/
|
||||||
|
public function buildFpm(string $extra_libs, string $use_lld): void
|
||||||
|
{
|
||||||
|
shell()->cd(SOURCE_PATH . '/php-src')
|
||||||
|
->exec('sed -i "s|//lib|/lib|g" Makefile')
|
||||||
|
->exec(
|
||||||
|
'make -j' . $this->concurrency .
|
||||||
|
' EXTRA_CFLAGS="-g -Os -fno-ident ' . implode(' ', array_map(fn ($x) => "-Xcompiler {$x}", $this->tune_c_flags)) . '" ' .
|
||||||
|
"EXTRA_LIBS=\"{$extra_libs}\" " .
|
||||||
|
"EXTRA_LDFLAGS_PROGRAM='{$use_lld} -all-static' " .
|
||||||
|
'fpm'
|
||||||
|
);
|
||||||
|
|
||||||
|
shell()->cd(SOURCE_PATH . '/php-src/sapi/fpm')
|
||||||
|
->exec("{$this->cross_compile_prefix}objcopy --only-keep-debug php-fpm php-fpm.debug")
|
||||||
|
->exec('elfedit --output-osabi linux php-fpm')
|
||||||
|
->exec("{$this->cross_compile_prefix}strip --strip-all php-fpm")
|
||||||
|
->exec("{$this->cross_compile_prefix}objcopy --update-section .comment=/tmp/comment --add-gnu-debuglink=php-fpm.debug --remove-section=.note php-fpm");
|
||||||
|
$this->deployBinary(BUILD_TARGET_FPM);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace SPC\builder\linux;
|
|||||||
use JetBrains\PhpStorm\ArrayShape;
|
use JetBrains\PhpStorm\ArrayShape;
|
||||||
use SPC\builder\traits\UnixSystemUtilTrait;
|
use SPC\builder\traits\UnixSystemUtilTrait;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\RuntimeException;
|
||||||
|
use SPC\exception\WrongUsageException;
|
||||||
|
|
||||||
class SystemUtil
|
class SystemUtil
|
||||||
{
|
{
|
||||||
@@ -128,10 +129,10 @@ class SystemUtil
|
|||||||
'clang' => match ($arch) {
|
'clang' => match ($arch) {
|
||||||
'x86_64' => '--target=x86_64-unknown-linux',
|
'x86_64' => '--target=x86_64-unknown-linux',
|
||||||
'arm64', 'aarch64' => '--target=arm64-unknown-linux',
|
'arm64', 'aarch64' => '--target=arm64-unknown-linux',
|
||||||
default => throw new RuntimeException('unsupported arch: ' . $arch),
|
default => throw new WrongUsageException('unsupported arch: ' . $arch),
|
||||||
},
|
},
|
||||||
'gcc' => '',
|
'gcc' => '',
|
||||||
default => throw new RuntimeException('cc compiler ' . $cc . ' is not supported'),
|
default => throw new WrongUsageException('cc compiler ' . $cc . ' is not supported'),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ abstract class LinuxLibraryBase extends LibraryBase
|
|||||||
{
|
{
|
||||||
// 传入 true,表明直接编译
|
// 传入 true,表明直接编译
|
||||||
if ($force_build) {
|
if ($force_build) {
|
||||||
logger()->info('Building required library ' . static::NAME);
|
logger()->info('Building required library [' . static::NAME . ']');
|
||||||
$this->build();
|
$this->build();
|
||||||
return BUILD_STATUS_OK;
|
return BUILD_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,8 +81,8 @@ EOF
|
|||||||
// lib:zlib
|
// lib:zlib
|
||||||
$zlib = $this->builder->getLib('zlib');
|
$zlib = $this->builder->getLib('zlib');
|
||||||
if ($zlib instanceof LinuxLibraryBase) {
|
if ($zlib instanceof LinuxLibraryBase) {
|
||||||
$extra .= '-DZLIB_LIBRARIES="' . $zlib->getStaticLibFiles(style: 'cmake') . '" ' .
|
$extra .= '-DZLIB_LIBRARY="' . $zlib->getStaticLibFiles(style: 'cmake') . '" ' .
|
||||||
'-DZLIB_INCLUDE_DIRS="' . BUILD_INCLUDE_PATH . '" ';
|
'-DZLIB_INCLUDE_DIR="' . BUILD_INCLUDE_PATH . '" ';
|
||||||
}
|
}
|
||||||
// lib:libssh2
|
// lib:libssh2
|
||||||
$libssh2 = $this->builder->getLib('libssh2');
|
$libssh2 = $this->builder->getLib('libssh2');
|
||||||
@@ -145,13 +145,16 @@ EOF
|
|||||||
->exec("{$this->builder->configure_env} cmake " .
|
->exec("{$this->builder->configure_env} cmake " .
|
||||||
'-DCMAKE_BUILD_TYPE=Release ' .
|
'-DCMAKE_BUILD_TYPE=Release ' .
|
||||||
'-DBUILD_SHARED_LIBS=OFF ' .
|
'-DBUILD_SHARED_LIBS=OFF ' .
|
||||||
|
'-DBUILD_CURL_EXE=OFF ' .
|
||||||
$extra .
|
$extra .
|
||||||
'-DCMAKE_INSTALL_PREFIX=/ ' .
|
"-DCMAKE_INSTALL_PREFIX={$destdir} " .
|
||||||
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
|
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
|
||||||
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
|
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
|
||||||
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
||||||
'..')
|
'..')
|
||||||
->exec("make -j{$this->builder->concurrency}")
|
->exec("make -j{$this->builder->concurrency}")
|
||||||
->exec("make install DESTDIR='{$destdir}'");
|
->exec("make install DESTDIR='{$destdir}'");
|
||||||
|
shell()->cd(BUILD_LIB_PATH . '/cmake/CURL/')
|
||||||
|
->exec("sed -ie 's|\"/lib/libcurl.a\"|\"" . BUILD_LIB_PATH . "/libcurl.a\"|g' CURLTargets-release.cmake");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ class libpng extends LinuxLibraryBase
|
|||||||
Patcher::patchUnixLibpng();
|
Patcher::patchUnixLibpng();
|
||||||
|
|
||||||
shell()->cd($this->source_dir)
|
shell()->cd($this->source_dir)
|
||||||
|
->exec('chmod +x ./configure')
|
||||||
->exec(
|
->exec(
|
||||||
"{$this->builder->configure_env} ./configure " .
|
"{$this->builder->configure_env} ./configure " .
|
||||||
"--host={$this->builder->gnu_arch}-unknown-linux " .
|
"--host={$this->builder->gnu_arch}-unknown-linux " .
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace SPC\builder\linux\library;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* is a template library class for unix
|
|
||||||
*/
|
|
||||||
class libuv extends LinuxLibraryBase
|
|
||||||
{
|
|
||||||
public const NAME = 'libuv';
|
|
||||||
|
|
||||||
protected function build()
|
|
||||||
{
|
|
||||||
[,,$destdir] = SEPARATED_PATH;
|
|
||||||
|
|
||||||
shell()->cd($this->source_dir)
|
|
||||||
->exec('./autogen.sh')
|
|
||||||
->exec(
|
|
||||||
"{$this->builder->configure_env} ./configure " .
|
|
||||||
'--enable-static --disable-shared ' .
|
|
||||||
'--prefix='
|
|
||||||
)
|
|
||||||
->exec('make clean')
|
|
||||||
->exec("make -j{$this->builder->concurrency}")
|
|
||||||
->exec("make install DESTDIR={$destdir}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -40,7 +40,7 @@ class openssl extends LinuxLibraryBase
|
|||||||
$ex_lib = '-ldl -pthread';
|
$ex_lib = '-ldl -pthread';
|
||||||
|
|
||||||
$env = $this->builder->pkgconf_env . " CFLAGS='{$this->builder->arch_c_flags}'";
|
$env = $this->builder->pkgconf_env . " CFLAGS='{$this->builder->arch_c_flags}'";
|
||||||
$env .= " CC='{$this->builder->cc} --static -static-libgcc -idirafter " . BUILD_INCLUDE_PATH .
|
$env .= " CC='{$this->builder->cc} -static -idirafter " . BUILD_INCLUDE_PATH .
|
||||||
' -idirafter /usr/include/ ' .
|
' -idirafter /usr/include/ ' .
|
||||||
' -idirafter /usr/include/' . $this->builder->arch . '-linux-gnu/ ' .
|
' -idirafter /usr/include/' . $this->builder->arch . '-linux-gnu/ ' .
|
||||||
"' ";
|
"' ";
|
||||||
@@ -64,8 +64,8 @@ class openssl extends LinuxLibraryBase
|
|||||||
->exec(
|
->exec(
|
||||||
"{$this->builder->configure_env} {$env} ./Configure no-shared {$extra} " .
|
"{$this->builder->configure_env} {$env} ./Configure no-shared {$extra} " .
|
||||||
'--prefix=/ ' .
|
'--prefix=/ ' .
|
||||||
"--libdir={$lib} " .
|
'--libdir=lib ' .
|
||||||
'--static -static ' .
|
'-static ' .
|
||||||
"{$zlib_extra}" .
|
"{$zlib_extra}" .
|
||||||
'no-legacy ' .
|
'no-legacy ' .
|
||||||
"linux-{$this->builder->arch}{$clang_postfix}"
|
"linux-{$this->builder->arch}{$clang_postfix}"
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use SPC\builder\macos\library\MacOSLibraryBase;
|
|||||||
use SPC\builder\traits\UnixBuilderTrait;
|
use SPC\builder\traits\UnixBuilderTrait;
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\FileSystemException;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\RuntimeException;
|
||||||
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\util\Patcher;
|
use SPC\util\Patcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,14 +21,15 @@ class MacOSBuilder extends BuilderBase
|
|||||||
/** 编译的 Unix 工具集 */
|
/** 编译的 Unix 工具集 */
|
||||||
use UnixBuilderTrait;
|
use UnixBuilderTrait;
|
||||||
|
|
||||||
/** @var string[] MacOS 环境下编译依赖的命令 */
|
|
||||||
public const REQUIRED_COMMANDS = ['make', 'bison', 'flex', 'pkg-config', 'git', 'autoconf', 'automake', 'tar', 'unzip', 'xz', 'gzip', 'bzip2', 'cmake'];
|
|
||||||
|
|
||||||
/** @var bool 标记是否 patch 了 phar */
|
/** @var bool 标记是否 patch 了 phar */
|
||||||
private bool $phar_patched = false;
|
private bool $phar_patched = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param null|string $cc C编译器名称,如果不传入则默认使用clang
|
||||||
|
* @param null|string $cxx C++编译器名称,如果不传入则默认使用clang++
|
||||||
|
* @param null|string $arch 当前架构,如果不传入则默认使用当前系统架构
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
|
* @throws WrongUsageException
|
||||||
*/
|
*/
|
||||||
public function __construct(?string $cc = null, ?string $cxx = null, ?string $arch = null)
|
public function __construct(?string $cc = null, ?string $cxx = null, ?string $arch = null)
|
||||||
{
|
{
|
||||||
@@ -51,16 +53,6 @@ class MacOSBuilder extends BuilderBase
|
|||||||
"CC='{$this->cc}' " .
|
"CC='{$this->cc}' " .
|
||||||
"CXX='{$this->cxx}' " .
|
"CXX='{$this->cxx}' " .
|
||||||
"CFLAGS='{$this->arch_c_flags} -Wimplicit-function-declaration'";
|
"CFLAGS='{$this->arch_c_flags} -Wimplicit-function-declaration'";
|
||||||
// 保存丢失的命令
|
|
||||||
$missing = [];
|
|
||||||
foreach (self::REQUIRED_COMMANDS as $cmd) {
|
|
||||||
if (SystemUtil::findCommand($cmd) === null) {
|
|
||||||
$missing[] = $cmd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!empty($missing)) {
|
|
||||||
throw new RuntimeException('missing system commands: ' . implode(', ', $missing));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创立 pkg-config 和放头文件的目录
|
// 创立 pkg-config 和放头文件的目录
|
||||||
f_mkdir(BUILD_LIB_PATH . '/pkgconfig', recursive: true);
|
f_mkdir(BUILD_LIB_PATH . '/pkgconfig', recursive: true);
|
||||||
@@ -127,7 +119,7 @@ class MacOSBuilder extends BuilderBase
|
|||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
* @throws FileSystemException
|
* @throws FileSystemException
|
||||||
*/
|
*/
|
||||||
public function buildPHP(int $build_micro_rule = BUILD_MICRO_NONE, bool $bloat = false): void
|
public function buildPHP(int $build_target = BUILD_TARGET_NONE, bool $bloat = false): void
|
||||||
{
|
{
|
||||||
$extra_libs = $this->getFrameworks(true) . ' ' . ($this->getExt('swoole') ? '-lc++ ' : '');
|
$extra_libs = $this->getFrameworks(true) . ' ' . ($this->getExt('swoole') ? '-lc++ ' : '');
|
||||||
if (!$bloat) {
|
if (!$bloat) {
|
||||||
@@ -146,11 +138,7 @@ class MacOSBuilder extends BuilderBase
|
|||||||
// patch before configure
|
// patch before configure
|
||||||
Patcher::patchPHPBeforeConfigure($this);
|
Patcher::patchPHPBeforeConfigure($this);
|
||||||
|
|
||||||
f_passthru(
|
shell()->cd(SOURCE_PATH . '/php-src')->exec('./buildconf --force');
|
||||||
$this->set_x . ' && ' .
|
|
||||||
'cd ' . SOURCE_PATH . '/php-src && ' .
|
|
||||||
'./buildconf --force'
|
|
||||||
);
|
|
||||||
|
|
||||||
Patcher::patchPHPConfigure($this);
|
Patcher::patchPHPConfigure($this);
|
||||||
|
|
||||||
@@ -158,46 +146,43 @@ class MacOSBuilder extends BuilderBase
|
|||||||
$extra_libs .= ' -liconv';
|
$extra_libs .= ' -liconv';
|
||||||
}
|
}
|
||||||
|
|
||||||
f_passthru(
|
shell()->cd(SOURCE_PATH . '/php-src')
|
||||||
$this->set_x . ' && ' .
|
->exec(
|
||||||
'cd ' . SOURCE_PATH . '/php-src && ' .
|
'./configure ' .
|
||||||
'./configure ' .
|
'--prefix= ' .
|
||||||
'--prefix= ' .
|
'--with-valgrind=no ' . // 不检测内存泄漏
|
||||||
'--with-valgrind=no ' . // 不检测内存泄漏
|
'--enable-shared=no ' .
|
||||||
'--enable-shared=no ' .
|
'--enable-static=yes ' .
|
||||||
'--enable-static=yes ' .
|
"--host={$this->gnu_arch}-apple-darwin " .
|
||||||
"--host={$this->gnu_arch}-apple-darwin " .
|
"CFLAGS='{$this->arch_c_flags} -Werror=unknown-warning-option' " .
|
||||||
"CFLAGS='{$this->arch_c_flags} -Werror=unknown-warning-option' " .
|
'--disable-all ' .
|
||||||
'--disable-all ' .
|
'--disable-cgi ' .
|
||||||
'--disable-cgi ' .
|
'--disable-phpdbg ' .
|
||||||
'--disable-phpdbg ' .
|
'--enable-cli ' .
|
||||||
'--enable-cli ' .
|
'--enable-fpm ' .
|
||||||
'--enable-micro ' .
|
'--enable-micro ' .
|
||||||
($this->zts ? '--enable-zts' : '') . ' ' .
|
($this->zts ? '--enable-zts' : '') . ' ' .
|
||||||
$this->makeExtensionArgs() . ' ' .
|
$this->makeExtensionArgs() . ' ' .
|
||||||
$this->configure_env
|
$this->configure_env
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->cleanMake();
|
$this->cleanMake();
|
||||||
|
|
||||||
switch ($build_micro_rule) {
|
if (($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) {
|
||||||
case BUILD_MICRO_NONE:
|
logger()->info('building cli');
|
||||||
logger()->info('building cli');
|
$this->buildCli($extra_libs);
|
||||||
$this->buildCli($extra_libs);
|
}
|
||||||
break;
|
if (($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM) {
|
||||||
case BUILD_MICRO_ONLY:
|
logger()->info('building fpm');
|
||||||
logger()->info('building micro');
|
$this->buildFpm($extra_libs);
|
||||||
$this->buildMicro($extra_libs);
|
}
|
||||||
break;
|
if (($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO) {
|
||||||
case BUILD_MICRO_BOTH:
|
logger()->info('building micro');
|
||||||
logger()->info('building cli and micro');
|
$this->buildMicro($extra_libs);
|
||||||
$this->buildCli($extra_libs);
|
|
||||||
$this->buildMicro($extra_libs);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (php_uname('m') === $this->arch) {
|
if (php_uname('m') === $this->arch) {
|
||||||
$this->sanityCheck($build_micro_rule);
|
$this->sanityCheck($build_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->phar_patched) {
|
if ($this->phar_patched) {
|
||||||
@@ -206,9 +191,24 @@ class MacOSBuilder extends BuilderBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建 phpmicro
|
* 构建 cli
|
||||||
*
|
*
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
|
* @throws FileSystemException
|
||||||
|
*/
|
||||||
|
public function buildCli(string $extra_libs): void
|
||||||
|
{
|
||||||
|
shell()->cd(SOURCE_PATH . '/php-src')
|
||||||
|
->exec("make -j{$this->concurrency} EXTRA_CFLAGS=\"-g -Os -fno-ident\" EXTRA_LIBS=\"{$extra_libs} -lresolv\" cli")
|
||||||
|
->exec('dsymutil -f sapi/cli/php')
|
||||||
|
->exec('strip sapi/cli/php');
|
||||||
|
$this->deployBinary(BUILD_TARGET_CLI);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建 phpmicro
|
||||||
|
*
|
||||||
|
* @throws FileSystemException|RuntimeException
|
||||||
*/
|
*/
|
||||||
public function buildMicro(string $extra_libs): void
|
public function buildMicro(string $extra_libs): void
|
||||||
{
|
{
|
||||||
@@ -218,49 +218,31 @@ class MacOSBuilder extends BuilderBase
|
|||||||
if ($this->getExt('phar')) {
|
if ($this->getExt('phar')) {
|
||||||
$this->phar_patched = true;
|
$this->phar_patched = true;
|
||||||
try {
|
try {
|
||||||
f_passthru('cd ' . SOURCE_PATH . '/php-src && patch -p1 < sapi/micro/patches/phar.patch');
|
// TODO: 未来改进一下 patch,让除了这种 patch 类型的文件以外可以恢复原文件
|
||||||
|
shell()->cd(SOURCE_PATH . '/php-src')->exec('patch -p1 < sapi/micro/patches/phar.patch');
|
||||||
} catch (RuntimeException $e) {
|
} catch (RuntimeException $e) {
|
||||||
logger()->error('failed to patch phat due to patch exit with code ' . $e->getCode());
|
logger()->error('failed to patch phat due to patch exit with code ' . $e->getCode());
|
||||||
$this->phar_patched = false;
|
$this->phar_patched = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f_passthru(
|
shell()->cd(SOURCE_PATH . '/php-src')
|
||||||
$this->set_x . ' && ' .
|
->exec("make -j{$this->concurrency} EXTRA_CFLAGS=\"-g -Os -fno-ident\" EXTRA_LIBS=\"{$extra_libs} -lresolv\" STRIP=\"dsymutil -f \" micro");
|
||||||
'cd ' . SOURCE_PATH . '/php-src && ' .
|
$this->deployBinary(BUILD_TARGET_MICRO);
|
||||||
"make -j{$this->concurrency} " .
|
|
||||||
'EXTRA_CFLAGS="-g -Os -fno-ident" ' .
|
|
||||||
"EXTRA_LIBS=\"{$extra_libs} -lresolv\" " .
|
|
||||||
'STRIP="dsymutil -f " ' .
|
|
||||||
// TODO: comment things
|
|
||||||
'micro'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建 cli
|
* 构建 fpm
|
||||||
*
|
*
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
|
* @throws FileSystemException
|
||||||
*/
|
*/
|
||||||
public function buildCli(string $extra_libs): void
|
public function buildFpm(string $extra_libs): void
|
||||||
{
|
{
|
||||||
f_passthru(
|
shell()->cd(SOURCE_PATH . '/php-src')
|
||||||
$this->set_x . ' && ' .
|
->exec("make -j{$this->concurrency} EXTRA_CFLAGS=\"-g -Os -fno-ident\" EXTRA_LIBS=\"{$extra_libs} -lresolv\" fpm")
|
||||||
'cd ' . SOURCE_PATH . '/php-src && ' .
|
->exec('dsymutil -f sapi/fpm/php-fpm')
|
||||||
"make -j{$this->concurrency} " .
|
->exec('strip sapi/fpm/php-fpm');
|
||||||
'EXTRA_CFLAGS="-g -Os -fno-ident" ' . // 生成调试信息、优化编译后的尺寸、禁用标识符(如变量、函数名)缩短
|
$this->deployBinary(BUILD_TARGET_FPM);
|
||||||
"EXTRA_LIBS=\"{$extra_libs} -lresolv\" " .
|
|
||||||
// TODO: comment things
|
|
||||||
'cli &&' .
|
|
||||||
'dsymutil -f sapi/cli/php &&' .
|
|
||||||
'strip sapi/cli/php'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPHPVersionID(): int
|
|
||||||
{
|
|
||||||
$file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h');
|
|
||||||
preg_match('/PHP_VERSION_ID (\d+)/', $file, $match);
|
|
||||||
return intval($match[1]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace SPC\builder\macos;
|
|||||||
|
|
||||||
use SPC\builder\traits\UnixSystemUtilTrait;
|
use SPC\builder\traits\UnixSystemUtilTrait;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\RuntimeException;
|
||||||
|
use SPC\exception\WrongUsageException;
|
||||||
|
|
||||||
class SystemUtil
|
class SystemUtil
|
||||||
{
|
{
|
||||||
@@ -30,14 +31,15 @@ class SystemUtil
|
|||||||
/**
|
/**
|
||||||
* 获取不同架构对应的 cflags 参数
|
* 获取不同架构对应的 cflags 参数
|
||||||
*
|
*
|
||||||
* @throws RuntimeException
|
* @param string $arch 架构名称
|
||||||
|
* @throws WrongUsageException
|
||||||
*/
|
*/
|
||||||
public static function getArchCFlags(string $arch): string
|
public static function getArchCFlags(string $arch): string
|
||||||
{
|
{
|
||||||
return match ($arch) {
|
return match ($arch) {
|
||||||
'x86_64' => '--target=x86_64-apple-darwin',
|
'x86_64' => '--target=x86_64-apple-darwin',
|
||||||
'arm64','aarch64' => '--target=arm64-apple-darwin',
|
'arm64','aarch64' => '--target=arm64-apple-darwin',
|
||||||
default => throw new RuntimeException('unsupported arch: ' . $arch),
|
default => throw new WrongUsageException('unsupported arch: ' . $arch),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,15 +14,8 @@ abstract class MacOSLibraryBase extends LibraryBase
|
|||||||
{
|
{
|
||||||
use UnixLibraryTrait;
|
use UnixLibraryTrait;
|
||||||
|
|
||||||
protected array $static_libs;
|
|
||||||
|
|
||||||
protected array $headers;
|
protected array $headers;
|
||||||
|
|
||||||
/**
|
|
||||||
* 依赖的名字及是否可选,例如:curl => true,代表依赖 curl 但可选
|
|
||||||
*/
|
|
||||||
protected array $dep_names;
|
|
||||||
|
|
||||||
public function __construct(protected MacOSBuilder $builder)
|
public function __construct(protected MacOSBuilder $builder)
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|||||||
@@ -27,23 +27,21 @@ class brotli extends MacOSLibraryBase
|
|||||||
protected function build()
|
protected function build()
|
||||||
{
|
{
|
||||||
[$lib, $include, $destdir] = SEPARATED_PATH;
|
[$lib, $include, $destdir] = SEPARATED_PATH;
|
||||||
f_passthru(
|
shell()->cd($this->source_dir)
|
||||||
"{$this->builder->set_x} && " .
|
->exec('rm -rf build')
|
||||||
"cd {$this->source_dir} && " .
|
->exec('mkdir -p build')
|
||||||
'rm -rf build && ' .
|
->cd($this->source_dir . '/build')
|
||||||
'mkdir -p build && ' .
|
->exec(
|
||||||
'cd build && ' .
|
"{$this->builder->configure_env} cmake " .
|
||||||
"{$this->builder->configure_env} " . ' cmake ' .
|
'-DCMAKE_BUILD_TYPE=Release ' .
|
||||||
// '--debug-find ' .
|
'-DBUILD_SHARED_LIBS=OFF ' .
|
||||||
'-DCMAKE_BUILD_TYPE=Release ' .
|
'-DCMAKE_INSTALL_PREFIX=/ ' .
|
||||||
'-DBUILD_SHARED_LIBS=OFF ' .
|
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
|
||||||
'-DCMAKE_INSTALL_PREFIX=/ ' .
|
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
|
||||||
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
|
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
||||||
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
|
'..'
|
||||||
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
)
|
||||||
'.. && ' .
|
->exec("cmake --build . -j {$this->builder->concurrency}")
|
||||||
"cmake --build . -j {$this->builder->concurrency} && " .
|
->exec("make install DESTDIR={$destdir}");
|
||||||
'make install DESTDIR="' . $destdir . '"'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,14 +26,10 @@ class bzip2 extends MacOSLibraryBase
|
|||||||
|
|
||||||
protected function build()
|
protected function build()
|
||||||
{
|
{
|
||||||
f_passthru(
|
shell()->cd($this->source_dir)
|
||||||
$this->builder->set_x . ' && ' .
|
->exec("make {$this->builder->configure_env} PREFIX='" . BUILD_ROOT_PATH . "' clean")
|
||||||
"cd {$this->source_dir} && " .
|
->exec("make -j{$this->builder->concurrency} {$this->builder->configure_env} PREFIX='" . BUILD_ROOT_PATH . "' libbz2.a")
|
||||||
"make {$this->builder->configure_env} PREFIX='" . BUILD_ROOT_PATH . "' clean" . ' && ' .
|
->exec('cp libbz2.a ' . BUILD_LIB_PATH)
|
||||||
"make -j{$this->builder->concurrency} {$this->builder->configure_env} PREFIX='" . BUILD_ROOT_PATH . "' libbz2.a" . ' && ' .
|
->exec('cp bzlib.h ' . BUILD_INCLUDE_PATH);
|
||||||
// make install may fail when cross-compiling, so we copy files.
|
|
||||||
'cp libbz2.a ' . BUILD_LIB_PATH . ' && ' .
|
|
||||||
'cp bzlib.h ' . BUILD_INCLUDE_PATH
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,24 +95,22 @@ class curl extends MacOSLibraryBase
|
|||||||
|
|
||||||
[$lib, $include, $destdir] = SEPARATED_PATH;
|
[$lib, $include, $destdir] = SEPARATED_PATH;
|
||||||
// compile!
|
// compile!
|
||||||
f_passthru(
|
shell()->cd($this->source_dir)
|
||||||
$this->builder->set_x . ' && ' .
|
->exec('rm -rf build')
|
||||||
"cd {$this->source_dir} && " .
|
->exec('mkdir -p build')
|
||||||
'rm -rf build && ' .
|
->cd($this->source_dir . '/build')
|
||||||
'mkdir -p build && ' .
|
->exec(
|
||||||
'cd build && ' .
|
"{$this->builder->configure_env} cmake " .
|
||||||
"{$this->builder->configure_env} " . ' cmake ' .
|
'-DCMAKE_BUILD_TYPE=Release ' .
|
||||||
// '--debug-find ' .
|
'-DBUILD_SHARED_LIBS=OFF ' .
|
||||||
'-DCMAKE_BUILD_TYPE=Release ' .
|
$extra .
|
||||||
'-DBUILD_SHARED_LIBS=OFF ' .
|
'-DCMAKE_INSTALL_PREFIX= ' .
|
||||||
$extra .
|
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
|
||||||
'-DCMAKE_INSTALL_PREFIX= ' .
|
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
|
||||||
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
|
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
||||||
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
|
'..'
|
||||||
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
)
|
||||||
'.. && ' .
|
->exec("make -j{$this->builder->concurrency}")
|
||||||
"make -j{$this->builder->concurrency} && " .
|
->exec("make install DESTDIR={$destdir}");
|
||||||
'make install DESTDIR="' . $destdir . '"'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,16 +23,14 @@ class freetype extends MacOSLibraryBase
|
|||||||
$suggested .= ($this->builder->getLib('brotli') instanceof MacOSLibraryBase) ? ('--with-brotli=' . BUILD_ROOT_PATH) : '--without-brotli';
|
$suggested .= ($this->builder->getLib('brotli') instanceof MacOSLibraryBase) ? ('--with-brotli=' . BUILD_ROOT_PATH) : '--without-brotli';
|
||||||
$suggested .= ' ';
|
$suggested .= ' ';
|
||||||
|
|
||||||
f_passthru(
|
shell()->cd($this->source_dir)
|
||||||
$this->builder->set_x . ' && ' .
|
->exec(
|
||||||
"cd {$this->source_dir} && " .
|
"{$this->builder->configure_env} ./configure " .
|
||||||
"{$this->builder->configure_env} ./configure " .
|
'--enable-static --disable-shared --without-harfbuzz --prefix= ' .
|
||||||
'--enable-static --disable-shared --without-harfbuzz ' .
|
$suggested
|
||||||
$suggested .
|
)
|
||||||
'--prefix= && ' . // use prefix=/
|
->exec('make clean')
|
||||||
'make clean && ' .
|
->exec("make -j{$this->builder->concurrency}")
|
||||||
"make -j{$this->builder->concurrency} && " .
|
->exec("make install DESTDIR={$destdir}");
|
||||||
'make install DESTDIR=' . $destdir
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,15 +15,14 @@ class gmp extends MacOSLibraryBase
|
|||||||
{
|
{
|
||||||
[,,$destdir] = SEPARATED_PATH;
|
[,,$destdir] = SEPARATED_PATH;
|
||||||
|
|
||||||
f_passthru(
|
shell()->cd($this->source_dir)
|
||||||
$this->builder->set_x . ' && ' .
|
->exec(
|
||||||
"cd {$this->source_dir} && " .
|
"{$this->builder->configure_env} ./configure " .
|
||||||
"{$this->builder->configure_env} ./configure " .
|
'--enable-static --disable-shared ' .
|
||||||
'--enable-static --disable-shared ' .
|
'--prefix='
|
||||||
'--prefix= && ' . // use prefix=/
|
)
|
||||||
'make clean && ' .
|
->exec('make clean')
|
||||||
"make -j{$this->builder->concurrency} && " .
|
->exec("make -j{$this->builder->concurrency}")
|
||||||
'make install DESTDIR=' . $destdir
|
->exec("make install DESTDIR={$destdir}");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,20 +26,19 @@ class libffi extends MacOSLibraryBase
|
|||||||
|
|
||||||
protected function build()
|
protected function build()
|
||||||
{
|
{
|
||||||
[$lib, $include, $destdir] = SEPARATED_PATH;
|
[$lib, , $destdir] = SEPARATED_PATH;
|
||||||
f_passthru(
|
shell()->cd($this->source_dir)
|
||||||
$this->builder->set_x . ' && ' .
|
->exec(
|
||||||
"cd {$this->source_dir} && " .
|
"{$this->builder->configure_env} ./configure " .
|
||||||
"{$this->builder->configure_env} ./configure " .
|
'--enable-static ' .
|
||||||
'--enable-static ' .
|
'--disable-shared ' .
|
||||||
'--disable-shared ' .
|
"--host={$this->builder->arch}-apple-darwin " .
|
||||||
"--host={$this->builder->arch}-apple-darwin " .
|
"--target={$this->builder->arch}-apple-darwin " .
|
||||||
"--target={$this->builder->arch}-apple-darwin " .
|
'--prefix= ' . // use prefix=/
|
||||||
'--prefix= ' . // use prefix=/
|
"--libdir={$lib}"
|
||||||
"--libdir={$lib} && " .
|
)
|
||||||
'make clean && ' .
|
->exec('make clean')
|
||||||
"make -j{$this->builder->concurrency} && " .
|
->exec("make -j{$this->builder->concurrency}")
|
||||||
"make install DESTDIR={$destdir}"
|
->exec("make install DESTDIR={$destdir}");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
47
src/SPC/builder/macos/library/libiconv.php
Normal file
47
src/SPC/builder/macos/library/libiconv.php
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
|
||||||
|
*
|
||||||
|
* lwmbs is licensed under Mulan PSL v2. You can use this
|
||||||
|
* software according to the terms and conditions of the
|
||||||
|
* Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
*
|
||||||
|
* http://license.coscl.org.cn/MulanPSL2
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\builder\macos\library;
|
||||||
|
|
||||||
|
use SPC\exception\RuntimeException;
|
||||||
|
|
||||||
|
class libiconv extends MacOSLibraryBase
|
||||||
|
{
|
||||||
|
public const NAME = 'libiconv';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws RuntimeException
|
||||||
|
*/
|
||||||
|
public function build()
|
||||||
|
{
|
||||||
|
[,,$destdir] = SEPARATED_PATH;
|
||||||
|
|
||||||
|
shell()->cd($this->source_dir)
|
||||||
|
->exec(
|
||||||
|
"{$this->builder->configure_env} ./configure " .
|
||||||
|
'--enable-static ' .
|
||||||
|
'--disable-shared ' .
|
||||||
|
'--prefix='
|
||||||
|
)
|
||||||
|
->exec('make clean')
|
||||||
|
->exec("make -j{$this->builder->concurrency}")
|
||||||
|
->exec('make install DESTDIR=' . $destdir);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,23 +43,21 @@ class libpng extends MacOSLibraryBase
|
|||||||
|
|
||||||
// patch configure
|
// patch configure
|
||||||
Patcher::patchUnixLibpng();
|
Patcher::patchUnixLibpng();
|
||||||
|
shell()->cd($this->source_dir)
|
||||||
f_passthru(
|
->exec('chmod +x ./configure')
|
||||||
$this->builder->set_x . ' && ' .
|
->exec(
|
||||||
"cd {$this->source_dir} && " .
|
"{$this->builder->configure_env} ./configure " .
|
||||||
"{$this->builder->configure_env} " .
|
"--host={$this->builder->gnu_arch}-apple-darwin " .
|
||||||
'./configure ' .
|
'--disable-shared ' .
|
||||||
"--host={$this->builder->gnu_arch}-apple-darwin " .
|
'--enable-static ' .
|
||||||
'--disable-shared ' .
|
'--enable-hardware-optimizations ' .
|
||||||
'--enable-static ' .
|
$optimizations .
|
||||||
'--enable-hardware-optimizations ' .
|
'--prefix='
|
||||||
$optimizations .
|
)
|
||||||
'--prefix= && ' . // use prefix=/
|
->exec('make clean')
|
||||||
'make clean && ' .
|
->exec("make -j{$this->builder->concurrency} DEFAULT_INCLUDES='-I. -I" . BUILD_INCLUDE_PATH . "' LIBS= libpng16.la")
|
||||||
"make -j{$this->builder->concurrency} DEFAULT_INCLUDES='-I. -I" . BUILD_INCLUDE_PATH . "' LIBS= libpng16.la && " .
|
->exec('make install-libLTLIBRARIES install-data-am DESTDIR=' . BUILD_ROOT_PATH)
|
||||||
'make install-libLTLIBRARIES install-data-am DESTDIR=' . BUILD_ROOT_PATH . ' && ' .
|
->cd(BUILD_LIB_PATH)
|
||||||
'cd ' . BUILD_LIB_PATH . ' && ' .
|
->exec('ln -sf libpng16.a libpng.a');
|
||||||
'ln -sf libpng16.a libpng.a'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,26 +31,24 @@ class libssh2 extends MacOSLibraryBase
|
|||||||
|
|
||||||
[$lib, $include, $destdir] = SEPARATED_PATH;
|
[$lib, $include, $destdir] = SEPARATED_PATH;
|
||||||
|
|
||||||
f_passthru(
|
shell()->cd($this->source_dir)
|
||||||
$this->builder->set_x . ' && ' .
|
->exec('rm -rf build')
|
||||||
"cd {$this->source_dir} && " .
|
->exec('mkdir -p build')
|
||||||
'rm -rf build && ' .
|
->cd($this->source_dir . '/build')
|
||||||
'mkdir -p build && ' .
|
->exec(
|
||||||
'cd build && ' .
|
"{$this->builder->configure_env} " . ' cmake ' .
|
||||||
"{$this->builder->configure_env} " . ' cmake ' .
|
'-DCMAKE_BUILD_TYPE=Release ' .
|
||||||
// '--debug-find ' .
|
'-DBUILD_SHARED_LIBS=OFF ' .
|
||||||
'-DCMAKE_BUILD_TYPE=Release ' .
|
'-DBUILD_EXAMPLES=OFF ' .
|
||||||
'-DBUILD_SHARED_LIBS=OFF ' .
|
'-DBUILD_TESTING=OFF ' .
|
||||||
'-DBUILD_EXAMPLES=OFF ' .
|
"-DENABLE_ZLIB_COMPRESSION={$enable_zlib} " .
|
||||||
'-DBUILD_TESTING=OFF ' .
|
'-DCMAKE_INSTALL_PREFIX=/ ' .
|
||||||
"-DENABLE_ZLIB_COMPRESSION={$enable_zlib} " .
|
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
|
||||||
'-DCMAKE_INSTALL_PREFIX=/ ' .
|
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
|
||||||
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
|
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
||||||
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
|
'..'
|
||||||
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
)
|
||||||
'.. && ' .
|
->exec("cmake --build . -j {$this->builder->concurrency} --target libssh2")
|
||||||
"cmake --build . -j {$this->builder->concurrency} --target libssh2 && " .
|
->exec("make install DESTDIR={$destdir}");
|
||||||
'make install DESTDIR="' . $destdir . '"'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace SPC\builder\macos\library;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* is a template library class for unix
|
|
||||||
*/
|
|
||||||
class libuv extends MacOSLibraryBase
|
|
||||||
{
|
|
||||||
public const NAME = 'libuv';
|
|
||||||
|
|
||||||
protected function build()
|
|
||||||
{
|
|
||||||
[,,$destdir] = SEPARATED_PATH;
|
|
||||||
|
|
||||||
f_passthru(
|
|
||||||
$this->builder->set_x . ' && ' .
|
|
||||||
"cd {$this->source_dir} && " .
|
|
||||||
"{$this->builder->configure_env} ./configure " .
|
|
||||||
'--enable-static --disable-shared ' .
|
|
||||||
'--prefix= && ' . // use prefix=/
|
|
||||||
'make clean && ' .
|
|
||||||
"make -j{$this->builder->concurrency} && " .
|
|
||||||
'make install DESTDIR=' . $destdir
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -37,30 +37,29 @@ class libxml2 extends MacOSLibraryBase
|
|||||||
|
|
||||||
[$lib, $include, $destdir] = SEPARATED_PATH;
|
[$lib, $include, $destdir] = SEPARATED_PATH;
|
||||||
|
|
||||||
f_passthru(
|
shell()->cd($this->source_dir)
|
||||||
$this->builder->set_x . ' && ' .
|
->exec('rm -rf build')
|
||||||
"cd {$this->source_dir} && " .
|
->exec('mkdir -p build')
|
||||||
'rm -rf build && ' .
|
->cd($this->source_dir . '/build')
|
||||||
'mkdir -p build && ' .
|
->exec(
|
||||||
'cd build && ' .
|
"{$this->builder->configure_env} " . ' cmake ' .
|
||||||
"{$this->builder->configure_env} " . ' cmake ' .
|
// '--debug-find ' .
|
||||||
// '--debug-find ' .
|
'-DCMAKE_BUILD_TYPE=Release ' .
|
||||||
'-DCMAKE_BUILD_TYPE=Release ' .
|
'-DBUILD_SHARED_LIBS=OFF ' .
|
||||||
'-DBUILD_SHARED_LIBS=OFF ' .
|
'-DLIBXML2_WITH_ICONV=ON ' .
|
||||||
'-DLIBXML2_WITH_ICONV=ON ' .
|
"-DLIBXML2_WITH_ZLIB={$enable_zlib} " .
|
||||||
"-DLIBXML2_WITH_ZLIB={$enable_zlib} " .
|
"-DLIBXML2_WITH_ICU={$enable_icu} " .
|
||||||
"-DLIBXML2_WITH_ICU={$enable_icu} " .
|
"-DLIBXML2_WITH_LZMA={$enable_xz} " .
|
||||||
"-DLIBXML2_WITH_LZMA={$enable_xz} " .
|
'-DLIBXML2_WITH_PYTHON=OFF ' .
|
||||||
'-DLIBXML2_WITH_PYTHON=OFF ' .
|
'-DLIBXML2_WITH_PROGRAMS=OFF ' .
|
||||||
'-DLIBXML2_WITH_PROGRAMS=OFF ' .
|
'-DLIBXML2_WITH_TESTS=OFF ' .
|
||||||
'-DLIBXML2_WITH_TESTS=OFF ' .
|
'-DCMAKE_INSTALL_PREFIX=/ ' .
|
||||||
'-DCMAKE_INSTALL_PREFIX=/ ' .
|
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
|
||||||
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
|
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
|
||||||
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
|
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
||||||
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
'..'
|
||||||
'.. && ' .
|
)
|
||||||
"cmake --build . -j {$this->builder->concurrency} && " .
|
->exec("cmake --build . -j {$this->builder->concurrency}")
|
||||||
'make install DESTDIR="' . $destdir . '"'
|
->exec("make install DESTDIR={$destdir}");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,24 +72,23 @@ EOF
|
|||||||
|
|
||||||
[$lib, $include, $destdir] = SEPARATED_PATH;
|
[$lib, $include, $destdir] = SEPARATED_PATH;
|
||||||
|
|
||||||
f_passthru(
|
shell()->cd($this->source_dir)
|
||||||
$this->builder->set_x . ' && ' .
|
->exec('rm -rf build')
|
||||||
"cd {$this->source_dir} && " .
|
->exec('mkdir -p build')
|
||||||
'rm -rf build && ' .
|
->cd($this->source_dir . '/build')
|
||||||
'mkdir -p build && ' .
|
->exec(
|
||||||
'cd build && ' .
|
"{$this->builder->configure_env} " . ' cmake ' .
|
||||||
"{$this->builder->configure_env} " . ' cmake ' .
|
// '--debug-find ' .
|
||||||
// '--debug-find ' .
|
'-DCMAKE_BUILD_TYPE=Release ' .
|
||||||
'-DCMAKE_BUILD_TYPE=Release ' .
|
'-DBUILD_TESTING=OFF ' .
|
||||||
'-DBUILD_TESTING=OFF ' .
|
'-DBUILD_SHARED_LIBS=OFF ' .
|
||||||
'-DBUILD_SHARED_LIBS=OFF ' .
|
'-DCMAKE_INSTALL_PREFIX=/ ' .
|
||||||
'-DCMAKE_INSTALL_PREFIX=/ ' .
|
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
|
||||||
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
|
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
|
||||||
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
|
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
||||||
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
'..'
|
||||||
'.. && ' .
|
)
|
||||||
"make -j{$this->builder->concurrency} && " .
|
->exec("make -j{$this->builder->concurrency}")
|
||||||
'make install DESTDIR=' . $destdir
|
->exec("make install DESTDIR={$destdir}");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,30 +72,29 @@ class libzip extends MacOSLibraryBase
|
|||||||
|
|
||||||
[$lib, $include, $destdir] = SEPARATED_PATH;
|
[$lib, $include, $destdir] = SEPARATED_PATH;
|
||||||
|
|
||||||
f_passthru(
|
shell()->cd($this->source_dir)
|
||||||
$this->builder->set_x . ' && ' .
|
->exec('rm -rf build')
|
||||||
"cd {$this->source_dir} && " .
|
->exec('mkdir -p build')
|
||||||
'rm -rf build && ' .
|
->cd($this->source_dir . '/build')
|
||||||
'mkdir -p build && ' .
|
->exec(
|
||||||
'cd build && ' .
|
"{$this->builder->configure_env} " . ' cmake ' .
|
||||||
"{$this->builder->configure_env} " . ' cmake ' .
|
// '--debug-find ' .
|
||||||
// '--debug-find ' .
|
'-DCMAKE_BUILD_TYPE=Release ' .
|
||||||
'-DCMAKE_BUILD_TYPE=Release ' .
|
'-DENABLE_GNUTLS=OFF ' .
|
||||||
'-DENABLE_GNUTLS=OFF ' .
|
'-DENABLE_MBEDTLS=OFF ' .
|
||||||
'-DENABLE_MBEDTLS=OFF ' .
|
'-DBUILD_SHARED_LIBS=OFF ' .
|
||||||
'-DBUILD_SHARED_LIBS=OFF ' .
|
'-DBUILD_DOC=OFF ' .
|
||||||
'-DBUILD_DOC=OFF ' .
|
'-DBUILD_EXAMPLES=OFF ' .
|
||||||
'-DBUILD_EXAMPLES=OFF ' .
|
'-DBUILD_REGRESS=OFF ' .
|
||||||
'-DBUILD_REGRESS=OFF ' .
|
'-DBUILD_TOOLS=OFF ' .
|
||||||
'-DBUILD_TOOLS=OFF ' .
|
$extra .
|
||||||
$extra .
|
'-DCMAKE_INSTALL_PREFIX=/ ' .
|
||||||
'-DCMAKE_INSTALL_PREFIX=/ ' .
|
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
|
||||||
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
|
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
|
||||||
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
|
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
||||||
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
'..'
|
||||||
'.. && ' .
|
)
|
||||||
"make -j{$this->builder->concurrency} && " .
|
->exec("make -j{$this->builder->concurrency}")
|
||||||
'make install DESTDIR=' . $destdir
|
->exec("make install DESTDIR={$destdir}");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,20 +44,19 @@ class nghttp2 extends MacOSLibraryBase
|
|||||||
|
|
||||||
[,,$destdir] = SEPARATED_PATH;
|
[,,$destdir] = SEPARATED_PATH;
|
||||||
|
|
||||||
f_passthru(
|
shell()->cd($this->source_dir)
|
||||||
$this->builder->set_x . ' && ' .
|
->exec(
|
||||||
"cd {$this->source_dir} && " .
|
"{$this->builder->configure_env} " . ' ./configure ' .
|
||||||
"{$this->builder->configure_env} " . ' ./configure ' .
|
'--enable-static ' .
|
||||||
'--enable-static ' .
|
'--disable-shared ' .
|
||||||
'--disable-shared ' .
|
"--host={$this->builder->gnu_arch}-apple-darwin " .
|
||||||
"--host={$this->builder->gnu_arch}-apple-darwin " .
|
'--enable-lib-only ' .
|
||||||
'--enable-lib-only ' .
|
'--with-boost=no ' .
|
||||||
'--with-boost=no ' .
|
$args . ' ' .
|
||||||
$args . ' ' .
|
'--prefix='
|
||||||
'--prefix= && ' . // use prefix=/
|
)
|
||||||
'make clean && ' .
|
->exec('make clean')
|
||||||
"make -j{$this->builder->concurrency} && " .
|
->exec("make -j{$this->builder->concurrency}")
|
||||||
"make install DESTDIR={$destdir}"
|
->exec("make install DESTDIR={$destdir}");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,17 +28,16 @@ class onig extends MacOSLibraryBase
|
|||||||
{
|
{
|
||||||
[,,$destdir] = SEPARATED_PATH;
|
[,,$destdir] = SEPARATED_PATH;
|
||||||
|
|
||||||
f_passthru(
|
shell()->cd($this->source_dir)
|
||||||
$this->builder->set_x . ' && ' .
|
->exec(
|
||||||
"cd {$this->source_dir} && " .
|
"{$this->builder->configure_env} " . ' ./configure ' .
|
||||||
"{$this->builder->configure_env} " . ' ./configure ' .
|
'--enable-static ' .
|
||||||
'--enable-static ' .
|
'--disable-shared ' .
|
||||||
'--disable-shared ' .
|
"--host={$this->builder->arch}-apple-darwin " .
|
||||||
"--host={$this->builder->arch}-apple-darwin " .
|
'--prefix='
|
||||||
'--prefix= && ' . // use prefix=/
|
)
|
||||||
'make clean && ' .
|
->exec('make clean')
|
||||||
"make -j{$this->builder->concurrency} && " .
|
->exec("make -j{$this->builder->concurrency}")
|
||||||
'make install DESTDIR=' . $destdir
|
->exec("make install DESTDIR={$destdir}");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,16 +37,15 @@ class openssl extends MacOSLibraryBase
|
|||||||
$ex_lib = trim($zlib->getStaticLibFiles() . ' ' . $ex_lib);
|
$ex_lib = trim($zlib->getStaticLibFiles() . ' ' . $ex_lib);
|
||||||
}
|
}
|
||||||
|
|
||||||
f_passthru(
|
shell()->cd($this->source_dir)
|
||||||
$this->builder->set_x . ' && ' .
|
->exec(
|
||||||
"cd {$this->source_dir} && " .
|
"{$this->builder->configure_env} ./Configure no-shared {$extra} " .
|
||||||
"{$this->builder->configure_env} ./Configure no-shared {$extra} " .
|
'--prefix=/ ' . // use prefix=/
|
||||||
'--prefix=/ ' . // use prefix=/
|
"--libdir={$lib} " .
|
||||||
"--libdir={$lib} " .
|
" darwin64-{$this->builder->arch}-cc"
|
||||||
" darwin64-{$this->builder->arch}-cc && " .
|
)
|
||||||
'make clean && ' .
|
->exec('make clean')
|
||||||
"make -j{$this->builder->concurrency} CNF_EX_LIBS=\"{$ex_lib}\" && " .
|
->exec("make -j{$this->builder->concurrency} CNF_EX_LIBS=\"{$ex_lib}\"")
|
||||||
'make install_sw DESTDIR=' . $destdir
|
->exec("make install_sw DESTDIR={$destdir}");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,16 +11,10 @@ class sqlite extends MacOSLibraryBase
|
|||||||
protected function build()
|
protected function build()
|
||||||
{
|
{
|
||||||
[,,$destdir] = SEPARATED_PATH;
|
[,,$destdir] = SEPARATED_PATH;
|
||||||
|
shell()->cd($this->source_dir)
|
||||||
f_passthru(
|
->exec("{$this->builder->configure_env} ./configure --enable-static --disable-shared --prefix=")
|
||||||
$this->builder->set_x . ' && ' .
|
->exec('make clean')
|
||||||
"cd {$this->source_dir} && " .
|
->exec("make -j{$this->builder->concurrency}")
|
||||||
"{$this->builder->configure_env} ./configure " .
|
->exec("make install DESTDIR={$destdir}");
|
||||||
'--enable-static --disable-shared ' .
|
|
||||||
'--prefix= && ' . // use prefix=/
|
|
||||||
'make clean && ' .
|
|
||||||
"make -j{$this->builder->concurrency} && " .
|
|
||||||
'make install DESTDIR=' . $destdir
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,25 +28,24 @@ class xz extends MacOSLibraryBase
|
|||||||
{
|
{
|
||||||
[,,$destdir] = SEPARATED_PATH;
|
[,,$destdir] = SEPARATED_PATH;
|
||||||
|
|
||||||
f_passthru(
|
shell()->cd($this->source_dir)
|
||||||
$this->builder->set_x . ' && ' .
|
->exec('autoreconf -i --force')
|
||||||
"cd {$this->source_dir} && " .
|
->exec(
|
||||||
'autoreconf -i --force && ' .
|
"{$this->builder->configure_env} ./configure " .
|
||||||
"{$this->builder->configure_env} ./configure " .
|
'--enable-static ' .
|
||||||
'--enable-static ' .
|
'--disable-shared ' .
|
||||||
'--disable-shared ' .
|
"--host={$this->builder->gnu_arch}-apple-darwin " .
|
||||||
"--host={$this->builder->gnu_arch}-apple-darwin " .
|
'--disable-xz ' .
|
||||||
'--disable-xz ' .
|
'--disable-xzdec ' .
|
||||||
'--disable-xzdec ' .
|
'--disable-lzmadec ' .
|
||||||
'--disable-lzmadec ' .
|
'--disable-lzmainfo ' .
|
||||||
'--disable-lzmainfo ' .
|
'--disable-scripts ' .
|
||||||
'--disable-scripts ' .
|
'--disable-doc ' .
|
||||||
'--disable-doc ' .
|
'--with-libiconv ' .
|
||||||
'--with-libiconv ' .
|
'--prefix='
|
||||||
'--prefix= && ' . // use prefix=/
|
)
|
||||||
'make clean && ' .
|
->exec('make clean')
|
||||||
"make -j{$this->builder->concurrency} && " .
|
->exec("make -j{$this->builder->concurrency}")
|
||||||
'make install DESTDIR=' . $destdir
|
->exec("make install DESTDIR={$destdir}");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,15 +28,10 @@ class zlib extends MacOSLibraryBase
|
|||||||
{
|
{
|
||||||
[,,$destdir] = SEPARATED_PATH;
|
[,,$destdir] = SEPARATED_PATH;
|
||||||
|
|
||||||
f_passthru(
|
shell()->cd($this->source_dir)
|
||||||
$this->builder->set_x . ' && ' .
|
->exec("{$this->builder->configure_env} ./configure --static --prefix=")
|
||||||
"cd {$this->source_dir} && " .
|
->exec('make clean')
|
||||||
"{$this->builder->configure_env} ./configure " .
|
->exec("make -j{$this->builder->concurrency}")
|
||||||
'--static ' .
|
->exec("make install DESTDIR={$destdir}");
|
||||||
'--prefix= && ' . // use prefix=/
|
|
||||||
'make clean && ' .
|
|
||||||
"make -j{$this->builder->concurrency} && " .
|
|
||||||
'make install DESTDIR=' . $destdir
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,16 +26,15 @@ class zstd extends MacOSLibraryBase
|
|||||||
|
|
||||||
protected function build()
|
protected function build()
|
||||||
{
|
{
|
||||||
f_passthru(
|
shell()->cd($this->source_dir)
|
||||||
$this->builder->set_x . ' && ' .
|
->exec("make {$this->builder->configure_env} PREFIX='" . BUILD_ROOT_PATH . "' clean")
|
||||||
"cd {$this->source_dir} && " .
|
->exec(
|
||||||
"make {$this->builder->configure_env} PREFIX='" . BUILD_ROOT_PATH . "' clean" . ' && ' .
|
"make -j{$this->builder->concurrency} " .
|
||||||
"make -j{$this->builder->concurrency} " .
|
"{$this->builder->configure_env} " .
|
||||||
"{$this->builder->configure_env} " .
|
"PREFIX='" . BUILD_ROOT_PATH . "' " .
|
||||||
"PREFIX='" . BUILD_ROOT_PATH . "' " .
|
'-C lib libzstd.a CPPFLAGS_STATLIB=-DZSTD_MULTITHREAD'
|
||||||
'-C lib libzstd.a CPPFLAGS_STATLIB=-DZSTD_MULTITHREAD && ' .
|
)
|
||||||
'cp lib/libzstd.a ' . BUILD_LIB_PATH . ' && ' .
|
->exec('cp lib/libzstd.a ' . BUILD_LIB_PATH)
|
||||||
'cp lib/zdict.h lib/zstd_errors.h lib/zstd.h ' . BUILD_INCLUDE_PATH
|
->exec('cp lib/zdict.h lib/zstd_errors.h lib/zstd.h ' . BUILD_INCLUDE_PATH);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace SPC\builder\traits;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 仅供 Command 使用,如果使用了该 Trait,则在执行对应命令时不打印 motd
|
|
||||||
*/
|
|
||||||
trait NoMotdTrait
|
|
||||||
{
|
|
||||||
protected bool $no_motd = true;
|
|
||||||
}
|
|
||||||
@@ -56,19 +56,22 @@ trait UnixBuilderTrait
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sanity check after build complete
|
||||||
|
*
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
*/
|
*/
|
||||||
public function sanityCheck(int $build_micro_rule): void
|
public function sanityCheck(int $build_target): void
|
||||||
{
|
{
|
||||||
logger()->info('running sanity check');
|
// sanity check for php-cli
|
||||||
if ($build_micro_rule !== BUILD_MICRO_ONLY) {
|
if (($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) {
|
||||||
|
logger()->info('running cli sanity check');
|
||||||
[$ret, $output] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -r "echo \"hello\";"');
|
[$ret, $output] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -r "echo \"hello\";"');
|
||||||
if ($ret !== 0 || trim(implode('', $output)) !== 'hello') {
|
if ($ret !== 0 || trim(implode('', $output)) !== 'hello') {
|
||||||
throw new RuntimeException('cli failed sanity check');
|
throw new RuntimeException('cli failed sanity check');
|
||||||
}
|
}
|
||||||
foreach ($this->exts as $ext) {
|
foreach ($this->exts as $ext) {
|
||||||
logger()->debug('testing ext: ' . $ext->getName());
|
logger()->debug('testing ext: ' . $ext->getName());
|
||||||
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php --ri ' . $ext->getName(), false);
|
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php --ri ' . $ext->getDistName(), false);
|
||||||
if ($ret !== 0) {
|
if ($ret !== 0) {
|
||||||
throw new RuntimeException('extension ' . $ext->getName() . ' failed compile check');
|
throw new RuntimeException('extension ' . $ext->getName() . ' failed compile check');
|
||||||
}
|
}
|
||||||
@@ -80,7 +83,9 @@ trait UnixBuilderTrait
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($build_micro_rule !== BUILD_MICRO_NONE) {
|
|
||||||
|
// sanity check for phpmicro
|
||||||
|
if (($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO) {
|
||||||
if (file_exists(SOURCE_PATH . '/hello.exe')) {
|
if (file_exists(SOURCE_PATH . '/hello.exe')) {
|
||||||
@unlink(SOURCE_PATH . '/hello.exe');
|
@unlink(SOURCE_PATH . '/hello.exe');
|
||||||
}
|
}
|
||||||
@@ -107,11 +112,12 @@ trait UnixBuilderTrait
|
|||||||
public function deployBinary(int $type): bool
|
public function deployBinary(int $type): bool
|
||||||
{
|
{
|
||||||
$src = match ($type) {
|
$src = match ($type) {
|
||||||
BUILD_TYPE_CLI => SOURCE_PATH . '/php-src/sapi/cli/php',
|
BUILD_TARGET_CLI => SOURCE_PATH . '/php-src/sapi/cli/php',
|
||||||
BUILD_TYPE_MICRO => SOURCE_PATH . '/php-src/sapi/micro/micro.sfx',
|
BUILD_TARGET_MICRO => SOURCE_PATH . '/php-src/sapi/micro/micro.sfx',
|
||||||
|
BUILD_TARGET_FPM => SOURCE_PATH . '/php-src/sapi/fpm/php-fpm',
|
||||||
default => throw new RuntimeException('Deployment does not accept type ' . $type),
|
default => throw new RuntimeException('Deployment does not accept type ' . $type),
|
||||||
};
|
};
|
||||||
logger()->info('Deploying ' . ($type === BUILD_TYPE_CLI ? 'cli' : 'micro') . ' file');
|
logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file');
|
||||||
FileSystem::createDir(BUILD_ROOT_PATH . '/bin');
|
FileSystem::createDir(BUILD_ROOT_PATH . '/bin');
|
||||||
shell()->exec('cp ' . escapeshellarg($src) . ' ' . escapeshellarg(BUILD_ROOT_PATH . '/bin/'));
|
shell()->exec('cp ' . escapeshellarg($src) . ' ' . escapeshellarg(BUILD_ROOT_PATH . '/bin/'));
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace SPC\builder\traits;
|
namespace SPC\builder\traits;
|
||||||
|
|
||||||
|
use SPC\store\FileSystem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unix 系统的工具函数 Trait,适用于 Linux、macOS
|
* Unix 系统的工具函数 Trait,适用于 Linux、macOS
|
||||||
*/
|
*/
|
||||||
@@ -48,7 +50,7 @@ CMAKE;
|
|||||||
if (PHP_OS_FAMILY === 'Linux') {
|
if (PHP_OS_FAMILY === 'Linux') {
|
||||||
$toolchain .= "\nSET(CMAKE_AR \"ar\")";
|
$toolchain .= "\nSET(CMAKE_AR \"ar\")";
|
||||||
}
|
}
|
||||||
file_put_contents(SOURCE_PATH . '/toolchain.cmake', $toolchain);
|
FileSystem::writeFile(SOURCE_PATH . '/toolchain.cmake', $toolchain);
|
||||||
return realpath(SOURCE_PATH . '/toolchain.cmake');
|
return realpath(SOURCE_PATH . '/toolchain.cmake');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,14 +13,32 @@ use ZM\Logger\ConsoleLogger;
|
|||||||
|
|
||||||
abstract class BaseCommand extends Command
|
abstract class BaseCommand extends Command
|
||||||
{
|
{
|
||||||
|
protected bool $no_motd = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入
|
||||||
|
*/
|
||||||
|
protected InputInterface $input;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输出
|
||||||
|
*
|
||||||
|
* 一般来说同样会是 ConsoleOutputInterface
|
||||||
|
*/
|
||||||
|
protected OutputInterface $output;
|
||||||
|
|
||||||
public function __construct(string $name = null)
|
public function __construct(string $name = null)
|
||||||
{
|
{
|
||||||
parent::__construct($name);
|
parent::__construct($name);
|
||||||
$this->addOption('debug', null, null, 'Enable debug mode');
|
$this->addOption('debug', null, null, 'Enable debug mode');
|
||||||
|
$this->addOption('no-motd', null, null, 'Disable motd');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function initialize(InputInterface $input, OutputInterface $output)
|
public function initialize(InputInterface $input, OutputInterface $output)
|
||||||
{
|
{
|
||||||
|
if ($input->getOption('no-motd')) {
|
||||||
|
$this->no_motd = true;
|
||||||
|
}
|
||||||
// 注册全局错误处理器
|
// 注册全局错误处理器
|
||||||
set_error_handler(static function ($error_no, $error_msg, $error_file, $error_line) {
|
set_error_handler(static function ($error_no, $error_msg, $error_file, $error_line) {
|
||||||
$tips = [
|
$tips = [
|
||||||
@@ -46,7 +64,7 @@ abstract class BaseCommand extends Command
|
|||||||
define('DEBUG_MODE', true);
|
define('DEBUG_MODE', true);
|
||||||
}
|
}
|
||||||
$version = ConsoleApplication::VERSION;
|
$version = ConsoleApplication::VERSION;
|
||||||
if (!isset($this->no_motd)) {
|
if (!$this->no_motd) {
|
||||||
echo " _ _ _ _
|
echo " _ _ _ _
|
||||||
___| |_ __ _| |_(_) ___ _ __ | |__ _ __
|
___| |_ __ _| |_(_) ___ _ __ | |__ _ __
|
||||||
/ __| __/ _` | __| |/ __|____| '_ \\| '_ \\| '_ \\
|
/ __| __/ _` | __| |/ __|____| '_ \\| '_ \\| '_ \\
|
||||||
@@ -56,4 +74,44 @@ abstract class BaseCommand extends Command
|
|||||||
";
|
";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract public function handle(): int;
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$this->input = $input;
|
||||||
|
$this->output = $output;
|
||||||
|
if ($this->shouldExecute()) {
|
||||||
|
try {
|
||||||
|
return $this->handle();
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$msg = explode("\n", $e->getMessage());
|
||||||
|
foreach ($msg as $v) {
|
||||||
|
logger()->error($v);
|
||||||
|
}
|
||||||
|
return self::FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getOption(string $name): mixed
|
||||||
|
{
|
||||||
|
return $this->input->getOption($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getArgument(string $name): mixed
|
||||||
|
{
|
||||||
|
return $this->input->getArgument($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否应该执行
|
||||||
|
*
|
||||||
|
* @return bool 返回 true 以继续执行,返回 false 以中断执行
|
||||||
|
*/
|
||||||
|
protected function shouldExecute(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,53 +6,60 @@ namespace SPC\command;
|
|||||||
|
|
||||||
use SPC\builder\BuilderProvider;
|
use SPC\builder\BuilderProvider;
|
||||||
use SPC\exception\ExceptionHandler;
|
use SPC\exception\ExceptionHandler;
|
||||||
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\util\DependencyUtil;
|
use SPC\util\DependencyUtil;
|
||||||
|
use SPC\util\LicenseDumper;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use ZM\Logger\ConsoleColor;
|
||||||
|
|
||||||
/** @noinspection PhpUnused */
|
#[AsCommand('build', 'build CLI binary')]
|
||||||
class BuildCliCommand extends BuildCommand
|
class BuildCliCommand extends BuildCommand
|
||||||
{
|
{
|
||||||
protected static $defaultName = 'build';
|
|
||||||
|
|
||||||
public function configure()
|
public function configure()
|
||||||
{
|
{
|
||||||
$this->setDescription('Build CLI binary');
|
|
||||||
$this->addArgument('extensions', InputArgument::REQUIRED, 'The extensions will be compiled, comma separated');
|
$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('with-libs', null, InputOption::VALUE_REQUIRED, 'add additional libraries, comma separated', '');
|
||||||
$this->addOption('build-micro', null, null, 'build micro only');
|
$this->addOption('build-micro', null, null, 'build micro');
|
||||||
$this->addOption('build-all', null, null, 'build both cli and micro');
|
$this->addOption('build-cli', null, null, 'build cli');
|
||||||
|
$this->addOption('build-fpm', null, null, 'build fpm');
|
||||||
|
$this->addOption('build-all', null, null, 'build cli, micro, fpm');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function execute(InputInterface $input, OutputInterface $output): int
|
public function handle(): int
|
||||||
{
|
{
|
||||||
// 从参数中获取要编译的 libraries,并转换为数组
|
// 从参数中获取要编译的 libraries,并转换为数组
|
||||||
$libraries = array_map('trim', array_filter(explode(',', $input->getOption('with-libs'))));
|
$libraries = array_map('trim', array_filter(explode(',', $this->getOption('with-libs'))));
|
||||||
// 从参数中获取要编译的 extensions,并转换为数组
|
// 从参数中获取要编译的 extensions,并转换为数组
|
||||||
$extensions = array_map('trim', array_filter(explode(',', $input->getArgument('extensions'))));
|
$extensions = array_map('trim', array_filter(explode(',', $this->getArgument('extensions'))));
|
||||||
|
|
||||||
define('BUILD_ALL_STATIC', true);
|
define('BUILD_ALL_STATIC', true);
|
||||||
|
|
||||||
if ($input->getOption('build-all')) {
|
$rule = BUILD_TARGET_NONE;
|
||||||
$rule = BUILD_MICRO_BOTH;
|
$rule = $rule | ($this->getOption('build-cli') ? BUILD_TARGET_CLI : BUILD_TARGET_NONE);
|
||||||
logger()->info('Builder will build php-cli and phpmicro SAPI');
|
$rule = $rule | ($this->getOption('build-micro') ? BUILD_TARGET_MICRO : BUILD_TARGET_NONE);
|
||||||
} elseif ($input->getOption('build-micro')) {
|
$rule = $rule | ($this->getOption('build-fpm') ? BUILD_TARGET_FPM : BUILD_TARGET_NONE);
|
||||||
$rule = BUILD_MICRO_ONLY;
|
$rule = $rule | ($this->getOption('build-all') ? BUILD_TARGET_ALL : BUILD_TARGET_NONE);
|
||||||
logger()->info('Builder will build phpmicro SAPI');
|
if ($rule === BUILD_TARGET_NONE) {
|
||||||
} else {
|
$this->output->writeln('<error>Please add at least one build target!</error>');
|
||||||
$rule = BUILD_MICRO_NONE;
|
$this->output->writeln("<comment>\t--build-cli\tBuild php-cli SAPI</comment>");
|
||||||
logger()->info('Builder will build php-cli SAPI');
|
$this->output->writeln("<comment>\t--build-micro\tBuild phpmicro SAPI</comment>");
|
||||||
|
$this->output->writeln("<comment>\t--build-fpm\tBuild php-fpm SAPI</comment>");
|
||||||
|
$this->output->writeln("<comment>\t--build-all\tBuild all SAPI: cli, micro, fpm</comment>");
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// 构建对象
|
// 构建对象
|
||||||
$builder = BuilderProvider::makeBuilderByInput($input);
|
$builder = BuilderProvider::makeBuilderByInput($this->input);
|
||||||
// 根据提供的扩展列表获取依赖库列表并编译
|
// 根据提供的扩展列表获取依赖库列表并编译
|
||||||
[$extensions, $libraries, $not_included] = DependencyUtil::getExtLibsByDeps($extensions, $libraries);
|
[$extensions, $libraries, $not_included] = DependencyUtil::getExtLibsByDeps($extensions, $libraries);
|
||||||
|
/* @phpstan-ignore-next-line */
|
||||||
logger()->info('Enabled extensions: ' . implode(', ', $extensions));
|
logger()->info('Build target: ' . ConsoleColor::yellow($builder->getBuildTypeName($rule)));
|
||||||
logger()->info('Required libraries: ' . implode(', ', $libraries));
|
/* @phpstan-ignore-next-line */
|
||||||
|
logger()->info('Enabled extensions: ' . ConsoleColor::yellow(implode(', ', $extensions)));
|
||||||
|
/* @phpstan-ignore-next-line */
|
||||||
|
logger()->info('Required libraries: ' . ConsoleColor::yellow(implode(', ', $libraries)));
|
||||||
if (!empty($not_included)) {
|
if (!empty($not_included)) {
|
||||||
logger()->warning('some extensions will be enabled due to dependencies: ' . implode(',', $not_included));
|
logger()->warning('some extensions will be enabled due to dependencies: ' . implode(',', $not_included));
|
||||||
}
|
}
|
||||||
@@ -62,19 +69,32 @@ class BuildCliCommand extends BuildCommand
|
|||||||
// 执行扩展检测
|
// 执行扩展检测
|
||||||
$builder->proveExts($extensions);
|
$builder->proveExts($extensions);
|
||||||
// 构建
|
// 构建
|
||||||
$builder->buildPHP($rule, $input->getOption('bloat'));
|
$builder->buildPHP($rule, $this->getOption('bloat'));
|
||||||
// 统计时间
|
// 统计时间
|
||||||
$time = round(microtime(true) - START_TIME, 3);
|
$time = round(microtime(true) - START_TIME, 3);
|
||||||
logger()->info('Build complete, used ' . $time . ' s !');
|
logger()->info('Build complete, used ' . $time . ' s !');
|
||||||
if ($rule !== BUILD_MICRO_ONLY) {
|
if (($rule & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) {
|
||||||
logger()->info('Static php binary path: ' . BUILD_ROOT_PATH . '/bin/php');
|
logger()->info('Static php binary path: ' . BUILD_ROOT_PATH . '/bin/php');
|
||||||
}
|
}
|
||||||
if ($rule !== BUILD_MICRO_NONE) {
|
if (($rule & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO) {
|
||||||
logger()->info('phpmicro binary path: ' . BUILD_ROOT_PATH . '/bin/micro.sfx');
|
logger()->info('phpmicro binary path: ' . BUILD_ROOT_PATH . '/bin/micro.sfx');
|
||||||
}
|
}
|
||||||
|
if (($rule & BUILD_TARGET_FPM) === BUILD_TARGET_FPM) {
|
||||||
|
logger()->info('Static php-fpm binary path: ' . BUILD_ROOT_PATH . '/bin/php-fpm');
|
||||||
|
}
|
||||||
|
// 导出相关元数据
|
||||||
|
file_put_contents(BUILD_ROOT_PATH . '/build-extensions.json', json_encode($extensions, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||||
|
file_put_contents(BUILD_ROOT_PATH . '/build-libraries.json', json_encode($libraries, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||||
|
// 导出 LICENSE
|
||||||
|
$dumper = new LicenseDumper();
|
||||||
|
$dumper->addExts($extensions)->addLibs($libraries)->addSources(['php-src'])->dump(BUILD_ROOT_PATH . '/license');
|
||||||
|
logger()->info('License path: ' . BUILD_ROOT_PATH . '/license/');
|
||||||
return 0;
|
return 0;
|
||||||
|
} catch (WrongUsageException $e) {
|
||||||
|
logger()->critical($e->getMessage());
|
||||||
|
return 1;
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
if ($input->getOption('debug')) {
|
if ($this->getOption('debug')) {
|
||||||
ExceptionHandler::getInstance()->handle($e);
|
ExceptionHandler::getInstance()->handle($e);
|
||||||
} else {
|
} else {
|
||||||
logger()->critical('Build failed with ' . get_class($e) . ': ' . $e->getMessage());
|
logger()->critical('Build failed with ' . get_class($e) . ': ' . $e->getMessage());
|
||||||
|
|||||||
@@ -6,20 +6,17 @@ namespace SPC\command;
|
|||||||
|
|
||||||
use SPC\builder\BuilderProvider;
|
use SPC\builder\BuilderProvider;
|
||||||
use SPC\exception\ExceptionHandler;
|
use SPC\exception\ExceptionHandler;
|
||||||
use SPC\exception\FileSystemException;
|
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\RuntimeException;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
/** @noinspection PhpUnused */
|
#[AsCommand('build:libs', 'Build dependencies')]
|
||||||
class BuildLibsCommand extends BuildCommand
|
class BuildLibsCommand extends BuildCommand
|
||||||
{
|
{
|
||||||
protected static $defaultName = 'build:libs';
|
|
||||||
|
|
||||||
public function configure()
|
public function configure()
|
||||||
{
|
{
|
||||||
$this->setDescription('Build dependencies');
|
|
||||||
$this->addArgument('libraries', InputArgument::REQUIRED, 'The libraries will be compiled, comma separated');
|
$this->addArgument('libraries', InputArgument::REQUIRED, 'The libraries will be compiled, comma separated');
|
||||||
$this->addOption('clean', null, null, 'Clean old download cache and source before fetch');
|
$this->addOption('clean', null, null, 'Clean old download cache and source before fetch');
|
||||||
$this->addOption('all', 'A', null, 'Build all libs that static-php-cli needed');
|
$this->addOption('all', 'A', null, 'Build all libs that static-php-cli needed');
|
||||||
@@ -36,15 +33,14 @@ class BuildLibsCommand extends BuildCommand
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
* @throws FileSystemException
|
|
||||||
*/
|
*/
|
||||||
public function execute(InputInterface $input, OutputInterface $output): int
|
public function handle(): int
|
||||||
{
|
{
|
||||||
// 从参数中获取要编译的 libraries,并转换为数组
|
// 从参数中获取要编译的 libraries,并转换为数组
|
||||||
$libraries = array_map('trim', array_filter(explode(',', $input->getArgument('libraries'))));
|
$libraries = array_map('trim', array_filter(explode(',', $this->getArgument('libraries'))));
|
||||||
|
|
||||||
// 删除旧资源
|
// 删除旧资源
|
||||||
if ($input->getOption('clean')) {
|
if ($this->getOption('clean')) {
|
||||||
logger()->warning('You are doing some operations that not recoverable: removing directories below');
|
logger()->warning('You are doing some operations that not recoverable: removing directories below');
|
||||||
logger()->warning(BUILD_ROOT_PATH);
|
logger()->warning(BUILD_ROOT_PATH);
|
||||||
logger()->warning('I will remove these dir after you press [Enter] !');
|
logger()->warning('I will remove these dir after you press [Enter] !');
|
||||||
@@ -59,7 +55,7 @@ class BuildLibsCommand extends BuildCommand
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 构建对象
|
// 构建对象
|
||||||
$builder = BuilderProvider::makeBuilderByInput($input);
|
$builder = BuilderProvider::makeBuilderByInput($this->input);
|
||||||
// 只编译 library 的情况下,标记
|
// 只编译 library 的情况下,标记
|
||||||
$builder->setLibsOnly();
|
$builder->setLibsOnly();
|
||||||
// 编译和检查库完整
|
// 编译和检查库完整
|
||||||
@@ -69,7 +65,7 @@ class BuildLibsCommand extends BuildCommand
|
|||||||
logger()->info('Build libs complete, used ' . $time . ' s !');
|
logger()->info('Build libs complete, used ' . $time . ' s !');
|
||||||
return 0;
|
return 0;
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
if ($input->getOption('debug')) {
|
if ($this->getOption('debug')) {
|
||||||
ExceptionHandler::getInstance()->handle($e);
|
ExceptionHandler::getInstance()->handle($e);
|
||||||
} else {
|
} else {
|
||||||
logger()->critical('Build failed with ' . get_class($e) . ': ' . $e->getMessage());
|
logger()->critical('Build failed with ' . get_class($e) . ': ' . $e->getMessage());
|
||||||
|
|||||||
@@ -7,32 +7,28 @@ namespace SPC\command;
|
|||||||
use CliHelper\Tools\ArgFixer;
|
use CliHelper\Tools\ArgFixer;
|
||||||
use CliHelper\Tools\DataProvider;
|
use CliHelper\Tools\DataProvider;
|
||||||
use CliHelper\Tools\SeekableArrayIterator;
|
use CliHelper\Tools\SeekableArrayIterator;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\Helper\ProgressBar;
|
use Symfony\Component\Console\Helper\ProgressBar;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
|
||||||
|
|
||||||
/** @noinspection PhpUnused */
|
#[AsCommand('deploy', 'Deploy static-php-cli self to an .phar application')]
|
||||||
class DeployCommand extends BaseCommand
|
class DeployCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected static $defaultName = 'deploy';
|
|
||||||
|
|
||||||
public function configure()
|
public function configure()
|
||||||
{
|
{
|
||||||
$this->setDescription('Deploy static-php-cli self to an .phar application');
|
|
||||||
$this->addArgument('target', InputArgument::OPTIONAL, 'The file or directory to pack.');
|
$this->addArgument('target', InputArgument::OPTIONAL, 'The file or directory to pack.');
|
||||||
$this->addOption('auto-phar-fix', null, InputOption::VALUE_NONE, 'Automatically fix ini option.');
|
$this->addOption('auto-phar-fix', null, InputOption::VALUE_NONE, 'Automatically fix ini option.');
|
||||||
$this->addOption('overwrite', 'W', InputOption::VALUE_NONE, 'Overwrite existing files.');
|
$this->addOption('overwrite', 'W', InputOption::VALUE_NONE, 'Overwrite existing files.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function execute(InputInterface $input, OutputInterface $output): int
|
public function handle(): int
|
||||||
{
|
{
|
||||||
// 第一阶段流程:如果没有写path,将会提示输入要打包的path
|
// 第一阶段流程:如果没有写path,将会提示输入要打包的path
|
||||||
$prompt = new ArgFixer($input, $output);
|
$prompt = new ArgFixer($this->input, $this->output);
|
||||||
// 首先得确认是不是关闭了readonly模式
|
// 首先得确认是不是关闭了readonly模式
|
||||||
if (ini_get('phar.readonly') == 1) {
|
if (ini_get('phar.readonly') == 1) {
|
||||||
if ($input->getOption('auto-phar-fix')) {
|
if ($this->getOption('auto-phar-fix')) {
|
||||||
$ask = true;
|
$ask = true;
|
||||||
} else {
|
} else {
|
||||||
$ask = $prompt->requireBool('<comment>pack command needs "phar.readonly" = "Off" !</comment>' . PHP_EOL . 'If you want to automatically set it and continue, just Enter', true);
|
$ask = $prompt->requireBool('<comment>pack command needs "phar.readonly" = "Off" !</comment>' . PHP_EOL . 'If you want to automatically set it and continue, just Enter', true);
|
||||||
@@ -41,12 +37,12 @@ class DeployCommand extends BaseCommand
|
|||||||
global $argv;
|
global $argv;
|
||||||
$args = array_merge(['-d', 'phar.readonly=0'], $_SERVER['argv']);
|
$args = array_merge(['-d', 'phar.readonly=0'], $_SERVER['argv']);
|
||||||
if (function_exists('pcntl_exec')) {
|
if (function_exists('pcntl_exec')) {
|
||||||
$output->writeln('<info>Changing to phar.readonly=0 mode ...</info>');
|
$this->output->writeln('<info>Changing to phar.readonly=0 mode ...</info>');
|
||||||
if (pcntl_exec(PHP_BINARY, $args) === false) {
|
if (pcntl_exec(PHP_BINARY, $args) === false) {
|
||||||
throw new \PharException('切换到读写模式失败,请检查环境。');
|
throw new \PharException('切换到读写模式失败,请检查环境。');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$output->writeln('<info>Now running command in child process.</info>');
|
$this->output->writeln('<info>Now running command in child process.</info>');
|
||||||
passthru(PHP_BINARY . ' -d phar.readonly=0 ' . implode(' ', $argv), $retcode);
|
passthru(PHP_BINARY . ' -d phar.readonly=0 ' . implode(' ', $argv), $retcode);
|
||||||
exit($retcode);
|
exit($retcode);
|
||||||
}
|
}
|
||||||
@@ -61,9 +57,9 @@ class DeployCommand extends BaseCommand
|
|||||||
$phar_path = '/tmp/' . $phar_path;
|
$phar_path = '/tmp/' . $phar_path;
|
||||||
}
|
}
|
||||||
if (file_exists($phar_path)) {
|
if (file_exists($phar_path)) {
|
||||||
$ask = $input->getOption('overwrite') ? true : $prompt->requireBool('<comment>The file "' . $phar_path . '" already exists, do you want to overwrite it?</comment>' . PHP_EOL . 'If you want to, just Enter');
|
$ask = $this->getOption('overwrite') ? true : $prompt->requireBool('<comment>The file "' . $phar_path . '" already exists, do you want to overwrite it?</comment>' . PHP_EOL . 'If you want to, just Enter');
|
||||||
if (!$ask) {
|
if (!$ask) {
|
||||||
$output->writeln('<comment>User canceled.</comment>');
|
$this->output->writeln('<comment>User canceled.</comment>');
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@unlink($phar_path);
|
@unlink($phar_path);
|
||||||
@@ -83,9 +79,9 @@ class DeployCommand extends BaseCommand
|
|||||||
$map[$v] = $path . '/' . $v;
|
$map[$v] = $path . '/' . $v;
|
||||||
}
|
}
|
||||||
|
|
||||||
$output->writeln('<info>Start packing files...</info>');
|
$this->output->writeln('<info>Start packing files...</info>');
|
||||||
try {
|
try {
|
||||||
foreach ($this->progress($output)->iterate($map) as $file => $origin_file) {
|
foreach ($this->progress()->iterate($map) as $file => $origin_file) {
|
||||||
$phar->addFromString($file, php_strip_whitespace($origin_file));
|
$phar->addFromString($file, php_strip_whitespace($origin_file));
|
||||||
}
|
}
|
||||||
// $phar->buildFromIterator(new SeekableArrayIterator($map, new ProgressBar($output)));
|
// $phar->buildFromIterator(new SeekableArrayIterator($map, new ProgressBar($output)));
|
||||||
@@ -100,30 +96,30 @@ class DeployCommand extends BaseCommand
|
|||||||
$stub = '.phar-entry.php';
|
$stub = '.phar-entry.php';
|
||||||
$phar->setStub($phar->createDefaultStub($stub));
|
$phar->setStub($phar->createDefaultStub($stub));
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
$output->writeln($e);
|
$this->output->writeln($e);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
$phar->addFromString('.prod', 'true');
|
$phar->addFromString('.prod', 'true');
|
||||||
$phar->stopBuffering();
|
$phar->stopBuffering();
|
||||||
$output->writeln(PHP_EOL . 'Done! Phar file is generated at "' . $phar_path . '".');
|
$this->output->writeln(PHP_EOL . 'Done! Phar file is generated at "' . $phar_path . '".');
|
||||||
if (file_exists(SOURCE_PATH . '/php-src/sapi/micro/micro.sfx')) {
|
if (file_exists(SOURCE_PATH . '/php-src/sapi/micro/micro.sfx')) {
|
||||||
$output->writeln('Detected you have already compiled micro binary, I will make executable now for you!');
|
$this->output->writeln('Detected you have already compiled micro binary, I will make executable now for you!');
|
||||||
file_put_contents(
|
file_put_contents(
|
||||||
pathinfo($phar_path, PATHINFO_DIRNAME) . '/spc',
|
pathinfo($phar_path, PATHINFO_DIRNAME) . '/spc',
|
||||||
file_get_contents(SOURCE_PATH . '/php-src/sapi/micro/micro.sfx') .
|
file_get_contents(SOURCE_PATH . '/php-src/sapi/micro/micro.sfx') .
|
||||||
file_get_contents($phar_path)
|
file_get_contents($phar_path)
|
||||||
);
|
);
|
||||||
chmod(pathinfo($phar_path, PATHINFO_DIRNAME) . '/spc', 0755);
|
chmod(pathinfo($phar_path, PATHINFO_DIRNAME) . '/spc', 0755);
|
||||||
$output->writeln('<info>Binary Executable: ' . pathinfo($phar_path, PATHINFO_DIRNAME) . '/spc</info>');
|
$this->output->writeln('<info>Binary Executable: ' . pathinfo($phar_path, PATHINFO_DIRNAME) . '/spc</info>');
|
||||||
}
|
}
|
||||||
chmod($phar_path, 0755);
|
chmod($phar_path, 0755);
|
||||||
$output->writeln('<info>Phar Executable: ' . $phar_path . '</info>');
|
$this->output->writeln('<info>Phar Executable: ' . $phar_path . '</info>');
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function progress(OutputInterface $output, int $max = 0): ProgressBar
|
private function progress(int $max = 0): ProgressBar
|
||||||
{
|
{
|
||||||
$progress = new ProgressBar($output, $max);
|
$progress = new ProgressBar($this->output, $max);
|
||||||
$progress->setBarCharacter('<fg=green>⚬</>');
|
$progress->setBarCharacter('<fg=green>⚬</>');
|
||||||
$progress->setEmptyBarCharacter('<fg=red>⚬</>');
|
$progress->setEmptyBarCharacter('<fg=red>⚬</>');
|
||||||
$progress->setProgressCharacter('<fg=green>➤</>');
|
$progress->setProgressCharacter('<fg=green>➤</>');
|
||||||
|
|||||||
25
src/SPC/command/DoctorCommand.php
Normal file
25
src/SPC/command/DoctorCommand.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\command;
|
||||||
|
|
||||||
|
use SPC\doctor\CheckListHandler;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
|
|
||||||
|
#[AsCommand('doctor', 'Diagnose whether the current environment can compile normally')]
|
||||||
|
class DoctorCommand extends BaseCommand
|
||||||
|
{
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$checker = new CheckListHandler($this->input, $this->output);
|
||||||
|
$checker->runCheck(FIX_POLICY_PROMPT);
|
||||||
|
$this->output->writeln('<info>Doctor check complete !</info>');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$this->output->writeln('<error>' . $e->getMessage() . '</error>');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,26 +4,70 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace SPC\command;
|
namespace SPC\command;
|
||||||
|
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use SPC\exception\FileSystemException;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use SPC\exception\RuntimeException;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use SPC\exception\WrongUsageException;
|
||||||
|
use SPC\util\DependencyUtil;
|
||||||
|
use SPC\util\LicenseDumper;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改 config 后对其 kv 进行排序的操作
|
* 修改 config 后对其 kv 进行排序的操作
|
||||||
*/
|
*/
|
||||||
|
#[AsCommand('dump-license', 'Dump licenses for required libraries')]
|
||||||
class DumpLicenseCommand extends BaseCommand
|
class DumpLicenseCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected static $defaultName = 'dump-license';
|
|
||||||
|
|
||||||
public function configure()
|
public function configure()
|
||||||
{
|
{
|
||||||
$this->setDescription('Dump licenses for required libraries');
|
$this->addOption('by-extensions', null, InputOption::VALUE_REQUIRED, 'Dump by extensions and related libraries', null);
|
||||||
$this->addArgument('config-name', InputArgument::REQUIRED, 'Your config to be sorted, you can sort "lib", "source" and "ext".');
|
$this->addOption('without-php', null, InputOption::VALUE_NONE, 'Dump without php-src');
|
||||||
|
$this->addOption('by-libs', null, InputOption::VALUE_REQUIRED, 'Dump by libraries', null);
|
||||||
|
$this->addOption('by-sources', null, InputOption::VALUE_REQUIRED, 'Dump by original sources (source.json)', null);
|
||||||
|
$this->addOption('dump-dir', null, InputOption::VALUE_REQUIRED, 'Change dump directory', BUILD_ROOT_PATH . '/license');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function execute(InputInterface $input, OutputInterface $output): int
|
/**
|
||||||
|
* @throws WrongUsageException
|
||||||
|
* @throws FileSystemException
|
||||||
|
* @throws RuntimeException
|
||||||
|
*/
|
||||||
|
public function handle(): int
|
||||||
{
|
{
|
||||||
$output->writeln('<info>not implemented</info>');
|
$dumper = new LicenseDumper();
|
||||||
|
if ($this->getOption('by-extensions') !== null) {
|
||||||
|
// 从参数中获取要编译的 extensions,并转换为数组
|
||||||
|
$extensions = array_map('trim', array_filter(explode(',', $this->getOption('by-extensions'))));
|
||||||
|
// 根据提供的扩展列表获取依赖库列表并编译
|
||||||
|
[$extensions, $libraries, $not_included] = DependencyUtil::getExtLibsByDeps($extensions);
|
||||||
|
$dumper->addExts($extensions);
|
||||||
|
$dumper->addLibs($libraries);
|
||||||
|
if (!$this->getOption('without-php')) {
|
||||||
|
$dumper->addSources(['php-src']);
|
||||||
|
}
|
||||||
|
$dumper->dump($this->getOption('dump-dir'));
|
||||||
|
$this->output->writeln('Dump license with extensions: ' . implode(', ', $extensions));
|
||||||
|
$this->output->writeln('Dump license with libraries: ' . implode(', ', $libraries));
|
||||||
|
$this->output->writeln('Dump license with' . ($this->getOption('without-php') ? 'out' : '') . ' php-src');
|
||||||
|
$this->output->writeln('Dump target dir: ' . $this->getOption('dump-dir'));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ($this->getOption('by-libs') !== null) {
|
||||||
|
$libraries = array_map('trim', array_filter(explode(',', $this->getOption('by-libs'))));
|
||||||
|
$libraries = DependencyUtil::getLibsByDeps($libraries);
|
||||||
|
$dumper->addLibs($libraries);
|
||||||
|
$dumper->dump($this->getOption('dump-dir'));
|
||||||
|
$this->output->writeln('Dump target dir: ' . $this->getOption('dump-dir'));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ($this->getOption('by-sources') !== null) {
|
||||||
|
$sources = array_map('trim', array_filter(explode(',', $this->getOption('by-sources'))));
|
||||||
|
$dumper->addSources($sources);
|
||||||
|
$dumper->dump($this->getOption('dump-dir'));
|
||||||
|
$this->output->writeln('Dump target dir: ' . $this->getOption('dump-dir'));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
$this->output->writeln('You must use one of "--by-extensions=", "--by-libs=", "--by-sources=" to dump');
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,23 +12,21 @@ use SPC\exception\RuntimeException;
|
|||||||
use SPC\store\Config;
|
use SPC\store\Config;
|
||||||
use SPC\store\Downloader;
|
use SPC\store\Downloader;
|
||||||
use SPC\util\Patcher;
|
use SPC\util\Patcher;
|
||||||
|
use SPC\util\Util;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
/** @noinspection PhpUnused */
|
/** @noinspection PhpUnused */
|
||||||
|
#[AsCommand('fetch', 'Fetch required sources')]
|
||||||
class FetchSourceCommand extends BaseCommand
|
class FetchSourceCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected static $defaultName = 'fetch';
|
|
||||||
|
|
||||||
protected string $php_major_ver;
|
protected string $php_major_ver;
|
||||||
|
|
||||||
protected InputInterface $input;
|
|
||||||
|
|
||||||
public function configure()
|
public function configure()
|
||||||
{
|
{
|
||||||
$this->setDescription('Fetch required sources');
|
|
||||||
$this->addArgument('extensions', InputArgument::REQUIRED, 'The extensions will be compiled, comma separated');
|
$this->addArgument('extensions', InputArgument::REQUIRED, 'The extensions will be compiled, comma separated');
|
||||||
$this->addArgument('libraries', InputArgument::REQUIRED, 'The libraries will be compiled, comma separated');
|
$this->addArgument('libraries', InputArgument::REQUIRED, 'The libraries will be compiled, comma separated');
|
||||||
$this->addOption('hash', null, null, 'Hash only');
|
$this->addOption('hash', null, null, 'Hash only');
|
||||||
@@ -49,12 +47,12 @@ class FetchSourceCommand extends BaseCommand
|
|||||||
parent::initialize($input, $output);
|
parent::initialize($input, $output);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function execute(InputInterface $input, OutputInterface $output): int
|
public function handle(): int
|
||||||
{
|
{
|
||||||
$this->input = $input;
|
|
||||||
try {
|
try {
|
||||||
// 匹配版本
|
// 匹配版本
|
||||||
$ver = $this->php_major_ver = $input->getOption('with-php') ?? '8.1';
|
$ver = $this->php_major_ver = $this->getOption('with-php') ?? '8.1';
|
||||||
|
define('SPC_BUILD_PHP_VERSION', $ver);
|
||||||
preg_match('/^\d+\.\d+$/', $ver, $matches);
|
preg_match('/^\d+\.\d+$/', $ver, $matches);
|
||||||
if (!$matches) {
|
if (!$matches) {
|
||||||
logger()->error("bad version arg: {$ver}, x.y required!");
|
logger()->error("bad version arg: {$ver}, x.y required!");
|
||||||
@@ -62,7 +60,7 @@ class FetchSourceCommand extends BaseCommand
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 删除旧资源
|
// 删除旧资源
|
||||||
if ($input->getOption('clean')) {
|
if ($this->getOption('clean')) {
|
||||||
logger()->warning('You are doing some operations that not recoverable: removing directories below');
|
logger()->warning('You are doing some operations that not recoverable: removing directories below');
|
||||||
logger()->warning(SOURCE_PATH);
|
logger()->warning(SOURCE_PATH);
|
||||||
logger()->warning(DOWNLOAD_PATH);
|
logger()->warning(DOWNLOAD_PATH);
|
||||||
@@ -83,7 +81,7 @@ class FetchSourceCommand extends BaseCommand
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 使用浅克隆可以减少调用 git 命令下载资源时的存储空间占用
|
// 使用浅克隆可以减少调用 git 命令下载资源时的存储空间占用
|
||||||
if ($input->getOption('shallow-clone')) {
|
if ($this->getOption('shallow-clone')) {
|
||||||
define('GIT_SHALLOW_CLONE', true);
|
define('GIT_SHALLOW_CLONE', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +89,7 @@ class FetchSourceCommand extends BaseCommand
|
|||||||
Config::getSource('openssl');
|
Config::getSource('openssl');
|
||||||
|
|
||||||
// 是否启用openssl11
|
// 是否启用openssl11
|
||||||
if ($input->getOption('with-openssl11')) {
|
if ($this->getOption('with-openssl11')) {
|
||||||
logger()->debug('Using openssl 1.1');
|
logger()->debug('Using openssl 1.1');
|
||||||
// 手动修改配置
|
// 手动修改配置
|
||||||
Config::$source['openssl']['regex'] = '/href="(?<file>openssl-(?<version>1.[^"]+)\.tar\.gz)\"/';
|
Config::$source['openssl']['regex'] = '/href="(?<file>openssl-(?<version>1.[^"]+)\.tar\.gz)\"/';
|
||||||
@@ -101,7 +99,7 @@ class FetchSourceCommand extends BaseCommand
|
|||||||
$chosen_sources = ['micro'];
|
$chosen_sources = ['micro'];
|
||||||
|
|
||||||
// 从参数中获取要编译的 libraries,并转换为数组
|
// 从参数中获取要编译的 libraries,并转换为数组
|
||||||
$libraries = array_map('trim', array_filter(explode(',', $input->getArgument('libraries'))));
|
$libraries = array_map('trim', array_filter(explode(',', $this->getArgument('libraries'))));
|
||||||
if ($libraries) {
|
if ($libraries) {
|
||||||
foreach ($libraries as $lib) {
|
foreach ($libraries as $lib) {
|
||||||
// 从 lib 的 config 中找到对应 source 资源名称,组成一个 lib 的 source 列表
|
// 从 lib 的 config 中找到对应 source 资源名称,组成一个 lib 的 source 列表
|
||||||
@@ -113,7 +111,7 @@ class FetchSourceCommand extends BaseCommand
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 从参数中获取要编译的 extensions,并转换为数组
|
// 从参数中获取要编译的 extensions,并转换为数组
|
||||||
$extensions = array_map('trim', array_filter(explode(',', $input->getArgument('extensions'))));
|
$extensions = array_map('trim', array_filter(explode(',', $this->getArgument('extensions'))));
|
||||||
if ($extensions) {
|
if ($extensions) {
|
||||||
foreach ($extensions as $lib) {
|
foreach ($extensions as $lib) {
|
||||||
if (Config::getExt($lib, 'type') !== 'builtin') {
|
if (Config::getExt($lib, 'type') !== 'builtin') {
|
||||||
@@ -131,9 +129,9 @@ class FetchSourceCommand extends BaseCommand
|
|||||||
$chosen_sources = array_unique($chosen_sources);
|
$chosen_sources = array_unique($chosen_sources);
|
||||||
|
|
||||||
// 是否只hash,不下载资源
|
// 是否只hash,不下载资源
|
||||||
if ($input->getOption('hash')) {
|
if ($this->getOption('hash')) {
|
||||||
$hash = $this->doHash($chosen_sources);
|
$hash = $this->doHash($chosen_sources);
|
||||||
$output->writeln($hash);
|
$this->output->writeln($hash);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,9 +140,7 @@ class FetchSourceCommand extends BaseCommand
|
|||||||
f_mkdir(DOWNLOAD_PATH);
|
f_mkdir(DOWNLOAD_PATH);
|
||||||
|
|
||||||
// 下载 PHP
|
// 下载 PHP
|
||||||
logger()->info('Fetching PHP source');
|
array_unshift($chosen_sources, 'php-src');
|
||||||
Downloader::fetchSource('php-src', Downloader::getLatestPHPInfo($ver));
|
|
||||||
|
|
||||||
// 下载别的依赖资源
|
// 下载别的依赖资源
|
||||||
$cnt = count($chosen_sources);
|
$cnt = count($chosen_sources);
|
||||||
$ni = 0;
|
$ni = 0;
|
||||||
@@ -167,10 +163,10 @@ class FetchSourceCommand extends BaseCommand
|
|||||||
return 0;
|
return 0;
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
// 不开 debug 模式就不要再显示复杂的调试栈信息了
|
// 不开 debug 模式就不要再显示复杂的调试栈信息了
|
||||||
if ($input->getOption('debug')) {
|
if ($this->getOption('debug')) {
|
||||||
ExceptionHandler::getInstance()->handle($e);
|
ExceptionHandler::getInstance()->handle($e);
|
||||||
} else {
|
} else {
|
||||||
logger()->emergency($e->getMessage() . ', previous message: ' . $e->getPrevious()->getMessage());
|
logger()->emergency($e->getMessage() . ', previous message: ' . $e->getPrevious()?->getMessage());
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -215,11 +211,11 @@ class FetchSourceCommand extends BaseCommand
|
|||||||
private function doPatch(): void
|
private function doPatch(): void
|
||||||
{
|
{
|
||||||
// swow 需要软链接内部的文件夹才能正常编译
|
// swow 需要软链接内部的文件夹才能正常编译
|
||||||
if (!file_exists(SOURCE_PATH . '/php-src/ext/swow')) {
|
if (!file_exists(SOURCE_PATH . '/php-src/ext/swow') && Util::getPHPVersionID() >= 80000) {
|
||||||
Patcher::patchSwow();
|
Patcher::patchSwow();
|
||||||
|
// patch 一些 PHP 的资源,以便编译
|
||||||
|
Patcher::patchMicroThings();
|
||||||
}
|
}
|
||||||
// patch 一些 PHP 的资源,以便编译
|
|
||||||
Patcher::patchPHPDepFiles();
|
|
||||||
|
|
||||||
// openssl 3 需要 patch 额外的东西
|
// openssl 3 需要 patch 额外的东西
|
||||||
if (!$this->input->getOption('with-openssl11') && $this->php_major_ver === '8.0') {
|
if (!$this->input->getOption('with-openssl11') && $this->php_major_ver === '8.0') {
|
||||||
|
|||||||
@@ -4,23 +4,19 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace SPC\command;
|
namespace SPC\command;
|
||||||
|
|
||||||
use SPC\builder\traits\NoMotdTrait;
|
use SPC\exception\FileSystemException;
|
||||||
use SPC\store\Config;
|
use SPC\store\Config;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
|
||||||
|
|
||||||
|
#[AsCommand('list-ext', 'List supported extensions')]
|
||||||
class ListExtCommand extends BaseCommand
|
class ListExtCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
use NoMotdTrait;
|
protected bool $no_motd = true;
|
||||||
|
|
||||||
protected static $defaultName = 'list-ext';
|
/**
|
||||||
|
* @throws FileSystemException
|
||||||
public function configure()
|
*/
|
||||||
{
|
public function handle(): int
|
||||||
$this->setDescription('List supported extensions');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function execute(InputInterface $input, OutputInterface $output)
|
|
||||||
{
|
{
|
||||||
foreach (Config::getExts() as $ext => $meta) {
|
foreach (Config::getExts() as $ext => $meta) {
|
||||||
echo $ext . PHP_EOL;
|
echo $ext . PHP_EOL;
|
||||||
|
|||||||
@@ -8,20 +8,17 @@ use SPC\exception\FileSystemException;
|
|||||||
use SPC\exception\ValidationException;
|
use SPC\exception\ValidationException;
|
||||||
use SPC\store\FileSystem;
|
use SPC\store\FileSystem;
|
||||||
use SPC\util\ConfigValidator;
|
use SPC\util\ConfigValidator;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改 config 后对其 kv 进行排序的操作
|
* 修改 config 后对其 kv 进行排序的操作
|
||||||
*/
|
*/
|
||||||
|
#[AsCommand('sort-config', 'After config edited, sort it by alphabet')]
|
||||||
class SortConfigCommand extends BaseCommand
|
class SortConfigCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected static $defaultName = 'sort-config';
|
|
||||||
|
|
||||||
public function configure()
|
public function configure()
|
||||||
{
|
{
|
||||||
$this->setDescription('After config edited, sort it by alphabet');
|
|
||||||
$this->addArgument('config-name', InputArgument::REQUIRED, 'Your config to be sorted, you can sort "lib", "source" and "ext".');
|
$this->addArgument('config-name', InputArgument::REQUIRED, 'Your config to be sorted, you can sort "lib", "source" and "ext".');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,9 +26,9 @@ class SortConfigCommand extends BaseCommand
|
|||||||
* @throws ValidationException
|
* @throws ValidationException
|
||||||
* @throws FileSystemException
|
* @throws FileSystemException
|
||||||
*/
|
*/
|
||||||
public function execute(InputInterface $input, OutputInterface $output): int
|
public function handle(): int
|
||||||
{
|
{
|
||||||
switch ($name = $input->getArgument('config-name')) {
|
switch ($name = $this->getArgument('config-name')) {
|
||||||
case 'lib':
|
case 'lib':
|
||||||
$file = json_decode(FileSystem::readFile(ROOT_DIR . '/config/lib.json'), true);
|
$file = json_decode(FileSystem::readFile(ROOT_DIR . '/config/lib.json'), true);
|
||||||
ConfigValidator::validateLibs($file);
|
ConfigValidator::validateLibs($file);
|
||||||
@@ -51,10 +48,10 @@ class SortConfigCommand extends BaseCommand
|
|||||||
file_put_contents(ROOT_DIR . '/config/ext.json', json_encode($file, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
file_put_contents(ROOT_DIR . '/config/ext.json', json_encode($file, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$output->writeln("<error>invalid config name: {$name}</error>");
|
$this->output->writeln("<error>invalid config name: {$name}</error>");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
$output->writeln('<info>sort success</info>');
|
$this->output->writeln('<info>sort success</info>');
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/SPC/doctor/AsCheckItem.php
Normal file
18
src/SPC/doctor/AsCheckItem.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\doctor;
|
||||||
|
|
||||||
|
#[\Attribute(\Attribute::TARGET_METHOD)]
|
||||||
|
class AsCheckItem
|
||||||
|
{
|
||||||
|
public mixed $callback = null;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public string $item_name,
|
||||||
|
public ?string $limit_os = null,
|
||||||
|
public int $level = 100
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/SPC/doctor/AsFixItem.php
Normal file
13
src/SPC/doctor/AsFixItem.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\doctor;
|
||||||
|
|
||||||
|
#[\Attribute(\Attribute::TARGET_METHOD)]
|
||||||
|
class AsFixItem
|
||||||
|
{
|
||||||
|
public function __construct(public string $name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
128
src/SPC/doctor/CheckListHandler.php
Normal file
128
src/SPC/doctor/CheckListHandler.php
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\doctor;
|
||||||
|
|
||||||
|
use SPC\exception\FileSystemException;
|
||||||
|
use SPC\exception\RuntimeException;
|
||||||
|
use SPC\store\FileSystem;
|
||||||
|
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||||
|
|
||||||
|
class CheckListHandler
|
||||||
|
{
|
||||||
|
/** @var AsCheckItem[] */
|
||||||
|
private array $check_list = [];
|
||||||
|
|
||||||
|
private array $fix_map = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws \ReflectionException
|
||||||
|
* @throws FileSystemException
|
||||||
|
* @throws RuntimeException
|
||||||
|
*/
|
||||||
|
public function __construct(private InputInterface $input, private OutputInterface $output)
|
||||||
|
{
|
||||||
|
$this->loadCheckList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws RuntimeException
|
||||||
|
*/
|
||||||
|
public function runCheck(int $fix_policy = FIX_POLICY_DIE): void
|
||||||
|
{
|
||||||
|
foreach ($this->check_list as $item) {
|
||||||
|
if ($item->limit_os !== null && $item->limit_os !== PHP_OS_FAMILY) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$this->output->write('Checking <comment>' . $item->item_name . '</comment> ... ');
|
||||||
|
$result = call_user_func($item->callback);
|
||||||
|
if ($result === null) {
|
||||||
|
$this->output->writeln('skipped');
|
||||||
|
} elseif ($result instanceof CheckResult) {
|
||||||
|
if ($result->isOK()) {
|
||||||
|
$this->output->writeln('ok');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Failed
|
||||||
|
$this->output->writeln('<error>' . $result->getMessage() . '</error>');
|
||||||
|
switch ($fix_policy) {
|
||||||
|
case FIX_POLICY_DIE:
|
||||||
|
throw new RuntimeException('Some check items can not be fixed !');
|
||||||
|
case FIX_POLICY_PROMPT:
|
||||||
|
if ($result->getFixItem() !== '') {
|
||||||
|
$helper = new QuestionHelper();
|
||||||
|
$question = new ConfirmationQuestion('Do you want to fix it? [Y/n] ', true);
|
||||||
|
if ($helper->ask($this->input, $this->output, $question)) {
|
||||||
|
$this->emitFix($result);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException('You cancelled fix');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException('Some check items can not be fixed !');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FIX_POLICY_AUTOFIX:
|
||||||
|
if ($result->getFixItem() !== '') {
|
||||||
|
$this->output->writeln('Automatically fixing ' . $result->getFixItem() . ' ...');
|
||||||
|
$this->emitFix($result);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException('Some check items can not be fixed !');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load Doctor check item list
|
||||||
|
*
|
||||||
|
* @throws \ReflectionException
|
||||||
|
* @throws RuntimeException
|
||||||
|
* @throws FileSystemException
|
||||||
|
*/
|
||||||
|
private function loadCheckList(): void
|
||||||
|
{
|
||||||
|
foreach (FileSystem::getClassesPsr4(__DIR__ . '/item', 'SPC\\doctor\\item') as $class) {
|
||||||
|
$ref = new \ReflectionClass($class);
|
||||||
|
foreach ($ref->getMethods() as $method) {
|
||||||
|
$attr = $method->getAttributes(AsCheckItem::class);
|
||||||
|
if (isset($attr[0])) {
|
||||||
|
/** @var AsCheckItem $instance */
|
||||||
|
$instance = $attr[0]->newInstance();
|
||||||
|
$instance->callback = [new $class(), $method->getName()];
|
||||||
|
$this->check_list[] = $instance;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$attr = $method->getAttributes(AsFixItem::class);
|
||||||
|
if (isset($attr[0])) {
|
||||||
|
/** @var AsFixItem $instance */
|
||||||
|
$instance = $attr[0]->newInstance();
|
||||||
|
// Redundant fix item
|
||||||
|
if (isset($this->fix_map[$instance->name])) {
|
||||||
|
throw new RuntimeException('Redundant doctor fix item: ' . $instance->name);
|
||||||
|
}
|
||||||
|
$this->fix_map[$instance->name] = [new $class(), $method->getName()];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// sort check list by level
|
||||||
|
usort($this->check_list, fn ($a, $b) => $a->level > $b->level ? -1 : ($a->level == $b->level ? 0 : 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function emitFix(CheckResult $result)
|
||||||
|
{
|
||||||
|
$fix = $this->fix_map[$result->getFixItem()];
|
||||||
|
$fix_result = call_user_func($fix, ...$result->getFixParams());
|
||||||
|
if ($fix_result) {
|
||||||
|
$this->output->writeln('<info>Fix done</info>');
|
||||||
|
} else {
|
||||||
|
$this->output->writeln('<error>Fix failed</error>');
|
||||||
|
throw new RuntimeException('Some check item are not fixed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
42
src/SPC/doctor/CheckResult.php
Normal file
42
src/SPC/doctor/CheckResult.php
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\doctor;
|
||||||
|
|
||||||
|
class CheckResult
|
||||||
|
{
|
||||||
|
public function __construct(private string $message = '', private string $fix_item = '', private array $fix_params = [])
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function fail(string $message, string $fix_item = '', array $fix_params = []): CheckResult
|
||||||
|
{
|
||||||
|
return new static($message, $fix_item, $fix_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function ok(): CheckResult
|
||||||
|
{
|
||||||
|
return new static();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMessage(): string
|
||||||
|
{
|
||||||
|
return $this->message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFixItem(): string
|
||||||
|
{
|
||||||
|
return $this->fix_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFixParams(): array
|
||||||
|
{
|
||||||
|
return $this->fix_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isOK(): bool
|
||||||
|
{
|
||||||
|
return empty($this->message);
|
||||||
|
}
|
||||||
|
}
|
||||||
84
src/SPC/doctor/item/MacOSToolCheckList.php
Normal file
84
src/SPC/doctor/item/MacOSToolCheckList.php
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\doctor\item;
|
||||||
|
|
||||||
|
use SPC\builder\traits\UnixSystemUtilTrait;
|
||||||
|
use SPC\doctor\AsCheckItem;
|
||||||
|
use SPC\doctor\AsFixItem;
|
||||||
|
use SPC\doctor\CheckResult;
|
||||||
|
use SPC\exception\RuntimeException;
|
||||||
|
|
||||||
|
class MacOSToolCheckList
|
||||||
|
{
|
||||||
|
use UnixSystemUtilTrait;
|
||||||
|
|
||||||
|
/** @var string[] MacOS 环境下编译依赖的命令 */
|
||||||
|
public const REQUIRED_COMMANDS = [
|
||||||
|
'curl',
|
||||||
|
'make',
|
||||||
|
'bison',
|
||||||
|
'flex',
|
||||||
|
'pkg-config',
|
||||||
|
'git',
|
||||||
|
'autoconf',
|
||||||
|
'automake',
|
||||||
|
'tar',
|
||||||
|
'unzip',
|
||||||
|
'xz',
|
||||||
|
'gzip',
|
||||||
|
'bzip2',
|
||||||
|
'gotop',
|
||||||
|
'cmake',
|
||||||
|
];
|
||||||
|
|
||||||
|
#[AsCheckItem('if homebrew has installed', limit_os: 'Darwin', level: 998)]
|
||||||
|
public function checkBrew(): ?CheckResult
|
||||||
|
{
|
||||||
|
// 检查 homebrew 是否已经安装
|
||||||
|
if ($this->findCommand('brew') === null) {
|
||||||
|
return CheckResult::fail('Homebrew is not installed', 'brew');
|
||||||
|
}
|
||||||
|
return CheckResult::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[AsCheckItem('if necessary tools are installed', limit_os: 'Darwin')]
|
||||||
|
public function checkCliTools(): ?CheckResult
|
||||||
|
{
|
||||||
|
$missing = [];
|
||||||
|
foreach (self::REQUIRED_COMMANDS as $cmd) {
|
||||||
|
if ($this->findCommand($cmd) === null) {
|
||||||
|
$missing[] = $cmd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($missing)) {
|
||||||
|
return CheckResult::fail('missing system commands: ' . implode(', ', $missing), 'build-tools', [$missing]);
|
||||||
|
}
|
||||||
|
return CheckResult::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[AsFixItem('brew')]
|
||||||
|
public function fixBrew(): bool
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
shell(true)->exec('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"');
|
||||||
|
} catch (RuntimeException) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[AsFixItem('build-tools')]
|
||||||
|
public function fixBuildTools(array $missing): bool
|
||||||
|
{
|
||||||
|
foreach ($missing as $cmd) {
|
||||||
|
try {
|
||||||
|
shell(true)->exec('brew install ' . escapeshellarg($cmd));
|
||||||
|
} catch (RuntimeException) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/SPC/doctor/item/OSCheckList.php
Normal file
23
src/SPC/doctor/item/OSCheckList.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\doctor\item;
|
||||||
|
|
||||||
|
use SPC\builder\traits\UnixSystemUtilTrait;
|
||||||
|
use SPC\doctor\AsCheckItem;
|
||||||
|
use SPC\doctor\CheckResult;
|
||||||
|
|
||||||
|
class OSCheckList
|
||||||
|
{
|
||||||
|
use UnixSystemUtilTrait;
|
||||||
|
|
||||||
|
#[AsCheckItem('if current os are supported', level: 999)]
|
||||||
|
public function checkOS(): ?CheckResult
|
||||||
|
{
|
||||||
|
if (!in_array(PHP_OS_FAMILY, ['Darwin', 'Linux'])) {
|
||||||
|
return CheckResult::fail('Current OS is not supported');
|
||||||
|
}
|
||||||
|
return CheckResult::ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
9
src/SPC/exception/WrongUsageException.php
Normal file
9
src/SPC/exception/WrongUsageException.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\exception;
|
||||||
|
|
||||||
|
class WrongUsageException extends \Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ namespace SPC\store;
|
|||||||
|
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\FileSystemException;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\RuntimeException;
|
||||||
|
use SPC\exception\WrongUsageException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 一个读取 config 配置的操作类
|
* 一个读取 config 配置的操作类
|
||||||
@@ -38,7 +39,7 @@ class Config
|
|||||||
* 对于 macOS 平台,支持 frameworks。
|
* 对于 macOS 平台,支持 frameworks。
|
||||||
*
|
*
|
||||||
* @throws FileSystemException
|
* @throws FileSystemException
|
||||||
* @throws RuntimeException
|
* @throws WrongUsageException
|
||||||
*/
|
*/
|
||||||
public static function getLib(string $name, ?string $key = null, mixed $default = null)
|
public static function getLib(string $name, ?string $key = null, mixed $default = null)
|
||||||
{
|
{
|
||||||
@@ -46,7 +47,7 @@ class Config
|
|||||||
self::$lib = FileSystem::loadConfigArray('lib');
|
self::$lib = FileSystem::loadConfigArray('lib');
|
||||||
}
|
}
|
||||||
if (!isset(self::$lib[$name])) {
|
if (!isset(self::$lib[$name])) {
|
||||||
throw new RuntimeException('lib [' . $name . '] is not supported yet for get');
|
throw new WrongUsageException('lib [' . $name . '] is not supported yet');
|
||||||
}
|
}
|
||||||
$supported_sys_based = ['static-libs', 'headers', 'lib-depends', 'lib-suggests', 'frameworks'];
|
$supported_sys_based = ['static-libs', 'headers', 'lib-depends', 'lib-suggests', 'frameworks'];
|
||||||
if ($key !== null && in_array($key, $supported_sys_based)) {
|
if ($key !== null && in_array($key, $supported_sys_based)) {
|
||||||
@@ -54,7 +55,7 @@ class Config
|
|||||||
'Windows' => ['-windows', '-win', ''],
|
'Windows' => ['-windows', '-win', ''],
|
||||||
'Darwin' => ['-macos', '-unix', ''],
|
'Darwin' => ['-macos', '-unix', ''],
|
||||||
'Linux' => ['-linux', '-unix', ''],
|
'Linux' => ['-linux', '-unix', ''],
|
||||||
default => throw new RuntimeException('OS ' . PHP_OS_FAMILY . ' is not supported'),
|
default => throw new WrongUsageException('OS ' . PHP_OS_FAMILY . ' is not supported'),
|
||||||
};
|
};
|
||||||
foreach ($m_key as $v) {
|
foreach ($m_key as $v) {
|
||||||
if (isset(self::$lib[$name][$key . $v])) {
|
if (isset(self::$lib[$name][$key . $v])) {
|
||||||
@@ -83,6 +84,7 @@ class Config
|
|||||||
/**
|
/**
|
||||||
* @throws FileSystemException
|
* @throws FileSystemException
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
|
* @throws WrongUsageException
|
||||||
*/
|
*/
|
||||||
public static function getExt(string $name, ?string $key = null, mixed $default = null)
|
public static function getExt(string $name, ?string $key = null, mixed $default = null)
|
||||||
{
|
{
|
||||||
@@ -90,7 +92,7 @@ class Config
|
|||||||
self::$ext = FileSystem::loadConfigArray('ext');
|
self::$ext = FileSystem::loadConfigArray('ext');
|
||||||
}
|
}
|
||||||
if (!isset(self::$ext[$name])) {
|
if (!isset(self::$ext[$name])) {
|
||||||
throw new RuntimeException('ext [' . $name . '] is not supported yet for get');
|
throw new WrongUsageException('ext [' . $name . '] is not supported yet');
|
||||||
}
|
}
|
||||||
$supported_sys_based = ['lib-depends', 'lib-suggests', 'ext-depends', 'ext-suggests', 'arg-type'];
|
$supported_sys_based = ['lib-depends', 'lib-suggests', 'ext-depends', 'ext-suggests', 'arg-type'];
|
||||||
if ($key !== null && in_array($key, $supported_sys_based)) {
|
if ($key !== null && in_array($key, $supported_sys_based)) {
|
||||||
@@ -98,7 +100,7 @@ class Config
|
|||||||
'Windows' => ['-windows', '-win', ''],
|
'Windows' => ['-windows', '-win', ''],
|
||||||
'Darwin' => ['-macos', '-unix', ''],
|
'Darwin' => ['-macos', '-unix', ''],
|
||||||
'Linux' => ['-linux', '-unix', ''],
|
'Linux' => ['-linux', '-unix', ''],
|
||||||
default => throw new RuntimeException('OS ' . PHP_OS_FAMILY . ' is not supported'),
|
default => throw new WrongUsageException('OS ' . PHP_OS_FAMILY . ' is not supported'),
|
||||||
};
|
};
|
||||||
foreach ($m_key as $v) {
|
foreach ($m_key as $v) {
|
||||||
if (isset(self::$ext[$name][$key . $v])) {
|
if (isset(self::$ext[$name][$key . $v])) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use JetBrains\PhpStorm\ArrayShape;
|
|||||||
use SPC\exception\DownloaderException;
|
use SPC\exception\DownloaderException;
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\FileSystemException;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\RuntimeException;
|
||||||
|
use SPC\store\source\CustomSourceBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 资源下载器
|
* 资源下载器
|
||||||
@@ -144,7 +145,7 @@ class Downloader
|
|||||||
}
|
}
|
||||||
uksort($versions, 'version_compare');
|
uksort($versions, 'version_compare');
|
||||||
|
|
||||||
return [$source['url'] . end($versions), end($versions)];
|
return [$source['url'] . end($versions), end($versions), key($versions)];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -267,6 +268,14 @@ class Downloader
|
|||||||
case 'git': // 通过拉回 Git 仓库的形式拉取
|
case 'git': // 通过拉回 Git 仓库的形式拉取
|
||||||
self::downloadGit($name, $source['url'], $source['rev'], $source['path'] ?? null);
|
self::downloadGit($name, $source['url'], $source['rev'], $source['path'] ?? null);
|
||||||
break;
|
break;
|
||||||
|
case 'custom':
|
||||||
|
$classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/store/source', 'SPC\\store\\source');
|
||||||
|
foreach ($classes as $class) {
|
||||||
|
if (is_a($class, CustomSourceBase::class, true) && $class::NAME === $name) {
|
||||||
|
(new $class())->fetch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new DownloaderException('unknown source type: ' . $source['type']);
|
throw new DownloaderException('unknown source type: ' . $source['type']);
|
||||||
}
|
}
|
||||||
@@ -295,8 +304,8 @@ class Downloader
|
|||||||
// 从官网直接下载
|
// 从官网直接下载
|
||||||
return [
|
return [
|
||||||
'type' => 'url',
|
'type' => 'url',
|
||||||
// 'url' => "https://www.php.net/distributions/php-{$version}.tar.gz",
|
'url' => "https://www.php.net/distributions/php-{$version}.tar.gz",
|
||||||
'url' => "https://mirrors.zhamao.xin/php/php-{$version}.tar.gz",
|
// 'url' => "https://mirrors.zhamao.xin/php/php-{$version}.tar.gz",
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,10 +331,10 @@ class Downloader
|
|||||||
|
|
||||||
$cmd = "curl -sfSL {$methodArg} {$headerArg} \"{$url}\"";
|
$cmd = "curl -sfSL {$methodArg} {$headerArg} \"{$url}\"";
|
||||||
if (getenv('CACHE_API_EXEC') === 'yes') {
|
if (getenv('CACHE_API_EXEC') === 'yes') {
|
||||||
if (!file_exists(SOURCE_PATH . '/.curl_exec_cache')) {
|
if (!file_exists(DOWNLOAD_PATH . '/.curl_exec_cache')) {
|
||||||
$cache = [];
|
$cache = [];
|
||||||
} else {
|
} else {
|
||||||
$cache = json_decode(file_get_contents(SOURCE_PATH . '/.curl_exec_cache'), true);
|
$cache = json_decode(file_get_contents(DOWNLOAD_PATH . '/.curl_exec_cache'), true);
|
||||||
}
|
}
|
||||||
if (isset($cache[$cmd]) && $cache[$cmd]['expire'] >= time()) {
|
if (isset($cache[$cmd]) && $cache[$cmd]['expire'] >= time()) {
|
||||||
return $cache[$cmd]['cache'];
|
return $cache[$cmd]['cache'];
|
||||||
@@ -336,7 +345,7 @@ class Downloader
|
|||||||
}
|
}
|
||||||
$cache[$cmd]['cache'] = implode("\n", $output);
|
$cache[$cmd]['cache'] = implode("\n", $output);
|
||||||
$cache[$cmd]['expire'] = time() + 3600;
|
$cache[$cmd]['expire'] = time() + 3600;
|
||||||
file_put_contents(SOURCE_PATH . '/.curl_exec_cache', json_encode($cache));
|
file_put_contents(DOWNLOAD_PATH . '/.curl_exec_cache', json_encode($cache));
|
||||||
return $cache[$cmd]['cache'];
|
return $cache[$cmd]['cache'];
|
||||||
}
|
}
|
||||||
f_exec($cmd, $output, $ret);
|
f_exec($cmd, $output, $ret);
|
||||||
|
|||||||
@@ -356,33 +356,56 @@ class FileSystem
|
|||||||
*
|
*
|
||||||
* @throws FileSystemException
|
* @throws FileSystemException
|
||||||
*/
|
*/
|
||||||
public static function removeDir(string $dir, bool $throw_on_fail = false): bool
|
public static function removeDir(string $dir): bool
|
||||||
{
|
{
|
||||||
$dir = FileSystem::convertPath($dir);
|
$dir = FileSystem::convertPath($dir);
|
||||||
logger()->warning('Removing path recursively: "' . $dir . '"');
|
logger()->debug('Removing path recursively: "' . $dir . '"');
|
||||||
switch (PHP_OS_FAMILY) {
|
// 不是目录不扫,直接 false 处理
|
||||||
case 'Windows':
|
if (!is_dir($dir)) {
|
||||||
case 'WINNT':
|
logger()->warning('Scan dir failed, no such directory.');
|
||||||
case 'Cygwin':
|
return false;
|
||||||
f_exec('rmdir /s /g "' . $dir . '"', $out, $ret);
|
|
||||||
break;
|
|
||||||
case 'Darwin':
|
|
||||||
case 'Linux':
|
|
||||||
f_exec('rm -rf ' . escapeshellarg($dir), $out, $ret);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new FileSystemException('Unsupported OS type: ' . PHP_OS_FAMILY);
|
|
||||||
}
|
}
|
||||||
if ($ret !== 0 && $throw_on_fail) {
|
logger()->debug('scanning directory ' . $dir);
|
||||||
throw new FileSystemException('Cannot remove dir "' . $dir . '"');
|
// 套上 zm_dir
|
||||||
|
$scan_list = scandir($dir);
|
||||||
|
if ($scan_list === false) {
|
||||||
|
logger()->warning('Scan dir failed, cannot scan directory: ' . $dir);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return $ret === 0;
|
// 遍历目录
|
||||||
|
foreach ($scan_list as $v) {
|
||||||
|
// Unix 系统排除这俩目录
|
||||||
|
if ($v == '.' || $v == '..') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$sub_file = self::convertPath($dir . '/' . $v);
|
||||||
|
if (is_dir($sub_file)) {
|
||||||
|
# 如果是 目录 且 递推 , 则递推添加下级文件
|
||||||
|
if (!self::removeDir($sub_file)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} elseif (is_link($sub_file) || is_file($sub_file)) {
|
||||||
|
if (!unlink($sub_file)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rmdir($dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function createDir(string $path): void
|
public static function createDir(string $path): void
|
||||||
{
|
{
|
||||||
if (!is_dir($path) && !mkdir($path, 0755, true) && !is_dir($path)) {
|
if (!is_dir($path) && !f_mkdir($path, 0755, true) && !is_dir($path)) {
|
||||||
throw new FileSystemException(sprintf('无法建立目录:%s', $path));
|
throw new FileSystemException(sprintf('无法建立目录:%s', $path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function writeFile(string $path, $content, ...$args): bool|string|int
|
||||||
|
{
|
||||||
|
$dir = pathinfo($path, PATHINFO_DIRNAME);
|
||||||
|
if (!is_dir($dir) && !mkdir($dir, 0755, true)) {
|
||||||
|
throw new FileSystemException('Write file failed, cannot create parent directory: ' . $dir);
|
||||||
|
}
|
||||||
|
return file_put_contents($path, $content, ...$args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/SPC/store/source/CustomSourceBase.php
Normal file
12
src/SPC/store/source/CustomSourceBase.php
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\store\source;
|
||||||
|
|
||||||
|
abstract class CustomSourceBase
|
||||||
|
{
|
||||||
|
public const NAME = 'unknown';
|
||||||
|
|
||||||
|
abstract public function fetch();
|
||||||
|
}
|
||||||
47
src/SPC/store/source/PhpSource.php
Normal file
47
src/SPC/store/source/PhpSource.php
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\store\source;
|
||||||
|
|
||||||
|
use JetBrains\PhpStorm\ArrayShape;
|
||||||
|
use SPC\exception\DownloaderException;
|
||||||
|
use SPC\exception\FileSystemException;
|
||||||
|
use SPC\exception\RuntimeException;
|
||||||
|
use SPC\store\Downloader;
|
||||||
|
|
||||||
|
class PhpSource extends CustomSourceBase
|
||||||
|
{
|
||||||
|
public const NAME = 'php-src';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws DownloaderException
|
||||||
|
* @throws FileSystemException
|
||||||
|
* @throws RuntimeException
|
||||||
|
*/
|
||||||
|
public function fetch()
|
||||||
|
{
|
||||||
|
$major = defined('SPC_BUILD_PHP_VERSION') ? SPC_BUILD_PHP_VERSION : '8.1';
|
||||||
|
Downloader::fetchSource('php-src', self::getLatestPHPInfo($major));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 PHP x.y 的具体版本号,例如通过 8.1 来获取 8.1.10
|
||||||
|
*
|
||||||
|
* @throws DownloaderException
|
||||||
|
*/
|
||||||
|
#[ArrayShape(['type' => 'string', 'path' => 'string', 'rev' => 'string', 'url' => 'string'])]
|
||||||
|
public function getLatestPHPInfo(string $major_version): array
|
||||||
|
{
|
||||||
|
// 查找最新的小版本号
|
||||||
|
$info = json_decode(Downloader::curlExec(url: "https://www.php.net/releases/index.php?json&version={$major_version}"), true);
|
||||||
|
$version = $info['version'];
|
||||||
|
|
||||||
|
// 从官网直接下载
|
||||||
|
return [
|
||||||
|
'type' => 'url',
|
||||||
|
'url' => "https://www.php.net/distributions/php-{$version}.tar.gz",
|
||||||
|
// 'url' => "https://mirrors.zhamao.xin/php/php-{$version}.tar.gz",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/SPC/store/source/PostgreSQLSource.php
Normal file
29
src/SPC/store/source/PostgreSQLSource.php
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\store\source;
|
||||||
|
|
||||||
|
use SPC\store\Downloader;
|
||||||
|
|
||||||
|
class PostgreSQLSource extends CustomSourceBase
|
||||||
|
{
|
||||||
|
public const NAME = 'postgresql';
|
||||||
|
|
||||||
|
public function fetch()
|
||||||
|
{
|
||||||
|
Downloader::fetchSource('postgresql', self::getLatestInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLatestInfo(): array
|
||||||
|
{
|
||||||
|
[$url, $filename, $version] = Downloader::getFromFileList('postgresql', [
|
||||||
|
'url' => 'https://www.postgresql.org/ftp/source/',
|
||||||
|
'regex' => '/href="(?<file>v(?<version>[^"]+)\/)"/',
|
||||||
|
]);
|
||||||
|
return [
|
||||||
|
'type' => 'url',
|
||||||
|
'url' => "https://ftp.postgresql.org/pub/source/{$filename}postgresql-{$version}.tar.gz",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
41
src/SPC/util/CustomExt.php
Normal file
41
src/SPC/util/CustomExt.php
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\util;
|
||||||
|
|
||||||
|
use SPC\builder\Extension;
|
||||||
|
use SPC\exception\FileSystemException;
|
||||||
|
use SPC\store\FileSystem;
|
||||||
|
|
||||||
|
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS)]
|
||||||
|
class CustomExt
|
||||||
|
{
|
||||||
|
private static array $custom_ext_class = [];
|
||||||
|
|
||||||
|
public function __construct(protected string $ext_name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load all custom extension classes
|
||||||
|
*
|
||||||
|
* @throws \ReflectionException
|
||||||
|
* @throws FileSystemException
|
||||||
|
*/
|
||||||
|
public static function loadCustomExt(): void
|
||||||
|
{
|
||||||
|
$classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/builder/extension', 'SPC\\builder\\extension');
|
||||||
|
foreach ($classes as $class) {
|
||||||
|
$reflection = new \ReflectionClass($class);
|
||||||
|
foreach ($reflection->getAttributes(CustomExt::class) as $attribute) {
|
||||||
|
self::$custom_ext_class[$attribute->getArguments()[0]] = $class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getExtClass(string $ext_name): string
|
||||||
|
{
|
||||||
|
return self::$custom_ext_class[$ext_name] ?? Extension::class;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ namespace SPC\util;
|
|||||||
|
|
||||||
use SPC\exception\FileSystemException;
|
use SPC\exception\FileSystemException;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\RuntimeException;
|
||||||
|
use SPC\exception\WrongUsageException;
|
||||||
use SPC\store\Config;
|
use SPC\store\Config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -19,8 +20,9 @@ class DependencyUtil
|
|||||||
* @param array $exts 要获取 libs 依赖的列表
|
* @param array $exts 要获取 libs 依赖的列表
|
||||||
* @param array $additional_libs 额外要添加的库列表,用于激活 lib-suggests 触发的额外库特性
|
* @param array $additional_libs 额外要添加的库列表,用于激活 lib-suggests 触发的额外库特性
|
||||||
* @return array 返回一个包含三个数组的数组,第一个是排序后的 ext 列表,第二个是排序后的 lib 列表,第三个是没有传入但是依赖了的 ext 列表
|
* @return array 返回一个包含三个数组的数组,第一个是排序后的 ext 列表,第二个是排序后的 lib 列表,第三个是没有传入但是依赖了的 ext 列表
|
||||||
* @throws FileSystemException
|
* @throws WrongUsageException
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
|
* @throws FileSystemException
|
||||||
*/
|
*/
|
||||||
public static function getExtLibsByDeps(array $exts, array $additional_libs = []): array
|
public static function getExtLibsByDeps(array $exts, array $additional_libs = []): array
|
||||||
{
|
{
|
||||||
@@ -33,9 +35,22 @@ class DependencyUtil
|
|||||||
self::visitExtDeps($ext, $visited, $sorted);
|
self::visitExtDeps($ext, $visited, $sorted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$sorted_suggests = [];
|
||||||
|
$visited_suggests = [];
|
||||||
|
$final = [];
|
||||||
|
foreach ($exts as $ext) {
|
||||||
|
if (!isset($visited_suggests[$ext])) {
|
||||||
|
self::visitExtAllDeps($ext, $visited_suggests, $sorted_suggests);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($sorted_suggests as $suggest) {
|
||||||
|
if (in_array($suggest, $sorted)) {
|
||||||
|
$final[] = $suggest;
|
||||||
|
}
|
||||||
|
}
|
||||||
$libs = $additional_libs;
|
$libs = $additional_libs;
|
||||||
// 遍历每一个 ext 的 libs
|
// 遍历每一个 ext 的 libs
|
||||||
foreach ($sorted as $ext) {
|
foreach ($final as $ext) {
|
||||||
if (!in_array($ext, $exts)) {
|
if (!in_array($ext, $exts)) {
|
||||||
$not_included_exts[] = $ext;
|
$not_included_exts[] = $ext;
|
||||||
}
|
}
|
||||||
@@ -45,7 +60,7 @@ class DependencyUtil
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [$sorted, self::getLibsByDeps($libs), $not_included_exts];
|
return [$final, self::getLibsByDeps($libs), $not_included_exts];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,6 +70,7 @@ class DependencyUtil
|
|||||||
* @return array 排序后的列表
|
* @return array 排序后的列表
|
||||||
* @throws FileSystemException
|
* @throws FileSystemException
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
|
* @throws WrongUsageException
|
||||||
*/
|
*/
|
||||||
public static function getLibsByDeps(array $libs): array
|
public static function getLibsByDeps(array $libs): array
|
||||||
{
|
{
|
||||||
@@ -67,12 +83,65 @@ class DependencyUtil
|
|||||||
self::visitLibDeps($lib, $visited, $sorted);
|
self::visitLibDeps($lib, $visited, $sorted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $sorted;
|
|
||||||
|
$sorted_suggests = [];
|
||||||
|
$visited_suggests = [];
|
||||||
|
$final = [];
|
||||||
|
foreach ($libs as $lib) {
|
||||||
|
if (!isset($visited_suggests[$lib])) {
|
||||||
|
self::visitLibAllDeps($lib, $visited_suggests, $sorted_suggests);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($sorted_suggests as $suggest) {
|
||||||
|
if (in_array($suggest, $sorted)) {
|
||||||
|
$final[] = $suggest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $final;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws FileSystemException
|
||||||
|
* @throws RuntimeException
|
||||||
|
* @throws WrongUsageException
|
||||||
|
*/
|
||||||
|
private static function visitLibAllDeps(string $lib_name, array &$visited, array &$sorted): void
|
||||||
|
{
|
||||||
|
// 如果已经识别到了,那就不管
|
||||||
|
if (isset($visited[$lib_name])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$visited[$lib_name] = true;
|
||||||
|
// 遍历该依赖的所有依赖(此处的 getLib 如果检测到当前库不存在的话,会抛出异常)
|
||||||
|
foreach (array_merge(Config::getLib($lib_name, 'lib-depends', []), Config::getLib($lib_name, 'lib-suggests', [])) as $dep) {
|
||||||
|
self::visitLibDeps($dep, $visited, $sorted);
|
||||||
|
}
|
||||||
|
$sorted[] = $lib_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
* @throws FileSystemException
|
* @throws FileSystemException
|
||||||
|
* @throws WrongUsageException
|
||||||
|
*/
|
||||||
|
private static function visitExtAllDeps(string $ext_name, array &$visited, array &$sorted): void
|
||||||
|
{
|
||||||
|
// 如果已经识别到了,那就不管
|
||||||
|
if (isset($visited[$ext_name])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$visited[$ext_name] = true;
|
||||||
|
// 遍历该依赖的所有依赖(此处的 getLib 如果检测到当前库不存在的话,会抛出异常)
|
||||||
|
foreach (array_merge(Config::getExt($ext_name, 'ext-depends', []), Config::getExt($ext_name, 'ext-suggests', [])) as $dep) {
|
||||||
|
self::visitExtDeps($dep, $visited, $sorted);
|
||||||
|
}
|
||||||
|
$sorted[] = $ext_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws RuntimeException
|
||||||
|
* @throws FileSystemException
|
||||||
|
* @throws WrongUsageException
|
||||||
*/
|
*/
|
||||||
private static function visitLibDeps(string $lib_name, array &$visited, array &$sorted): void
|
private static function visitLibDeps(string $lib_name, array &$visited, array &$sorted): void
|
||||||
{
|
{
|
||||||
@@ -91,6 +160,7 @@ class DependencyUtil
|
|||||||
/**
|
/**
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
* @throws FileSystemException
|
* @throws FileSystemException
|
||||||
|
* @throws WrongUsageException
|
||||||
*/
|
*/
|
||||||
private static function visitExtDeps(string $ext_name, array &$visited, array &$sorted): void
|
private static function visitExtDeps(string $ext_name, array &$visited, array &$sorted): void
|
||||||
{
|
{
|
||||||
|
|||||||
100
src/SPC/util/LicenseDumper.php
Normal file
100
src/SPC/util/LicenseDumper.php
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\util;
|
||||||
|
|
||||||
|
use SPC\exception\FileSystemException;
|
||||||
|
use SPC\exception\RuntimeException;
|
||||||
|
use SPC\exception\WrongUsageException;
|
||||||
|
use SPC\store\Config;
|
||||||
|
use SPC\store\FileSystem;
|
||||||
|
|
||||||
|
class LicenseDumper
|
||||||
|
{
|
||||||
|
private array $exts = [];
|
||||||
|
|
||||||
|
private array $libs = [];
|
||||||
|
|
||||||
|
private array $sources = [];
|
||||||
|
|
||||||
|
public function addExts(array $exts): LicenseDumper
|
||||||
|
{
|
||||||
|
$this->exts = array_merge($exts, $this->exts);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addLibs(array $libs): LicenseDumper
|
||||||
|
{
|
||||||
|
$this->libs = array_merge($libs, $this->libs);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addSources(array $sources): LicenseDumper
|
||||||
|
{
|
||||||
|
$this->sources = array_merge($sources, $this->sources);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws WrongUsageException
|
||||||
|
* @throws FileSystemException
|
||||||
|
* @throws RuntimeException
|
||||||
|
*/
|
||||||
|
public function dump(string $target_dir): bool
|
||||||
|
{
|
||||||
|
// mkdir first
|
||||||
|
if (is_dir($target_dir) && !FileSystem::removeDir($target_dir)) {
|
||||||
|
logger()->warning('Target dump directory is noe empty, be aware!');
|
||||||
|
}
|
||||||
|
FileSystem::createDir($target_dir);
|
||||||
|
foreach ($this->exts as $ext) {
|
||||||
|
if (Config::getExt($ext, 'type') !== 'external') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$source_name = Config::getExt($ext, 'source');
|
||||||
|
$content = $this->getSourceLicense($source_name);
|
||||||
|
file_put_contents($target_dir . '/ext_' . $ext . '.txt', $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->libs as $lib) {
|
||||||
|
$source_name = Config::getLib($lib, 'source');
|
||||||
|
$content = $this->getSourceLicense($source_name);
|
||||||
|
file_put_contents($target_dir . '/lib_' . $lib . '.txt', $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->sources as $source) {
|
||||||
|
file_put_contents($target_dir . '/src_' . $source . '.txt', $this->getSourceLicense($source));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws FileSystemException
|
||||||
|
* @throws RuntimeException
|
||||||
|
*/
|
||||||
|
private function getSourceLicense(string $source_name): ?string
|
||||||
|
{
|
||||||
|
$src = Config::getSource($source_name)['license'] ?? null;
|
||||||
|
if ($src === null) {
|
||||||
|
throw new RuntimeException('source [' . $source_name . '] license meta is not exist');
|
||||||
|
}
|
||||||
|
|
||||||
|
return match ($src['type']) {
|
||||||
|
'text' => $src['text'],
|
||||||
|
'file' => $this->loadSourceFile($source_name, $src['path'], Config::getSource($source_name)['path'] ?? null),
|
||||||
|
default => throw new RuntimeException('source [' . $source_name . '] license type is not allowed'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws RuntimeException
|
||||||
|
*/
|
||||||
|
private function loadSourceFile(string $source_name, string $in_path, ?string $custom_base_path = null): string
|
||||||
|
{
|
||||||
|
if (!file_exists(SOURCE_PATH . '/' . ($custom_base_path ?? $source_name) . '/' . $in_path)) {
|
||||||
|
throw new RuntimeException('source [' . $source_name . '] license file [' . $in_path . '] is not exist');
|
||||||
|
}
|
||||||
|
return file_get_contents(SOURCE_PATH . '/' . ($custom_base_path ?? $source_name) . '/' . $in_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@ class Patcher
|
|||||||
* @throws FileSystemException
|
* @throws FileSystemException
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
*/
|
*/
|
||||||
public static function patchPHPDepFiles(): void
|
public static function patchMicroThings(): void
|
||||||
{
|
{
|
||||||
$ver_file = SOURCE_PATH . '/php-src/main/php_version.h';
|
$ver_file = SOURCE_PATH . '/php-src/main/php_version.h';
|
||||||
if (!file_exists($ver_file)) {
|
if (!file_exists($ver_file)) {
|
||||||
@@ -29,6 +29,9 @@ class Patcher
|
|||||||
logger()->info('Patching php');
|
logger()->info('Patching php');
|
||||||
|
|
||||||
$major_ver = $match[1] . $match[2];
|
$major_ver = $match[1] . $match[2];
|
||||||
|
if ($major_ver === '74') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$check = !defined('DEBUG_MODE') ? ' -q' : '';
|
$check = !defined('DEBUG_MODE') ? ' -q' : '';
|
||||||
// f_passthru('cd ' . SOURCE_PATH . '/php-src && git checkout' . $check . ' HEAD');
|
// f_passthru('cd ' . SOURCE_PATH . '/php-src && git checkout' . $check . ' HEAD');
|
||||||
|
|
||||||
@@ -196,7 +199,7 @@ class Patcher
|
|||||||
case 'x86_64':
|
case 'x86_64':
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException('unsupported arch: ' . $builder->arch);
|
throw new RuntimeException('unsupported arch while patching php configure: ' . $builder->arch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ class UnixShell
|
|||||||
|
|
||||||
private bool $debug;
|
private bool $debug;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct(?bool $debug = null)
|
||||||
{
|
{
|
||||||
$this->debug = defined('DEBUG_MODE');
|
$this->debug = $debug ?? defined('DEBUG_MODE');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function cd(string $dir): UnixShell
|
public function cd(string $dir): UnixShell
|
||||||
|
|||||||
18
src/SPC/util/Util.php
Normal file
18
src/SPC/util/Util.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SPC\util;
|
||||||
|
|
||||||
|
class Util
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get current PHP version ID (downloaded)
|
||||||
|
*/
|
||||||
|
public static function getPHPVersionID(): int
|
||||||
|
{
|
||||||
|
$file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h');
|
||||||
|
preg_match('/PHP_VERSION_ID (\d+)/', $file, $match);
|
||||||
|
return intval($match[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,16 +2,14 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
// 工作目录
|
|
||||||
use ZM\Logger\ConsoleLogger;
|
use ZM\Logger\ConsoleLogger;
|
||||||
|
|
||||||
define('WORKING_DIR', getcwd());
|
define('WORKING_DIR', getcwd());
|
||||||
const ROOT_DIR = __DIR__ . '/../..';
|
const ROOT_DIR = __DIR__ . '/../..';
|
||||||
|
|
||||||
// 程序启动时间
|
// CLI start time
|
||||||
define('START_TIME', microtime(true));
|
define('START_TIME', microtime(true));
|
||||||
|
|
||||||
// 规定目录
|
|
||||||
define('BUILD_ROOT_PATH', is_string($a = getenv('BUILD_ROOT_PATH')) ? $a : (WORKING_DIR . '/buildroot'));
|
define('BUILD_ROOT_PATH', is_string($a = getenv('BUILD_ROOT_PATH')) ? $a : (WORKING_DIR . '/buildroot'));
|
||||||
define('SOURCE_PATH', is_string($a = getenv('SOURCE_PATH')) ? $a : (WORKING_DIR . '/source'));
|
define('SOURCE_PATH', is_string($a = getenv('SOURCE_PATH')) ? $a : (WORKING_DIR . '/source'));
|
||||||
define('DOWNLOAD_PATH', is_string($a = getenv('DOWNLOAD_PATH')) ? $a : (WORKING_DIR . '/downloads'));
|
define('DOWNLOAD_PATH', is_string($a = getenv('DOWNLOAD_PATH')) ? $a : (WORKING_DIR . '/downloads'));
|
||||||
@@ -24,29 +22,32 @@ define('SEPARATED_PATH', [
|
|||||||
BUILD_ROOT_PATH,
|
BUILD_ROOT_PATH,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 危险的命令额外用 notice 级别提醒
|
// dangerous command
|
||||||
const DANGER_CMD = [
|
const DANGER_CMD = [
|
||||||
'rm',
|
'rm',
|
||||||
'rmdir',
|
'rmdir',
|
||||||
];
|
];
|
||||||
|
|
||||||
// 替换方案
|
// file replace strategy
|
||||||
const REPLACE_FILE_STR = 1;
|
const REPLACE_FILE_STR = 1;
|
||||||
const REPLACE_FILE_PREG = 2;
|
const REPLACE_FILE_PREG = 2;
|
||||||
const REPLACE_FILE_USER = 3;
|
const REPLACE_FILE_USER = 3;
|
||||||
|
|
||||||
// 编译输出类型
|
// library build status
|
||||||
const BUILD_MICRO_NONE = 0;
|
|
||||||
const BUILD_MICRO_ONLY = 1;
|
|
||||||
const BUILD_MICRO_BOTH = 2;
|
|
||||||
|
|
||||||
// 编译状态
|
|
||||||
const BUILD_STATUS_OK = 0;
|
const BUILD_STATUS_OK = 0;
|
||||||
const BUILD_STATUS_ALREADY = 1;
|
const BUILD_STATUS_ALREADY = 1;
|
||||||
const BUILD_STATUS_FAILED = 2;
|
const BUILD_STATUS_FAILED = 2;
|
||||||
|
|
||||||
// 编译类型
|
// build target type
|
||||||
const BUILD_TYPE_CLI = 1;
|
const BUILD_TARGET_NONE = 0;
|
||||||
const BUILD_TYPE_MICRO = 2;
|
const BUILD_TARGET_CLI = 1;
|
||||||
|
const BUILD_TARGET_MICRO = 2;
|
||||||
|
const BUILD_TARGET_FPM = 4;
|
||||||
|
const BUILD_TARGET_ALL = 7;
|
||||||
|
|
||||||
|
// doctor error fix policy
|
||||||
|
const FIX_POLICY_DIE = 1; // die directly
|
||||||
|
const FIX_POLICY_PROMPT = 2; // if it can be fixed, ask fix or not
|
||||||
|
const FIX_POLICY_AUTOFIX = 3; // if it can be fixed, just fix automatically
|
||||||
|
|
||||||
ConsoleLogger::$date_format = 'H:i:s';
|
ConsoleLogger::$date_format = 'H:i:s';
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user