mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-03-17 20:34:51 +08:00
Merge branch 'main' into libargon2-support
# Conflicts: # config/lib.json # config/source.json
This commit is contained in:
commit
4f5335bba4
16
.github/workflows/build-linux-x86_64.yml
vendored
16
.github/workflows/build-linux-x86_64.yml
vendored
@ -40,11 +40,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# Install Ubuntu missing packages and mark os suffix
|
||||
- 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
|
||||
@ -54,7 +49,7 @@ jobs:
|
||||
|
||||
# If there's no Composer cache, install dependencies
|
||||
- if: steps.cache-composer-deps.outputs.cache-hit != 'true'
|
||||
run: composer update --no-dev
|
||||
run: composer update --no-dev --classmap-authoritative
|
||||
|
||||
# Cache downloaded source
|
||||
- id: cache-download
|
||||
@ -77,10 +72,10 @@ jobs:
|
||||
|
||||
# If there's no dependencies cache, fetch sources, with or without debug
|
||||
- if: steps.cache-download.outputs.cache-hit != 'true'
|
||||
run: CACHE_API_EXEC=yes ./bin/spc download --with-php=${{ inputs.version }} --all ${{ env.SPC_BUILD_DEBUG }}
|
||||
run: CACHE_API_EXEC=yes ./bin/spc-alpine-docker download --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 }}
|
||||
- run: ./bin/spc-alpine-docker 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 }}
|
||||
@ -115,8 +110,3 @@ jobs:
|
||||
buildroot/build-extensions.json
|
||||
buildroot/build-libraries.json
|
||||
|
||||
# Upload downloaded files
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: download-files
|
||||
path: downloads/
|
||||
|
||||
7
.github/workflows/build-macos-x86_64.yml
vendored
7
.github/workflows/build-macos-x86_64.yml
vendored
@ -54,7 +54,7 @@ jobs:
|
||||
|
||||
# If there's no Composer cache, install dependencies
|
||||
- if: steps.cache-composer-deps.outputs.cache-hit != 'true'
|
||||
run: composer update --no-dev
|
||||
run: composer update --no-dev --classmap-authoritative
|
||||
|
||||
# Cache downloaded source
|
||||
- id: cache-download
|
||||
@ -115,8 +115,3 @@ jobs:
|
||||
buildroot/build-extensions.json
|
||||
buildroot/build-libraries.json
|
||||
|
||||
# Upload downloaded files
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: download-files
|
||||
path: downloads/
|
||||
|
||||
40
.github/workflows/download-cache.yml
vendored
Normal file
40
.github/workflows/download-cache.yml
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
name: archive download sources weekly
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "* 14 * * 5"
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
jobs:
|
||||
download:
|
||||
name: cache download sources
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
php-version: [ "8.0", "8.1", "8.2" ]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# Cache composer dependencies
|
||||
- id: cache-composer-deps
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: vendor
|
||||
key: composer-dependencies
|
||||
|
||||
# If there's no Composer cache, install dependencies
|
||||
- if: steps.cache-composer-deps.outputs.cache-hit != 'true'
|
||||
run: composer update --no-dev
|
||||
|
||||
# If there's no dependencies cache, fetch sources, with or without debug
|
||||
- if: steps.cache-download.outputs.cache-hit != 'true'
|
||||
run: ./bin/spc download --with-php=${{ matrix.php-version }} --all --debug
|
||||
|
||||
# Upload downloaded files
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: download-files-${{ matrix.php-version }}
|
||||
path: downloads/
|
||||
47
.github/workflows/release-build.yml
vendored
Normal file
47
.github/workflows/release-build.yml
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
name: Upload SPC Binary (Release)
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-release-artifacts:
|
||||
name: "Upload SPC Binary (Release)"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
operating-system:
|
||||
- "linux-x86_64"
|
||||
- "macos-x86_64"
|
||||
- "linux-aarch64"
|
||||
- "macos-aarch64"
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
uses: "actions/checkout@v4"
|
||||
|
||||
- name: Reuse static-php-cli-hosted artifacts
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
repo: static-php/static-php-cli-hosted
|
||||
branch: master
|
||||
workflow: build-spc-release.yml
|
||||
name: "spc-${{ matrix.operating-system }}"
|
||||
|
||||
- name: "Archive Executable"
|
||||
run: |
|
||||
tar -czf spc-${{ matrix.operating-system }}.tar.gz spc
|
||||
echo "filename=spc-${{ matrix.operating-system }}.tar.gz" >> $GITHUB_ENV
|
||||
|
||||
- name: upload binaries to release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: ${{startsWith(github.ref, 'refs/tags/') }}
|
||||
with:
|
||||
files: ${{ env.filename }}
|
||||
|
||||
- name: "Upload Artifact"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
path: spc
|
||||
name: spc-${{ matrix.operating-system }}
|
||||
98
.github/workflows/tests.yml
vendored
Normal file
98
.github/workflows/tests.yml
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
php-cs-fixer:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.1'
|
||||
extensions: curl, openssl, mbstring
|
||||
ini-values: memory_limit=-1
|
||||
tools: pecl, composer, php-cs-fixer
|
||||
|
||||
- name: Run PHP-CS-Fixer fix
|
||||
run: php-cs-fixer fix --dry-run --diff --ansi
|
||||
|
||||
phpstan:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.1'
|
||||
extensions: curl, openssl, mbstring
|
||||
ini-values: memory_limit=-1
|
||||
tools: composer
|
||||
|
||||
- name: Cache Composer packages
|
||||
id: composer-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: vendor
|
||||
key: ${{ runner.os }}-phpstan-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-phpstan-
|
||||
|
||||
- name: Install Dependencies
|
||||
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
|
||||
|
||||
- name: Run phpstan
|
||||
run: vendor/bin/phpstan analyse
|
||||
|
||||
phpunit:
|
||||
name: PHPUnit (PHP ${{ matrix.php }})
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- php: '8.1'
|
||||
- php: '8.2'
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: "${{ matrix.php }}"
|
||||
tools: pecl, composer
|
||||
extensions: curl, openssl, mbstring
|
||||
ini-values: memory_limit=-1
|
||||
|
||||
- name: Cache Composer packages
|
||||
id: composer-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: vendor
|
||||
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-php-
|
||||
|
||||
- name: Install Dependencies
|
||||
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
|
||||
|
||||
- name: Run PHPUnit tests
|
||||
run: |
|
||||
vendor/bin/phpunit tests/ --no-coverage
|
||||
9
.gitignore
vendored
9
.gitignore
vendored
@ -4,8 +4,7 @@ docker/libraries/
|
||||
docker/extensions/
|
||||
docker/source/
|
||||
|
||||
# Composer file
|
||||
composer.lock
|
||||
# Vendor files
|
||||
/vendor/
|
||||
|
||||
# default source extract directory
|
||||
@ -17,11 +16,15 @@ composer.lock
|
||||
# default source build root directory
|
||||
/buildroot/
|
||||
|
||||
# php cs fixer cache file
|
||||
# tools cache files
|
||||
.php-cs-fixer.cache
|
||||
.phpunit.result.cache
|
||||
|
||||
# exclude self-runtime
|
||||
/bin/*
|
||||
!/bin/spc
|
||||
!/bin/setup-runtime
|
||||
!/bin/spc-alpine-docker
|
||||
|
||||
# default test directory
|
||||
/tests/var/
|
||||
|
||||
@ -65,5 +65,5 @@ return (new PhpCsFixer\Config())
|
||||
'phpdoc_var_without_name' => false,
|
||||
])
|
||||
->setFinder(
|
||||
PhpCsFixer\Finder::create()->in(__DIR__ . '/src')
|
||||
PhpCsFixer\Finder::create()->in([__DIR__ . '/src', __DIR__ . '/tests/SPC'])
|
||||
);
|
||||
|
||||
240
README-en.md
240
README-en.md
@ -1,241 +1,3 @@
|
||||
# static-php-cli
|
||||
|
||||
Compile A Statically Linked PHP With Swoole and other Extensions.
|
||||
|
||||
Compile a purely static php-cli binary file with various extensions to make PHP applications more portable! (cli SAPI)
|
||||
|
||||
<img width="600" alt="截屏2023-05-02 15 53 13" src="https://user-images.githubusercontent.com/20330940/235610282-23e58d68-bd35-4092-8465-171cff2d5ba8.png">
|
||||
|
||||
You can also use the micro binary file to combine php binary and php source code into one for distribution!
|
||||
This feature is provided by [dixyes/phpmicro](https://github.com/dixyes/phpmicro). (micro SAPI)
|
||||
|
||||
<img width="600" alt="截屏2023-05-02 15 52 33" src="https://user-images.githubusercontent.com/20330940/235610318-2ef4e3f1-278b-4ca4-99f4-b38120efc395.png">
|
||||
|
||||
[]()
|
||||
[]()
|
||||
[](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml)
|
||||
[](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml)
|
||||
|
||||
[]()
|
||||
[]()
|
||||
|
||||
## Compilation Requirements
|
||||
|
||||
Yes, this project is written in PHP, pretty funny.
|
||||
But static-php-cli runtime only requires an environment above PHP 8.0 and `tokenizer`, `iconv` extension.
|
||||
|
||||
Here is the architecture support status, where `CI` represents support for GitHub Action builds,
|
||||
`Local` represents support for local builds, and blank represents not currently supported.
|
||||
|
||||
| | x86_64 | aarch64 |
|
||||
|---------|-----------|-----------|
|
||||
| macOS | CI, Local | Local |
|
||||
| Linux | CI, Local | CI, Local |
|
||||
| Windows | | |
|
||||
|
||||
> 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.
|
||||
|
||||
Currently supported PHP versions for compilation are: `7.4`, `8.0`, `8.1`, `8.2`.
|
||||
|
||||
## Usage
|
||||
|
||||
Please first select the extension you want to compile based on the extension list below.
|
||||
|
||||
### Direct Download
|
||||
|
||||
If you don't compile yourself, you can download pre-compiled artifact from Actions, or from self-hosted server: [Here](https://dl.zhamao.xin/static-php-cli/)
|
||||
|
||||
> self-hosted server contains extensions: `bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,gd,gmp,iconv,xml,mbstring,mbregex,mysqlnd,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,redis,session,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip`
|
||||
|
||||
### Supported Extensions
|
||||
|
||||
[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
|
||||
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
|
||||
./bin/spc fetch --all
|
||||
# with bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl extension, build both CLI and phpmicro SAPI
|
||||
./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
|
||||
```
|
||||
|
||||
In addition, we build NTS by default. If you are going to build ZTS version, just add `--enable-zts` option.
|
||||
|
||||
```bash
|
||||
./bin/spc build openssl,pcntl --build-all --enable-zts
|
||||
```
|
||||
|
||||
Adding option `--no-strip` can produce binaries with debug symbols, in order to debug (using gdb). Disabling strip will increase the size of static binary.
|
||||
|
||||
### php-cli Usage
|
||||
|
||||
> 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`,
|
||||
which can be distributed and used directly.
|
||||
This file will be located in the directory `buildroot/bin/`, copy it out for use.
|
||||
|
||||
```bash
|
||||
cd buildroot/bin/
|
||||
./php -v # check version
|
||||
./php -m # check extensions
|
||||
./php your_code.php # run your php code
|
||||
./php your_project.phar # run your phar (project archive)
|
||||
```
|
||||
|
||||
### 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`,
|
||||
the final compilation result will output a file named `./micro.sfx`,
|
||||
which needs to be used with your PHP source code like `code.php`.
|
||||
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.
|
||||
|
||||
```bash
|
||||
echo "<?php echo 'Hello world' . PHP_EOL;" > code.php
|
||||
cat micro.sfx code.php > single-app && chmod +x single-app
|
||||
./single-app
|
||||
|
||||
# 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.
|
||||
|
||||
### 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
|
||||
|
||||
- [X] Basic CLI framework (by `symfony/console`)
|
||||
- [X] Linux support
|
||||
- [X] macOS support
|
||||
- [X] Exception handler
|
||||
- [ ] Windows support
|
||||
- [X] PHP 7.4 support
|
||||
- [X] fpm support
|
||||
|
||||
More functions and features are coming soon, Bugs and TODOs: https://github.com/crazywhalecc/static-php-cli/issues/32
|
||||
|
||||
## Contribution
|
||||
|
||||
Currently, there are only a few supported extensions.
|
||||
If the extension you need is missing, you can create an issue.
|
||||
If you are familiar with this project, you are also welcome to initiate a pull request.
|
||||
|
||||
The basic principles for contributing are as follows:
|
||||
|
||||
- This project uses php-cs-fixer and phpstan as code formatting tools. Before contributing, please run `composer analyze` and `composer cs-fix` on the updated code.
|
||||
- If other open source libraries are involved, the corresponding licenses should be provided.
|
||||
Also, configuration files should be sorted using the command `sort-config` after modification.
|
||||
For more information about sorting commands, see the documentation.
|
||||
- Naming conventions should be followed, such as using the extension name registered in PHP for the extension name itself,
|
||||
and external library names should follow the project's own naming conventions. For internal logic functions, class names, variables, etc.,
|
||||
camelCase and underscore formats should be followed, and mixing within the same module is prohibited.
|
||||
- When compiling external libraries and creating patches, compatibility with different operating systems should be considered.
|
||||
|
||||
## Sponsor this project
|
||||
|
||||
You can sponsor my project on [this page](https://github.com/crazywhalecc/crazywhalecc/blob/master/FUNDING.md).
|
||||
|
||||
## Open-Source License
|
||||
|
||||
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:
|
||||
|
||||
- [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)
|
||||
|
||||
Due to the special nature of this project,
|
||||
many other open source projects such as curl and protobuf will be used during the project compilation process,
|
||||
and they all have their own open source licenses.
|
||||
|
||||
Please use the `bin/spc dump-license` command to export the open source licenses used in the project after compilation,
|
||||
and comply with the corresponding project's LICENSE.
|
||||
|
||||
## Advanced
|
||||
|
||||
This project is pure open source project, and some modules are separated for developing.
|
||||
|
||||
This section will be improved after refactor version released.
|
||||
English README has been moved to [README.md](README.md).
|
||||
|
||||
252
README-zh.md
Executable file
252
README-zh.md
Executable file
@ -0,0 +1,252 @@
|
||||
# static-php-cli
|
||||
|
||||
Build single static PHP binary, with PHP project together, with popular extensions included.
|
||||
|
||||
🌐 **[中文](README-zh.md)** | **[English](README.md)**
|
||||
|
||||
编译纯静态的 PHP Binary 二进制文件,带有各种扩展,让 PHP-cli 应用变得更便携!(cli SAPI)
|
||||
|
||||
<img width="600" alt="截屏2023-05-02 15 53 13" src="https://user-images.githubusercontent.com/20330940/235610282-23e58d68-bd35-4092-8465-171cff2d5ba8.png">
|
||||
|
||||
同时可以使用 micro 二进制文件,将 PHP 源码和 PHP 二进制构建为一个文件分发!(micro SAPI)
|
||||
|
||||
<img width="600" alt="截屏2023-05-02 15 52 33" src="https://user-images.githubusercontent.com/20330940/235610318-2ef4e3f1-278b-4ca4-99f4-b38120efc395.png">
|
||||
|
||||
> 该 SAPI 源自 [dixyes/phpmicro](https://github.com/dixyes/phpmicro) 的 [Fork 仓库](https://github.com/static-php/phpmicro)。
|
||||
|
||||
[]()
|
||||
[]()
|
||||
[](https://github.com/static-php/static-php-cli-hosted/actions/workflows/build-php-common.yml)
|
||||
[]()
|
||||
[]()
|
||||
|
||||
> 项目名称是 static-php-cli,但其实支持 cli、fpm、micro 和 embed SAPI 😎
|
||||
|
||||
## 文档
|
||||
|
||||
目前 README 编写了基本用法。有关 static-php-cli 所有的功能,请点击这里查看文档:<https://static-php.dev>。
|
||||
|
||||
## 自托管直接下载
|
||||
|
||||
如果你不想自行编译 PHP,可以从本项目现有的示例 Action 下载 Artifact,也可以从自托管的服务器下载:[进入](https://dl.static-php.dev/static-php-cli/common/)
|
||||
|
||||
> 自托管的服务器默认包含的扩展有:`bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,gd,gmp,iconv,xml,mbstring,mbregex,mysqlnd,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,redis,session,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip`
|
||||
|
||||
## 使用 static-php-cli 构建 PHP
|
||||
|
||||
### 编译环境需求
|
||||
|
||||
是的,本项目采用 PHP 编写,编译前需要一个 PHP 环境,比较滑稽。
|
||||
但本项目默认可通过自身构建的 micro 和 static-php 二进制运行,其他只需要包含 mbstring、pcntl 扩展和 PHP 版本大于等于 8.1 即可。
|
||||
|
||||
下面是架构支持情况,:octocat: 代表支持 GitHub Action 构建,:computer: 代表支持本地构建,空 代表暂不支持。
|
||||
|
||||
| | x86_64 | aarch64 |
|
||||
|---------|----------------------|----------------------|
|
||||
| macOS | :octocat: :computer: | :computer: |
|
||||
| Linux | :octocat: :computer: | :octocat: :computer: |
|
||||
| Windows | | |
|
||||
| FreeBSD | :computer: | :computer: |
|
||||
|
||||
> macOS-arm64 因 GitHub 暂未提供 arm runner,如果要构建 arm 二进制,可以使用手动构建。
|
||||
|
||||
目前支持编译的 PHP 版本为:`7.3`,`7.4`,`8.0`,`8.1`,`8.2`,`8.3`。
|
||||
|
||||
### 支持的扩展情况
|
||||
|
||||
请先根据下方扩展列表选择你要编译的扩展。
|
||||
|
||||
- [扩展支持列表](https://static-php.dev/zh/guide/extensions.html)
|
||||
- [编译命令生成器](https://static-php.dev/zh/guide/cli-generator.html)
|
||||
|
||||
> 如果这里没有你需要的扩展,可以提交 Issue。
|
||||
|
||||
### 使用 Actions 构建
|
||||
|
||||
使用 GitHub Action 可以方便地构建一个静态编译的 PHP,同时可以自行定义要编译的扩展。
|
||||
|
||||
1. Fork 本项目。
|
||||
2. 进入项目的 Actions,选择 CI。
|
||||
3. 选择 `Run workflow`,填入你要编译的 PHP 版本、目标类型、扩展列表。(扩展列表使用英文逗号分割,例如 `bcmath,curl,mbstring`)
|
||||
4. 等待大约一段时间后,进入对应的任务中,获取 `Artifacts`。
|
||||
|
||||
如果你选择了 `debug`,则会在构建时输出所有日志,包括编译的日志,以供排查错误。
|
||||
|
||||
### 手动构建(使用 SPC 二进制)
|
||||
|
||||
本项目提供了一个 static-php-cli 的二进制文件,你可以直接下载对应平台的二进制文件,然后使用它来构建静态的 PHP。目前 `spc` 二进制支持的平台有 Linux 和 macOS。
|
||||
|
||||
下面是从 GitHub Action 下载的方法:
|
||||
|
||||
1. 进入 [GitHub Action](https://github.com/crazywhalecc/static-php-cli/actions/workflows/release-build.yml)。
|
||||
2. 选择一个最新的构建任务,进入后选择 `Artifacts`,下载对应平台的二进制文件。
|
||||
3. 解压 `.zip` 文件。解压后,为其添加执行权限:`chmod +x ./spc`。
|
||||
|
||||
你也可以从自托管的服务器下载二进制文件:[进入](https://dl.static-php.dev/static-php-cli/spc-bin/nightly/)。
|
||||
|
||||
### 手动构建(使用源码)
|
||||
|
||||
先克隆本项目:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/crazywhalecc/static-php-cli.git
|
||||
```
|
||||
|
||||
如果你本机没有安装 PHP,你需要先使用包管理(例如 brew、apt、yum、apk 等)安装 php。
|
||||
|
||||
你也可以通过 `bin/setup-runtime` 命令下载静态编译好的 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
|
||||
|
||||
# 初始化本项目
|
||||
cd static-php-cli
|
||||
composer update
|
||||
chmod +x bin/spc
|
||||
```
|
||||
|
||||
### 使用 static-php-cli 命令行程序
|
||||
|
||||
下面是使用 static-php-cli 编译静态 php 和 micro 的基础用法:
|
||||
|
||||
> 如果你使用的是打包好的 `spc` 二进制,你需要将下列命令的 `bin/spc` 替换为 `./spc`。
|
||||
|
||||
```bash
|
||||
# 检查环境依赖,并根据提示的命令安装缺失的编译工具
|
||||
./bin/spc doctor
|
||||
# 拉取所有依赖库
|
||||
./bin/spc fetch --all
|
||||
# 只拉取编译指定扩展需要的所有依赖
|
||||
./bin/spc download --for-extensions=openssl,pcntl,mbstring,pdo_sqlite
|
||||
# 构建包含 bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl 扩展的 php-cli 和 micro.sfx
|
||||
./bin/spc build "bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl" --build-cli --build-micro
|
||||
```
|
||||
|
||||
你也可以使用参数 `--with-php=x.y` 来指定下载的 PHP 版本,目前支持 7.3 ~ 8.2:
|
||||
|
||||
```bash
|
||||
# 优先考虑使用 >= 8.0 的 PHP 版本,因为 phpmicro 不支持在 PHP7 中构建
|
||||
./bin/spc download --with-php=8.2 --all
|
||||
```
|
||||
|
||||
其中,目前支持构建 cli,micro,fpm 三种静态二进制,使用以下参数的一个或多个来指定编译的 SAPI:
|
||||
|
||||
- `--build-cli`:构建 cli 二进制
|
||||
- `--build-micro`:构建 phpmicro 自执行二进制
|
||||
- `--build-fpm`:构建 fpm
|
||||
- `--build-embed`:构建 embed(libphp)
|
||||
- `--build-all`:构建所有
|
||||
|
||||
如果出现了任何错误,可以使用 `--debug` 参数来展示完整的输出日志,以供排查错误:
|
||||
|
||||
```bash
|
||||
./bin/spc build openssl,pcntl,mbstring --debug --build-all
|
||||
./bin/spc fetch --all --debug
|
||||
```
|
||||
|
||||
此外,默认编译的 PHP 为 NTS 版本。如需编译线程安全版本(ZTS),只需添加参数 `--enable-zts` 即可。
|
||||
|
||||
```bash
|
||||
./bin/spc build openssl,pcntl --build-all --enable-zts
|
||||
```
|
||||
|
||||
同时,你也可以使用参数 `--no-strip` 来关闭裁剪,关闭裁剪后可以使用 gdb 等工具调试,但这样会让静态二进制体积变大。
|
||||
|
||||
## 不同 SAPI 的使用
|
||||
|
||||
### 使用 cli
|
||||
|
||||
> php-cli 是一个静态的二进制文件,类似 Go、Rust 语言编译后的单个可移植的二进制文件。
|
||||
|
||||
采用参数 `--build-cli` 或`--build-all` 参数时,最后编译结果会输出一个 `./php` 的二进制文件,此文件可分发、可直接使用。
|
||||
该文件编译后会存放在 `buildroot/bin/` 目录中,名称为 `php`,拷贝出来即可。
|
||||
|
||||
```bash
|
||||
cd buildroot/bin/
|
||||
./php -v # 检查版本
|
||||
./php -m # 检查编译的扩展
|
||||
./php your_code.php # 运行代码
|
||||
./php your_project.phar # 运行打包为 phar 单文件的项目
|
||||
```
|
||||
|
||||
### 使用 micro
|
||||
|
||||
> phpmicro 是一个提供自执行二进制 PHP 的项目,本项目依赖 phpmicro 进行编译自执行二进制。详见 [dixyes/phpmicro](https://github.com/dixyes/phpmicro)。
|
||||
|
||||
采用项目参数 `--build-micro` 或 `--build-all` 时,最后编译结果会输出一个 `./micro.sfx` 的文件,此文件需要配合你的 PHP 源码使用。
|
||||
该文件编译后会存放在 `buildroot/bin/` 目录中,拷贝出来即可。
|
||||
|
||||
使用时应准备好你的项目源码文件,可以是单个 PHP 文件,也可以是 Phar 文件。
|
||||
|
||||
```bash
|
||||
echo "<?php echo 'Hello world' . PHP_EOL;" > code.php
|
||||
cat micro.sfx code.php > single-app && chmod +x single-app
|
||||
./single-app
|
||||
```
|
||||
|
||||
如果打包 PHAR 文件,仅需把 code.php 更换为 phar 文件路径即可。
|
||||
你可以使用 [box-project/box](https://github.com/box-project/box) 将你的 CLI 项目打包为 Phar,
|
||||
然后将它与 phpmicro 结合,生成独立可执行的二进制文件。
|
||||
|
||||
```bash
|
||||
# 使用 static-php-cli 生成的 micro.sfx 结合,也可以直接使用 cat 命令结合它们
|
||||
bin/spc micro:combine my-app.phar
|
||||
cat buildroot/bin/micro.sfx my-app.phar > my-app && chmod +x my-app
|
||||
|
||||
# 使用 micro:combine 结合可以将 INI 选项注入到二进制中
|
||||
bin/spc micro:combine my-app.phar -I "memory_limit=4G" -I "disable_functions=system" --output my-app-2
|
||||
```
|
||||
|
||||
> 有些情况下的 phar 文件或 PHP 项目可能无法在 micro 环境下运行。
|
||||
|
||||
### 使用 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`。
|
||||
|
||||
### 使用 embed
|
||||
|
||||
采用项目参数 `--build-embed` 或 `--build-all` 时,最后编译结果会输出一个 `libphp.a`、`php-config` 以及一系列头文件,存放在 `buildroot/`,你可以在你的其他代码中引入它们。
|
||||
|
||||
如果你知道 [embed SAPI](https://github.com/php/php-src/tree/master/sapi/embed),你应该知道如何使用它。对于有可能编译用到引入其他库的问题,你可以使用 `buildroot/bin/php-config` 来获取编译时的配置。
|
||||
|
||||
另外,有关如何使用此功能的高级示例,请查看[如何使用它构建 FrankenPHP 的静态版本](https://github.com/dunglas/frankenphp/blob/main/docs/static.md)。
|
||||
|
||||
## 贡献
|
||||
|
||||
如果缺少你需要的扩展,可发起 Issue。如果你对本项目较熟悉,也欢迎为本项目发起 Pull Request。
|
||||
|
||||
另外,添加新扩展的贡献方式,可以参考下方 `进阶`。
|
||||
|
||||
如果你想贡献文档内容,请到项目仓库 [static-php/static-php-cli-docs](https://github.com/static-php/static-php-cli-docs) 贡献。
|
||||
|
||||
## 赞助本项目
|
||||
|
||||
你可以在 [我的个人赞助页](https://github.com/crazywhalecc/crazywhalecc/blob/master/FUNDING.md) 支持我和我的项目。
|
||||
|
||||
## 开源协议
|
||||
|
||||
本项目依据旧版本惯例采用 MIT License 开源,部分扩展的集成编译命令参考或修改自以下项目:
|
||||
|
||||
- [dixyes/lwmbs](https://github.com/dixyes/lwmbs)(木兰宽松许可证)
|
||||
- [swoole/swoole-cli](https://github.com/swoole/swoole-cli)(Apache 2.0 LICENSE、SWOOLE-CLI LICENSE)
|
||||
|
||||
因本项目的特殊性,使用项目编译过程中会使用很多其他开源项目,例如 curl、protobuf 等,它们都有各自的开源协议。
|
||||
请在编译完成后,使用命令 `bin/spc dump-license` 导出项目使用项目的开源协议,并遵守对应项目的 LICENSE。
|
||||
|
||||
## 进阶
|
||||
|
||||
本项目重构分支为模块化编写。如果你对本项目感兴趣,想加入开发,可以参照文档的 [贡献指南](https://static-php.dev) 贡献代码或文档。
|
||||
293
README.md
293
README.md
@ -1,221 +1,292 @@
|
||||
# static-php-cli
|
||||
|
||||
Compile A Statically Linked PHP With Swoole and other Extensions.
|
||||
Build single static PHP binary, with PHP project together, with popular extensions included.
|
||||
|
||||
If you are using English, see [English README](README-en.md).
|
||||
🌐 **[中文](README-zh.md)** | **[English](README.md)**
|
||||
|
||||
编译纯静态的 PHP Binary 二进制文件,带有各种扩展,让 PHP-cli 应用变得更便携!(cli SAPI)
|
||||
The project name is static-php-cli, but it actually supports cli, fpm, micro and embed SAPI 😎
|
||||
|
||||
<img width="600" alt="截屏2023-05-02 15 53 13" src="https://user-images.githubusercontent.com/20330940/235610282-23e58d68-bd35-4092-8465-171cff2d5ba8.png">
|
||||
Compile a purely static php-cli binary file with various extensions to make PHP applications more portable! (cli SAPI)
|
||||
|
||||
同时可以使用 micro 二进制文件,将 PHP 源码和 PHP 二进制构建为一个文件分发!(由 [dixyes/phpmicro](https://github.com/dixyes/phpmicro) 提供支持)(micro SAPI)
|
||||
<img width="600" alt="2023-05-02 15 53 13" src="https://user-images.githubusercontent.com/20330940/235610282-23e58d68-bd35-4092-8465-171cff2d5ba8.png">
|
||||
|
||||
<img width="600" alt="截屏2023-05-02 15 52 33" src="https://user-images.githubusercontent.com/20330940/235610318-2ef4e3f1-278b-4ca4-99f4-b38120efc395.png">
|
||||
You can also use the micro binary file to combine php binary and php source code into one for distribution! (micro SAPI)
|
||||
|
||||
[]()
|
||||
<img width="600" alt="2023-05-02 15 52 33" src="https://user-images.githubusercontent.com/20330940/235610318-2ef4e3f1-278b-4ca4-99f4-b38120efc395.png">
|
||||
|
||||
> This SAPI feature is from the [Fork](https://github.com/static-php/phpmicro) of [dixyes/phpmicro](https://github.com/dixyes/phpmicro).
|
||||
|
||||
[]()
|
||||
[]()
|
||||
[](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml)
|
||||
[](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml)
|
||||
[]()
|
||||
|
||||
[]()
|
||||
[]()
|
||||
|
||||
## 编译环境需求
|
||||
## Docs
|
||||
|
||||
是的,本项目采用 PHP 编写,编译前需要一个 PHP 环境,比较滑稽。
|
||||
但本项目默认可通过自身构建的 micro 和 static-php 二进制运行,其他只需要包含 tokenizer 扩展和 PHP 版本大于等于 8.0 即可。
|
||||
The current README contains basic usage. For all the features of static-php-cli,
|
||||
see <https://static-php.dev> .
|
||||
|
||||
下面是架构支持情况,`CI` 代表支持 GitHub Action 构建,`Local` 代表支持本地构建,空 代表暂不支持。
|
||||
## Direct Download
|
||||
|
||||
| | x86_64 | aarch64 |
|
||||
|---------|-----------|-----------|
|
||||
| macOS | CI, Local | Local |
|
||||
| Linux | CI, Local | CI, Local |
|
||||
| Windows | | |
|
||||
If you don't want to compile yourself, you can download example pre-compiled artifact from [Actions](https://github.com/static-php/static-php-cli-hosted/actions/workflows/build-php-common.yml), or from [self-hosted server](https://dl.static-php.dev/static-php-cli/common/).
|
||||
|
||||
> macOS-arm64 因 GitHub 暂未提供 arm runner,如果要构建 arm 二进制,可以使用手动构建。
|
||||
> self-hosted server contains extensions: `bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,gd,gmp,iconv,xml,mbstring,mbregex,mysqlnd,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,redis,session,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip`
|
||||
|
||||
目前支持编译的 PHP 版本为:`7.4`,`8.0`,`8.1`,`8.2`。
|
||||
## Use static-php-cli to build PHP
|
||||
|
||||
## 使用
|
||||
### Compilation Requirements
|
||||
|
||||
请先根据下方扩展列表选择你要编译的扩展。
|
||||
Yes, this project is written in PHP, pretty funny.
|
||||
But static-php-cli runtime only requires an environment above PHP 8.1 and `mbstring`, `pcntl` extension.
|
||||
|
||||
### 自托管直接下载
|
||||
Here is the architecture support status, where :octocat: represents support for GitHub Action builds,
|
||||
:computer: represents support for local manual builds, and blank represents not currently supported.
|
||||
|
||||
如果你不想自行编译,可以从本项目现有的 Action 下载 Artifact,也可以从自托管的服务器下载:[进入](https://dl.zhamao.xin/static-php-cli/)
|
||||
| | x86_64 | aarch64 |
|
||||
|---------|----------------------|----------------------|
|
||||
| macOS | :octocat: :computer: | :computer: |
|
||||
| Linux | :octocat: :computer: | :octocat: :computer: |
|
||||
| Windows | | |
|
||||
| FreeBSD | :computer: | :computer: |
|
||||
|
||||
> 自托管的服务器默认包含的扩展有:`bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,gd,gmp,iconv,xml,mbstring,mbregex,mysqlnd,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,redis,session,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip`
|
||||
> 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.
|
||||
|
||||
### 支持的扩展情况
|
||||
Currently supported PHP versions for compilation are: `7.3`, `7.4`, `8.0`, `8.1`, `8.2`, `8.3`.
|
||||
|
||||
[扩展支持列表](/ext-support.md)
|
||||
### Supported Extensions
|
||||
|
||||
> 如果这里没有你需要的扩展,可以提交 Issue。
|
||||
Please first select the extension you want to compile based on the extension list below.
|
||||
|
||||
### 使用 Actions 构建
|
||||
- [Supported Extension List](https://static-php.dev/en/guide/extensions.html)
|
||||
- [Command Generator](https://static-php.dev/en/guide/cli-generator.html)
|
||||
|
||||
使用 GitHub Action 可以方便地构建一个静态编译的 PHP 和 phpmicro,同时可以自行定义要编译的扩展。
|
||||
> If an extension you need is missing, you can submit an issue.
|
||||
|
||||
1. Fork 本项目。
|
||||
2. 进入项目的 Actions,选择 CI。
|
||||
3. 选择 `Run workflow`,填入你要编译的 PHP 版本、目标类型、扩展列表。(扩展列表使用英文逗号分割,例如 `bcmath,curl,mbstring`)
|
||||
4. 等待大约一段时间后,进入对应的任务中,获取 `Artifacts`。
|
||||
### GitHub Actions Build
|
||||
|
||||
如果你选择了 `debug`,则会在构建时输出所有日志,包括编译的日志,以供排查错误。
|
||||
Use GitHub Action to easily build a statically compiled PHP,
|
||||
and at the same time define the extensions to be compiled by yourself.
|
||||
|
||||
### 手动构建
|
||||
1. Fork 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 (using SPC binary)
|
||||
|
||||
This project provides a binary file of static-php-cli.
|
||||
You can directly download the binary file of the corresponding platform and then use it to build static PHP.
|
||||
Currently, the platforms supported by `spc` binary are Linux and macOS.
|
||||
|
||||
Here's how to download from GitHub Actions:
|
||||
|
||||
1. Enter [GitHub Actions](https://github.com/crazywhalecc/static-php-cli/actions/workflows/release-build.yml).
|
||||
2. Select the latest build task, select `Artifacts`, and download the binary file of the corresponding platform.
|
||||
3. Unzip the `.zip` file. After decompressing, add execution permissions to it: `chmod +x ./spc`.
|
||||
|
||||
You can also download binaries from a self-hosted server: [enter](https://dl.static-php.dev/static-php-cli/spc-bin/nightly/).
|
||||
|
||||
> SPC single-file binary is built by phpmicro and box.
|
||||
|
||||
### Manual build (using source code)
|
||||
|
||||
Clone repo first:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/crazywhalecc/static-php-cli.git
|
||||
```
|
||||
|
||||
如果你本机没有安装 PHP,你可以通过命令下载静态编译好的 php-cli 和 Composer。
|
||||
If you have not installed php on your system, you can use package management to install PHP (such as brew, apt, yum, apk etc.).
|
||||
|
||||
下载的 php 和 Composer 将保存为 `bin/php` 和 `bin/composer`。
|
||||
And you can also download single-file php binary and composer using command `bin/setup-runtime`.
|
||||
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
|
||||
# It will download php-cli from self-hosted server and composer from getcomposer.org
|
||||
./bin/setup-runtime
|
||||
|
||||
# 使用独立的 php 运行 static-php-cli
|
||||
# Use this php runtime to run static-php-cli compiler
|
||||
./bin/php bin/spc
|
||||
|
||||
# 使用 composer
|
||||
# Use composer
|
||||
./bin/php bin/composer
|
||||
```
|
||||
|
||||
下面是使用 static-php-cli 编译静态 php 和 micro 的基础用法:
|
||||
|
||||
```bash
|
||||
# 克隆本项目
|
||||
# Initialize this project
|
||||
cd static-php-cli
|
||||
composer update
|
||||
chmod +x bin/spc
|
||||
# 检查环境依赖,并根据提示的命令安装缺失的编译工具(目前仅支持 macOS,Linux 后续会支持)
|
||||
./bin/spc doctor
|
||||
# 拉取所有依赖库
|
||||
./bin/spc fetch --all
|
||||
# 构建包含 bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl 扩展的 php-cli 和 micro.sfx
|
||||
./bin/spc build "bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl" --build-cli --build-micro
|
||||
```
|
||||
|
||||
你也可以使用参数 `--with-php=x.y` 来指定下载的 PHP 版本,目前支持 7.4 ~ 8.2:
|
||||
### Use static-php-cli
|
||||
|
||||
Basic usage for building php and micro with some extensions:
|
||||
|
||||
> If you are using the packaged `spc` binary, you need to replace `bin/spc` with `./spc` in the following commands.
|
||||
|
||||
```bash
|
||||
# 优先考虑使用 >= 8.0 的 PHP 版本
|
||||
# Check system tool dependencies, fix them automatically
|
||||
./bin/spc doctor
|
||||
# fetch all libraries
|
||||
./bin/spc download --all
|
||||
# only fetch necessary sources by needed extensions
|
||||
./bin/spc download --for-extensions=openssl,pcntl,mbstring,pdo_sqlite
|
||||
# with bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl extension, build both CLI and phpmicro SAPI
|
||||
./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 PHP7 cannot use phpmicro
|
||||
./bin/spc fetch --with-php=8.2 --all
|
||||
```
|
||||
|
||||
其中,目前支持构建 cli,micro,fpm 三种静态二进制,使用以下参数的一个或多个来指定编译的 SAPI:
|
||||
Now we support `cli`, `micro`, `fpm`, you can use one or more of the following parameters to specify the compiled SAPI:
|
||||
|
||||
- `--build-cli`:构建 cli 二进制
|
||||
- `--build-micro`:构建 phpmicro 自执行二进制
|
||||
- `--build-fpm`:构建 fpm
|
||||
- `--build-all`:构建所有
|
||||
- `--build-cli`: build static cli executable
|
||||
- `--build-micro`: build static phpmicro self-extracted executable
|
||||
- `--build-fpm`: build static fpm binary
|
||||
- `--build-embed`: build embed (libphp)
|
||||
- `--build-all`: build all
|
||||
|
||||
如果出现了任何错误,可以使用 `--debug` 参数来展示完整的输出日志,以供排查错误:
|
||||
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 为 NTS 版本。如需编译线程安全版本(ZTS),只需添加参数 `--enable-zts` 即可。
|
||||
In addition, we build NTS by default. If you are going to build ZTS version, just add `--enable-zts` option.
|
||||
|
||||
```bash
|
||||
./bin/spc build openssl,pcntl --build-all --enable-zts
|
||||
```
|
||||
|
||||
同时,你也可以使用参数 `--no-strip` 来关闭裁剪,关闭裁剪后可以使用 gdb 等工具调试,但这样会让静态二进制体积变大。
|
||||
Adding option `--no-strip` can produce binaries with debug symbols, in order to debug (using gdb). Disabling strip will increase the size of static binary.
|
||||
|
||||
### 使用 php-cli
|
||||
## Different SAPI Usage
|
||||
|
||||
> php-cli 是一个静态的二进制文件,类似 Go、Rust 语言编译后的单个可移植的二进制文件。
|
||||
### Use cli
|
||||
|
||||
采用参数 `--build-cli` 或`--build-all` 参数时,最后编译结果会输出一个 `./php` 的二进制文件,此文件可分发、可直接使用。
|
||||
该文件编译后会存放在 `buildroot/bin/` 目录中,名称为 `php`,拷贝出来即可。
|
||||
> 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`,
|
||||
which can be distributed and used directly.
|
||||
This file will be located in the directory `buildroot/bin/`, copy it out for use.
|
||||
|
||||
```bash
|
||||
cd buildroot/bin/
|
||||
./php -v # 检查版本
|
||||
./php -m # 检查编译的扩展
|
||||
./php your_code.php # 运行代码
|
||||
./php your_project.phar # 运行打包为 phar 单文件的项目
|
||||
./php -v # check version
|
||||
./php -m # check extensions
|
||||
./php your_code.php # run your php code
|
||||
./php your_project.phar # run your phar (project archive)
|
||||
```
|
||||
|
||||
### 使用 micro.sfx
|
||||
### Use micro
|
||||
|
||||
> phpmicro 是一个提供自执行二进制 PHP 的项目,本项目依赖 phpmicro 进行编译自执行二进制。详见 [dixyes/phpmicro](https://github.com/dixyes/phpmicro)。
|
||||
> phpmicro is a SelF-extracted eXecutable SAPI module,
|
||||
> provided by [phpmicro](https://github.com/dixyes/phpmicro) project.
|
||||
> But this project is using a [fork](https://github.com/static-php/phpmicro) of phpmicro, because we need to add some features to it.
|
||||
> It can put php runtime and your source code together.
|
||||
|
||||
采用项目参数 `--build-micro` 或 `--build-all` 时,最后编译结果会输出一个 `./micro.sfx` 的文件,此文件需要配合你的 PHP 源码使用。
|
||||
该文件编译后会存放在 `buildroot/bin/` 目录中,拷贝出来即可。
|
||||
When using the parameter `--build-all` or `--build-micro`,
|
||||
the final compilation result will output a file named `./micro.sfx`,
|
||||
which needs to be used with your PHP source code like `code.php`.
|
||||
This file will be located in the path `buildroot/bin/micro.sfx`, simply copy it out for use.
|
||||
|
||||
使用时应准备好你的项目源码文件,可以是单个 PHP 文件,也可以是 Phar 文件。
|
||||
Prepare your project source code, which can be a single PHP file or a Phar file, for use.
|
||||
|
||||
```bash
|
||||
echo "<?php echo 'Hello world' . PHP_EOL;" > code.php
|
||||
cat micro.sfx code.php > single-app && chmod +x single-app
|
||||
./single-app
|
||||
|
||||
# 如果打包 PHAR 文件,仅需把 code.php 更换为 phar 文件路径即可
|
||||
```
|
||||
|
||||
> 有些情况下的 phar 文件可能无法在 micro 环境下运行。
|
||||
If you package a PHAR file, just replace `code.php` with the phar file path.
|
||||
You can use [box-project/box](https://github.com/box-project/box) to package your CLI project as Phar,
|
||||
It is then combined with phpmicro to produce a standalone executable binary.
|
||||
|
||||
### 使用 php-fpm
|
||||
```bash
|
||||
# Use the micro.sfx generated by static-php-cli to combine,
|
||||
bin/spc micro:combine my-app.phar
|
||||
# or you can directly use the cat command to combine them.
|
||||
cat buildroot/bin/micro.sfx my-app.phar > my-app && chmod +x my-app
|
||||
|
||||
采用项目参数 `--build-fpm` 或 `--build-all` 时,最后编译结果会输出一个 `./php-fpm` 的文件。
|
||||
该文件存放在 `buildroot/bin/` 目录,拷贝出来即可使用。
|
||||
# Use micro:combine combination to inject INI options into the binary.
|
||||
bin/spc micro:combine my-app.phar -I "memory_limit=4G" -I "disable_functions=system" --output my-app-2
|
||||
```
|
||||
|
||||
在正常的 Linux 发行版和 macOS 系统中,安装 php-fpm 后包管理会自动生成默认的 fpm 配置文件。
|
||||
因为 php-fpm 必须指定配置文件才可启动,本项目编译的 php-fpm 不会带任何配置文件,所以需自行编写 `php-fpm.conf` 和 `pool.conf` 配置文件。
|
||||
> In some cases, PHAR files may not run in a micro environment.
|
||||
|
||||
指定 `php-fpm.conf` 可以使用命令参数 `-y`,例如:`./php-fpm -y php-fpm.conf`。
|
||||
### Use fpm
|
||||
|
||||
## 项目支持情况
|
||||
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.
|
||||
|
||||
- [X] 基础结构编写(采用 `symfony/console`)
|
||||
- [X] 错误处理
|
||||
- [X] macOS 支持
|
||||
- [ ] Windows 支持
|
||||
- [X] Linux 支持
|
||||
- [X] PHP 7.4 支持
|
||||
- [X] fpm 支持
|
||||
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.
|
||||
|
||||
更多功能和特性正在陆续支持中,详见:https://github.com/crazywhalecc/static-php-cli/issues/32
|
||||
Specifying `php-fpm.conf` can use the command parameter `-y`, for example: `./php-fpm -y php-fpm.conf`.
|
||||
|
||||
## 贡献
|
||||
### Use embed
|
||||
|
||||
目前支持的扩展较少,如果缺少你需要的扩展,可发起 Issue。如果你对本项目较熟悉,也欢迎为本项目发起 Pull Request。
|
||||
When using the project parameters `--build-embed` or `--build-all`,
|
||||
the final compilation result will output a `libphp.a`, `php-config` and a series of header files,
|
||||
stored in `buildroot/`. You can introduce them in your other projects.
|
||||
|
||||
贡献基本原则如下:
|
||||
If you know [embed SAPI](https://github.com/php/php-src/tree/master/sapi/embed), you should know how to use it.
|
||||
You may require the introduction of other libraries during compilation,
|
||||
you can use `buildroot/bin/php-config` to obtain the compile-time configuration.
|
||||
|
||||
- 项目采用了 php-cs-fixer、phpstan 作为代码规范工具,贡献前请对更新的代码执行 `composer analyze` 和 `composer cs-fix`。
|
||||
- 涉及到其他开源库的部分应提供对应库的协议,同时对配置文件在修改后采用命令 `sort-config` 排序。有关排序的命令,见文档。
|
||||
- 应遵循命名规范,例如扩展名称应采取 PHP 内注册的扩展名本身,外部库名应遵循项目本身的名称,内部逻辑的函数、类名、变量等应遵循驼峰、下划线等格式,禁止同一模块混用。
|
||||
- 涉及编译外部库的命令和 Patch 时应注意兼容不同操作系统。
|
||||
For an advanced example of how to use this feature, take a look at [how to use it to build a static version of FrankenPHP](https://github.com/dunglas/frankenphp/blob/main/docs/static.md).
|
||||
|
||||
另外,添加新扩展的贡献方式,可以参考下方 `进阶`。
|
||||
## Contribution
|
||||
|
||||
## 赞助本项目
|
||||
If the extension you need is missing, you can create an issue.
|
||||
If you are familiar with this project, you are also welcome to initiate a pull request.
|
||||
|
||||
你可以在 [我的个人赞助页](https://github.com/crazywhalecc/crazywhalecc/blob/master/FUNDING.md) 支持我和我的项目。
|
||||
If you want to contribute documentation, please go to [static-php/static-php-cli-docs](https://github.com/static-php/static-php-cli-docs).
|
||||
|
||||
## 开源协议
|
||||
Now there is a [static-php](https://github.com/static-php) organization, which is used to store the repo related to the project.
|
||||
|
||||
本项目依据旧版本惯例采用 MIT License 开源,自身的部分代码引用或修改自以下项目:
|
||||
Part of the English document is written by me, and part is translated by Google,
|
||||
and there may be inaccurate descriptions, strange or offensive expressions.
|
||||
If you are a native English speaker, some corrections to the documentation are welcome.
|
||||
|
||||
- [dixyes/lwmbs](https://github.com/dixyes/lwmbs)(木兰宽松许可证)
|
||||
- [swoole/swoole-cli](https://github.com/swoole/swoole-cli)(Apache 2.0 LICENSE、SWOOLE-CLI LICENSE)
|
||||
## Sponsor this project
|
||||
|
||||
因本项目的特殊性,使用项目编译过程中会使用很多其他开源项目,例如 curl、protobuf 等,它们都有各自的开源协议。
|
||||
请在编译完成后,使用命令 `bin/spc dump-license` 导出项目使用项目的开源协议,并遵守对应项目的 LICENSE。
|
||||
You can sponsor my project on [this page](https://github.com/crazywhalecc/crazywhalecc/blob/master/FUNDING.md).
|
||||
|
||||
## 进阶
|
||||
## Open-Source License
|
||||
|
||||
本项目重构分支为模块化编写。
|
||||
This project itself is based on MIT License,
|
||||
some newly added extensions and dependencies may originate from the following projects (including but not limited to),
|
||||
and the headers of these code files will also be given additional instructions LICENSE and AUTHOR:
|
||||
|
||||
TODO:这部分将在基础功能完成后编写完成。
|
||||
- [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)
|
||||
|
||||
Due to the special nature of this project,
|
||||
many other open source projects such as curl and protobuf will be used during the project compilation process,
|
||||
and they all have their own open source licenses.
|
||||
|
||||
Please use the `bin/spc dump-license` command to export the open source licenses used in the project after compilation,
|
||||
and comply with the corresponding project's LICENSE.
|
||||
|
||||
## Advanced
|
||||
|
||||
The refactoring branch of this project is written modularly.
|
||||
If you are interested in this project and want to join the development,
|
||||
you can refer to the [Contribution Guide](https://static-php.dev) of the documentation to contribute code or documentation.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# set error-quit, verbose, non-variable-quit
|
||||
set -eu
|
||||
@ -22,10 +22,10 @@ esac
|
||||
|
||||
# set project dir
|
||||
__DIR__=$(cd "$(dirname "$0")" && pwd)
|
||||
__PROJECT__=$(cd ${__DIR__}/../ && pwd)
|
||||
__PROJECT__=$(cd "${__DIR__}"/../ && pwd)
|
||||
|
||||
# set download dir
|
||||
__PHP_RUNTIME_URL__="https://dl.zhamao.xin/static-php-cli/php-8.2.6-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz"
|
||||
__PHP_RUNTIME_URL__="https://dl.static-php.dev/static-php-cli/common/php-8.2.10-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz"
|
||||
__COMPOSER_URL__="https://getcomposer.org/download/latest-stable/composer.phar"
|
||||
|
||||
# use china mirror
|
||||
@ -46,23 +46,27 @@ done
|
||||
|
||||
case "$mirror" in
|
||||
china)
|
||||
__PHP_RUNTIME_URL__="https://dl.zhamao.xin/static-php-cli/php-8.2.6-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz"
|
||||
__PHP_RUNTIME_URL__="https://dl.static-php.dev/static-php-cli/common/php-8.2.10-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz"
|
||||
__COMPOSER_URL__="https://mirrors.aliyun.com/composer/composer.phar"
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
test -d ${__PROJECT__}/downloads || mkdir ${__PROJECT__}/downloads
|
||||
if ! command -v curl > /dev/null && command -v apk > /dev/null; then
|
||||
apk add --no-cache curl
|
||||
fi
|
||||
|
||||
test -d "${__PROJECT__}"/downloads || mkdir "${__PROJECT__}"/downloads
|
||||
# download static php binary
|
||||
test -f ${__PROJECT__}/downloads/runtime.tar.gz || { echo "Downloading $__PHP_RUNTIME_URL__ ..." && curl -#fSL -o ${__PROJECT__}/downloads/runtime.tar.gz "$__PHP_RUNTIME_URL__" ; }
|
||||
test -f ${__DIR__}/php || { tar -xf ${__PROJECT__}/downloads/runtime.tar.gz -C ${__DIR__}/ ; }
|
||||
chmod +x ${__DIR__}/php
|
||||
test -f "${__PROJECT__}"/downloads/runtime.tar.gz || { echo "Downloading $__PHP_RUNTIME_URL__ ..." && curl -#fSL -o "${__PROJECT__}"/downloads/runtime.tar.gz "$__PHP_RUNTIME_URL__" ; }
|
||||
test -f "${__DIR__}"/php || { tar -xf "${__PROJECT__}"/downloads/runtime.tar.gz -C "${__DIR__}"/ ; }
|
||||
chmod +x "${__DIR__}"/php
|
||||
# download composer
|
||||
test -f ${__DIR__}/composer || curl -#fSL -o ${__DIR__}/composer "$__COMPOSER_URL__"
|
||||
chmod +x ${__DIR__}/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; }
|
||||
"${__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:"
|
||||
|
||||
8
bin/spc
8
bin/spc
@ -1,6 +1,9 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
use SPC\ConsoleApplication;
|
||||
use SPC\exception\ExceptionHandler;
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
// 防止 Micro 打包状态下不支持中文的显示(虽然这个项目目前好像没输出过中文?)
|
||||
@ -8,9 +11,8 @@ if (PHP_OS_FAMILY === 'Windows' && Phar::running()) {
|
||||
exec('CHCP 65001');
|
||||
}
|
||||
|
||||
// 跑,反正一条命令跑就对了
|
||||
try {
|
||||
(new \SPC\ConsoleApplication())->run();
|
||||
(new ConsoleApplication())->run();
|
||||
} catch (Exception $e) {
|
||||
\SPC\exception\ExceptionHandler::getInstance()->handle($e);
|
||||
ExceptionHandler::getInstance()->handle($e);
|
||||
}
|
||||
|
||||
@ -2,18 +2,18 @@
|
||||
|
||||
# This file is using docker to run commands
|
||||
|
||||
self_dir=$(cd "$(dirname "$0")";pwd)
|
||||
|
||||
# Detect docker can run
|
||||
if ! which docker >/dev/null; then
|
||||
echo "Docker is not installed, please install docker first !"
|
||||
exit 1
|
||||
fi
|
||||
DOCKER_EXECUTABLE="docker"
|
||||
# shellcheck disable=SC2046
|
||||
if [ $(id -u) -ne 0 ]; then
|
||||
if ! docker info > /dev/null 2>&1; then
|
||||
if [ "$SPC_USE_SUDO" != "yes" ]; then
|
||||
echo "Docker command requires sudo"
|
||||
# shellcheck disable=SC2039
|
||||
echo -n 'To use sudo to run docker, run "export SPC_USE_SUDO=yes" and run command again'
|
||||
exit 1
|
||||
fi
|
||||
@ -33,6 +33,7 @@ x86_64)
|
||||
;;
|
||||
aarch64)
|
||||
ALPINE_FROM=multiarch/alpine:aarch64-edge
|
||||
# shellcheck disable=SC2039
|
||||
echo -e "\e[033m* Using different arch needs to setup qemu-static for docker !\e[0m"
|
||||
$DOCKER_EXECUTABLE run --rm --privileged multiarch/qemu-user-static:register --reset > /dev/null
|
||||
;;
|
||||
@ -51,24 +52,52 @@ fi
|
||||
# Detect docker env is setup
|
||||
if ! $DOCKER_EXECUTABLE images | grep -q cwcc-spc-$SPC_USE_ARCH; then
|
||||
echo "Docker container does not exist. Building docker image ..."
|
||||
ALPINE_DOCKERFILE=$(cat << EOF
|
||||
$DOCKER_EXECUTABLE build -t cwcc-spc-$SPC_USE_ARCH -f- . <<EOF
|
||||
FROM $ALPINE_FROM
|
||||
$SPC_USE_MIRROR
|
||||
RUN apk update
|
||||
RUN apk add bash file wget cmake gcc g++ jq autoconf git libstdc++ linux-headers make m4 libgcc binutils bison flex pkgconfig automake curl
|
||||
RUN apk add build-base xz php81 php81-common php81-pcntl php81-tokenizer php81-phar php81-posix php81-xml composer
|
||||
RUN mkdir /app
|
||||
RUN apk update; \
|
||||
apk add --no-cache \
|
||||
autoconf \
|
||||
automake \
|
||||
gettext \
|
||||
bash \
|
||||
binutils \
|
||||
bison \
|
||||
build-base \
|
||||
cmake \
|
||||
curl \
|
||||
file \
|
||||
flex \
|
||||
g++ \
|
||||
gcc \
|
||||
git \
|
||||
jq \
|
||||
libgcc \
|
||||
libstdc++ \
|
||||
linux-headers \
|
||||
m4 \
|
||||
make \
|
||||
php82 \
|
||||
php82-common \
|
||||
php82-pcntl \
|
||||
php82-phar \
|
||||
php82-posix \
|
||||
php82-sodium \
|
||||
php82-tokenizer \
|
||||
php82-dom \
|
||||
php82-xml \
|
||||
php82-xmlwriter \
|
||||
composer \
|
||||
pkgconfig \
|
||||
wget \
|
||||
xz
|
||||
|
||||
WORKDIR /app
|
||||
ADD ./src /app/src
|
||||
ADD ./composer.json /app/composer.json
|
||||
COPY ./composer.* /app/
|
||||
ADD ./bin /app/bin
|
||||
RUN composer update --no-dev
|
||||
RUN composer install --no-dev --classmap-authoritative
|
||||
EOF
|
||||
)
|
||||
echo "$ALPINE_DOCKERFILE" > $(pwd)/Dockerfile
|
||||
|
||||
$DOCKER_EXECUTABLE build -t cwcc-spc-$SPC_USE_ARCH .
|
||||
rm $(pwd)/Dockerfile
|
||||
fi
|
||||
|
||||
# Check if in ci (local terminal can execute with -it)
|
||||
@ -79,4 +108,5 @@ else
|
||||
fi
|
||||
|
||||
# Run docker
|
||||
$DOCKER_EXECUTABLE run --rm $INTERACT -e SPC_FIX_DEPLOY_ROOT=$(pwd) -v $(pwd)/config:/app/config -v $(pwd)/src:/app/src -v $(pwd)/buildroot:/app/buildroot -v $(pwd)/source:/app/source -v $(pwd)/downloads:/app/downloads cwcc-spc-$SPC_USE_ARCH bin/spc $@
|
||||
# shellcheck disable=SC2068
|
||||
$DOCKER_EXECUTABLE run --rm $INTERACT -e SPC_FIX_DEPLOY_ROOT="$(pwd)" -v "$(pwd)"/config:/app/config -v "$(pwd)"/src:/app/src -v "$(pwd)"/buildroot:/app/buildroot -v "$(pwd)"/source:/app/source -v "$(pwd)"/downloads:/app/downloads cwcc-spc-$SPC_USE_ARCH bin/spc $@
|
||||
|
||||
19
box.json
Normal file
19
box.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"alias": "spc-php.phar",
|
||||
"banner": false,
|
||||
"blacklist": [
|
||||
".github"
|
||||
],
|
||||
"directories": [
|
||||
"config",
|
||||
"src",
|
||||
"vendor/psr",
|
||||
"vendor/laravel/prompts",
|
||||
"vendor/illuminate",
|
||||
"vendor/symfony",
|
||||
"vendor/zhamao"
|
||||
],
|
||||
"git-commit-short": "git_commit_short",
|
||||
"metadata": "ConsoleApplication::VERSION",
|
||||
"output": "spc.phar"
|
||||
}
|
||||
@ -9,20 +9,21 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">= 8.0",
|
||||
"ext-tokenizer": "*",
|
||||
"ext-iconv": "*",
|
||||
"symfony/console": "^6 || ^5 || ^4",
|
||||
"zhamao/logger": "^1.0",
|
||||
"crazywhalecc/cli-helper": "^0.1.0",
|
||||
"nunomaduro/collision": "*",
|
||||
"ext-pcntl": "*"
|
||||
"php": ">= 8.1",
|
||||
"ext-mbstring": "*",
|
||||
"ext-pcntl": "*",
|
||||
"laravel/prompts": "^0.1.12",
|
||||
"symfony/console": "^5.4 || ^6 || ^7",
|
||||
"zhamao/logger": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.2 != 3.7.0",
|
||||
"phpstan/phpstan": "^1.1",
|
||||
"captainhook/captainhook": "^5.10",
|
||||
"captainhook/plugin-composer": "^5.3"
|
||||
"captainhook/plugin-composer": "^5.3",
|
||||
"friendsofphp/php-cs-fixer": "^3.25",
|
||||
"humbug/box": "^4.3",
|
||||
"nunomaduro/collision": "^7.8",
|
||||
"phpstan/phpstan": "^1.10",
|
||||
"phpunit/phpunit": "^10.3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@ -33,13 +34,19 @@
|
||||
"src/globals/functions.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"SPC\\Tests\\": "tests/SPC"
|
||||
}
|
||||
},
|
||||
"bin": [
|
||||
"bin/spc"
|
||||
],
|
||||
"scripts": {
|
||||
"analyse": "phpstan analyse --memory-limit 300M",
|
||||
"cs-fix": "php-cs-fixer fix",
|
||||
"test": "bin/phpunit --no-coverage"
|
||||
"test": "vendor/bin/phpunit tests/ --no-coverage",
|
||||
"build:phar": "vendor/bin/box compile"
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
|
||||
6030
composer.lock
generated
Normal file
6030
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
115
config/ext.json
115
config/ext.json
@ -100,6 +100,14 @@
|
||||
"gettext"
|
||||
]
|
||||
},
|
||||
"glfw": {
|
||||
"type": "external",
|
||||
"arg-type": "custom",
|
||||
"source": "ext-glfw",
|
||||
"lib-depends": [
|
||||
"glfw"
|
||||
]
|
||||
},
|
||||
"gmp": {
|
||||
"type": "builtin",
|
||||
"arg-type": "with-prefix",
|
||||
@ -144,15 +152,23 @@
|
||||
},
|
||||
"ldap": {
|
||||
"type": "builtin",
|
||||
"arg-type": "with",
|
||||
"arg-type": "with-prefix",
|
||||
"lib-depends": [
|
||||
"ldap"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"gmp",
|
||||
"libsodium"
|
||||
],
|
||||
"ext-suggests": [
|
||||
"openssl"
|
||||
]
|
||||
},
|
||||
"mbregex": {
|
||||
"type": "builtin",
|
||||
"lib-depends": [
|
||||
"onig"
|
||||
"arg-type": "custom",
|
||||
"ext-depends": [
|
||||
"mbstring"
|
||||
]
|
||||
},
|
||||
"mbstring": {
|
||||
@ -162,16 +178,39 @@
|
||||
"onig"
|
||||
]
|
||||
},
|
||||
"memcache": {
|
||||
"type": "external",
|
||||
"source": "ext-memcache",
|
||||
"arg-type": "custom",
|
||||
"lib-depends": [
|
||||
"zlib"
|
||||
],
|
||||
"ext-depends": [
|
||||
"session"
|
||||
]
|
||||
},
|
||||
"memcached": {
|
||||
"type": "external",
|
||||
"source": "memcached",
|
||||
"arg-type": "custom",
|
||||
"cpp-extension": true,
|
||||
"lib-depends": [
|
||||
"libmemcached"
|
||||
],
|
||||
"ext-depends": [
|
||||
"session",
|
||||
"zlib"
|
||||
]
|
||||
},
|
||||
"mongodb": {
|
||||
"type": "external",
|
||||
"source": "mongodb",
|
||||
"arg-type": "custom",
|
||||
"lib-depends": [
|
||||
"zstd"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"icu",
|
||||
"openssl"
|
||||
"openssl",
|
||||
"zstd",
|
||||
"zlib"
|
||||
]
|
||||
},
|
||||
"mysqli": {
|
||||
@ -183,16 +222,22 @@
|
||||
},
|
||||
"mysqlnd": {
|
||||
"type": "builtin",
|
||||
"arg-type-windows": "with"
|
||||
"arg-type-windows": "with",
|
||||
"lib-depends": [
|
||||
"zlib"
|
||||
]
|
||||
},
|
||||
"opcache": {
|
||||
"type": "builtin"
|
||||
},
|
||||
"openssl": {
|
||||
"type": "builtin",
|
||||
"arg-type": "with",
|
||||
"arg-type": "custom",
|
||||
"lib-depends": [
|
||||
"openssl"
|
||||
],
|
||||
"ext-depends": [
|
||||
"zlib"
|
||||
]
|
||||
},
|
||||
"password-argon2": {
|
||||
@ -219,12 +264,13 @@
|
||||
},
|
||||
"pdo_pgsql": {
|
||||
"type": "builtin",
|
||||
"arg-type": "with",
|
||||
"arg-type": "with-prefix",
|
||||
"ext-depends": [
|
||||
"pdo"
|
||||
"pdo",
|
||||
"pgsql"
|
||||
],
|
||||
"lib-depends": [
|
||||
"pq"
|
||||
"postgresql"
|
||||
]
|
||||
},
|
||||
"pdo_sqlite": {
|
||||
@ -238,6 +284,13 @@
|
||||
"sqlite"
|
||||
]
|
||||
},
|
||||
"pgsql": {
|
||||
"type": "builtin",
|
||||
"arg-type": "with-prefix",
|
||||
"lib-depends": [
|
||||
"postgresql"
|
||||
]
|
||||
},
|
||||
"phar": {
|
||||
"type": "builtin",
|
||||
"ext-depends": [
|
||||
@ -269,7 +322,10 @@
|
||||
"redis": {
|
||||
"type": "external",
|
||||
"source": "redis",
|
||||
"arg-type": "custom"
|
||||
"arg-type": "custom",
|
||||
"ext-suggests": [
|
||||
"session"
|
||||
]
|
||||
},
|
||||
"session": {
|
||||
"type": "builtin"
|
||||
@ -285,6 +341,18 @@
|
||||
"libxml2"
|
||||
]
|
||||
},
|
||||
"snappy": {
|
||||
"type": "external",
|
||||
"source": "ext-snappy",
|
||||
"cpp-extension": true,
|
||||
"arg-type": "custom",
|
||||
"lib-depends": [
|
||||
"snappy"
|
||||
],
|
||||
"ext-suggest": [
|
||||
"apcu"
|
||||
]
|
||||
},
|
||||
"snmp": {
|
||||
"type": "builtin",
|
||||
"arg-type": "with",
|
||||
@ -328,6 +396,7 @@
|
||||
"type": "external",
|
||||
"source": "swoole",
|
||||
"arg-type": "custom",
|
||||
"cpp-extension": true,
|
||||
"lib-depends": [
|
||||
"openssl"
|
||||
],
|
||||
@ -335,7 +404,8 @@
|
||||
"openssl"
|
||||
],
|
||||
"ext-suggests": [
|
||||
"curl"
|
||||
"curl",
|
||||
"pgsql"
|
||||
],
|
||||
"unix-only": true
|
||||
},
|
||||
@ -374,6 +444,15 @@
|
||||
"tokenizer": {
|
||||
"type": "builtin"
|
||||
},
|
||||
"xlswriter": {
|
||||
"type": "external",
|
||||
"source": "xlswriter",
|
||||
"arg-type": "custom",
|
||||
"ext-depends": [
|
||||
"zlib",
|
||||
"zip"
|
||||
]
|
||||
},
|
||||
"xml": {
|
||||
"type": "builtin",
|
||||
"arg-type": "custom",
|
||||
@ -398,9 +477,13 @@
|
||||
},
|
||||
"xsl": {
|
||||
"type": "builtin",
|
||||
"arg-type": "with",
|
||||
"arg-type": "with-prefix",
|
||||
"lib-depends": [
|
||||
"libxslt"
|
||||
],
|
||||
"ext-depends": [
|
||||
"xml",
|
||||
"dom"
|
||||
]
|
||||
},
|
||||
"yaml": {
|
||||
@ -421,7 +504,7 @@
|
||||
},
|
||||
"zlib": {
|
||||
"type": "builtin",
|
||||
"arg-type": "with",
|
||||
"arg-type": "custom",
|
||||
"arg-type-windows": "enable",
|
||||
"lib-depends": [
|
||||
"zlib"
|
||||
|
||||
@ -42,14 +42,14 @@
|
||||
"curl"
|
||||
],
|
||||
"lib-depends-unix": [
|
||||
"openssl",
|
||||
"zlib"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"libssh2",
|
||||
"brotli",
|
||||
"nghttp2",
|
||||
"zstd",
|
||||
"openssl"
|
||||
"zstd"
|
||||
],
|
||||
"lib-suggests-windows": [
|
||||
"zlib",
|
||||
@ -63,6 +63,7 @@
|
||||
],
|
||||
"frameworks": [
|
||||
"CoreFoundation",
|
||||
"CoreServices",
|
||||
"SystemConfiguration"
|
||||
]
|
||||
},
|
||||
@ -84,6 +85,18 @@
|
||||
"brotli"
|
||||
]
|
||||
},
|
||||
"glfw": {
|
||||
"source": "ext-glfw",
|
||||
"static-libs-unix": [
|
||||
"libglfw3.a"
|
||||
],
|
||||
"frameworks": [
|
||||
"CoreVideo",
|
||||
"OpenGL",
|
||||
"Cocoa",
|
||||
"IOKit"
|
||||
]
|
||||
},
|
||||
"gmp": {
|
||||
"source": "gmp",
|
||||
"static-libs-unix": [
|
||||
@ -98,6 +111,7 @@
|
||||
},
|
||||
"icu": {
|
||||
"source": "icu",
|
||||
"cpp-library": true,
|
||||
"static-libs-unix": [
|
||||
"libicui18n.a",
|
||||
"libicuio.a",
|
||||
@ -109,20 +123,20 @@
|
||||
"source": "imagemagick",
|
||||
"static-libs-unix": [
|
||||
"libMagick++-7.Q16HDRI.a",
|
||||
"libMagickCore-7.Q16HDRI.a",
|
||||
"libMagickWand-7.Q16HDRI.a"
|
||||
"libMagickWand-7.Q16HDRI.a",
|
||||
"libMagickCore-7.Q16HDRI.a"
|
||||
],
|
||||
"lib-depends": [
|
||||
"zlib",
|
||||
"libpng",
|
||||
"libjpeg",
|
||||
"bzip2",
|
||||
"libwebp",
|
||||
"freetype"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"zstd",
|
||||
"xz",
|
||||
"bzip2",
|
||||
"libzip",
|
||||
"libxml2"
|
||||
]
|
||||
@ -133,6 +147,18 @@
|
||||
"libargon2.a"
|
||||
]
|
||||
},
|
||||
"ldap": {
|
||||
"source": "ldap",
|
||||
"static-libs-unix": [
|
||||
"liblber.a",
|
||||
"libldap.a"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"openssl",
|
||||
"gmp",
|
||||
"libsodium"
|
||||
]
|
||||
},
|
||||
"libavif": {
|
||||
"source": "libavif",
|
||||
"static-libs-unix": [
|
||||
@ -194,10 +220,17 @@
|
||||
"libmcrypt.a"
|
||||
]
|
||||
},
|
||||
"libmemcached": {
|
||||
"source": "libmemcached",
|
||||
"static-libs-unix": [
|
||||
"libmemcached.a",
|
||||
"libmemcachedutil.a"
|
||||
]
|
||||
},
|
||||
"libpng": {
|
||||
"source": "libpng",
|
||||
"static-libs-unix": [
|
||||
"libpng.a"
|
||||
"libpng16.a"
|
||||
],
|
||||
"static-libs-windows": [
|
||||
"libpng16_static.lib"
|
||||
@ -266,19 +299,29 @@
|
||||
"libxml2"
|
||||
],
|
||||
"lib-depends": [
|
||||
"libiconv"
|
||||
"libiconv",
|
||||
"zlib"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"xz",
|
||||
"zlib"
|
||||
"icu"
|
||||
],
|
||||
"lib-suggests-windows": [
|
||||
"icu",
|
||||
"xz",
|
||||
"zlib",
|
||||
"pthreads4w"
|
||||
]
|
||||
},
|
||||
"libxslt": {
|
||||
"source": "libxslt",
|
||||
"static-libs-unix": [
|
||||
"libxslt.a",
|
||||
"libexslt.a"
|
||||
],
|
||||
"lib-depends": [
|
||||
"libxml2"
|
||||
]
|
||||
},
|
||||
"libyaml": {
|
||||
"source": "libyaml",
|
||||
"static-libs-unix": [
|
||||
@ -386,7 +429,22 @@
|
||||
"postgresql": {
|
||||
"source": "postgresql",
|
||||
"static-libs-unix": [
|
||||
"libpg.a"
|
||||
"libpq.a",
|
||||
"libpgport.a",
|
||||
"libpgcommon.a"
|
||||
],
|
||||
"lib-depends": [
|
||||
"libiconv",
|
||||
"libxml2",
|
||||
"openssl",
|
||||
"zlib",
|
||||
"readline"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"icu",
|
||||
"libxslt",
|
||||
"ldap",
|
||||
"zstd"
|
||||
]
|
||||
},
|
||||
"pthreads4w": {
|
||||
@ -410,6 +468,21 @@
|
||||
"ncurses"
|
||||
]
|
||||
},
|
||||
"snappy": {
|
||||
"source": "snappy",
|
||||
"static-libs-unix": [
|
||||
"libsnappy.a"
|
||||
],
|
||||
"headers-unix": [
|
||||
"snappy.h",
|
||||
"snappy-c.h",
|
||||
"snappy-sinksource.h",
|
||||
"snappy-stubs-public.h"
|
||||
],
|
||||
"lib-depends": [
|
||||
"zlib"
|
||||
]
|
||||
},
|
||||
"sqlite": {
|
||||
"source": "sqlite",
|
||||
"static-libs-unix": [
|
||||
@ -476,4 +549,4 @@
|
||||
"zstd_errors.h"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
110
ext-support.md
110
ext-support.md
@ -1,111 +1,3 @@
|
||||
# Extension List
|
||||
|
||||
> - yes: supported and tested
|
||||
> - untested: supported, but not tested
|
||||
> - empty: not supported yet
|
||||
> - no with issue link: not supported yet due to issue
|
||||
> - partial with issue link: supported but not perfect due to issue
|
||||
|
||||
| | Linux | macOS | Windows |
|
||||
|------------|---------------------------------------------------------------------|----------------------------------------------------------------|---------|
|
||||
| apcu | yes, untested | yes, untested | |
|
||||
| bcmath | yes | yes | |
|
||||
| bz2 | yes | yes | |
|
||||
| calendar | yes | yes | |
|
||||
| ctype | yes | yes | |
|
||||
| curl | yes | yes | |
|
||||
| dba | yes | yes | |
|
||||
| dom | yes | yes | |
|
||||
| enchant | | | |
|
||||
| event | yes | yes | |
|
||||
| exif | yes | yes | |
|
||||
| ffi | | yes, [docs]() | |
|
||||
| filter | yes | yes | |
|
||||
| fileinfo | yes | yes | |
|
||||
| ftp | yes | yes | |
|
||||
| gd | yes | yes | |
|
||||
| gettext | | | |
|
||||
| gmp | yes | yes | |
|
||||
| iconv | yes | yes | |
|
||||
| imagick | yes | yes | |
|
||||
| inotify | yes | yes | |
|
||||
| intl | | | |
|
||||
| mbstring | yes | yes | |
|
||||
| mbregex | yes | yes | |
|
||||
| mcrypt | | [no](https://github.com/crazywhalecc/static-php-cli/issues/32) | |
|
||||
| mongodb | yes | yes | |
|
||||
| mysqli | yes | yes | |
|
||||
| mysqlnd | yes | yes | |
|
||||
| openssl | yes | yes | |
|
||||
| password-argon2 | | | |
|
||||
| pcntl | yes | yes | |
|
||||
| pdo | yes | yes | |
|
||||
| pdo_mysql | yes | yes | |
|
||||
| pdo_sqlite | yes | yes | |
|
||||
| pdo_pgsql | | | |
|
||||
| phar | yes | yes | |
|
||||
| posix | yes | yes | |
|
||||
| protobuf | yes | yes | |
|
||||
| readline | yes, untested | yes, untested | |
|
||||
| redis | yes | yes | |
|
||||
| session | yes | yes | |
|
||||
| shmop | yes | yes | |
|
||||
| simplexml | yes | yes | |
|
||||
| soap | yes | yes | |
|
||||
| sockets | yes | yes | |
|
||||
| sodium | yes | yes | |
|
||||
| sqlite3 | yes | yes | |
|
||||
| ssh2 | yes, untested | yes, untested | |
|
||||
| swow | yes | yes | |
|
||||
| swoole | [partial](https://github.com/crazywhalecc/static-php-cli/issues/51) | yes | |
|
||||
| tokenizer | yes | yes | |
|
||||
| xlswriter | | | |
|
||||
| xml | yes | yes | |
|
||||
| xmlreader | yes, untested | yes, untested | |
|
||||
| xmlwriter | yes, untested | yes, untested | |
|
||||
| zip | yes, untested | yes, untested | |
|
||||
| zlib | yes | yes | |
|
||||
| zstd | yes | yes | |
|
||||
|
||||
## Additional Requirements
|
||||
|
||||
- phpmicro requires PHP >= 8.0
|
||||
- swoole >= 5.0 requires PHP >= 8.0
|
||||
- swow requires PHP >= 8.0
|
||||
|
||||
## Typical Extension List Example
|
||||
|
||||
Here are some extension list example for different use.
|
||||
|
||||
- For general use: `"bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,ftp,filter,gd,iconv,xml,mbstring,mysqlnd,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,redis,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip"`
|
||||
- For static-php-cli self: `"posix,pcntl,phar,tokenizer,iconv,zlib"`
|
||||
- For static-php-cli self (with dev dependencies): `"posix,pcntl,phar,tokenizer,iconv,zlib,xml,dom,xmlwriter,xmlreader,fileinfo"`
|
||||
- Minimum, with no extension: `""`
|
||||
|
||||
Compile with all supported extensions (exclude `swow`, `swoole`, because these will change the default behavior of php):
|
||||
|
||||
```bash
|
||||
bin/spc build --build-all bcmath,bz2,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,ftp,gd,gmp,iconv,mbregex,mbstring,mongodb,mysqli,mysqlnd,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,protobuf,redis,session,shmop,simplexml,soap,sockets,sqlite3,tokenizer,xml,xmlreader,xmlwriter,yaml,zip,zlib,zstd --with-libs=libjpeg,freetype,libwebp,libavif --debug
|
||||
```
|
||||
|
||||
## Additional Libraries
|
||||
|
||||
Some extensions have soft dependencies, you can enable extra features by adding these libs using `--with-libs`.
|
||||
|
||||
For example, to compile with gd extension, with `libwebp, libgif, libavif, libjpeg, freetype` extra features:
|
||||
|
||||
```bash
|
||||
bin/spc build gd --with-libs=libjpeg,freetype,libwebp,libavif --build-cli
|
||||
```
|
||||
|
||||
> If you don't add them, your compilation will not enable these features.
|
||||
|
||||
## 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)
|
||||
- some extensions need system configuration, e.g. `curl` and `openssl` will search ssl certificate on your system.
|
||||
|
||||
## Bugs and TODOs
|
||||
|
||||
See [#32](https://github.com/crazywhalecc/static-php-cli/issues/32).
|
||||
See: [Docs - Extensions](https://static-php.dev/en/guide/extensions.html)
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
# 快速启动容器环境
|
||||
|
||||
> 提供了 debian 11 构建 和 alpine 构建环境
|
||||
> 任意选一个就可以
|
||||
|
||||
## debian 11 构建环境
|
||||
|
||||
```bash
|
||||
|
||||
# 启动 debian 11 容器环境
|
||||
sh quickstart/linux/run-debian-11-container.sh
|
||||
|
||||
# 进入容器
|
||||
sh quickstart/linux/connection-static-php-cli.sh
|
||||
|
||||
# 准备构建基础软件
|
||||
sh quickstart/linux/debian-11-init.sh
|
||||
|
||||
```
|
||||
|
||||
## aline 构建环境
|
||||
|
||||
```bash
|
||||
|
||||
# 启动 alpine 容器环境
|
||||
sh quickstart/linux/run-alpine-3.16-container.sh
|
||||
|
||||
# 进入容器
|
||||
sh sh quickstart/linux/connection-static-php-cli.sh
|
||||
|
||||
# 准备构建基础软件
|
||||
sh quickstart/linux/alpine-3.16-init.sh
|
||||
|
||||
```
|
||||
@ -1,40 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -exu
|
||||
__DIR__=$(
|
||||
cd "$(dirname "$0")"
|
||||
pwd
|
||||
)
|
||||
cd ${__DIR__}
|
||||
|
||||
|
||||
# use china mirror
|
||||
# bash quickstart/linux/x86_64/alpine-3.16-init.sh --mirror china
|
||||
mirror=''
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--mirror)
|
||||
mirror="$2"
|
||||
shift
|
||||
;;
|
||||
--*)
|
||||
echo "Illegal option $1"
|
||||
;;
|
||||
esac
|
||||
shift $(( $# > 0 ? 1 : 0 ))
|
||||
done
|
||||
|
||||
case "$mirror" in
|
||||
china)
|
||||
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
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
|
||||
apk update
|
||||
|
||||
apk add vim alpine-sdk xz autoconf automake linux-headers clang-dev clang lld libtool cmake bison re2c gettext coreutils
|
||||
apk add bash p7zip zip unzip flex pkgconf ca-certificates
|
||||
apk add wget git curl
|
||||
@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -exu
|
||||
__DIR__=$(
|
||||
cd "$(dirname "$0")"
|
||||
pwd
|
||||
)
|
||||
|
||||
cd ${__DIR__}
|
||||
|
||||
docker exec -it static-php-cli-dev-1 sh
|
||||
@ -1,41 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -exu
|
||||
__DIR__=$(
|
||||
cd "$(dirname "$0")"
|
||||
pwd
|
||||
)
|
||||
cd ${__DIR__}
|
||||
|
||||
# use china mirror
|
||||
# bash quickstart/linux/x86_64/debian-11-init.sh --mirror china
|
||||
mirror=''
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--mirror)
|
||||
mirror="$2"
|
||||
shift
|
||||
;;
|
||||
--*)
|
||||
echo "Illegal option $1"
|
||||
;;
|
||||
esac
|
||||
shift $(( $# > 0 ? 1 : 0 ))
|
||||
done
|
||||
|
||||
case "$mirror" in
|
||||
china)
|
||||
test -f /etc/apt/sources.list.save || cp /etc/apt/sources.list /etc/apt/sources.list.save
|
||||
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
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
|
||||
apt update -y
|
||||
apt install -y git curl wget ca-certificates
|
||||
apt install -y xz-utils autoconf automake lld libtool cmake bison re2c gettext coreutils lzip zip unzip
|
||||
apt install -y pkg-config bzip2 flex p7zip
|
||||
apt install -y musl-tools g++
|
||||
apt install -y clang
|
||||
@ -1,25 +0,0 @@
|
||||
#!/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
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
#!/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
|
||||
|
||||
@ -1,52 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -exu
|
||||
__DIR__=$(
|
||||
cd "$(dirname "$0")"
|
||||
pwd
|
||||
)
|
||||
__PROJECT__=$(
|
||||
cd ${__DIR__}/../
|
||||
pwd
|
||||
)
|
||||
cd ${__PROJECT__}
|
||||
|
||||
OS=$(uname -s)
|
||||
ARCH=$(uname -m)
|
||||
|
||||
if [[ $OS = "Linux" && -f /etc/os-release ]]; then
|
||||
OS_NAME=$(cat /etc/os-release | grep '^ID=' | awk -F '=' '{print $2}')
|
||||
# debian ubuntu alpine
|
||||
fi
|
||||
|
||||
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
|
||||
|
||||
chmod +x bin/spc
|
||||
|
||||
./bin/spc fetch --all --debug
|
||||
|
||||
./bin/spc list-ext
|
||||
|
||||
EXTENSIONS="calendar,ctype,exif,fileinfo,filter,ftp"
|
||||
EXTENSIONS="${EXTENSIONS},session,tokenizer"
|
||||
EXTENSIONS="${EXTENSIONS},phar,posix"
|
||||
EXTENSIONS="${EXTENSIONS},iconv"
|
||||
EXTENSIONS="${EXTENSIONS},xml,dom,simplexml,xmlwriter,xmlreader"
|
||||
EXTENSIONS="${EXTENSIONS},phar,posix"
|
||||
EXTENSIONS="${EXTENSIONS},soap"
|
||||
EXTENSIONS="${EXTENSIONS},mbstring,mbregex"
|
||||
EXTENSIONS="${EXTENSIONS},openssl"
|
||||
EXTENSIONS="${EXTENSIONS},sockets,gmp,bcmath"
|
||||
EXTENSIONS="${EXTENSIONS},pcntl"
|
||||
EXTENSIONS="${EXTENSIONS},curl"
|
||||
EXTENSIONS="${EXTENSIONS},zlib,zip,bz2"
|
||||
EXTENSIONS="${EXTENSIONS},gd"
|
||||
EXTENSIONS="${EXTENSIONS},redis"
|
||||
EXTENSIONS="${EXTENSIONS},pdo,pdo_mysql,pdo_sqlite"
|
||||
EXTENSIONS="${EXTENSIONS},mysqlnd,sqlite3"
|
||||
EXTENSIONS="${EXTENSIONS},mongodb"
|
||||
# EXTENSIONS="${EXTENSIONS},swoole"
|
||||
EXTENSIONS="${EXTENSIONS},swow"
|
||||
|
||||
./bin/spc build "${EXTENSIONS}" --build-cli --cc=clang --cxx=clang++ --debug
|
||||
# ./bin/spc build "${EXTENSIONS}" --build-cli --cc=gcc --cxx=g++ --debug
|
||||
@ -4,47 +4,49 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC;
|
||||
|
||||
use SPC\command\DeployCommand;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\command\BuildCliCommand;
|
||||
use SPC\command\BuildLibsCommand;
|
||||
use SPC\command\dev\AllExtCommand;
|
||||
use SPC\command\dev\PhpVerCommand;
|
||||
use SPC\command\dev\SortConfigCommand;
|
||||
use SPC\command\DoctorCommand;
|
||||
use SPC\command\DownloadCommand;
|
||||
use SPC\command\DumpLicenseCommand;
|
||||
use SPC\command\ExtractCommand;
|
||||
use SPC\command\MicroCombineCommand;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Command\HelpCommand;
|
||||
use Symfony\Component\Console\Command\ListCommand;
|
||||
|
||||
/**
|
||||
* spc 应用究级入口
|
||||
* static-php-cli console app entry
|
||||
*/
|
||||
class ConsoleApplication extends Application
|
||||
final class ConsoleApplication extends Application
|
||||
{
|
||||
public const VERSION = '2.0-rc1';
|
||||
public const VERSION = '2.0.0-rc8';
|
||||
|
||||
/**
|
||||
* @throws \ReflectionException
|
||||
* @throws exception\FileSystemException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('static-php-cli', self::VERSION);
|
||||
|
||||
global $argv;
|
||||
$this->addCommands(
|
||||
[
|
||||
new BuildCliCommand(),
|
||||
new BuildLibsCommand(),
|
||||
new DoctorCommand(),
|
||||
new DownloadCommand(),
|
||||
new DumpLicenseCommand(),
|
||||
new ExtractCommand(),
|
||||
new MicroCombineCommand(),
|
||||
|
||||
// 生产环境不显示详细的调试错误,只使用 symfony console 自带的错误显示
|
||||
$this->setCatchExceptions(file_exists(ROOT_DIR . '/.prod') || !in_array('--debug', $argv));
|
||||
|
||||
// 通过扫描目录 src/static-php-cli/command/ 添加子命令
|
||||
$commands = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/command', 'SPC\\command');
|
||||
$this->addCommands(array_map(function ($x) { return new $x(); }, array_filter($commands, function ($y) {
|
||||
if (is_a($y, DeployCommand::class, true) && (class_exists('\\Phar') && \Phar::running() || !class_exists('\\Phar'))) {
|
||||
return false;
|
||||
}
|
||||
$reflection = new \ReflectionClass($y);
|
||||
return !$reflection->isAbstract() && !$reflection->isInterface();
|
||||
})));
|
||||
// Dev commands
|
||||
new AllExtCommand(),
|
||||
new PhpVerCommand(),
|
||||
new SortConfigCommand(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重载以去除一些不必要的默认命令
|
||||
*/
|
||||
protected function getDefaultCommands(): array
|
||||
{
|
||||
return [new HelpCommand(), new ListCommand()];
|
||||
|
||||
@ -9,48 +9,38 @@ use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\store\SourceExtractor;
|
||||
use SPC\util\CustomExt;
|
||||
use SPC\util\DependencyUtil;
|
||||
|
||||
abstract class BuilderBase
|
||||
{
|
||||
/** @var bool 是否启用 ZTS 线程安全 */
|
||||
public bool $zts = false;
|
||||
|
||||
/** @var string 编译目标架构 */
|
||||
public string $arch;
|
||||
|
||||
/** @var string GNU 格式的编译目标架构 */
|
||||
public string $gnu_arch;
|
||||
|
||||
/** @var int 编译进程数 */
|
||||
/** @var int Concurrency */
|
||||
public int $concurrency = 1;
|
||||
|
||||
/** @var array<string, LibraryBase> 要编译的 libs 列表 */
|
||||
/** @var array<string, LibraryBase> libraries */
|
||||
protected array $libs = [];
|
||||
|
||||
/** @var array<string, Extension> 要编译的扩展列表 */
|
||||
/** @var array<string, Extension> extensions */
|
||||
protected array $exts = [];
|
||||
|
||||
/** @var array<int, string> 要编译的扩展列表(仅名字列表,用于最后生成编译的扩展列表给 micro) */
|
||||
protected array $plain_extensions = [];
|
||||
|
||||
/** @var bool 本次编译是否只编译 libs,不编译 PHP */
|
||||
/** @var bool compile libs only (just mark it) */
|
||||
protected bool $libs_only = false;
|
||||
|
||||
/** @var bool 是否 strip 最终的二进制 */
|
||||
protected bool $strip = true;
|
||||
/** @var array<string, mixed> compile options */
|
||||
protected array $options = [];
|
||||
|
||||
/**
|
||||
* 构建指定列表的 libs
|
||||
* Build libraries
|
||||
*
|
||||
* @param array<string> $libraries Libraries to build
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function buildLibs(array $libraries): void
|
||||
{
|
||||
// 通过扫描目录查找 lib
|
||||
// search all supported libs
|
||||
$support_lib_list = [];
|
||||
$classes = FileSystem::getClassesPsr4(
|
||||
ROOT_DIR . '/src/SPC/builder/' . osfamily2dir() . '/library',
|
||||
@ -62,19 +52,22 @@ abstract class BuilderBase
|
||||
}
|
||||
}
|
||||
|
||||
// 如果传入了空,则默认检查和安置所有支持的lib,libraries为要build的,support_lib_list为支持的列表
|
||||
// if no libs specified, compile all supported libs
|
||||
if ($libraries === [] && $this->isLibsOnly()) {
|
||||
$libraries = array_keys($support_lib_list);
|
||||
}
|
||||
|
||||
// pkg-config must be compiled first, whether it is specified or not
|
||||
if (!in_array('pkg-config', $libraries)) {
|
||||
array_unshift($libraries, 'pkg-config');
|
||||
}
|
||||
|
||||
// 排序 libs,根据依赖计算一个新的列表出来
|
||||
// append dependencies
|
||||
$libraries = DependencyUtil::getLibsByDeps($libraries);
|
||||
|
||||
// 过滤不支持的库后添加
|
||||
// add lib object for builder
|
||||
foreach ($libraries as $library) {
|
||||
// if some libs are not supported (but in config "lib.json", throw exception)
|
||||
if (!isset($support_lib_list[$library])) {
|
||||
throw new RuntimeException('library [' . $library . '] is in the lib.json list but not supported to compile, but in the future I will support it!');
|
||||
}
|
||||
@ -82,16 +75,17 @@ abstract class BuilderBase
|
||||
$this->addLib($lib);
|
||||
}
|
||||
|
||||
// 计算依赖,经过这里的遍历,如果没有抛出异常,说明依赖符合要求,可以继续下面的
|
||||
// calculate and check dependencies
|
||||
foreach ($this->libs as $lib) {
|
||||
$lib->calcDependency();
|
||||
}
|
||||
|
||||
$this->initSource(libs: $libraries);
|
||||
// extract sources
|
||||
SourceExtractor::initSource(libs: $libraries);
|
||||
|
||||
// 构建库
|
||||
// build all libs
|
||||
foreach ($this->libs as $lib) {
|
||||
match ($lib->tryBuild()) {
|
||||
match ($lib->tryBuild($this->getOption('rebuild', false))) {
|
||||
BUILD_STATUS_OK => logger()->info('lib [' . $lib::NAME . '] build success'),
|
||||
BUILD_STATUS_ALREADY => logger()->notice('lib [' . $lib::NAME . '] already built'),
|
||||
BUILD_STATUS_FAILED => logger()->error('lib [' . $lib::NAME . '] build failed'),
|
||||
@ -101,9 +95,9 @@ abstract class BuilderBase
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加要编译的 Lib 库
|
||||
* Add library to build.
|
||||
*
|
||||
* @param LibraryBase $library Lib 库对象
|
||||
* @param LibraryBase $library Library object
|
||||
*/
|
||||
public function addLib(LibraryBase $library): void
|
||||
{
|
||||
@ -111,9 +105,7 @@ abstract class BuilderBase
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取要编译的 Lib 库对象
|
||||
*
|
||||
* @param string $name 库名称
|
||||
* Get library object by name.
|
||||
*/
|
||||
public function getLib(string $name): ?LibraryBase
|
||||
{
|
||||
@ -121,9 +113,17 @@ abstract class BuilderBase
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加要编译的扩展
|
||||
* Get all library objects.
|
||||
*
|
||||
* @param Extension $extension 扩展对象
|
||||
* @return LibraryBase[]
|
||||
*/
|
||||
public function getLibs(): array
|
||||
{
|
||||
return $this->libs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add extension to build.
|
||||
*/
|
||||
public function addExt(Extension $extension): void
|
||||
{
|
||||
@ -131,9 +131,7 @@ abstract class BuilderBase
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取要编译的扩展对象
|
||||
*
|
||||
* @param string $name 扩展名称
|
||||
* Get extension object by name.
|
||||
*/
|
||||
public function getExt(string $name): ?Extension
|
||||
{
|
||||
@ -141,7 +139,41 @@ abstract class BuilderBase
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置本次 Builder 是否为仅编译库的模式
|
||||
* Get all extension objects.
|
||||
*
|
||||
* @return Extension[]
|
||||
*/
|
||||
public function getExts(): array
|
||||
{
|
||||
return $this->exts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is a cpp extensions or libraries.
|
||||
*
|
||||
* @throws FileSystemException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function hasCpp(): bool
|
||||
{
|
||||
// judge cpp-extension
|
||||
$exts = array_keys($this->getExts());
|
||||
foreach ($exts as $ext) {
|
||||
if (Config::getExt($ext, 'cpp-extension', false) === true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
$libs = array_keys($this->getLibs());
|
||||
foreach ($libs as $lib) {
|
||||
if (Config::getLib($lib, 'cpp-library', false) === true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set libs only mode.
|
||||
*/
|
||||
public function setLibsOnly(bool $status = true): void
|
||||
{
|
||||
@ -149,19 +181,21 @@ abstract class BuilderBase
|
||||
}
|
||||
|
||||
/**
|
||||
* 检验 ext 扩展列表是否合理,并声明 Extension 对象,检查扩展的依赖
|
||||
* Verify the list of "ext" extensions for validity and declare an Extension object to check the dependencies of the extensions.
|
||||
*
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws \ReflectionException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function proveExts(array $extensions): void
|
||||
{
|
||||
CustomExt::loadCustomExt();
|
||||
$this->initSource(sources: ['php-src']);
|
||||
SourceExtractor::initSource(sources: ['php-src']);
|
||||
if ($this->getPHPVersionID() >= 80000) {
|
||||
$this->initSource(sources: ['micro']);
|
||||
SourceExtractor::initSource(sources: ['micro']);
|
||||
}
|
||||
$this->initSource(exts: $extensions);
|
||||
SourceExtractor::initSource(exts: $extensions);
|
||||
foreach ($extensions as $extension) {
|
||||
$class = CustomExt::getExtClass($extension);
|
||||
$ext = new $class($extension, $this);
|
||||
@ -169,27 +203,23 @@ abstract class BuilderBase
|
||||
}
|
||||
|
||||
foreach ($this->exts as $ext) {
|
||||
// 检查下依赖就行了,作用是导入依赖给 Extension 对象,今后可以对库依赖进行选择性处理
|
||||
$ext->checkDependency();
|
||||
}
|
||||
|
||||
$this->plain_extensions = $extensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始构建 PHP
|
||||
* Start to build PHP
|
||||
*
|
||||
* @param int $build_target 规则
|
||||
* @param bool $bloat 保留
|
||||
* @param int $build_target Build target, see BUILD_TARGET_*
|
||||
*/
|
||||
abstract public function buildPHP(int $build_target = BUILD_TARGET_NONE, bool $bloat = false);
|
||||
abstract public function buildPHP(int $build_target = BUILD_TARGET_NONE);
|
||||
|
||||
/**
|
||||
* 生成依赖的扩展编译启用参数
|
||||
* 例如 --enable-mbstring 等
|
||||
* Generate extension enable arguments for configure.
|
||||
* e.g. --enable-mbstring
|
||||
*
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function makeExtensionArgs(): string
|
||||
{
|
||||
@ -202,7 +232,7 @@ abstract class BuilderBase
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回是否只编译 libs 的模式
|
||||
* Get libs only mode.
|
||||
*/
|
||||
public function isLibsOnly(): bool
|
||||
{
|
||||
@ -210,15 +240,30 @@ abstract class BuilderBase
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前即将编译的 PHP 的版本 ID,五位数那个
|
||||
* Get PHP Version ID from php-src/main/php_version.h
|
||||
*
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function getPHPVersionID(): int
|
||||
{
|
||||
if (!file_exists(SOURCE_PATH . '/php-src/main/php_version.h')) {
|
||||
throw new WrongUsageException('PHP source files are not available, you need to download them first');
|
||||
}
|
||||
|
||||
$file = file_get_contents(SOURCE_PATH . '/php-src/main/php_version.h');
|
||||
preg_match('/PHP_VERSION_ID (\d+)/', $file, $match);
|
||||
return intval($match[1]);
|
||||
if (preg_match('/PHP_VERSION_ID (\d+)/', $file, $match) !== 0) {
|
||||
return intval($match[1]);
|
||||
}
|
||||
|
||||
throw new RuntimeException('PHP version file format is malformed, please remove it and download again');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get build type name string to display.
|
||||
*
|
||||
* @param int $type Build target type
|
||||
*/
|
||||
public function getBuildTypeName(int $type): string
|
||||
{
|
||||
$ls = [];
|
||||
@ -231,16 +276,64 @@ abstract class BuilderBase
|
||||
if (($type & BUILD_TARGET_FPM) === BUILD_TARGET_FPM) {
|
||||
$ls[] = 'fpm';
|
||||
}
|
||||
if (($type & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED) {
|
||||
$ls[] = 'embed';
|
||||
}
|
||||
return implode(', ', $ls);
|
||||
}
|
||||
|
||||
public function setStrip(bool $strip): void
|
||||
/**
|
||||
* Get builder options (maybe changed by user)
|
||||
*
|
||||
* @param string $key Option key
|
||||
* @param mixed $default If not exists, return this value
|
||||
*/
|
||||
public function getOption(string $key, mixed $default = null): mixed
|
||||
{
|
||||
$this->strip = $strip;
|
||||
return $this->options[$key] ?? $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否存在 lib 库对应的源码,如果不存在,则抛出异常
|
||||
* Get all builder options
|
||||
*/
|
||||
public function getOptions(): array
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set builder options if not exists.
|
||||
*/
|
||||
public function setOptionIfNotExist(string $key, mixed $value): void
|
||||
{
|
||||
if (!isset($this->options[$key])) {
|
||||
$this->options[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set builder options.
|
||||
*/
|
||||
public function setOption(string $key, mixed $value): void
|
||||
{
|
||||
$this->options[$key] = $value;
|
||||
}
|
||||
|
||||
public function getEnvString(array $vars = ['cc', 'cxx', 'ar', 'ld']): string
|
||||
{
|
||||
$env = [];
|
||||
foreach ($vars as $var) {
|
||||
$var = strtoupper($var);
|
||||
if (getenv($var) !== false) {
|
||||
$env[] = "{$var}=" . getenv($var);
|
||||
}
|
||||
}
|
||||
return implode(' ', $env);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if all libs are downloaded.
|
||||
* If not, throw exception.
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
@ -261,52 +354,4 @@ abstract class BuilderBase
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected function initSource(?array $sources = null, ?array $libs = null, ?array $exts = null): void
|
||||
{
|
||||
if (!file_exists(DOWNLOAD_PATH . '/.lock.json')) {
|
||||
throw new WrongUsageException('Download lock file "downloads/.lock.json" not found, maybe you need to download sources first ?');
|
||||
}
|
||||
$lock = json_decode(FileSystem::readFile(DOWNLOAD_PATH . '/.lock.json'), true);
|
||||
|
||||
$sources_extracted = [];
|
||||
// source check exist
|
||||
if (is_array($sources)) {
|
||||
foreach ($sources as $source) {
|
||||
$sources_extracted[$source] = true;
|
||||
}
|
||||
}
|
||||
// lib check source exist
|
||||
if (is_array($libs)) {
|
||||
foreach ($libs as $lib) {
|
||||
// get source name for lib
|
||||
$source = Config::getLib($lib, 'source');
|
||||
$sources_extracted[$source] = true;
|
||||
}
|
||||
}
|
||||
// ext check source exist
|
||||
if (is_array($exts)) {
|
||||
foreach ($exts as $ext) {
|
||||
// get source name for ext
|
||||
if (Config::getExt($ext, 'type') !== 'external') {
|
||||
continue;
|
||||
}
|
||||
$source = Config::getExt($ext, 'source');
|
||||
$sources_extracted[$source] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// start check
|
||||
foreach ($sources_extracted as $source => $item) {
|
||||
if (!isset($lock[$source])) {
|
||||
throw new WrongUsageException('Source [' . $source . '] not downloaded, you should download it first !');
|
||||
}
|
||||
|
||||
// check source dir exist
|
||||
$check = $lock[$source]['move_path'] === null ? SOURCE_PATH . '/' . $source : SOURCE_PATH . '/' . $lock[$source]['move_path'];
|
||||
if (!is_dir($check)) {
|
||||
FileSystem::extractSource($source, DOWNLOAD_PATH . '/' . ($lock[$source]['filename'] ?? $lock[$source]['dirname']), $lock[$source]['move_path']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,9 +4,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder;
|
||||
|
||||
use SPC\builder\freebsd\BSDBuilder;
|
||||
use SPC\builder\linux\LinuxBuilder;
|
||||
use SPC\builder\macos\MacOSBuilder;
|
||||
use SPC\builder\windows\WindowsBuilder;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
@ -17,7 +18,9 @@ use Symfony\Component\Console\Input\InputInterface;
|
||||
class BuilderProvider
|
||||
{
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public static function makeBuilderByInput(InputInterface $input): BuilderBase
|
||||
{
|
||||
@ -27,18 +30,9 @@ class BuilderProvider
|
||||
// vs_ver: $input->getOption('vs-ver'),
|
||||
// arch: $input->getOption('arch'),
|
||||
// ),
|
||||
'Darwin' => new MacOSBuilder(
|
||||
cc: $input->getOption('cc'),
|
||||
cxx: $input->getOption('cxx'),
|
||||
arch: $input->getOption('arch'),
|
||||
zts: $input->hasOption('enable-zts') ? $input->getOption('enable-zts') : false,
|
||||
),
|
||||
'Linux' => new LinuxBuilder(
|
||||
cc: $input->getOption('cc'),
|
||||
cxx: $input->getOption('cxx'),
|
||||
arch: $input->getOption('arch'),
|
||||
zts: $input->hasOption('enable-zts') ? $input->getOption('enable-zts') : false,
|
||||
),
|
||||
'Darwin' => new MacOSBuilder($input->getOptions()),
|
||||
'Linux' => new LinuxBuilder($input->getOptions()),
|
||||
'BSD' => new BSDBuilder($input->getOptions()),
|
||||
default => throw new WrongUsageException('Current OS "' . PHP_OS_FAMILY . '" is not supported yet'),
|
||||
};
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ class Extension
|
||||
/**
|
||||
* 获取开启该扩展的 PHP 编译添加的参数
|
||||
*
|
||||
* @throws FileSystemException|RuntimeException
|
||||
* @throws FileSystemException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function getConfigureArg(): string
|
||||
@ -46,6 +46,7 @@ class Extension
|
||||
break;
|
||||
case 'Darwin':
|
||||
case 'Linux':
|
||||
case 'BSD':
|
||||
$arg .= $this->getUnixConfigureArg();
|
||||
break;
|
||||
}
|
||||
@ -56,7 +57,6 @@ class Extension
|
||||
* 根据 ext 的 arg-type 获取对应开启的参数,一般都是 --enable-xxx 和 --with-xxx
|
||||
*
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function getEnableArg(): string
|
||||
@ -136,6 +136,33 @@ class Extension
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch code before ./buildconf
|
||||
* If you need to patch some code, overwrite this and return true
|
||||
*/
|
||||
public function patchBeforeBuildconf(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch code before ./configure
|
||||
* If you need to patch some code, overwrite this and return true
|
||||
*/
|
||||
public function patchBeforeConfigure(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch code before make
|
||||
* If you need to patch some code, overwrite this and return true
|
||||
*/
|
||||
public function patchBeforeMake(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
|
||||
@ -4,25 +4,22 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder;
|
||||
|
||||
use SPC\builder\macos\library\MacOSLibraryBase;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
|
||||
/**
|
||||
* Lib 库的基类操作对象
|
||||
*/
|
||||
abstract class LibraryBase
|
||||
{
|
||||
/** @var string lib 依赖名称,必须重写 */
|
||||
/** @var string */
|
||||
public const NAME = 'unknown';
|
||||
|
||||
/** @var string lib 依赖的根目录 */
|
||||
protected string $source_dir;
|
||||
|
||||
/** @var array 依赖列表 */
|
||||
protected array $dependencies = [];
|
||||
|
||||
protected bool $patched = false;
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
@ -35,7 +32,7 @@ abstract class LibraryBase
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 lib 库的根目录
|
||||
* Get current lib source root dir.
|
||||
*/
|
||||
public function getSourceDir(): string
|
||||
{
|
||||
@ -43,10 +40,9 @@ abstract class LibraryBase
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前 lib 库的所有依赖列表
|
||||
* Get current lib dependencies.
|
||||
*
|
||||
* @param bool $recursive 是否递归获取(默认为 False)
|
||||
* @return array<string, LibraryBase> 依赖的 Map
|
||||
* @return array<string, LibraryBase>
|
||||
*/
|
||||
public function getDependencies(bool $recursive = false): array
|
||||
{
|
||||
@ -55,7 +51,6 @@ abstract class LibraryBase
|
||||
return $this->dependencies;
|
||||
}
|
||||
|
||||
// 下面为递归获取依赖列表,根据依赖顺序
|
||||
$deps = [];
|
||||
|
||||
$added = 1;
|
||||
@ -78,20 +73,21 @@ abstract class LibraryBase
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算依赖列表,不符合依赖将抛出异常
|
||||
* Calculate dependencies for current library.
|
||||
*
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function calcDependency(): void
|
||||
{
|
||||
// 先从配置文件添加依赖,这里根据不同的操作系统分别选择不同的元信息
|
||||
// Add dependencies from the configuration file. Here, choose different metadata based on the operating system.
|
||||
/*
|
||||
选择规则:
|
||||
如果是 Windows 系统,则依次尝试有无 lib-depends-windows、lib-depends-win、lib-depends。
|
||||
如果是 macOS 系统,则依次尝试 lib-depends-darwin、lib-depends-unix、lib-depends。
|
||||
如果是 Linux 系统,则依次尝试 lib-depends-linux、lib-depends-unix、lib-depends。
|
||||
*/
|
||||
Rules:
|
||||
If it is a Windows system, try the following dependencies in order: lib-depends-windows, lib-depends-win, lib-depends.
|
||||
If it is a macOS system, try the following dependencies in order: lib-depends-darwin, lib-depends-unix, lib-depends.
|
||||
If it is a Linux system, try the following dependencies in order: lib-depends-linux, lib-depends-unix, lib-depends.
|
||||
*/
|
||||
foreach (Config::getLib(static::NAME, 'lib-depends', []) as $dep_name) {
|
||||
$this->addLibraryDependency($dep_name);
|
||||
}
|
||||
@ -101,11 +97,10 @@ abstract class LibraryBase
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前库编译出来获取到的静态库文件列表
|
||||
* Get config static libs.
|
||||
*
|
||||
* @return string[] 获取编译出来后的需要的静态库文件列表
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function getStaticLibs(): array
|
||||
{
|
||||
@ -113,11 +108,10 @@ abstract class LibraryBase
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前 lib 编译出来的 C Header 文件列表
|
||||
* Get config headers.
|
||||
*
|
||||
* @return string[] 获取编译出来后需要的 C Header 文件列表
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function getHeaders(): array
|
||||
{
|
||||
@ -125,73 +119,89 @@ abstract class LibraryBase
|
||||
}
|
||||
|
||||
/**
|
||||
* 证明该库是否已编译好且就绪,如果没有就绪,内部会调用 build 来进行构建该库
|
||||
* Try to build this library, before build, we check first.
|
||||
*
|
||||
* BUILD_STATUS_OK if build success
|
||||
* BUILD_STATUS_ALREADY if already built
|
||||
* BUILD_STATUS_FAILED if build failed
|
||||
*
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function tryBuild(bool $force_build = false): int
|
||||
{
|
||||
// 传入 true,表明直接编译
|
||||
if (file_exists($this->source_dir . '/.spc.patched')) {
|
||||
$this->patched = true;
|
||||
}
|
||||
// force means just build
|
||||
if ($force_build) {
|
||||
logger()->info('Building required library [' . static::NAME . ']');
|
||||
if (!$this->patched && $this->patchBeforeBuild()) {
|
||||
file_put_contents($this->source_dir . '/.spc.patched', 'PATCHED!!!');
|
||||
}
|
||||
$this->build();
|
||||
return BUILD_STATUS_OK;
|
||||
}
|
||||
|
||||
// 看看这些库是不是存在,如果不存在,则调用编译并返回结果状态
|
||||
// check if these libraries exist, if not, invoke compilation and return the result status
|
||||
foreach ($this->getStaticLibs() as $name) {
|
||||
if (!file_exists(BUILD_LIB_PATH . "/{$name}")) {
|
||||
$this->tryBuild(true);
|
||||
return BUILD_STATUS_OK;
|
||||
}
|
||||
}
|
||||
// 头文件同理
|
||||
// header files the same
|
||||
foreach ($this->getHeaders() as $name) {
|
||||
if (!file_exists(BUILD_INCLUDE_PATH . "/{$name}")) {
|
||||
$this->tryBuild(true);
|
||||
return BUILD_STATUS_OK;
|
||||
}
|
||||
}
|
||||
// pkg-config 做特殊处理,如果是 pkg-config 就检查有没有 pkg-config 二进制
|
||||
if ($this instanceof MacOSLibraryBase && static::NAME === 'pkg-config' && !file_exists(BUILD_ROOT_PATH . '/bin/pkg-config')) {
|
||||
// pkg-config is treated specially. If it is pkg-config, check if the pkg-config binary exists
|
||||
if (static::NAME === 'pkg-config' && !file_exists(BUILD_ROOT_PATH . '/bin/pkg-config')) {
|
||||
$this->tryBuild(true);
|
||||
return BUILD_STATUS_OK;
|
||||
}
|
||||
// 到这里说明所有的文件都存在,就跳过编译
|
||||
// if all the files exist at this point, skip the compilation process
|
||||
return BUILD_STATUS_ALREADY;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取构建当前 lib 的 Builder 对象
|
||||
* Patch before build, overwrite this and return true to patch libs.
|
||||
*/
|
||||
public function patchBeforeBuild(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current builder object.
|
||||
*/
|
||||
abstract public function getBuilder(): BuilderBase;
|
||||
|
||||
/**
|
||||
* 构建该库需要调用的命令和操作
|
||||
* Build this library.
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
abstract protected function build();
|
||||
|
||||
/**
|
||||
* 添加 lib 库的依赖库
|
||||
* Add lib dependency
|
||||
*
|
||||
* @param string $name 依赖名称
|
||||
* @param bool $optional 是否是可选依赖(默认为 False)
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
protected function addLibraryDependency(string $name, bool $optional = false): void
|
||||
{
|
||||
// Log::i("add $name as dep of {$this->name}");
|
||||
$dep_lib = $this->getBuilder()->getLib($name);
|
||||
if (!$dep_lib) {
|
||||
if (!$optional) {
|
||||
throw new RuntimeException(static::NAME . " requires library {$name}");
|
||||
}
|
||||
logger()->debug('enabling ' . static::NAME . " without {$name}");
|
||||
} else {
|
||||
if ($dep_lib) {
|
||||
$this->dependencies[$name] = $dep_lib;
|
||||
return;
|
||||
}
|
||||
if (!$optional) {
|
||||
throw new RuntimeException(static::NAME . " requires library {$name}");
|
||||
}
|
||||
logger()->debug('enabling ' . static::NAME . " without {$name}");
|
||||
}
|
||||
}
|
||||
|
||||
27
src/SPC/builder/extension/bz2.php
Normal file
27
src/SPC/builder/extension/bz2.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\builder\macos\MacOSBuilder;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('bz2')]
|
||||
class bz2 extends Extension
|
||||
{
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function patchBeforeConfigure(): bool
|
||||
{
|
||||
$frameworks = $this->builder instanceof MacOSBuilder ? ' ' . $this->builder->getFrameworks(true) . ' ' : '';
|
||||
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/configure', '/-lbz2/', $this->getLibFilesString() . $frameworks);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
57
src/SPC/builder/extension/curl.php
Normal file
57
src/SPC/builder/extension/curl.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\builder\macos\MacOSBuilder;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('curl')]
|
||||
class curl extends Extension
|
||||
{
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function patchBeforeBuildconf(): bool
|
||||
{
|
||||
logger()->info('patching before-configure for curl checks');
|
||||
$file1 = "AC_DEFUN([PHP_CHECK_LIBRARY], [\n $3\n])";
|
||||
$files = FileSystem::readFile(SOURCE_PATH . '/php-src/ext/curl/config.m4');
|
||||
$file2 = 'AC_DEFUN([PHP_CHECK_LIBRARY], [
|
||||
save_old_LDFLAGS=$LDFLAGS
|
||||
ac_stuff="$5"
|
||||
|
||||
save_ext_shared=$ext_shared
|
||||
ext_shared=yes
|
||||
PHP_EVAL_LIBLINE([$]ac_stuff, LDFLAGS)
|
||||
AC_CHECK_LIB([$1],[$2],[
|
||||
LDFLAGS=$save_old_LDFLAGS
|
||||
ext_shared=$save_ext_shared
|
||||
$3
|
||||
],[
|
||||
LDFLAGS=$save_old_LDFLAGS
|
||||
ext_shared=$save_ext_shared
|
||||
unset ac_cv_lib_$1[]_$2
|
||||
$4
|
||||
])dnl
|
||||
])';
|
||||
file_put_contents(SOURCE_PATH . '/php-src/ext/curl/config.m4', $file1 . "\n" . $files . "\n" . $file2);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function patchBeforeConfigure(): bool
|
||||
{
|
||||
$frameworks = $this->builder instanceof MacOSBuilder ? ' ' . $this->builder->getFrameworks(true) . ' ' : '';
|
||||
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/configure', '/-lcurl/', $this->getLibFilesString() . $frameworks);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,8 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('event')]
|
||||
@ -23,4 +25,13 @@ class event extends Extension
|
||||
}
|
||||
return $arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function patchBeforeConfigure(): bool
|
||||
{
|
||||
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/configure', '/-levent_openssl/', $this->getLibFilesString());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
37
src/SPC/builder/extension/glfw.php
Normal file
37
src/SPC/builder/extension/glfw.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('glfw')]
|
||||
class glfw extends Extension
|
||||
{
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function patchBeforeBuildconf(): bool
|
||||
{
|
||||
if (file_exists(SOURCE_PATH . '/php-src/ext/glfw')) {
|
||||
return false;
|
||||
}
|
||||
FileSystem::copyDir(SOURCE_PATH . '/ext-glfw', SOURCE_PATH . '/php-src/ext/glfw');
|
||||
return true;
|
||||
}
|
||||
|
||||
public function patchBeforeConfigure(): bool
|
||||
{
|
||||
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/configure', '-lglfw ', '-lglfw3 ');
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getUnixConfigureArg(): string
|
||||
{
|
||||
return '--enable-glfw --with-glfw-dir=' . BUILD_ROOT_PATH;
|
||||
}
|
||||
}
|
||||
27
src/SPC/builder/extension/iconv.php
Normal file
27
src/SPC/builder/extension/iconv.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\builder\macos\MacOSBuilder;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('iconv')]
|
||||
class iconv extends Extension
|
||||
{
|
||||
public function patchBeforeConfigure(): bool
|
||||
{
|
||||
// macOS need to link iconv dynamically, we add it to extra-libs
|
||||
if (!$this->builder instanceof MacOSBuilder) {
|
||||
return false;
|
||||
}
|
||||
$extra_libs = $this->builder->getOption('extra-libs', '');
|
||||
if (!str_contains($extra_libs, '-liconv')) {
|
||||
$extra_libs .= ' -liconv';
|
||||
}
|
||||
$this->builder->setOption('extra-libs', $extra_libs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -10,6 +10,15 @@ use SPC\util\CustomExt;
|
||||
#[CustomExt('imagick')]
|
||||
class imagick extends Extension
|
||||
{
|
||||
public function patchBeforeMake(): bool
|
||||
{
|
||||
// imagick may call omp_pause_all which requires -lgomp
|
||||
$extra_libs = $this->builder->getOption('extra-libs', '');
|
||||
$extra_libs .= ' -lgomp ';
|
||||
$this->builder->setOption('extra-libs', $extra_libs);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getUnixConfigureArg(): string
|
||||
{
|
||||
return '--with-imagick=' . BUILD_ROOT_PATH;
|
||||
|
||||
@ -14,4 +14,9 @@ class mbregex extends Extension
|
||||
{
|
||||
return 'mbstring';
|
||||
}
|
||||
|
||||
public function getConfigureArg(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
50
src/SPC/builder/extension/memcache.php
Normal file
50
src/SPC/builder/extension/memcache.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('memcache')]
|
||||
class memcache extends Extension
|
||||
{
|
||||
public function getUnixConfigureArg(): string
|
||||
{
|
||||
return '--enable-memcache --with-zlib-dir=' . BUILD_ROOT_PATH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function patchBeforeBuildconf(): bool
|
||||
{
|
||||
FileSystem::replaceFileStr(
|
||||
SOURCE_PATH . '/php-src/ext/memcache/config9.m4',
|
||||
'if test -d $abs_srcdir/src ; then',
|
||||
'if test -d $abs_srcdir/main ; then'
|
||||
);
|
||||
FileSystem::replaceFileStr(
|
||||
SOURCE_PATH . '/php-src/ext/memcache/config9.m4',
|
||||
'export CPPFLAGS="$CPPFLAGS $INCLUDES"',
|
||||
'export CPPFLAGS="$CPPFLAGS $INCLUDES -I$abs_srcdir/main"'
|
||||
);
|
||||
// add for in-tree building
|
||||
file_put_contents(
|
||||
SOURCE_PATH . '/php-src/ext/memcache/php_memcache.h',
|
||||
<<<'EOF'
|
||||
#ifndef PHP_MEMCACHE_H
|
||||
#define PHP_MEMCACHE_H
|
||||
|
||||
extern zend_module_entry memcache_module_entry;
|
||||
#define phpext_memcache_ptr &memcache_module_entry
|
||||
|
||||
#endif
|
||||
EOF
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
18
src/SPC/builder/extension/memcached.php
Normal file
18
src/SPC/builder/extension/memcached.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('memcached')]
|
||||
class memcached extends Extension
|
||||
{
|
||||
public function getUnixConfigureArg(): string
|
||||
{
|
||||
$rootdir = BUILD_ROOT_PATH;
|
||||
return "--enable-memcached --with-zlib-dir={$rootdir} --with-libmemcached-dir={$rootdir} --disable-memcached-sasl --enable-memcached-json";
|
||||
}
|
||||
}
|
||||
@ -13,16 +13,15 @@ class mongodb extends Extension
|
||||
public function getUnixConfigureArg(): string
|
||||
{
|
||||
$arg = ' --enable-mongodb ';
|
||||
$arg .= ' --with-mongodb-system-libs=no ';
|
||||
$arg .= ' --with-mongodb-system-libs=no --with-mongodb-client-side-encryption=no ';
|
||||
$arg .= ' --with-mongodb-sasl=no ';
|
||||
if ($this->builder->getLib('openssl')) {
|
||||
$arg .= '--with-mongodb-ssl=openssl';
|
||||
}
|
||||
if ($this->builder->getLib('icu')) {
|
||||
$arg .= ' --with-mongodb-icu=yes ';
|
||||
} else {
|
||||
$arg .= ' --with-mongodb-icu=no ';
|
||||
}
|
||||
$arg .= $this->builder->getLib('icu') ? ' --with-mongodb-icu=yes ' : ' --with-mongodb-icu=no ';
|
||||
$arg .= $this->builder->getLib('zstd') ? ' --with-mongodb-zstd=yes ' : ' --with-mongodb-zstd=no ';
|
||||
// $arg .= $this->builder->getLib('snappy') ? ' --with-mongodb-snappy=yes ' : ' --with-mongodb-snappy=no ';
|
||||
$arg .= $this->builder->getLib('zlib') ? ' --with-mongodb-zlib=yes ' : ' --with-mongodb-zlib=bundled ';
|
||||
return $arg;
|
||||
}
|
||||
}
|
||||
|
||||
30
src/SPC/builder/extension/openssl.php
Normal file
30
src/SPC/builder/extension/openssl.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('openssl')]
|
||||
class openssl extends Extension
|
||||
{
|
||||
public function patchBeforeMake(): bool
|
||||
{
|
||||
// patch openssl3 with php8.0 bug
|
||||
if (file_exists(SOURCE_PATH . '/openssl/VERSION.dat') && $this->builder->getPHPVersionID() < 80100) {
|
||||
$openssl_c = file_get_contents(SOURCE_PATH . '/php-src/ext/openssl/openssl.c');
|
||||
$openssl_c = preg_replace('/REGISTER_LONG_CONSTANT\s*\(\s*"OPENSSL_SSLV23_PADDING"\s*.+;/', '', $openssl_c);
|
||||
file_put_contents(SOURCE_PATH . '/php-src/ext/openssl/openssl.c', $openssl_c);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getUnixConfigureArg(): string
|
||||
{
|
||||
return '--with-openssl=' . BUILD_ROOT_PATH . ' --with-openssl-dir=' . BUILD_ROOT_PATH;
|
||||
}
|
||||
}
|
||||
27
src/SPC/builder/extension/pdo_sqlite.php
Normal file
27
src/SPC/builder/extension/pdo_sqlite.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('pdo_sqlite')]
|
||||
class pdo_sqlite extends Extension
|
||||
{
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function patchBeforeConfigure(): bool
|
||||
{
|
||||
FileSystem::replaceFileRegex(
|
||||
SOURCE_PATH . '/php-src/configure',
|
||||
'/sqlite3_column_table_name=yes/',
|
||||
'sqlite3_column_table_name=no'
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
27
src/SPC/builder/extension/pgsql.php
Normal file
27
src/SPC/builder/extension/pgsql.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('pgsql')]
|
||||
class pgsql extends Extension
|
||||
{
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function patchBeforeConfigure(): bool
|
||||
{
|
||||
FileSystem::replaceFileRegex(
|
||||
SOURCE_PATH . '/php-src/configure',
|
||||
'/-lpq/',
|
||||
$this->getLibFilesString()
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
27
src/SPC/builder/extension/readline.php
Normal file
27
src/SPC/builder/extension/readline.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('readline')]
|
||||
class readline extends Extension
|
||||
{
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function patchBeforeConfigure(): bool
|
||||
{
|
||||
FileSystem::replaceFileRegex(
|
||||
SOURCE_PATH . '/php-src/configure',
|
||||
'/-lncurses/',
|
||||
$this->getLibFilesString()
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -12,7 +12,12 @@ class redis extends Extension
|
||||
{
|
||||
public function getUnixConfigureArg(): string
|
||||
{
|
||||
$arg = '--enable-redis --disable-redis-session';
|
||||
$arg = '--enable-redis';
|
||||
if (!$this->builder->getExt('session')) {
|
||||
$arg .= ' --disable-redis-session';
|
||||
} else {
|
||||
$arg .= ' --enable-redis-session';
|
||||
}
|
||||
if ($this->builder->getLib('zstd')) {
|
||||
$arg .= ' --enable-redis-zstd --with-libzstd="' . BUILD_ROOT_PATH . '"';
|
||||
}
|
||||
|
||||
33
src/SPC/builder/extension/snappy.php
Normal file
33
src/SPC/builder/extension/snappy.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\builder\macos\MacOSBuilder;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('snappy')]
|
||||
class snappy extends Extension
|
||||
{
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function patchBeforeConfigure(): bool
|
||||
{
|
||||
FileSystem::replaceFileRegex(
|
||||
SOURCE_PATH . '/php-src/configure',
|
||||
'/-lsnappy/',
|
||||
$this->getLibFilesString() . ($this->builder instanceof MacOSBuilder ? ' -lc++' : ' -lstdc++')
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getUnixConfigureArg(): string
|
||||
{
|
||||
return '--enable-snappy --with-snappy-includedir="' . BUILD_ROOT_PATH . '"';
|
||||
}
|
||||
}
|
||||
27
src/SPC/builder/extension/ssh2.php
Normal file
27
src/SPC/builder/extension/ssh2.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('ssh2')]
|
||||
class ssh2 extends Extension
|
||||
{
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function patchBeforeConfigure(): bool
|
||||
{
|
||||
FileSystem::replaceFileRegex(
|
||||
SOURCE_PATH . '/php-src/configure',
|
||||
'/-lssh2/',
|
||||
$this->getLibFilesString()
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -13,10 +13,11 @@ class swoole extends Extension
|
||||
public function getUnixConfigureArg(): string
|
||||
{
|
||||
$arg = '--enable-swoole';
|
||||
// pgsql hook is buggy for static php
|
||||
$arg .= ' --disable-swoole-pgsql';
|
||||
$arg .= $this->builder->getLib('openssl') ? ' --enable-openssl' : ' --disable-openssl --without-openssl';
|
||||
$arg .= $this->builder->getLib('brotli') ? (' --enable-brotli --with-brotli-dir=' . BUILD_ROOT_PATH) : '';
|
||||
// curl hook is buggy for static php
|
||||
$arg .= ' --disable-swoole-curl';
|
||||
$arg .= $this->builder->getExt('curl') ? ' --enable-swoole-curl' : ' --disable-swoole-curl';
|
||||
return $arg;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('swow')]
|
||||
@ -17,4 +18,20 @@ class swow extends Extension
|
||||
$arg .= $this->builder->getLib('curl') ? ' --enable-swow-curl' : ' --disable-swow-curl';
|
||||
return $arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function patchBeforeBuildconf(): bool
|
||||
{
|
||||
if ($this->builder->getPHPVersionID() >= 80000 && !is_link(SOURCE_PATH . '/php-src/ext/swow')) {
|
||||
if (PHP_OS_FAMILY === 'Windows') {
|
||||
f_passthru('cd ' . SOURCE_PATH . '/php-src/ext && mklink /D swow swow-src\ext');
|
||||
} else {
|
||||
f_passthru('cd ' . SOURCE_PATH . '/php-src/ext && ln -s swow-src/ext swow');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
17
src/SPC/builder/extension/xlswriter.php
Normal file
17
src/SPC/builder/extension/xlswriter.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('xlswriter')]
|
||||
class xlswriter extends Extension
|
||||
{
|
||||
public function getUnixConfigureArg(): string
|
||||
{
|
||||
return '--with-xlswriter --enable-reader';
|
||||
}
|
||||
}
|
||||
17
src/SPC/builder/extension/zlib.php
Normal file
17
src/SPC/builder/extension/zlib.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('zlib')]
|
||||
class zlib extends Extension
|
||||
{
|
||||
public function getUnixConfigureArg(): string
|
||||
{
|
||||
return '--with-zlib --with-zlib-dir="' . BUILD_ROOT_PATH . '"';
|
||||
}
|
||||
}
|
||||
253
src/SPC/builder/freebsd/BSDBuilder.php
Normal file
253
src/SPC/builder/freebsd/BSDBuilder.php
Normal file
@ -0,0 +1,253 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\freebsd;
|
||||
|
||||
use SPC\builder\BuilderBase;
|
||||
use SPC\builder\traits\UnixBuilderTrait;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\store\SourcePatcher;
|
||||
|
||||
class BSDBuilder extends BuilderBase
|
||||
{
|
||||
/** Unix compatible builder methods */
|
||||
use UnixBuilderTrait;
|
||||
|
||||
/** @var bool Micro patch phar flag */
|
||||
private bool $phar_patched = false;
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
$this->options = $options;
|
||||
|
||||
// ---------- set necessary options ----------
|
||||
// set C Compiler (default: clang)
|
||||
f_putenv('CC=' . $this->getOption('cc', 'clang'));
|
||||
// set C++ Composer (default: clang++)
|
||||
f_putenv('CXX=' . $this->getOption('cxx', 'clang++'));
|
||||
// set PATH
|
||||
f_putenv('PATH=' . BUILD_ROOT_PATH . '/bin:' . getenv('PATH'));
|
||||
// set PKG_CONFIG
|
||||
f_putenv('PKG_CONFIG=' . BUILD_ROOT_PATH . '/bin/pkg-config');
|
||||
// set PKG_CONFIG_PATH
|
||||
f_putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig/');
|
||||
|
||||
// set arch (default: current)
|
||||
$this->setOptionIfNotExist('arch', php_uname('m'));
|
||||
$this->setOptionIfNotExist('gnu-arch', arch2gnu($this->getOption('arch')));
|
||||
|
||||
// ---------- set necessary compile environments ----------
|
||||
// concurrency
|
||||
$this->concurrency = SystemUtil::getCpuCount();
|
||||
// cflags
|
||||
$this->arch_c_flags = SystemUtil::getArchCFlags($this->getOption('arch'));
|
||||
$this->arch_cxx_flags = SystemUtil::getArchCFlags($this->getOption('arch'));
|
||||
// cmake toolchain
|
||||
$this->cmake_toolchain_file = SystemUtil::makeCmakeToolchainFile('BSD', $this->getOption('arch'), $this->arch_c_flags);
|
||||
|
||||
// create pkgconfig and include dir (some libs cannot create them automatically)
|
||||
f_mkdir(BUILD_LIB_PATH . '/pkgconfig', recursive: true);
|
||||
f_mkdir(BUILD_INCLUDE_PATH, recursive: true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Just start to build statically linked php binary
|
||||
*
|
||||
* @param int $build_target build target
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function buildPHP(int $build_target = BUILD_TARGET_NONE): void
|
||||
{
|
||||
// ---------- Update extra-libs ----------
|
||||
$extra_libs = $this->getOption('extra-libs', '');
|
||||
// add libc++, some extensions or libraries need it (C++ cannot be linked statically)
|
||||
$extra_libs .= (empty($extra_libs) ? '' : ' ') . ($this->hasCpp() ? '-lc++ ' : '');
|
||||
if (!$this->getOption('bloat', false)) {
|
||||
$extra_libs .= (empty($extra_libs) ? '' : ' ') . implode(' ', $this->getAllStaticLibFiles());
|
||||
} else {
|
||||
logger()->info('bloat linking');
|
||||
$extra_libs .= (empty($extra_libs) ? '' : ' ') . implode(' ', array_map(fn ($x) => "-Wl,-force_load,{$x}", array_filter($this->getAllStaticLibFiles())));
|
||||
}
|
||||
$this->setOption('extra-libs', $extra_libs);
|
||||
|
||||
SourcePatcher::patchBeforeBuildconf($this);
|
||||
|
||||
shell()->cd(SOURCE_PATH . '/php-src')->exec('./buildconf --force');
|
||||
|
||||
SourcePatcher::patchBeforeConfigure($this);
|
||||
|
||||
$json_74 = $this->getPHPVersionID() < 80000 ? '--enable-json ' : '';
|
||||
$zts = $this->getOption('enable-zts', false) ? '--enable-zts --disable-zend-signals ' : '';
|
||||
|
||||
$enableCli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI;
|
||||
$enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
|
||||
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
|
||||
$enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
|
||||
|
||||
shell()->cd(SOURCE_PATH . '/php-src')
|
||||
->exec(
|
||||
'./configure ' .
|
||||
'--prefix= ' .
|
||||
'--with-valgrind=no ' . // Not detect memory leak
|
||||
'--enable-shared=no ' .
|
||||
'--enable-static=yes ' .
|
||||
"CFLAGS='{$this->arch_c_flags} -Werror=unknown-warning-option' " .
|
||||
'--disable-all ' .
|
||||
'--disable-cgi ' .
|
||||
'--disable-phpdbg ' .
|
||||
($enableCli ? '--enable-cli ' : '--disable-cli ') .
|
||||
($enableFpm ? '--enable-fpm ' : '--disable-fpm ') .
|
||||
($enableEmbed ? '--enable-embed=static ' : '--disable-embed ') .
|
||||
($enableMicro ? '--enable-micro ' : '--disable-micro ') .
|
||||
$json_74 .
|
||||
$zts .
|
||||
$this->makeExtensionArgs()
|
||||
);
|
||||
|
||||
SourcePatcher::patchBeforeMake($this);
|
||||
|
||||
$this->cleanMake();
|
||||
|
||||
if ($enableCli) {
|
||||
logger()->info('building cli');
|
||||
$this->buildCli();
|
||||
}
|
||||
if ($enableFpm) {
|
||||
logger()->info('building fpm');
|
||||
$this->buildFpm();
|
||||
}
|
||||
if ($enableMicro) {
|
||||
logger()->info('building micro');
|
||||
$this->buildMicro();
|
||||
}
|
||||
if ($enableEmbed) {
|
||||
logger()->info('building embed');
|
||||
if ($enableMicro) {
|
||||
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/Makefile', 'OVERALL_TARGET =', 'OVERALL_TARGET = libphp.la');
|
||||
}
|
||||
$this->buildEmbed();
|
||||
}
|
||||
|
||||
if (php_uname('m') === $this->getOption('arch')) {
|
||||
$this->sanityCheck($build_target);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build cli sapi
|
||||
*
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function buildCli(): void
|
||||
{
|
||||
$vars = SystemUtil::makeEnvVarString([
|
||||
'EXTRA_CFLAGS' => '-g -Os', // with debug information, but optimize for size
|
||||
'EXTRA_LIBS' => "{$this->getOption('extra-libs')} /usr/lib/libm.a",
|
||||
]);
|
||||
|
||||
$shell = shell()->cd(SOURCE_PATH . '/php-src');
|
||||
$shell->exec('sed -ie "s|//lib|/lib|g" Makefile');
|
||||
$shell->exec("make -j{$this->concurrency} {$vars} cli");
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
$shell->exec('strip sapi/cli/php');
|
||||
}
|
||||
$this->deployBinary(BUILD_TARGET_CLI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build phpmicro sapi
|
||||
*
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function buildMicro(): void
|
||||
{
|
||||
if ($this->getPHPVersionID() < 80000) {
|
||||
throw new WrongUsageException('phpmicro only support PHP >= 8.0!');
|
||||
}
|
||||
if ($this->getExt('phar')) {
|
||||
$this->phar_patched = true;
|
||||
SourcePatcher::patchMicro(['phar']);
|
||||
}
|
||||
|
||||
$enable_fake_cli = $this->getOption('with-micro-fake-cli', false) ? ' -DPHP_MICRO_FAKE_CLI' : '';
|
||||
$vars = [
|
||||
// with debug information, optimize for size, remove identifiers, patch fake cli for micro
|
||||
'EXTRA_CFLAGS' => '-g -Os' . $enable_fake_cli,
|
||||
// link resolv library (macOS needs it)
|
||||
'EXTRA_LIBS' => "{$this->getOption('extra-libs')} /usr/lib/libm.a",
|
||||
];
|
||||
$vars = SystemUtil::makeEnvVarString($vars);
|
||||
|
||||
shell()->cd(SOURCE_PATH . '/php-src')
|
||||
->exec("make -j{$this->concurrency} {$vars} micro");
|
||||
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/micro')->exec('strip --strip-all micro.sfx');
|
||||
}
|
||||
$this->deployBinary(BUILD_TARGET_MICRO);
|
||||
|
||||
if ($this->phar_patched) {
|
||||
SourcePatcher::patchMicro(['phar'], true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build fpm sapi
|
||||
*
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function buildFpm(): void
|
||||
{
|
||||
$vars = SystemUtil::makeEnvVarString([
|
||||
'EXTRA_CFLAGS' => '-g -Os', // with debug information, but optimize for size
|
||||
'EXTRA_LIBS' => "{$this->getOption('extra-libs')} /usr/lib/libm.a", // link resolv library (macOS needs it)
|
||||
]);
|
||||
|
||||
$shell = shell()->cd(SOURCE_PATH . '/php-src');
|
||||
$shell->exec("make -j{$this->concurrency} {$vars} fpm");
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
$shell->exec('strip sapi/fpm/php-fpm');
|
||||
}
|
||||
$this->deployBinary(BUILD_TARGET_FPM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build embed sapi
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function buildEmbed(): void
|
||||
{
|
||||
$vars = SystemUtil::makeEnvVarString([
|
||||
'EXTRA_CFLAGS' => '-g -Os', // with debug information, but optimize for size
|
||||
'EXTRA_LIBS' => "{$this->getOption('extra-libs')} /usr/lib/libm.a", // link resolv library (macOS needs it)
|
||||
]);
|
||||
|
||||
shell()
|
||||
->cd(SOURCE_PATH . '/php-src')
|
||||
->exec('make INSTALL_ROOT=' . BUILD_ROOT_PATH . " -j{$this->concurrency} {$vars} install")
|
||||
// Workaround for https://github.com/php/php-src/issues/12082
|
||||
->exec('rm -Rf ' . BUILD_ROOT_PATH . '/lib/php-o')
|
||||
->exec('mkdir ' . BUILD_ROOT_PATH . '/lib/php-o')
|
||||
->cd(BUILD_ROOT_PATH . '/lib/php-o')
|
||||
->exec('ar x ' . BUILD_ROOT_PATH . '/lib/libphp.a')
|
||||
->exec('rm ' . BUILD_ROOT_PATH . '/lib/libphp.a')
|
||||
->exec('ar rcs ' . BUILD_ROOT_PATH . '/lib/libphp.a *.o')
|
||||
->exec('rm -Rf ' . BUILD_ROOT_PATH . '/lib/php-o');
|
||||
}
|
||||
}
|
||||
46
src/SPC/builder/freebsd/SystemUtil.php
Normal file
46
src/SPC/builder/freebsd/SystemUtil.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\freebsd;
|
||||
|
||||
use SPC\builder\traits\UnixSystemUtilTrait;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
|
||||
class SystemUtil
|
||||
{
|
||||
/** Unix System Util Compatible */
|
||||
use UnixSystemUtilTrait;
|
||||
|
||||
/**
|
||||
* Get Logic CPU Count for macOS
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public static function getCpuCount(): int
|
||||
{
|
||||
[$ret, $output] = shell()->execWithResult('sysctl -n hw.ncpu');
|
||||
if ($ret !== 0) {
|
||||
throw new RuntimeException('Failed to get cpu count');
|
||||
}
|
||||
|
||||
return (int) $output[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Target Arch CFlags
|
||||
*
|
||||
* @param string $arch Arch Name
|
||||
* @return string return Arch CFlags string
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public static function getArchCFlags(string $arch): string
|
||||
{
|
||||
return match ($arch) {
|
||||
'amd64', 'x86_64' => '--target=x86_64-unknown-freebsd',
|
||||
'arm64','aarch64' => '--target=aarch-unknown-freebsd',
|
||||
default => throw new WrongUsageException('unsupported arch: ' . $arch),
|
||||
};
|
||||
}
|
||||
}
|
||||
27
src/SPC/builder/freebsd/library/BSDLibraryBase.php
Normal file
27
src/SPC/builder/freebsd/library/BSDLibraryBase.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\freebsd\library;
|
||||
|
||||
use SPC\builder\BuilderBase;
|
||||
use SPC\builder\freebsd\BSDBuilder;
|
||||
use SPC\builder\LibraryBase;
|
||||
use SPC\builder\traits\UnixLibraryTrait;
|
||||
|
||||
abstract class BSDLibraryBase extends LibraryBase
|
||||
{
|
||||
use UnixLibraryTrait;
|
||||
|
||||
protected array $headers;
|
||||
|
||||
public function __construct(protected BSDBuilder $builder)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function getBuilder(): BuilderBase
|
||||
{
|
||||
return $this->builder;
|
||||
}
|
||||
}
|
||||
12
src/SPC/builder/freebsd/library/bzip2.php
Normal file
12
src/SPC/builder/freebsd/library/bzip2.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\freebsd\library;
|
||||
|
||||
class bzip2 extends BSDLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\bzip2;
|
||||
|
||||
public const NAME = 'bzip2';
|
||||
}
|
||||
21
src/SPC/builder/freebsd/library/curl.php
Normal file
21
src/SPC/builder/freebsd/library/curl.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\freebsd\library;
|
||||
|
||||
class curl extends BSDLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\curl;
|
||||
|
||||
public const NAME = 'curl';
|
||||
|
||||
public function getStaticLibFiles(string $style = 'autoconf', bool $recursive = true): string
|
||||
{
|
||||
$libs = parent::getStaticLibFiles($style, $recursive);
|
||||
if ($this->builder->getLib('openssl')) {
|
||||
$this->builder->setOption('extra-libs', $this->builder->getOption('extra-libs') . ' /usr/lib/libpthread.a /usr/lib/libdl.a');
|
||||
}
|
||||
return $libs;
|
||||
}
|
||||
}
|
||||
12
src/SPC/builder/freebsd/library/onig.php
Normal file
12
src/SPC/builder/freebsd/library/onig.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\freebsd\library;
|
||||
|
||||
class onig extends BSDLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\onig;
|
||||
|
||||
public const NAME = 'onig';
|
||||
}
|
||||
63
src/SPC/builder/freebsd/library/openssl.php
Normal file
63
src/SPC/builder/freebsd/library/openssl.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?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\freebsd\library;
|
||||
|
||||
use SPC\builder\macos\library\MacOSLibraryBase;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
|
||||
class openssl extends BSDLibraryBase
|
||||
{
|
||||
public const NAME = 'openssl';
|
||||
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
protected function build(): void
|
||||
{
|
||||
[$lib,,$destdir] = SEPARATED_PATH;
|
||||
|
||||
// lib:zlib
|
||||
$extra = '';
|
||||
$ex_lib = '';
|
||||
$zlib = $this->builder->getLib('zlib');
|
||||
if ($zlib instanceof MacOSLibraryBase) {
|
||||
$extra = 'zlib';
|
||||
$ex_lib = trim($zlib->getStaticLibFiles() . ' ' . $ex_lib);
|
||||
}
|
||||
|
||||
shell()->cd($this->source_dir)
|
||||
->exec(
|
||||
"./Configure no-shared {$extra} " .
|
||||
'--prefix=/ ' . // use prefix=/
|
||||
"--libdir={$lib} " .
|
||||
'--openssldir=/etc/ssl ' .
|
||||
'BSD-' . arch2gnu($this->builder->getOption('arch'))
|
||||
)
|
||||
->exec('make clean')
|
||||
->exec("make -j{$this->builder->concurrency} CNF_EX_LIBS=\"{$ex_lib}\"")
|
||||
->exec("make install_sw DESTDIR={$destdir}");
|
||||
$this->patchPkgconfPrefix(['libssl.pc', 'openssl.pc', 'libcrypto.pc']);
|
||||
}
|
||||
}
|
||||
15
src/SPC/builder/freebsd/library/pkgconfig.php
Normal file
15
src/SPC/builder/freebsd/library/pkgconfig.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\freebsd\library;
|
||||
|
||||
/**
|
||||
* gmp is a template library class for unix
|
||||
*/
|
||||
class pkgconfig extends BSDLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\pkgconfig;
|
||||
|
||||
public const NAME = 'pkg-config';
|
||||
}
|
||||
12
src/SPC/builder/freebsd/library/zlib.php
Normal file
12
src/SPC/builder/freebsd/library/zlib.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\freebsd\library;
|
||||
|
||||
class zlib extends BSDLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\zlib;
|
||||
|
||||
public const NAME = 'zlib';
|
||||
}
|
||||
@ -10,96 +10,95 @@ use SPC\builder\traits\UnixBuilderTrait;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\store\SourcePatcher;
|
||||
|
||||
/**
|
||||
* Linux 系统环境下的构建器
|
||||
*/
|
||||
class LinuxBuilder extends BuilderBase
|
||||
{
|
||||
/** 编译的 Unix 工具集 */
|
||||
/** Unix compatible builder methods */
|
||||
use UnixBuilderTrait;
|
||||
|
||||
/** @var string[] Linux 环境下编译依赖的命令 */
|
||||
public const REQUIRED_COMMANDS = ['make', 'bison', 'flex', 'pkg-config', 'git', 'autoconf', 'automake', 'tar', 'unzip', /* 'xz', 好像不需要 */ 'gzip', 'bzip2', 'cmake'];
|
||||
|
||||
/** @var string 使用的 libc */
|
||||
public string $libc;
|
||||
|
||||
/** @var array 特殊架构下的 cflags */
|
||||
/** @var array Tune cflags */
|
||||
public array $tune_c_flags;
|
||||
|
||||
/** @var string pkg-config 环境变量 */
|
||||
public string $pkgconf_env;
|
||||
|
||||
/** @var string 交叉编译变量 */
|
||||
public string $cross_compile_prefix = '';
|
||||
|
||||
public string $note_section = "Je pense, donc je suis\0";
|
||||
|
||||
/** @var bool Micro patch phar flag */
|
||||
private bool $phar_patched = false;
|
||||
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function __construct(?string $cc = null, ?string $cxx = null, ?string $arch = null, bool $zts = false)
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
// 初始化一些默认参数
|
||||
$this->cc = $cc ?? match (SystemUtil::getOSRelease()['dist']) {
|
||||
'alpine' => 'gcc',
|
||||
default => 'musl-gcc'
|
||||
};
|
||||
$this->cxx = $cxx ?? 'g++';
|
||||
$this->arch = $arch ?? php_uname('m');
|
||||
$this->gnu_arch = arch2gnu($this->arch);
|
||||
$this->zts = $zts;
|
||||
$this->libc = 'musl'; // SystemUtil::selectLibc($this->cc);
|
||||
$this->options = $options;
|
||||
|
||||
// 根据 CPU 线程数设置编译进程数
|
||||
// ---------- set necessary options ----------
|
||||
// set C/C++ compilers (default: alpine: gcc, others: musl-cross-make)
|
||||
if (SystemUtil::isMuslDist()) {
|
||||
f_putenv("CC={$this->getOption('cc', 'gcc')}");
|
||||
f_putenv("CXX={$this->getOption('cxx', 'g++')}");
|
||||
f_putenv("AR={$this->getOption('ar', 'ar')}");
|
||||
f_putenv("LD={$this->getOption('ld', 'ld.gold')}");
|
||||
} else {
|
||||
$arch = arch2gnu(php_uname('m'));
|
||||
f_putenv("CC={$this->getOption('cc', "{$arch}-linux-musl-gcc")}");
|
||||
f_putenv("CXX={$this->getOption('cxx', "{$arch}-linux-musl-g++")}");
|
||||
f_putenv("AR={$this->getOption('ar', "{$arch}-linux-musl-ar")}");
|
||||
f_putenv("LD={$this->getOption('ld', 'ld.gold')}");
|
||||
f_putenv("PATH=/usr/local/musl/bin:/usr/local/musl/{$arch}-linux-musl/bin:" . BUILD_ROOT_PATH . '/bin:' . getenv('PATH'));
|
||||
|
||||
// set library path, some libraries need it. (We cannot use `putenv` here, because cmake will be confused)
|
||||
$this->setOptionIfNotExist('library_path', "LIBRARY_PATH=/usr/local/musl/{$arch}-linux-musl/lib");
|
||||
$this->setOptionIfNotExist('ld_library_path', "LD_LIBRARY_PATH=/usr/local/musl/{$arch}-linux-musl/lib");
|
||||
|
||||
// check musl-cross make installed if we use musl-cross-make
|
||||
if (str_ends_with(getenv('CC'), 'linux-musl-gcc') && !file_exists("/usr/local/musl/bin/{$arch}-linux-musl-gcc")) {
|
||||
throw new WrongUsageException('musl-cross-make not installed, please install it first. (You can use `doctor` command to install it)');
|
||||
}
|
||||
}
|
||||
|
||||
// set PKG_CONFIG
|
||||
f_putenv('PKG_CONFIG=' . BUILD_ROOT_PATH . '/bin/pkg-config');
|
||||
// set PKG_CONFIG_PATH
|
||||
f_putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig');
|
||||
|
||||
// set arch (default: current)
|
||||
$this->setOptionIfNotExist('arch', php_uname('m'));
|
||||
$this->setOptionIfNotExist('gnu-arch', arch2gnu($this->getOption('arch')));
|
||||
|
||||
// concurrency
|
||||
$this->concurrency = SystemUtil::getCpuCount();
|
||||
// 设置 cflags
|
||||
$this->arch_c_flags = SystemUtil::getArchCFlags($this->cc, $this->arch);
|
||||
$this->arch_cxx_flags = SystemUtil::getArchCFlags($this->cxx, $this->arch);
|
||||
$this->tune_c_flags = SystemUtil::checkCCFlags(SystemUtil::getTuneCFlags($this->arch), $this->cc);
|
||||
// 设置 cmake
|
||||
// cflags
|
||||
$this->arch_c_flags = SystemUtil::getArchCFlags(getenv('CC'), $this->getOption('arch'));
|
||||
$this->arch_cxx_flags = SystemUtil::getArchCFlags(getenv('CXX'), $this->getOption('arch'));
|
||||
$this->tune_c_flags = SystemUtil::checkCCFlags(SystemUtil::getTuneCFlags($this->getOption('arch')), getenv('CC'));
|
||||
// cmake toolchain
|
||||
$this->cmake_toolchain_file = SystemUtil::makeCmakeToolchainFile(
|
||||
os: 'Linux',
|
||||
target_arch: $this->arch,
|
||||
cflags: $this->arch_c_flags,
|
||||
cc: $this->cc,
|
||||
cxx: $this->cxx
|
||||
'Linux',
|
||||
$this->getOption('arch'),
|
||||
$this->arch_c_flags,
|
||||
getenv('CC'),
|
||||
getenv('CXX'),
|
||||
);
|
||||
// 设置 pkgconfig
|
||||
$this->pkgconf_env = 'PKG_CONFIG="' . BUILD_ROOT_PATH . '/bin/pkg-config" PKG_CONFIG_PATH="' . BUILD_LIB_PATH . '/pkgconfig"';
|
||||
// 设置 configure 依赖的环境变量
|
||||
$this->configure_env =
|
||||
$this->pkgconf_env . ' ' .
|
||||
"CC='{$this->cc}' " .
|
||||
"CXX='{$this->cxx}' " .
|
||||
(php_uname('m') === $this->arch ? '' : "CFLAGS='{$this->arch_c_flags}'");
|
||||
// 交叉编译依赖的,TODO
|
||||
if (php_uname('m') !== $this->arch) {
|
||||
|
||||
// cross-compiling is not supported yet
|
||||
/*if (php_uname('m') !== $this->arch) {
|
||||
$this->cross_compile_prefix = SystemUtil::getCrossCompilePrefix($this->cc, $this->arch);
|
||||
logger()->info('using cross compile prefix: ' . $this->cross_compile_prefix);
|
||||
$this->configure_env .= " CROSS_COMPILE='{$this->cross_compile_prefix}'";
|
||||
}
|
||||
}*/
|
||||
|
||||
$missing = [];
|
||||
foreach (self::REQUIRED_COMMANDS as $cmd) {
|
||||
if (SystemUtil::findCommand($cmd) === null) {
|
||||
$missing[] = $cmd;
|
||||
}
|
||||
}
|
||||
if (!empty($missing)) {
|
||||
throw new WrongUsageException('missing system commands: ' . implode(', ', $missing));
|
||||
}
|
||||
|
||||
// 创立 pkg-config 和放头文件的目录
|
||||
// create pkgconfig and include dir (some libs cannot create them automatically)
|
||||
f_mkdir(BUILD_LIB_PATH . '/pkgconfig', recursive: true);
|
||||
f_mkdir(BUILD_INCLUDE_PATH, recursive: true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function makeAutoconfArgs(string $name, array $libSpecs): string
|
||||
{
|
||||
$ret = '';
|
||||
@ -124,64 +123,56 @@ class LinuxBuilder extends BuilderBase
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function buildPHP(int $build_target = BUILD_TARGET_NONE, bool $with_clean = false, bool $bloat = false)
|
||||
public function buildPHP(int $build_target = BUILD_TARGET_NONE): void
|
||||
{
|
||||
if (!$bloat) {
|
||||
$extra_libs = implode(' ', $this->getAllStaticLibFiles());
|
||||
// ---------- Update extra-libs ----------
|
||||
$extra_libs = $this->getOption('extra-libs', '');
|
||||
// non-bloat linking
|
||||
if (!$this->getOption('bloat', false)) {
|
||||
$extra_libs .= (empty($extra_libs) ? '' : ' ') . implode(' ', $this->getAllStaticLibFiles());
|
||||
} else {
|
||||
logger()->info('bloat linking');
|
||||
$extra_libs = implode(
|
||||
' ',
|
||||
array_map(
|
||||
fn ($x) => "-Xcompiler {$x}",
|
||||
array_filter($this->getAllStaticLibFiles())
|
||||
)
|
||||
);
|
||||
}
|
||||
if ($this->getExt('swoole') || $this->getExt('intl')) {
|
||||
$extra_libs .= ' -lstdc++';
|
||||
}
|
||||
if ($this->getExt('imagick')) {
|
||||
$extra_libs .= ' /usr/lib/libMagick++-7.Q16HDRI.a /usr/lib/libMagickCore-7.Q16HDRI.a /usr/lib/libMagickWand-7.Q16HDRI.a';
|
||||
$extra_libs .= (empty($extra_libs) ? '' : ' ') . implode(' ', array_map(fn ($x) => "-Xcompiler {$x}", array_filter($this->getAllStaticLibFiles())));
|
||||
}
|
||||
// add libstdc++, some extensions or libraries need it
|
||||
$extra_libs .= (empty($extra_libs) ? '' : ' ') . ($this->hasCpp() ? '-lstdc++ ' : '');
|
||||
$this->setOption('extra-libs', $extra_libs);
|
||||
|
||||
$envs = $this->pkgconf_env . ' ' .
|
||||
"CC='{$this->cc}' " .
|
||||
"CXX='{$this->cxx}' ";
|
||||
$cflags = $this->arch_c_flags;
|
||||
$use_lld = '';
|
||||
|
||||
switch ($this->libc) {
|
||||
case 'musl_wrapper':
|
||||
case 'glibc':
|
||||
$cflags .= ' -static-libgcc -I"' . BUILD_INCLUDE_PATH . '"';
|
||||
break;
|
||||
case 'musl':
|
||||
if (str_ends_with($this->cc, 'clang') && SystemUtil::findCommand('lld')) {
|
||||
$use_lld = '-Xcompiler -fuse-ld=lld';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new WrongUsageException('libc ' . $this->libc . ' is not implemented yet');
|
||||
}
|
||||
// prepare build php envs
|
||||
$envs_build_php = SystemUtil::makeEnvVarString([
|
||||
'CFLAGS' => $cflags,
|
||||
'LIBS' => '-ldl -lpthread',
|
||||
]);
|
||||
|
||||
$envs = "{$envs} CFLAGS='{$cflags}' LIBS='-ldl -lpthread'";
|
||||
|
||||
SourcePatcher::patchPHPBuildconf($this);
|
||||
SourcePatcher::patchBeforeBuildconf($this);
|
||||
|
||||
shell()->cd(SOURCE_PATH . '/php-src')->exec('./buildconf --force');
|
||||
|
||||
SourcePatcher::patchPHPConfigure($this);
|
||||
SourcePatcher::patchBeforeConfigure($this);
|
||||
|
||||
if ($this->getPHPVersionID() < 80000) {
|
||||
$json_74 = '--enable-json ';
|
||||
$phpVersionID = $this->getPHPVersionID();
|
||||
$json_74 = $phpVersionID < 80000 ? '--enable-json ' : '';
|
||||
|
||||
if ($this->getOption('enable-zts', false)) {
|
||||
$maxExecutionTimers = $phpVersionID >= 80100 ? '--enable-zend-max-execution-timers ' : '';
|
||||
$zts = '--enable-zts --disable-zend-signals ';
|
||||
} else {
|
||||
$json_74 = '';
|
||||
$maxExecutionTimers = '';
|
||||
$zts = '';
|
||||
}
|
||||
$disable_jit = $this->getOption('disable-opcache-jit', false) ? '--disable-opcache-jit ' : '';
|
||||
|
||||
$enableCli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI;
|
||||
$enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
|
||||
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
|
||||
$enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
|
||||
|
||||
shell()->cd(SOURCE_PATH . '/php-src')
|
||||
->exec(
|
||||
"{$this->getOption('ld_library_path')} " .
|
||||
'./configure ' .
|
||||
'--prefix= ' .
|
||||
'--with-valgrind=no ' .
|
||||
@ -190,43 +181,96 @@ class LinuxBuilder extends BuilderBase
|
||||
'--disable-all ' .
|
||||
'--disable-cgi ' .
|
||||
'--disable-phpdbg ' .
|
||||
'--enable-cli ' .
|
||||
'--enable-fpm ' .
|
||||
($enableCli ? '--enable-cli ' : '--disable-cli ') .
|
||||
($enableFpm ? '--enable-fpm ' : '--disable-fpm ') .
|
||||
($enableEmbed ? '--enable-embed=static ' : '--disable-embed ') .
|
||||
($enableMicro ? '--enable-micro=all-static ' : '--disable-micro ') .
|
||||
$disable_jit .
|
||||
$json_74 .
|
||||
'--enable-micro=all-static ' .
|
||||
($this->zts ? '--enable-zts' : '') . ' ' .
|
||||
$zts .
|
||||
$maxExecutionTimers .
|
||||
$this->makeExtensionArgs() . ' ' .
|
||||
$envs
|
||||
$envs_build_php
|
||||
);
|
||||
|
||||
SourcePatcher::patchPHPAfterConfigure($this);
|
||||
SourcePatcher::patchBeforeMake($this);
|
||||
|
||||
file_put_contents('/tmp/comment', $this->note_section);
|
||||
|
||||
// 清理
|
||||
$this->cleanMake();
|
||||
|
||||
if ($bloat) {
|
||||
logger()->info('bloat linking');
|
||||
$extra_libs = "-Wl,--whole-archive {$extra_libs} -Wl,--no-whole-archive";
|
||||
}
|
||||
|
||||
if (($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) {
|
||||
if ($enableCli) {
|
||||
logger()->info('building cli');
|
||||
$this->buildCli($extra_libs, $use_lld);
|
||||
$this->buildCli();
|
||||
}
|
||||
if (($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM) {
|
||||
if ($enableFpm) {
|
||||
logger()->info('building fpm');
|
||||
$this->buildFpm($extra_libs, $use_lld);
|
||||
$this->buildFpm();
|
||||
}
|
||||
if (($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO) {
|
||||
if ($enableMicro) {
|
||||
logger()->info('building micro');
|
||||
$this->buildMicro($extra_libs, $use_lld, $cflags);
|
||||
$this->buildMicro();
|
||||
}
|
||||
if ($enableEmbed) {
|
||||
logger()->info('building embed');
|
||||
if ($enableMicro) {
|
||||
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/Makefile', 'OVERALL_TARGET =', 'OVERALL_TARGET = libphp.la');
|
||||
}
|
||||
$this->buildEmbed();
|
||||
}
|
||||
|
||||
if (php_uname('m') === $this->arch) {
|
||||
if (php_uname('m') === $this->getOption('arch')) {
|
||||
$this->sanityCheck($build_target);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build cli sapi
|
||||
*
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function buildCli(): void
|
||||
{
|
||||
$vars = SystemUtil::makeEnvVarString($this->getBuildVars());
|
||||
shell()->cd(SOURCE_PATH . '/php-src')
|
||||
->exec('sed -i "s|//lib|/lib|g" Makefile')
|
||||
->exec("make -j{$this->concurrency} {$vars} cli");
|
||||
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/cli')->exec('strip --strip-all php');
|
||||
}
|
||||
|
||||
$this->deployBinary(BUILD_TARGET_CLI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build phpmicro sapi
|
||||
*
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function buildMicro(): void
|
||||
{
|
||||
if ($this->getPHPVersionID() < 80000) {
|
||||
throw new WrongUsageException('phpmicro only support PHP >= 8.0!');
|
||||
}
|
||||
if ($this->getExt('phar')) {
|
||||
$this->phar_patched = true;
|
||||
SourcePatcher::patchMicro(['phar']);
|
||||
}
|
||||
|
||||
$vars = SystemUtil::makeEnvVarString($this->getBuildVars([
|
||||
'EXTRA_CFLAGS' => $this->getOption('with-micro-fake-cli', false) ? ' -DPHP_MICRO_FAKE_CLI' : '',
|
||||
]));
|
||||
shell()->cd(SOURCE_PATH . '/php-src')
|
||||
->exec('sed -i "s|//lib|/lib|g" Makefile')
|
||||
->exec("make -j{$this->concurrency} {$vars} micro");
|
||||
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/micro')->exec('strip --strip-all micro.sfx');
|
||||
}
|
||||
|
||||
$this->deployBinary(BUILD_TARGET_MICRO);
|
||||
|
||||
if ($this->phar_patched) {
|
||||
SourcePatcher::patchMicro(['phar'], true);
|
||||
@ -234,78 +278,54 @@ class LinuxBuilder extends BuilderBase
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function buildCli(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' " .
|
||||
'cli'
|
||||
);
|
||||
|
||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/cli')
|
||||
->exec("{$this->cross_compile_prefix}objcopy --only-keep-debug php php.debug")
|
||||
->exec('elfedit --output-osabi linux 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");
|
||||
$this->deployBinary(BUILD_TARGET_CLI);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
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')) {
|
||||
$this->phar_patched = true;
|
||||
SourcePatcher::patchMicro(['phar']);
|
||||
}
|
||||
|
||||
shell()->cd(SOURCE_PATH . '/php-src')
|
||||
->exec('sed -i "s|//lib|/lib|g" Makefile')
|
||||
->exec(
|
||||
"make -j{$this->concurrency} " .
|
||||
'EXTRA_CFLAGS=' . quote('-g -Os -fno-ident ' . implode(' ', array_map(fn ($x) => "-Xcompiler {$x}", $this->tune_c_flags))) . ' ' .
|
||||
'EXTRA_LIBS=' . quote($extra_libs) . ' ' .
|
||||
'EXTRA_LDFLAGS_PROGRAM=' . quote("{$cflags} {$use_lld}" . ' -all-static', "'") . ' ' .
|
||||
'micro'
|
||||
);
|
||||
|
||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/micro')->exec("{$this->cross_compile_prefix}strip --strip-all micro.sfx");
|
||||
|
||||
$this->deployBinary(BUILD_TARGET_MICRO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 fpm
|
||||
* Build fpm sapi
|
||||
*
|
||||
* @throws FileSystemException|RuntimeException
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function buildFpm(string $extra_libs, string $use_lld): void
|
||||
public function buildFpm(): void
|
||||
{
|
||||
$vars = SystemUtil::makeEnvVarString($this->getBuildVars());
|
||||
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'
|
||||
);
|
||||
->exec("make -j{$this->concurrency} {$vars} fpm");
|
||||
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/fpm')->exec('strip --strip-all php-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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build embed sapi
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function buildEmbed(): void
|
||||
{
|
||||
$vars = SystemUtil::makeEnvVarString($this->getBuildVars());
|
||||
|
||||
shell()
|
||||
->cd(SOURCE_PATH . '/php-src')
|
||||
->exec('sed -i "s|//lib|/lib|g" Makefile')
|
||||
->exec('make INSTALL_ROOT=' . BUILD_ROOT_PATH . " -j{$this->concurrency} {$vars} install");
|
||||
}
|
||||
|
||||
private function getBuildVars($input = []): array
|
||||
{
|
||||
$use_lld = '';
|
||||
if (str_ends_with(getenv('CC'), 'clang') && SystemUtil::findCommand('lld')) {
|
||||
$use_lld = '-Xcompiler -fuse-ld=lld';
|
||||
}
|
||||
$optimization = $this->getOption('no-strip', false) ? '-g -O0' : '-g0 -Os';
|
||||
$cflags = isset($input['EXTRA_CFLAGS']) && $input['EXTRA_CFLAGS'] ? " {$input['EXTRA_CFLAGS']}" : '';
|
||||
$libs = isset($input['EXTRA_LIBS']) && $input['EXTRA_LIBS'] ? " {$input['EXTRA_LIBS']}" : '';
|
||||
$ldflags = isset($input['EXTRA_LDFLAGS_PROGRAM']) && $input['EXTRA_LDFLAGS_PROGRAM'] ? " {$input['EXTRA_LDFLAGS_PROGRAM']}" : '';
|
||||
return [
|
||||
'EXTRA_CFLAGS' => "{$optimization} -fno-ident -fPIE " . implode(' ', array_map(fn ($x) => "-Xcompiler {$x}", $this->tune_c_flags)) . $cflags,
|
||||
'EXTRA_LIBS' => $this->getOption('extra-libs', '') . $libs,
|
||||
'EXTRA_LDFLAGS_PROGRAM' => "{$use_lld} -all-static" . $ldflags,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux;
|
||||
|
||||
use JetBrains\PhpStorm\ArrayShape;
|
||||
use SPC\builder\traits\UnixSystemUtilTrait;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
@ -13,7 +12,7 @@ class SystemUtil
|
||||
{
|
||||
use UnixSystemUtilTrait;
|
||||
|
||||
#[ArrayShape(['dist' => 'mixed|string', 'ver' => 'mixed|string'])]
|
||||
/** @noinspection PhpMissingBreakStatementInspection */
|
||||
public static function getOSRelease(): array
|
||||
{
|
||||
$ret = [
|
||||
@ -21,6 +20,19 @@ class SystemUtil
|
||||
'ver' => 'unknown',
|
||||
];
|
||||
switch (true) {
|
||||
case file_exists('/etc/centos-release'):
|
||||
$lines = file('/etc/centos-release');
|
||||
goto rh;
|
||||
case file_exists('/etc/redhat-release'):
|
||||
$lines = file('/etc/redhat-release');
|
||||
rh:
|
||||
foreach ($lines as $line) {
|
||||
if (preg_match('/release\s+(\d*(\.\d+)*)/', $line, $matches)) {
|
||||
$ret['dist'] = 'redhat';
|
||||
$ret['ver'] = $matches[1];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case file_exists('/etc/os-release'):
|
||||
$lines = file('/etc/os-release');
|
||||
foreach ($lines as $line) {
|
||||
@ -37,23 +49,15 @@ class SystemUtil
|
||||
$ret['dist'] = 'redhat';
|
||||
}
|
||||
break;
|
||||
case file_exists('/etc/centos-release'):
|
||||
$lines = file('/etc/centos-release');
|
||||
goto rh;
|
||||
case file_exists('/etc/redhat-release'):
|
||||
$lines = file('/etc/redhat-release');
|
||||
rh:
|
||||
foreach ($lines as $line) {
|
||||
if (preg_match('/release\s+(\d+(\.\d+)*)/', $line, $matches)) {
|
||||
$ret['dist'] = 'redhat';
|
||||
$ret['ver'] = $matches[1];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public static function isMuslDist(): bool
|
||||
{
|
||||
return static::getOSRelease()['dist'] === 'alpine';
|
||||
}
|
||||
|
||||
public static function getCpuCount(): int
|
||||
{
|
||||
$ncpu = 1;
|
||||
@ -81,6 +85,8 @@ class SystemUtil
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public static function getArchCFlags(string $cc, string $arch): string
|
||||
{
|
||||
@ -120,7 +126,7 @@ class SystemUtil
|
||||
|
||||
public static function checkCCFlag(string $flag, string $cc): string
|
||||
{
|
||||
[$ret] = shell()->execWithResult("echo | {$cc} -E -x c - {$flag}");
|
||||
[$ret] = shell()->execWithResult("echo | {$cc} -E -x c - {$flag} 2>/dev/null");
|
||||
if ($ret != 0) {
|
||||
return '';
|
||||
}
|
||||
@ -129,6 +135,7 @@ class SystemUtil
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public static function getCrossCompilePrefix(string $cc, string $arch): string
|
||||
{
|
||||
@ -159,6 +166,7 @@ class SystemUtil
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @noinspection PhpUnused */
|
||||
public static function findStaticLibs(array $names): ?array
|
||||
{
|
||||
$ret = [];
|
||||
@ -187,6 +195,7 @@ class SystemUtil
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @noinspection PhpUnused */
|
||||
public static function findHeaders(array $names): ?array
|
||||
{
|
||||
$ret = [];
|
||||
|
||||
@ -8,7 +8,6 @@ use SPC\builder\BuilderBase;
|
||||
use SPC\builder\LibraryBase;
|
||||
use SPC\builder\linux\LinuxBuilder;
|
||||
use SPC\builder\traits\UnixLibraryTrait;
|
||||
use SPC\exception\RuntimeException;
|
||||
|
||||
abstract class LinuxLibraryBase extends LibraryBase
|
||||
{
|
||||
@ -34,50 +33,4 @@ abstract class LinuxLibraryBase extends LibraryBase
|
||||
{
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function tryBuild(bool $force_build = false): int
|
||||
{
|
||||
// 传入 true,表明直接编译
|
||||
if ($force_build) {
|
||||
logger()->info('Building required library [' . static::NAME . ']');
|
||||
$this->build();
|
||||
return BUILD_STATUS_OK;
|
||||
}
|
||||
|
||||
// 看看这些库是不是存在,如果不存在,则调用编译并返回结果状态
|
||||
foreach ($this->getStaticLibs() as $name) {
|
||||
if (!file_exists(BUILD_LIB_PATH . "/{$name}")) {
|
||||
$this->tryBuild(true);
|
||||
return BUILD_STATUS_OK;
|
||||
}
|
||||
}
|
||||
// 头文件同理
|
||||
foreach ($this->getHeaders() as $name) {
|
||||
if (!file_exists(BUILD_INCLUDE_PATH . "/{$name}")) {
|
||||
$this->tryBuild(true);
|
||||
return BUILD_STATUS_OK;
|
||||
}
|
||||
}
|
||||
// pkg-config 做特殊处理,如果是 pkg-config 就检查有没有 pkg-config 二进制
|
||||
if (static::NAME === 'pkg-config' && !file_exists(BUILD_ROOT_PATH . '/bin/pkg-config')) {
|
||||
$this->tryBuild(true);
|
||||
return BUILD_STATUS_OK;
|
||||
}
|
||||
// 到这里说明所有的文件都存在,就跳过编译
|
||||
return BUILD_STATUS_ALREADY;
|
||||
}
|
||||
|
||||
protected function makeFakePkgconfs()
|
||||
{
|
||||
$workspace = BUILD_ROOT_PATH;
|
||||
if ($workspace === '/') {
|
||||
$workspace = '';
|
||||
}
|
||||
foreach ($this->pkgconfs as $name => $content) {
|
||||
file_put_contents(BUILD_LIB_PATH . "/pkgconfig/{$name}", "prefix={$workspace}\n" . $content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,13 +8,15 @@ class icu extends LinuxLibraryBase
|
||||
{
|
||||
public const NAME = 'icu';
|
||||
|
||||
protected function build()
|
||||
protected function build(): void
|
||||
{
|
||||
$root = BUILD_ROOT_PATH;
|
||||
$cppflag = 'CPPFLAGS="-DU_CHARSET_IS_UTF8=1 -DU_USING_ICU_NAMESPACE=1 -DU_STATIC_IMPLEMENTATION=1"';
|
||||
$cppflags = 'CPPFLAGS="-DU_CHARSET_IS_UTF8=1 -DU_USING_ICU_NAMESPACE=1 -DU_STATIC_IMPLEMENTATION=1"';
|
||||
$cxxflags = 'CXXFLAGS="-std=c++11"';
|
||||
$ldflags = 'LDFLAGS="-static"';
|
||||
shell()->cd($this->source_dir . '/source')
|
||||
->exec(
|
||||
"{$this->builder->configure_env} {$cppflag} ./runConfigureICU Linux " .
|
||||
"{$cppflags} {$cxxflags} {$ldflags} " .
|
||||
'./runConfigureICU Linux ' .
|
||||
'--enable-static ' .
|
||||
'--disable-shared ' .
|
||||
'--with-data-packaging=static ' .
|
||||
@ -25,7 +27,7 @@ class icu extends LinuxLibraryBase
|
||||
'--enable-tools=yes ' .
|
||||
'--enable-tests=no ' .
|
||||
'--enable-samples=no ' .
|
||||
"--prefix={$root}"
|
||||
'--prefix=' . BUILD_ROOT_PATH
|
||||
)
|
||||
->exec('make clean')
|
||||
->exec("make -j{$this->builder->concurrency}")
|
||||
|
||||
12
src/SPC/builder/linux/library/ldap.php
Normal file
12
src/SPC/builder/linux/library/ldap.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
class ldap extends LinuxLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\ldap;
|
||||
|
||||
public const NAME = 'ldap';
|
||||
}
|
||||
50
src/SPC/builder/linux/library/libffi.php
Normal file
50
src/SPC/builder/linux/library/libffi.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
use SPC\exception\RuntimeException;
|
||||
|
||||
class libffi extends LinuxLibraryBase
|
||||
{
|
||||
public const NAME = 'libffi';
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function build(): void
|
||||
{
|
||||
[$lib, , $destdir] = SEPARATED_PATH;
|
||||
|
||||
/*$env = $this->builder->pkgconf_env . ' CFLAGS="' . $this->builder->arch_c_flags . '"';
|
||||
|
||||
$env .= match ($this->builder->libc) {
|
||||
'musl_wrapper' => " CC='{$this->builder->getOption('cc')} --static -idirafter " . BUILD_INCLUDE_PATH .
|
||||
($this->builder->getOption('arch') === php_uname('m') ? '-idirafter /usr/include/ ' : '') .
|
||||
"-idirafter /usr/include/{$this->builder->getOption('arch')}-linux-gnu/'",
|
||||
'musl', 'glibc' => " CC='{$this->builder->getOption('cc')}'",
|
||||
default => throw new RuntimeException('unsupported libc: ' . $this->builder->libc),
|
||||
};*/
|
||||
|
||||
shell()->cd($this->source_dir)
|
||||
->exec(
|
||||
'./configure ' .
|
||||
'--enable-static ' .
|
||||
'--disable-shared ' .
|
||||
"--host={$this->builder->getOption('arch')}-unknown-linux " .
|
||||
"--target={$this->builder->getOption('arch')}-unknown-linux " .
|
||||
'--prefix= ' . // use prefix=/
|
||||
"--libdir={$lib}"
|
||||
)
|
||||
->exec('make clean')
|
||||
->exec("make -j{$this->builder->concurrency}")
|
||||
->exec("make install DESTDIR={$destdir}");
|
||||
|
||||
if (is_file(BUILD_ROOT_PATH . '/lib64/libffi.a')) {
|
||||
copy(BUILD_ROOT_PATH . '/lib64/libffi.a', BUILD_ROOT_PATH . '/lib/libffi.a');
|
||||
unlink(BUILD_ROOT_PATH . '/lib64/libffi.a');
|
||||
}
|
||||
$this->patchPkgconfPrefix(['libffi.pc']);
|
||||
}
|
||||
}
|
||||
20
src/SPC/builder/linux/library/libmemcached.php
Normal file
20
src/SPC/builder/linux/library/libmemcached.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
use SPC\exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* gmp is a template library class for unix
|
||||
*/
|
||||
class libmemcached extends LinuxLibraryBase
|
||||
{
|
||||
public const NAME = 'libmemcached';
|
||||
|
||||
public function build()
|
||||
{
|
||||
throw new RuntimeException('libmemcached is currently not supported on Linux platform');
|
||||
}
|
||||
}
|
||||
@ -22,32 +22,30 @@ namespace SPC\builder\linux\library;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\store\SourcePatcher;
|
||||
use SPC\exception\WrongUsageException;
|
||||
|
||||
class libpng extends LinuxLibraryBase
|
||||
{
|
||||
public const NAME = 'libpng';
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function build()
|
||||
public function build(): void
|
||||
{
|
||||
$optimizations = match ($this->builder->arch) {
|
||||
$optimizations = match ($this->builder->getOption('arch')) {
|
||||
'x86_64' => '--enable-intel-sse ',
|
||||
'arm64' => '--enable-arm-neon ',
|
||||
default => '',
|
||||
};
|
||||
|
||||
// patch configure
|
||||
SourcePatcher::patchUnixLibpng();
|
||||
|
||||
shell()->cd($this->source_dir)
|
||||
->exec('chmod +x ./configure')
|
||||
->exec('chmod +x ./install-sh')
|
||||
->exec(
|
||||
"{$this->builder->configure_env} ./configure " .
|
||||
"--host={$this->builder->gnu_arch}-unknown-linux " .
|
||||
'LDFLAGS="-L' . BUILD_LIB_PATH . '" ' .
|
||||
'./configure ' .
|
||||
'--disable-shared ' .
|
||||
'--enable-static ' .
|
||||
'--enable-hardware-optimizations ' .
|
||||
@ -56,10 +54,8 @@ class libpng extends LinuxLibraryBase
|
||||
'--prefix='
|
||||
)
|
||||
->exec('make clean')
|
||||
->exec("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)
|
||||
->cd(BUILD_LIB_PATH)
|
||||
->exec('ln -sf libpng16.a libpng.a');
|
||||
->exec("make -j{$this->builder->concurrency} DEFAULT_INCLUDES='-I{$this->source_dir} -I" . BUILD_INCLUDE_PATH . "' LIBS= libpng16.la")
|
||||
->exec('make install-libLTLIBRARIES install-data-am DESTDIR=' . BUILD_ROOT_PATH);
|
||||
$this->patchPkgconfPrefix(['libpng16.pc'], PKGCONF_PATCH_PREFIX);
|
||||
$this->cleanLaFiles();
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
@ -13,23 +14,22 @@ class libxml2 extends LinuxLibraryBase
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function build()
|
||||
public function build(): void
|
||||
{
|
||||
$enable_zlib = $this->builder->getLib('zlib') ? 'ON' : 'OFF';
|
||||
$enable_icu = $this->builder->getLib('icu') ? 'ON' : 'OFF';
|
||||
$enable_xz = $this->builder->getLib('xz') ? 'ON' : 'OFF';
|
||||
|
||||
[$lib, $include, $destdir] = SEPARATED_PATH;
|
||||
|
||||
FileSystem::resetDir($this->source_dir . '/build');
|
||||
shell()->cd($this->source_dir . '/build')
|
||||
->exec(
|
||||
"{$this->builder->configure_env} " . ' cmake ' .
|
||||
'cmake ' .
|
||||
"{$this->builder->makeCmakeArgs()} " .
|
||||
'-DBUILD_SHARED_LIBS=OFF ' .
|
||||
'-DLIBXML2_WITH_ICONV=ON ' .
|
||||
'-DIconv_IS_BUILT_IN=OFF ' .
|
||||
'-DLIBXML2_WITH_ICONV=ON ' .
|
||||
"-DLIBXML2_WITH_ZLIB={$enable_zlib} " .
|
||||
"-DLIBXML2_WITH_ICU={$enable_icu} " .
|
||||
"-DLIBXML2_WITH_LZMA={$enable_xz} " .
|
||||
@ -39,15 +39,12 @@ class libxml2 extends LinuxLibraryBase
|
||||
'..'
|
||||
)
|
||||
->exec("cmake --build . -j {$this->builder->concurrency}")
|
||||
->exec("make install DESTDIR={$destdir}");
|
||||
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
|
||||
|
||||
if (is_dir(BUILD_INCLUDE_PATH . '/libxml2/libxml')) {
|
||||
if (is_dir(BUILD_INCLUDE_PATH . '/libxml')) {
|
||||
shell()->exec('rm -rf "' . BUILD_INCLUDE_PATH . '/libxml"');
|
||||
}
|
||||
$path = FileSystem::convertPath(BUILD_INCLUDE_PATH . '/libxml2/libxml');
|
||||
$dst_path = FileSystem::convertPath(BUILD_INCLUDE_PATH . '/');
|
||||
shell()->exec('mv "' . $path . '" "' . $dst_path . '"');
|
||||
}
|
||||
FileSystem::replaceFileStr(
|
||||
BUILD_LIB_PATH . '/pkgconfig/libxml-2.0.pc',
|
||||
'-licudata -licui18n -licuuc',
|
||||
'-licui18n -licuuc -licudata'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
15
src/SPC/builder/linux/library/libxslt.php
Normal file
15
src/SPC/builder/linux/library/libxslt.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
/**
|
||||
* gmp is a template library class for unix
|
||||
*/
|
||||
class libxslt extends LinuxLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\libxslt;
|
||||
|
||||
public const NAME = 'libxslt';
|
||||
}
|
||||
@ -20,11 +20,20 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
|
||||
class nghttp2 extends LinuxLibraryBase
|
||||
{
|
||||
public const NAME = 'nghttp2';
|
||||
|
||||
public function build()
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function build(): void
|
||||
{
|
||||
$args = $this->builder->makeAutoconfArgs(static::NAME, [
|
||||
'zlib' => null,
|
||||
@ -46,10 +55,10 @@ class nghttp2 extends LinuxLibraryBase
|
||||
|
||||
shell()->cd($this->source_dir)
|
||||
->exec(
|
||||
"{$this->builder->configure_env} ./configure " .
|
||||
'./configure ' .
|
||||
'--enable-static ' .
|
||||
'--disable-shared ' .
|
||||
"--host={$this->builder->gnu_arch}-unknown-linux " .
|
||||
"--host={$this->builder->getOption('gnu-arch')}-unknown-linux " .
|
||||
'--enable-lib-only ' .
|
||||
'--with-boost=no ' .
|
||||
$args . ' ' .
|
||||
|
||||
@ -23,26 +23,28 @@ namespace SPC\builder\linux\library;
|
||||
use SPC\builder\linux\SystemUtil;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
|
||||
class openssl extends LinuxLibraryBase
|
||||
{
|
||||
public const NAME = 'openssl';
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function build()
|
||||
public function build(): void
|
||||
{
|
||||
[$lib,$include,$destdir] = SEPARATED_PATH;
|
||||
[,,$destdir] = SEPARATED_PATH;
|
||||
|
||||
$extra = '';
|
||||
$ex_lib = '-ldl -pthread';
|
||||
|
||||
$env = $this->builder->pkgconf_env . " CFLAGS='{$this->builder->arch_c_flags}'";
|
||||
$env .= " CC='{$this->builder->cc} -static -idirafter " . BUILD_INCLUDE_PATH .
|
||||
$env = "CFLAGS='{$this->builder->arch_c_flags}'";
|
||||
$env .= " CC='" . getenv('CC') . ' -static -idirafter ' . BUILD_INCLUDE_PATH .
|
||||
' -idirafter /usr/include/ ' .
|
||||
' -idirafter /usr/include/' . $this->builder->arch . '-linux-gnu/ ' .
|
||||
' -idirafter /usr/include/' . $this->builder->getOption('arch') . '-linux-gnu/ ' .
|
||||
"' ";
|
||||
// lib:zlib
|
||||
$zlib = $this->builder->getLib('zlib');
|
||||
@ -58,17 +60,17 @@ class openssl extends LinuxLibraryBase
|
||||
|
||||
$ex_lib = trim($ex_lib);
|
||||
|
||||
$clang_postfix = SystemUtil::getCCType($this->builder->cc) === 'clang' ? '-clang' : '';
|
||||
$clang_postfix = SystemUtil::getCCType(getenv('CC')) === 'clang' ? '-clang' : '';
|
||||
|
||||
shell()->cd($this->source_dir)
|
||||
->exec(
|
||||
"{$this->builder->configure_env} {$env} ./Configure no-shared {$extra} " .
|
||||
"{$env} ./Configure no-shared {$extra} " .
|
||||
'--prefix=/ ' .
|
||||
'--libdir=lib ' .
|
||||
'-static ' .
|
||||
"{$zlib_extra}" .
|
||||
'no-legacy ' .
|
||||
"linux-{$this->builder->arch}{$clang_postfix}"
|
||||
"linux-{$this->builder->getOption('arch')}{$clang_postfix}"
|
||||
)
|
||||
->exec('make clean')
|
||||
->exec("make -j{$this->builder->concurrency} CNF_EX_LIBS=\"{$ex_lib}\"")
|
||||
|
||||
12
src/SPC/builder/linux/library/postgresql.php
Normal file
12
src/SPC/builder/linux/library/postgresql.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
class postgresql extends LinuxLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\postgresql;
|
||||
|
||||
public const NAME = 'postgresql';
|
||||
}
|
||||
12
src/SPC/builder/linux/library/snappy.php
Normal file
12
src/SPC/builder/linux/library/snappy.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
class snappy extends LinuxLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\snappy;
|
||||
|
||||
public const NAME = 'snappy';
|
||||
}
|
||||
@ -10,59 +10,58 @@ use SPC\builder\traits\UnixBuilderTrait;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\store\SourcePatcher;
|
||||
|
||||
/**
|
||||
* macOS 系统环境下的构建器
|
||||
* 源于 Config,但因为感觉叫 Config 不太合适,就换成了 Builder
|
||||
*/
|
||||
class MacOSBuilder extends BuilderBase
|
||||
{
|
||||
/** 编译的 Unix 工具集 */
|
||||
/** Unix compatible builder methods */
|
||||
use UnixBuilderTrait;
|
||||
|
||||
/** @var bool 标记是否 patch 了 phar */
|
||||
/** @var bool Micro patch phar flag */
|
||||
private bool $phar_patched = false;
|
||||
|
||||
/**
|
||||
* @param null|string $cc C编译器名称,如果不传入则默认使用clang
|
||||
* @param null|string $cxx C++编译器名称,如果不传入则默认使用clang++
|
||||
* @param null|string $arch 当前架构,如果不传入则默认使用当前系统架构
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function __construct(?string $cc = null, ?string $cxx = null, ?string $arch = null, bool $zts = false)
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
// 如果是 Debug 模式,才使用 set -x 显示每条执行的命令
|
||||
$this->set_x = defined('DEBUG_MODE') ? 'set -x' : 'true';
|
||||
// 初始化一些默认参数
|
||||
$this->cc = $cc ?? 'clang';
|
||||
$this->cxx = $cxx ?? 'clang++';
|
||||
$this->arch = $arch ?? php_uname('m');
|
||||
$this->gnu_arch = arch2gnu($this->arch);
|
||||
$this->zts = $zts;
|
||||
// 根据 CPU 线程数设置编译进程数
|
||||
$this->concurrency = SystemUtil::getCpuCount();
|
||||
// 设置 cflags
|
||||
$this->arch_c_flags = SystemUtil::getArchCFlags($this->arch);
|
||||
$this->arch_cxx_flags = SystemUtil::getArchCFlags($this->arch);
|
||||
// 设置 cmake
|
||||
$this->cmake_toolchain_file = SystemUtil::makeCmakeToolchainFile('Darwin', $this->arch, $this->arch_c_flags);
|
||||
// 设置 configure 依赖的环境变量
|
||||
$this->configure_env =
|
||||
'PKG_CONFIG="' . BUILD_ROOT_PATH . '/bin/pkg-config" ' .
|
||||
'PKG_CONFIG_PATH="' . BUILD_LIB_PATH . '/pkgconfig/" ' .
|
||||
"CC='{$this->cc}' " .
|
||||
"CXX='{$this->cxx}' " .
|
||||
"CFLAGS='{$this->arch_c_flags} -Wimplicit-function-declaration'";
|
||||
$this->options = $options;
|
||||
|
||||
// 创立 pkg-config 和放头文件的目录
|
||||
// ---------- set necessary options ----------
|
||||
// set C Compiler (default: clang)
|
||||
f_putenv('CC=' . $this->getOption('cc', 'clang'));
|
||||
// set C++ Composer (default: clang++)
|
||||
f_putenv('CXX=' . $this->getOption('cxx', 'clang++'));
|
||||
// set PATH
|
||||
f_putenv('PATH=' . BUILD_ROOT_PATH . '/bin:' . getenv('PATH'));
|
||||
// set PKG_CONFIG
|
||||
f_putenv('PKG_CONFIG=' . BUILD_ROOT_PATH . '/bin/pkg-config');
|
||||
// set PKG_CONFIG_PATH
|
||||
f_putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig/');
|
||||
|
||||
// set arch (default: current)
|
||||
$this->setOptionIfNotExist('arch', php_uname('m'));
|
||||
$this->setOptionIfNotExist('gnu-arch', arch2gnu($this->getOption('arch')));
|
||||
|
||||
// ---------- set necessary compile environments ----------
|
||||
// concurrency
|
||||
$this->concurrency = SystemUtil::getCpuCount();
|
||||
// cflags
|
||||
$this->arch_c_flags = SystemUtil::getArchCFlags($this->getOption('arch'));
|
||||
$this->arch_cxx_flags = SystemUtil::getArchCFlags($this->getOption('arch'));
|
||||
// cmake toolchain
|
||||
$this->cmake_toolchain_file = SystemUtil::makeCmakeToolchainFile('Darwin', $this->getOption('arch'), $this->arch_c_flags);
|
||||
|
||||
// create pkgconfig and include dir (some libs cannot create them automatically)
|
||||
f_mkdir(BUILD_LIB_PATH . '/pkgconfig', recursive: true);
|
||||
f_mkdir(BUILD_INCLUDE_PATH, recursive: true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成库构建采用的 autoconf 参数列表
|
||||
* [deprecated] 生成库构建采用的 autoconf 参数列表
|
||||
*
|
||||
* @param string $name 要构建的 lib 库名,传入仅供输出日志
|
||||
* @param array $lib_specs 依赖的 lib 库的 autoconf 文件
|
||||
@ -76,7 +75,6 @@ class MacOSBuilder extends BuilderBase
|
||||
$arr = $arr ?? [];
|
||||
|
||||
$disableArgs = $arr[0] ?? null;
|
||||
$prefix = $arr[1] ?? null;
|
||||
if ($lib instanceof MacOSLibraryBase) {
|
||||
logger()->info("{$name} \033[32;1mwith\033[0;1m {$libName} support");
|
||||
$ret .= '--with-' . $libName . '=yes ';
|
||||
@ -89,9 +87,11 @@ class MacOSBuilder extends BuilderBase
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回 macOS 系统依赖的框架列表
|
||||
* Get dynamically linked macOS frameworks
|
||||
*
|
||||
* @param bool $asString 是否以字符串形式返回(默认为 False)
|
||||
* @param bool $asString If true, return as string
|
||||
* @throws FileSystemException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function getFrameworks(bool $asString = false): array|string
|
||||
{
|
||||
@ -118,82 +118,145 @@ class MacOSBuilder extends BuilderBase
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* Just start to build statically linked php binary
|
||||
*
|
||||
* @param int $build_target build target
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function buildPHP(int $build_target = BUILD_TARGET_NONE, bool $bloat = false): void
|
||||
public function buildPHP(int $build_target = BUILD_TARGET_NONE): void
|
||||
{
|
||||
$extra_libs = $this->getFrameworks(true) . ' ' . ($this->getExt('swoole') || $this->getExt('intl') ? '-lc++ ' : '');
|
||||
if (!$bloat) {
|
||||
$extra_libs .= implode(' ', $this->getAllStaticLibFiles());
|
||||
// ---------- Update extra-libs ----------
|
||||
$extra_libs = $this->getOption('extra-libs', '');
|
||||
// add macOS frameworks
|
||||
$extra_libs .= (empty($extra_libs) ? '' : ' ') . $this->getFrameworks(true);
|
||||
// add libc++, some extensions or libraries need it (C++ cannot be linked statically)
|
||||
$extra_libs .= (empty($extra_libs) ? '' : ' ') . ($this->hasCpp() ? '-lc++ ' : '');
|
||||
if (!$this->getOption('bloat', false)) {
|
||||
$extra_libs .= (empty($extra_libs) ? '' : ' ') . implode(' ', $this->getAllStaticLibFiles());
|
||||
} else {
|
||||
logger()->info('bloat linking');
|
||||
$extra_libs .= implode(
|
||||
' ',
|
||||
array_map(
|
||||
fn ($x) => "-Wl,-force_load,{$x}",
|
||||
array_filter($this->getAllStaticLibFiles())
|
||||
)
|
||||
);
|
||||
$extra_libs .= (empty($extra_libs) ? '' : ' ') . implode(' ', array_map(fn ($x) => "-Wl,-force_load,{$x}", array_filter($this->getAllStaticLibFiles())));
|
||||
}
|
||||
$this->setOption('extra-libs', $extra_libs);
|
||||
|
||||
// patch before configure
|
||||
SourcePatcher::patchPHPBuildconf($this);
|
||||
SourcePatcher::patchBeforeBuildconf($this);
|
||||
|
||||
shell()->cd(SOURCE_PATH . '/php-src')->exec('./buildconf --force');
|
||||
|
||||
SourcePatcher::patchPHPConfigure($this);
|
||||
SourcePatcher::patchBeforeConfigure($this);
|
||||
|
||||
if ($this->getLib('libxml2') || $this->getExt('iconv')) {
|
||||
$extra_libs .= ' -liconv';
|
||||
}
|
||||
$json_74 = $this->getPHPVersionID() < 80000 ? '--enable-json ' : '';
|
||||
$zts = $this->getOption('enable-zts', false) ? '--enable-zts --disable-zend-signals ' : '';
|
||||
|
||||
if ($this->getPHPVersionID() < 80000) {
|
||||
$json_74 = '--enable-json ';
|
||||
} else {
|
||||
$json_74 = '';
|
||||
}
|
||||
$enableCli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI;
|
||||
$enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
|
||||
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
|
||||
$enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
|
||||
|
||||
shell()->cd(SOURCE_PATH . '/php-src')
|
||||
->exec(
|
||||
'./configure ' .
|
||||
'--prefix= ' .
|
||||
'--with-valgrind=no ' . // 不检测内存泄漏
|
||||
'--with-valgrind=no ' . // Not detect memory leak
|
||||
'--enable-shared=no ' .
|
||||
'--enable-static=yes ' .
|
||||
"CFLAGS='{$this->arch_c_flags} -Werror=unknown-warning-option' " .
|
||||
'--disable-all ' .
|
||||
'--disable-cgi ' .
|
||||
'--disable-phpdbg ' .
|
||||
'--enable-cli ' .
|
||||
'--enable-fpm ' .
|
||||
($enableCli ? '--enable-cli ' : '--disable-cli ') .
|
||||
($enableFpm ? '--enable-fpm ' : '--disable-fpm ') .
|
||||
($enableEmbed ? '--enable-embed=static ' : '--disable-embed ') .
|
||||
($enableMicro ? '--enable-micro ' : '--disable-micro ') .
|
||||
$json_74 .
|
||||
'--enable-micro ' .
|
||||
($this->zts ? '--enable-zts' : '') . ' ' .
|
||||
$this->makeExtensionArgs() . ' ' .
|
||||
$this->configure_env
|
||||
$zts .
|
||||
$this->makeExtensionArgs()
|
||||
);
|
||||
|
||||
SourcePatcher::patchPHPAfterConfigure($this);
|
||||
SourcePatcher::patchBeforeMake($this);
|
||||
|
||||
$this->cleanMake();
|
||||
|
||||
if (($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) {
|
||||
if ($enableCli) {
|
||||
logger()->info('building cli');
|
||||
$this->buildCli($extra_libs);
|
||||
$this->buildCli();
|
||||
}
|
||||
if (($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM) {
|
||||
if ($enableFpm) {
|
||||
logger()->info('building fpm');
|
||||
$this->buildFpm($extra_libs);
|
||||
$this->buildFpm();
|
||||
}
|
||||
if (($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO) {
|
||||
if ($enableMicro) {
|
||||
logger()->info('building micro');
|
||||
$this->buildMicro($extra_libs);
|
||||
$this->buildMicro();
|
||||
}
|
||||
if ($enableEmbed) {
|
||||
logger()->info('building embed');
|
||||
if ($enableMicro) {
|
||||
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/Makefile', 'OVERALL_TARGET =', 'OVERALL_TARGET = libphp.la');
|
||||
}
|
||||
$this->buildEmbed();
|
||||
}
|
||||
|
||||
if (php_uname('m') === $this->arch) {
|
||||
if (php_uname('m') === $this->getOption('arch')) {
|
||||
$this->sanityCheck($build_target);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build cli sapi
|
||||
*
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function buildCli(): void
|
||||
{
|
||||
$vars = SystemUtil::makeEnvVarString([
|
||||
'EXTRA_CFLAGS' => '-g -Os', // with debug information, but optimize for size
|
||||
'EXTRA_LIBS' => "{$this->getOption('extra-libs')} -lresolv", // link resolv library (macOS needs it)
|
||||
]);
|
||||
|
||||
$shell = shell()->cd(SOURCE_PATH . '/php-src');
|
||||
$shell->exec("make -j{$this->concurrency} {$vars} cli");
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
$shell->exec('dsymutil -f sapi/cli/php')->exec('strip sapi/cli/php');
|
||||
}
|
||||
$this->deployBinary(BUILD_TARGET_CLI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build phpmicro sapi
|
||||
*
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function buildMicro(): void
|
||||
{
|
||||
if ($this->getPHPVersionID() < 80000) {
|
||||
throw new WrongUsageException('phpmicro only support PHP >= 8.0!');
|
||||
}
|
||||
if ($this->getExt('phar')) {
|
||||
$this->phar_patched = true;
|
||||
SourcePatcher::patchMicro(['phar']);
|
||||
}
|
||||
|
||||
$enable_fake_cli = $this->getOption('with-micro-fake-cli', false) ? ' -DPHP_MICRO_FAKE_CLI' : '';
|
||||
$vars = [
|
||||
// with debug information, optimize for size, remove identifiers, patch fake cli for micro
|
||||
'EXTRA_CFLAGS' => '-g -Os -fno-ident' . $enable_fake_cli,
|
||||
// link resolv library (macOS needs it)
|
||||
'EXTRA_LIBS' => "{$this->getOption('extra-libs')} -lresolv",
|
||||
];
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
$vars['STRIP'] = 'dsymutil -f ';
|
||||
}
|
||||
$vars = SystemUtil::makeEnvVarString($vars);
|
||||
|
||||
shell()->cd(SOURCE_PATH . '/php-src')
|
||||
->exec("make -j{$this->concurrency} {$vars} micro");
|
||||
$this->deployBinary(BUILD_TARGET_MICRO);
|
||||
|
||||
if ($this->phar_patched) {
|
||||
SourcePatcher::patchMicro(['phar'], true);
|
||||
@ -201,54 +264,48 @@ class MacOSBuilder extends BuilderBase
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 cli
|
||||
* Build fpm sapi
|
||||
*
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function buildCli(string $extra_libs): void
|
||||
public function buildFpm(): void
|
||||
{
|
||||
$vars = SystemUtil::makeEnvVarString([
|
||||
'EXTRA_CFLAGS' => '-g -Os', // with debug information, but optimize for size
|
||||
'EXTRA_LIBS' => "{$this->getOption('extra-libs')} -lresolv", // link resolv library (macOS needs it)
|
||||
]);
|
||||
|
||||
$shell = shell()->cd(SOURCE_PATH . '/php-src');
|
||||
$shell->exec("make -j{$this->concurrency} EXTRA_CFLAGS=\"-g -Os -fno-ident\" EXTRA_LIBS=\"{$extra_libs} -lresolv\" cli");
|
||||
if ($this->strip) {
|
||||
$shell->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
|
||||
{
|
||||
if ($this->getPHPVersionID() < 80000) {
|
||||
throw new RuntimeException('phpmicro only support PHP >= 8.0!');
|
||||
}
|
||||
if ($this->getExt('phar')) {
|
||||
$this->phar_patched = true;
|
||||
SourcePatcher::patchMicro(['phar']);
|
||||
}
|
||||
|
||||
shell()->cd(SOURCE_PATH . '/php-src')
|
||||
->exec("make -j{$this->concurrency} EXTRA_CFLAGS=\"-g -Os -fno-ident\" EXTRA_LIBS=\"{$extra_libs} -lresolv\" " . ($this->strip ? 'STRIP="dsymutil -f " ' : '') . 'micro');
|
||||
$this->deployBinary(BUILD_TARGET_MICRO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 fpm
|
||||
*
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function buildFpm(string $extra_libs): void
|
||||
{
|
||||
$shell = shell()->cd(SOURCE_PATH . '/php-src');
|
||||
$shell->exec("make -j{$this->concurrency} EXTRA_CFLAGS=\"-g -Os -fno-ident\" EXTRA_LIBS=\"{$extra_libs} -lresolv\" fpm");
|
||||
if ($this->strip) {
|
||||
$shell->exec("make -j{$this->concurrency} {$vars} fpm");
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
$shell->exec('dsymutil -f sapi/fpm/php-fpm')->exec('strip sapi/fpm/php-fpm');
|
||||
}
|
||||
$this->deployBinary(BUILD_TARGET_FPM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build embed sapi
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function buildEmbed(): void
|
||||
{
|
||||
$vars = SystemUtil::makeEnvVarString([
|
||||
'EXTRA_CFLAGS' => '-g -Os', // with debug information, but optimize for size
|
||||
'EXTRA_LIBS' => "{$this->getOption('extra-libs')} -lresolv", // link resolv library (macOS needs it)
|
||||
]);
|
||||
|
||||
shell()
|
||||
->cd(SOURCE_PATH . '/php-src')
|
||||
->exec('make INSTALL_ROOT=' . BUILD_ROOT_PATH . " -j{$this->concurrency} {$vars} install")
|
||||
// Workaround for https://github.com/php/php-src/issues/12082
|
||||
->exec('rm -Rf ' . BUILD_ROOT_PATH . '/lib/php-o')
|
||||
->exec('mkdir ' . BUILD_ROOT_PATH . '/lib/php-o')
|
||||
->cd(BUILD_ROOT_PATH . '/lib/php-o')
|
||||
->exec('ar x ' . BUILD_ROOT_PATH . '/lib/libphp.a')
|
||||
->exec('rm ' . BUILD_ROOT_PATH . '/lib/libphp.a')
|
||||
->exec('ar rcs ' . BUILD_ROOT_PATH . '/lib/libphp.a *.o')
|
||||
->exec('rm -Rf ' . BUILD_ROOT_PATH . '/lib/php-o');
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,11 +10,11 @@ use SPC\exception\WrongUsageException;
|
||||
|
||||
class SystemUtil
|
||||
{
|
||||
/** macOS 兼容 unix 的系统工具 */
|
||||
/** Unix System Util Compatible */
|
||||
use UnixSystemUtilTrait;
|
||||
|
||||
/**
|
||||
* 获取系统 CPU 逻辑内核数
|
||||
* Get Logic CPU Count for macOS
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
@ -29,9 +29,10 @@ class SystemUtil
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取不同架构对应的 cflags 参数
|
||||
* Get Target Arch CFlags
|
||||
*
|
||||
* @param string $arch 架构名称
|
||||
* @param string $arch Arch Name
|
||||
* @return string return Arch CFlags string
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public static function getArchCFlags(string $arch): string
|
||||
|
||||
@ -8,6 +8,8 @@ use SPC\builder\BuilderBase;
|
||||
use SPC\builder\LibraryBase;
|
||||
use SPC\builder\macos\MacOSBuilder;
|
||||
use SPC\builder\traits\UnixLibraryTrait;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
|
||||
abstract class MacOSLibraryBase extends LibraryBase
|
||||
@ -27,7 +29,8 @@ abstract class MacOSLibraryBase extends LibraryBase
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前 lib 库依赖的 macOS framework
|
||||
* @throws WrongUsageException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function getFrameworks(): array
|
||||
{
|
||||
|
||||
@ -20,19 +20,35 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
use SPC\store\SourcePatcher;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
class curl extends MacOSLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\curl {
|
||||
build as unixBuild;
|
||||
}
|
||||
use \SPC\builder\unix\library\curl;
|
||||
|
||||
public const NAME = 'curl';
|
||||
|
||||
protected function build()
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function patchBeforeBuild(): bool
|
||||
{
|
||||
SourcePatcher::patchCurlMacOS();
|
||||
$this->unixBuild();
|
||||
FileSystem::replaceFileRegex(
|
||||
SOURCE_PATH . '/curl/CMakeLists.txt',
|
||||
'/NOT COREFOUNDATION_FRAMEWORK/m',
|
||||
'FALSE'
|
||||
);
|
||||
FileSystem::replaceFileRegex(
|
||||
SOURCE_PATH . '/curl/CMakeLists.txt',
|
||||
'/NOT SYSTEMCONFIGURATION_FRAMEWORK/m',
|
||||
'FALSE'
|
||||
);
|
||||
FileSystem::replaceFileRegex(
|
||||
SOURCE_PATH . '/curl/CMakeLists.txt',
|
||||
'/NOT CORESERVICES_FRAMEWORK/m',
|
||||
'FALSE'
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
28
src/SPC/builder/macos/library/glfw.php
Normal file
28
src/SPC/builder/macos/library/glfw.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
|
||||
class glfw extends MacOSLibraryBase
|
||||
{
|
||||
public const NAME = 'glfw';
|
||||
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
protected function build(): void
|
||||
{
|
||||
// compile!
|
||||
shell()->cd(SOURCE_PATH . '/ext-glfw/vendor/glfw')
|
||||
->exec("cmake . {$this->builder->makeCmakeArgs()} -DBUILD_SHARED_LIBS=OFF -DGLFW_BUILD_EXAMPLES=OFF -DGLFW_BUILD_TESTS=OFF")
|
||||
->exec("make -j{$this->builder->concurrency}")
|
||||
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
|
||||
// patch pkgconf
|
||||
$this->patchPkgconfPrefix(['glfw3.pc']);
|
||||
}
|
||||
}
|
||||
@ -8,11 +8,11 @@ class icu extends MacOSLibraryBase
|
||||
{
|
||||
public const NAME = 'icu';
|
||||
|
||||
protected function build()
|
||||
protected function build(): void
|
||||
{
|
||||
$root = BUILD_ROOT_PATH;
|
||||
shell()->cd($this->source_dir . '/source')
|
||||
->exec("{$this->builder->configure_env} ./runConfigureICU MacOSX --enable-static --disable-shared --prefix={$root}")
|
||||
->exec("./runConfigureICU MacOSX --enable-static --disable-shared --prefix={$root}")
|
||||
->exec('make clean')
|
||||
->exec("make -j{$this->builder->concurrency}")
|
||||
->exec('make install');
|
||||
|
||||
12
src/SPC/builder/macos/library/ldap.php
Normal file
12
src/SPC/builder/macos/library/ldap.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
class ldap extends MacOSLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\ldap;
|
||||
|
||||
public const NAME = 'ldap';
|
||||
}
|
||||
@ -1,39 +1,30 @@
|
||||
<?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\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
|
||||
class libffi extends MacOSLibraryBase
|
||||
{
|
||||
public const NAME = 'libffi';
|
||||
|
||||
protected function build()
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
protected function build(): void
|
||||
{
|
||||
[$lib, , $destdir] = SEPARATED_PATH;
|
||||
[, , $destdir] = SEPARATED_PATH;
|
||||
shell()->cd($this->source_dir)
|
||||
->exec(
|
||||
"{$this->builder->configure_env} ./configure " .
|
||||
'./configure ' .
|
||||
'--enable-static ' .
|
||||
'--disable-shared ' .
|
||||
"--host={$this->builder->arch}-apple-darwin " .
|
||||
"--target={$this->builder->arch}-apple-darwin " .
|
||||
"--host={$this->builder->getOption('arch')}-apple-darwin " .
|
||||
"--target={$this->builder->getOption('arch')}-apple-darwin " .
|
||||
'--prefix= ' // use prefix=/
|
||||
)
|
||||
->exec('make clean')
|
||||
|
||||
31
src/SPC/builder/macos/library/libmemcached.php
Normal file
31
src/SPC/builder/macos/library/libmemcached.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
/**
|
||||
* gmp is a template library class for unix
|
||||
*/
|
||||
class libmemcached extends MacOSLibraryBase
|
||||
{
|
||||
public const NAME = 'libmemcached';
|
||||
|
||||
public function build(): void
|
||||
{
|
||||
$rootdir = BUILD_ROOT_PATH;
|
||||
|
||||
shell()->cd($this->source_dir)
|
||||
->exec('chmod +x configure')
|
||||
->exec(
|
||||
'./configure ' .
|
||||
'--enable-static --disable-shared ' .
|
||||
'--disable-sasl ' .
|
||||
"--prefix={$rootdir}"
|
||||
)
|
||||
->exec('make clean')
|
||||
->exec('sed -ie "s/-Werror//g" ' . $this->source_dir . '/Makefile')
|
||||
->exec("make -j{$this->builder->concurrency}")
|
||||
->exec('make install');
|
||||
}
|
||||
}
|
||||
@ -22,6 +22,7 @@ namespace SPC\builder\macos\library;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
|
||||
class libpng extends MacOSLibraryBase
|
||||
{
|
||||
@ -30,19 +31,21 @@ class libpng extends MacOSLibraryBase
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
protected function build()
|
||||
protected function build(): void
|
||||
{
|
||||
$optimizations = match ($this->builder->arch) {
|
||||
$optimizations = match ($this->builder->getOption('arch')) {
|
||||
'x86_64' => '--enable-intel-sse ',
|
||||
'arm64' => '--enable-arm-neon ',
|
||||
default => '',
|
||||
};
|
||||
shell()->cd($this->source_dir)
|
||||
->exec('chmod +x ./configure')
|
||||
->exec('chmod +x ./install-sh')
|
||||
->exec(
|
||||
"{$this->builder->configure_env} ./configure " .
|
||||
"--host={$this->builder->gnu_arch}-apple-darwin " .
|
||||
'./configure ' .
|
||||
"--host={$this->builder->getOption('gnu-arch')}-apple-darwin " .
|
||||
'--disable-shared ' .
|
||||
'--enable-static ' .
|
||||
'--enable-hardware-optimizations ' .
|
||||
|
||||
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
@ -13,21 +14,20 @@ class libxml2 extends MacOSLibraryBase
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
protected function build()
|
||||
protected function build(): void
|
||||
{
|
||||
$enable_zlib = $this->builder->getLib('zlib') ? 'ON' : 'OFF';
|
||||
$enable_icu = $this->builder->getLib('icu') ? 'ON' : 'OFF';
|
||||
$enable_xz = $this->builder->getLib('xz') ? 'ON' : 'OFF';
|
||||
|
||||
[$lib, $include, $destdir] = SEPARATED_PATH;
|
||||
|
||||
FileSystem::resetDir($this->source_dir . '/build');
|
||||
shell()->cd($this->source_dir . '/build')
|
||||
->exec(
|
||||
"{$this->builder->configure_env} " . ' cmake ' .
|
||||
'cmake ' .
|
||||
// '--debug-find ' .
|
||||
'-DCMAKE_BUILD_TYPE=Release ' .
|
||||
"{$this->builder->makeCmakeArgs()} " .
|
||||
'-DBUILD_SHARED_LIBS=OFF ' .
|
||||
'-DLIBXML2_WITH_ICONV=ON ' .
|
||||
"-DLIBXML2_WITH_ZLIB={$enable_zlib} " .
|
||||
@ -36,13 +36,9 @@ class libxml2 extends MacOSLibraryBase
|
||||
'-DLIBXML2_WITH_PYTHON=OFF ' .
|
||||
'-DLIBXML2_WITH_PROGRAMS=OFF ' .
|
||||
'-DLIBXML2_WITH_TESTS=OFF ' .
|
||||
'-DCMAKE_INSTALL_PREFIX=/ ' .
|
||||
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
|
||||
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
|
||||
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
||||
'..'
|
||||
)
|
||||
->exec("cmake --build . -j {$this->builder->concurrency}")
|
||||
->exec("make install DESTDIR={$destdir}");
|
||||
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
|
||||
}
|
||||
}
|
||||
|
||||
15
src/SPC/builder/macos/library/libxslt.php
Normal file
15
src/SPC/builder/macos/library/libxslt.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
/**
|
||||
* gmp is a template library class for unix
|
||||
*/
|
||||
class libxslt extends MacOSLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\libxslt;
|
||||
|
||||
public const NAME = 'libxslt';
|
||||
}
|
||||
@ -20,11 +20,18 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
|
||||
class nghttp2 extends MacOSLibraryBase
|
||||
{
|
||||
public const NAME = 'nghttp2';
|
||||
|
||||
protected function build()
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
protected function build(): void
|
||||
{
|
||||
$args = $this->builder->makeAutoconfArgs(static::NAME, [
|
||||
'zlib' => null,
|
||||
@ -46,10 +53,10 @@ class nghttp2 extends MacOSLibraryBase
|
||||
|
||||
shell()->cd($this->source_dir)
|
||||
->exec(
|
||||
"{$this->builder->configure_env} " . ' ./configure ' .
|
||||
'./configure ' .
|
||||
'--enable-static ' .
|
||||
'--disable-shared ' .
|
||||
"--host={$this->builder->gnu_arch}-apple-darwin " .
|
||||
"--host={$this->builder->getOption('gnu-arch')}-apple-darwin " .
|
||||
'--enable-lib-only ' .
|
||||
'--with-boost=no ' .
|
||||
$args . ' ' .
|
||||
|
||||
@ -20,11 +20,20 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
|
||||
class openssl extends MacOSLibraryBase
|
||||
{
|
||||
public const NAME = 'openssl';
|
||||
|
||||
protected function build()
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
protected function build(): void
|
||||
{
|
||||
[$lib,,$destdir] = SEPARATED_PATH;
|
||||
|
||||
@ -39,10 +48,11 @@ class openssl extends MacOSLibraryBase
|
||||
|
||||
shell()->cd($this->source_dir)
|
||||
->exec(
|
||||
"{$this->builder->configure_env} ./Configure no-shared {$extra} " .
|
||||
"./Configure no-shared {$extra} " .
|
||||
'--prefix=/ ' . // use prefix=/
|
||||
"--libdir={$lib} " .
|
||||
" darwin64-{$this->builder->arch}-cc"
|
||||
'--openssldir=/System/Library/OpenSSL ' .
|
||||
"darwin64-{$this->builder->getOption('arch')}-cc"
|
||||
)
|
||||
->exec('make clean')
|
||||
->exec("make -j{$this->builder->concurrency} CNF_EX_LIBS=\"{$ex_lib}\"")
|
||||
|
||||
12
src/SPC/builder/macos/library/postgresql.php
Normal file
12
src/SPC/builder/macos/library/postgresql.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
class postgresql extends MacOSLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\postgresql;
|
||||
|
||||
public const NAME = 'postgresql';
|
||||
}
|
||||
12
src/SPC/builder/macos/library/snappy.php
Normal file
12
src/SPC/builder/macos/library/snappy.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
class snappy extends MacOSLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\snappy;
|
||||
|
||||
public const NAME = 'snappy';
|
||||
}
|
||||
@ -4,6 +4,4 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\traits;
|
||||
|
||||
trait LibraryTrait
|
||||
{
|
||||
}
|
||||
trait LibraryTrait {}
|
||||
|
||||
@ -7,31 +7,24 @@ namespace SPC\builder\traits;
|
||||
use SPC\builder\linux\LinuxBuilder;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
trait UnixBuilderTrait
|
||||
{
|
||||
/** @var string 设置的命令前缀,设置为 set -x 可以在终端打印命令 */
|
||||
public string $set_x = 'set -x';
|
||||
|
||||
/** @var string C 编译器命令 */
|
||||
public string $cc;
|
||||
|
||||
/** @var string C++ 编译器命令 */
|
||||
public string $cxx;
|
||||
|
||||
/** @var string cflags 参数 */
|
||||
/** @var string cflags */
|
||||
public string $arch_c_flags;
|
||||
|
||||
/** @var string C++ flags 参数 */
|
||||
/** @var string C++ flags */
|
||||
public string $arch_cxx_flags;
|
||||
|
||||
/** @var string cmake toolchain file */
|
||||
public string $cmake_toolchain_file;
|
||||
|
||||
/** @var string configure 环境依赖的变量 */
|
||||
public string $configure_env;
|
||||
|
||||
/**
|
||||
* @throws WrongUsageException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function getAllStaticLibFiles(): array
|
||||
{
|
||||
$libs = [];
|
||||
@ -70,14 +63,23 @@ trait UnixBuilderTrait
|
||||
if ($ret !== 0 || trim(implode('', $output)) !== 'hello') {
|
||||
throw new RuntimeException('cli failed sanity check');
|
||||
}
|
||||
|
||||
foreach ($this->exts as $ext) {
|
||||
logger()->debug('testing ext: ' . $ext->getName());
|
||||
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php --ri "' . $ext->getDistName() . '"', false);
|
||||
if ($ret !== 0) {
|
||||
throw new RuntimeException('extension ' . $ext->getName() . ' failed compile check');
|
||||
}
|
||||
|
||||
if (file_exists(ROOT_DIR . '/src/globals/tests/' . $ext->getName() . '.php')) {
|
||||
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php ' . ROOT_DIR . '/src/globals/tests/' . $ext->getName() . '.php');
|
||||
// Trim additional content & escape special characters to allow inline usage
|
||||
$test = str_replace(
|
||||
['<?php', 'declare(strict_types=1);', "\n", '"', '$'],
|
||||
['', '', '', '\"', '\$'],
|
||||
file_get_contents(ROOT_DIR . '/src/globals/tests/' . $ext->getName() . '.php')
|
||||
);
|
||||
|
||||
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -r "' . trim($test) . '"');
|
||||
if ($ret !== 0) {
|
||||
throw new RuntimeException('extension ' . $ext->getName() . ' failed sanity check');
|
||||
}
|
||||
@ -125,7 +127,7 @@ trait UnixBuilderTrait
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理编译好的文件
|
||||
* Run php clean
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
@ -140,12 +142,35 @@ trait UnixBuilderTrait
|
||||
*/
|
||||
public function makeCmakeArgs(): string
|
||||
{
|
||||
[$lib, $include] = SEPARATED_PATH;
|
||||
$extra = $this instanceof LinuxBuilder ? '-DCMAKE_C_COMPILER=' . $this->cc . ' ' : '';
|
||||
return $extra . '-DCMAKE_BUILD_TYPE=Release ' .
|
||||
$extra = $this instanceof LinuxBuilder ? '-DCMAKE_C_COMPILER=' . getenv('CC') . ' ' : '';
|
||||
return $extra .
|
||||
'-DCMAKE_BUILD_TYPE=Release ' .
|
||||
'-DCMAKE_INSTALL_PREFIX=/ ' .
|
||||
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
|
||||
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
|
||||
'-DCMAKE_INSTALL_BINDIR=/bin ' .
|
||||
'-DCMAKE_INSTALL_LIBDIR=/lib ' .
|
||||
'-DCMAKE_INSTALL_INCLUDEDIR=/include ' .
|
||||
"-DCMAKE_TOOLCHAIN_FILE={$this->cmake_toolchain_file}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate configure flags
|
||||
*/
|
||||
public function makeAutoconfFlags(int $flag = AUTOCONF_ALL): string
|
||||
{
|
||||
$extra = '';
|
||||
// TODO: add auto pkg-config support
|
||||
if (($flag & AUTOCONF_LIBS) === AUTOCONF_LIBS) {
|
||||
$extra .= 'LIBS="' . BUILD_LIB_PATH . '" ';
|
||||
}
|
||||
if (($flag & AUTOCONF_CFLAGS) === AUTOCONF_CFLAGS) {
|
||||
$extra .= 'CFLAGS="-I' . BUILD_INCLUDE_PATH . '" ';
|
||||
}
|
||||
if (($flag & AUTOCONF_CPPFLAGS) === AUTOCONF_CPPFLAGS) {
|
||||
$extra .= 'CPPFLAGS="-I' . BUILD_INCLUDE_PATH . '" ';
|
||||
}
|
||||
if (($flag & AUTOCONF_LDFLAGS) === AUTOCONF_LDFLAGS) {
|
||||
$extra .= 'LDFLAGS="-L' . BUILD_LIB_PATH . '" ';
|
||||
}
|
||||
return $extra;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ namespace SPC\builder\traits;
|
||||
use SPC\builder\LibraryBase;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
trait UnixLibraryTrait
|
||||
@ -16,6 +17,7 @@ trait UnixLibraryTrait
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function getStaticLibFiles(string $style = 'autoconf', bool $recursive = true): string
|
||||
{
|
||||
@ -43,6 +45,11 @@ trait UnixLibraryTrait
|
||||
return implode($sep, $ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function makeAutoconfEnv(string $prefix = null): string
|
||||
{
|
||||
if ($prefix === null) {
|
||||
@ -59,7 +66,7 @@ trait UnixLibraryTrait
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function patchPkgconfPrefix(array $files, int $patch_option = PKGCONF_PATCH_ALL): void
|
||||
public function patchPkgconfPrefix(array $files, int $patch_option = PKGCONF_PATCH_ALL, ?array $custom_replace = null): void
|
||||
{
|
||||
logger()->info('Patching library [' . static::NAME . '] pkgconfig');
|
||||
foreach ($files as $name) {
|
||||
@ -74,6 +81,7 @@ trait UnixLibraryTrait
|
||||
$file = ($patch_option & PKGCONF_PATCH_EXEC_PREFIX) === PKGCONF_PATCH_EXEC_PREFIX ? preg_replace('/^exec_prefix=.*$/m', 'exec_prefix=${prefix}', $file) : $file;
|
||||
$file = ($patch_option & PKGCONF_PATCH_LIBDIR) === PKGCONF_PATCH_LIBDIR ? preg_replace('/^libdir=.*$/m', 'libdir=${prefix}/lib', $file) : $file;
|
||||
$file = ($patch_option & PKGCONF_PATCH_INCLUDEDIR) === PKGCONF_PATCH_INCLUDEDIR ? preg_replace('/^includedir=.*$/m', 'includedir=${prefix}/include', $file) : $file;
|
||||
$file = ($patch_option & PKGCONF_PATCH_CUSTOM) === PKGCONF_PATCH_CUSTOM && $custom_replace !== null ? preg_replace($custom_replace[0], $custom_replace[1], $file) : $file;
|
||||
FileSystem::writeFile($realpath, $file);
|
||||
}
|
||||
}
|
||||
@ -82,7 +90,7 @@ trait UnixLibraryTrait
|
||||
* remove libtool archive files
|
||||
*
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function cleanLaFiles(): void
|
||||
{
|
||||
|
||||
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\traits;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
/**
|
||||
@ -14,11 +15,12 @@ trait UnixSystemUtilTrait
|
||||
/**
|
||||
* 生成 toolchain.cmake,用于 cmake 构建
|
||||
*
|
||||
* @param string $os 操作系统代号
|
||||
* @param string $target_arch 目标架构
|
||||
* @param string $cflags CFLAGS 参数
|
||||
* @param null|string $cc CC 参数(默认空)
|
||||
* @param null|string $cxx CXX 参数(默认空)
|
||||
* @param string $os 操作系统代号
|
||||
* @param string $target_arch 目标架构
|
||||
* @param string $cflags CFLAGS 参数
|
||||
* @param null|string $cc CC 参数(默认空)
|
||||
* @param null|string $cxx CXX 参数(默认空)
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public static function makeCmakeToolchainFile(
|
||||
string $os,
|
||||
@ -76,4 +78,20 @@ CMAKE;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $vars Variables, like: ["CFLAGS" => "-Ixxx"]
|
||||
* @return string like: CFLAGS="-Ixxx"
|
||||
*/
|
||||
public static function makeEnvVarString(array $vars): string
|
||||
{
|
||||
$str = '';
|
||||
foreach ($vars as $key => $value) {
|
||||
if ($str !== '') {
|
||||
$str .= ' ';
|
||||
}
|
||||
$str .= $key . '=' . escapeshellarg($value);
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,16 +4,22 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
trait brotli
|
||||
{
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
protected function build(): void
|
||||
{
|
||||
FileSystem::resetDir($this->source_dir . '/build-dir');
|
||||
shell()->cd($this->source_dir . '/build-dir')
|
||||
->exec(
|
||||
$this->builder->configure_env . ' cmake ' .
|
||||
'cmake ' .
|
||||
"{$this->builder->makeCmakeArgs()} " .
|
||||
'-DBUILD_SHARED_LIBS=OFF ' .
|
||||
'..'
|
||||
@ -22,9 +28,9 @@ trait brotli
|
||||
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
|
||||
$this->patchPkgconfPrefix(['libbrotlicommon.pc', 'libbrotlidec.pc', 'libbrotlienc.pc']);
|
||||
shell()->cd(BUILD_ROOT_PATH . '/lib')
|
||||
->exec('ln -s libbrotlicommon-static.a libbrotlicommon.a')
|
||||
->exec('ln -s libbrotlidec-static.a libbrotlidec.a')
|
||||
->exec('ln -s libbrotlienc-static.a libbrotlienc.a');
|
||||
->exec('ln -s libbrotlicommon.a libbrotlicommon-static.a')
|
||||
->exec('ln -s libbrotlidec.a libbrotlidec-static.a')
|
||||
->exec('ln -s libbrotlienc.a libbrotlienc-static.a');
|
||||
foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) {
|
||||
if (str_starts_with($filename, 'libbrotli') && (str_contains($filename, '.so') || str_ends_with($filename, '.dylib'))) {
|
||||
unlink(BUILD_ROOT_PATH . '/lib/' . $filename);
|
||||
|
||||
@ -9,8 +9,8 @@ trait bzip2
|
||||
protected function build(): void
|
||||
{
|
||||
shell()->cd($this->source_dir)
|
||||
->exec("make {$this->builder->configure_env} PREFIX='" . BUILD_ROOT_PATH . "' clean")
|
||||
->exec("make -j{$this->builder->concurrency} {$this->builder->configure_env} PREFIX='" . BUILD_ROOT_PATH . "' libbz2.a")
|
||||
->exec("make PREFIX='" . BUILD_ROOT_PATH . "' clean")
|
||||
->exec("make -j{$this->builder->concurrency} {$this->builder->getEnvString()} PREFIX='" . BUILD_ROOT_PATH . "' libbz2.a")
|
||||
->exec('cp libbz2.a ' . BUILD_LIB_PATH)
|
||||
->exec('cp bzlib.h ' . BUILD_INCLUDE_PATH);
|
||||
}
|
||||
|
||||
@ -4,11 +4,17 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
trait curl
|
||||
{
|
||||
protected function build()
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
protected function build(): void
|
||||
{
|
||||
$extra = '';
|
||||
// lib:openssl
|
||||
@ -33,8 +39,8 @@ trait curl
|
||||
} else {
|
||||
$extra .= '-DUSE_NGHTTP2=OFF ';
|
||||
}
|
||||
// TODO: ldap is not supported yet
|
||||
$extra .= '-DCURL_DISABLE_LDAP=ON ';
|
||||
// lib:ldap
|
||||
$extra .= $this->builder->getLib('ldap') ? '-DCURL_DISABLE_LDAP=OFF ' : '-DCURL_DISABLE_LDAP=ON ';
|
||||
// lib:zstd
|
||||
$extra .= $this->builder->getLib('zstd') ? '-DCURL_ZSTD=ON ' : '-DCURL_ZSTD=OFF ';
|
||||
// lib:idn2
|
||||
@ -45,7 +51,8 @@ trait curl
|
||||
FileSystem::resetDir($this->source_dir . '/build');
|
||||
// compile!
|
||||
shell()->cd($this->source_dir . '/build')
|
||||
->exec("{$this->builder->configure_env} cmake {$this->builder->makeCmakeArgs()} -DBUILD_SHARED_LIBS=OFF -DBUILD_CURL_EXE=OFF {$extra} ..")
|
||||
->exec('sed -i.save s@\${CMAKE_C_IMPLICIT_LINK_LIBRARIES}@@ ../CMakeLists.txt')
|
||||
->exec("cmake {$this->builder->makeCmakeArgs()} -DBUILD_SHARED_LIBS=OFF -DBUILD_CURL_EXE=OFF {$extra} ..")
|
||||
->exec("make -j{$this->builder->concurrency}")
|
||||
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
|
||||
// patch pkgconf
|
||||
|
||||
@ -4,11 +4,19 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
trait freetype
|
||||
{
|
||||
protected function build()
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
protected function build(): void
|
||||
{
|
||||
$suggested = $this->builder->getLib('libpng') ? '--with-png' : '--without-png';
|
||||
$suggested .= ' ';
|
||||
@ -19,7 +27,7 @@ trait freetype
|
||||
|
||||
shell()->cd($this->source_dir)
|
||||
->exec(
|
||||
"{$this->builder->configure_env} ./configure " .
|
||||
'./configure ' .
|
||||
'--enable-static --disable-shared --without-harfbuzz --prefix= ' .
|
||||
$suggested
|
||||
)
|
||||
@ -27,9 +35,8 @@ trait freetype
|
||||
->exec("make -j{$this->builder->concurrency}")
|
||||
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
|
||||
$this->patchPkgconfPrefix(['freetype2.pc']);
|
||||
FileSystem::replaceFile(
|
||||
FileSystem::replaceFileStr(
|
||||
BUILD_ROOT_PATH . '/lib/pkgconfig/freetype2.pc',
|
||||
REPLACE_FILE_STR,
|
||||
' -L/lib ',
|
||||
' -L' . BUILD_ROOT_PATH . '/lib '
|
||||
);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user