mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-02 22:35:43 +08:00
Compare commits
39 Commits
2.1.0-beta
...
2.1.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9664709f21 | ||
|
|
b46655ecfe | ||
|
|
842e0add29 | ||
|
|
254764761d | ||
|
|
5f6c1a0f40 | ||
|
|
d5dcd193cf | ||
|
|
5012da96be | ||
|
|
df0e37cd0f | ||
|
|
4ab7b6bfdc | ||
|
|
f498250001 | ||
|
|
3945ac037b | ||
|
|
b0d8b00fcc | ||
|
|
62b0bf8af0 | ||
|
|
905e080770 | ||
|
|
097ecd3fb0 | ||
|
|
b9359759dd | ||
|
|
50fe366c42 | ||
|
|
9dd89e6b02 | ||
|
|
c03220d1ee | ||
|
|
9db843ab66 | ||
|
|
304973d9bc | ||
|
|
ab386f820c | ||
|
|
4adf1f5e2e | ||
|
|
b4ae87585c | ||
|
|
ae3298472d | ||
|
|
d241cb993e | ||
|
|
8376122634 | ||
|
|
a30e054d7d | ||
|
|
78f4317660 | ||
|
|
3ac3dab6c8 | ||
|
|
1a7e436ee1 | ||
|
|
f11b36ab3c | ||
|
|
e2ef195a84 | ||
|
|
faed569e8a | ||
|
|
49ddb3ec13 | ||
|
|
71c0387ab0 | ||
|
|
e5d2d5e689 | ||
|
|
227bf73870 | ||
|
|
05e3898e7a |
6
.github/workflows/release-build.yml
vendored
6
.github/workflows/release-build.yml
vendored
@@ -70,10 +70,10 @@ jobs:
|
||||
|
||||
- name: "Generate Executable"
|
||||
run: |
|
||||
bin/spc micro:combine spc.phar -M micro.sfx -O spc -I "memory_limit=2G"
|
||||
if [ "${{ matrix.operating-system }}" = "windows-x64" ]; then
|
||||
cat micro.sfx spc.phar > spc.exe
|
||||
mv spc spc.exe
|
||||
else
|
||||
cat micro.sfx spc.phar > spc
|
||||
chmod +x spc
|
||||
fi
|
||||
|
||||
@@ -104,7 +104,7 @@ jobs:
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: ${{startsWith(github.ref, 'refs/tags/') }}
|
||||
with:
|
||||
files: ${{ env.filename }}
|
||||
files: dist/${{ env.filename }}
|
||||
|
||||
- name: "Deploy to Self-Hosted Server"
|
||||
if: github.repository == 'crazywhalecc/static-php-cli'
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -16,6 +16,9 @@ docker/source/
|
||||
# default source build root directory
|
||||
/buildroot/
|
||||
|
||||
# default package root directory
|
||||
/pkgroot/
|
||||
|
||||
# tools cache files
|
||||
.php-cs-fixer.cache
|
||||
.phpunit.result.cache
|
||||
|
||||
49
README-zh.md
49
README-zh.md
@@ -20,11 +20,12 @@ static-php-cli(简称 `spc`)有许多特性:
|
||||
- :handbag: 构建独立的单文件 PHP 解释器,无需任何依赖
|
||||
- :hamburger: 构建 **[phpmicro](https://github.com/dixyes/phpmicro)** 自执行二进制(将 PHP 代码和 PHP 解释器打包为一个文件)
|
||||
- :pill: 提供一键检查和修复编译环境的 Doctor 模块
|
||||
- :zap: 支持多个系统:`Linux`、`macOS`、`FreeBSD`、[`Windows (WIP)`](https://github.com/crazywhalecc/static-php-cli/pull/301)
|
||||
- :zap: 支持多个系统:`Linux`、`macOS`、`FreeBSD`、`Windows`
|
||||
- :wrench: 高度自定义的代码 patch 功能
|
||||
- :books: 自带编译依赖管理
|
||||
- 📦 提供由自身编译的独立 `spc` 二进制(使用 spc 和 [box](https://github.com/box-project/box) 构建)
|
||||
- :fire: 支持大量 [扩展](https://static-php.dev/zh/guide/extensions.html)
|
||||
- :floppy_disk: 整合 UPX 工具(减小二进制文件体积)
|
||||
|
||||
**静态 php-cli:**
|
||||
|
||||
@@ -46,16 +47,18 @@ static-php-cli(简称 `spc`)有许多特性:
|
||||
- [扩展组合 - bulk](https://dl.static-php.dev/static-php-cli/bulk/):bulk 组合包含了 [50+](https://dl.static-php.dev/static-php-cli/bulk/README.txt) 个扩展,体积为 70MB 左右。
|
||||
- [扩展组合 - minimal](https://dl.static-php.dev/static-php-cli/minimal/):minimal 组合包含了 [5](https://dl.static-php.dev/static-php-cli/minimal/README.txt) 个扩展,体积为 6MB 左右。
|
||||
|
||||
对于 Windows 系统,目前支持的扩展较少,故仅提供 SPC 自身运行的最小扩展组合的 `cli` 和 `micro`:[扩展组合 - spc-min](https://dl.static-php.dev/static-php-cli/windows/spc-min/)。
|
||||
|
||||
## 使用 static-php-cli 构建 PHP
|
||||
|
||||
### 编译环境需求
|
||||
|
||||
- PHP >= 8.1(这是 spc 自身需要的版本,不是支持的构建版本)
|
||||
- 扩展:`mbstring,pcntl,posix,tokenizer,phar`
|
||||
- 扩展:`mbstring,tokenizer,phar`
|
||||
- 系统安装了 `curl` 和 `git`
|
||||
|
||||
是的,本项目采用 PHP 编写,编译前需要一个 PHP 环境,比较滑稽。
|
||||
但本项目默认可通过自身构建的 micro 和 static-php 二进制运行,其他只需要包含 mbstring、pcntl 扩展和 PHP 版本大于等于 8.1 即可。
|
||||
但本项目默认可通过自身构建的 micro 和 static-php 二进制运行,其他只需要包含上面提到的扩展和 PHP 版本大于等于 8.1 即可。
|
||||
|
||||
下面是架构支持情况,:octocat: 代表支持 GitHub Action 构建,:computer: 代表支持本地构建,空 代表暂不支持。
|
||||
|
||||
@@ -63,10 +66,26 @@ static-php-cli(简称 `spc`)有许多特性:
|
||||
|---------|----------------------|----------------------|
|
||||
| macOS | :octocat: :computer: | :octocat: :computer: |
|
||||
| Linux | :octocat: :computer: | :octocat: :computer: |
|
||||
| Windows | | |
|
||||
| Windows | :computer: | |
|
||||
| FreeBSD | :computer: | :computer: |
|
||||
|
||||
目前支持编译的 PHP 版本为:`7.3`,`7.4`,`8.0`,`8.1`,`8.2`,`8.3`。
|
||||
当前支持编译的 PHP 版本:
|
||||
|
||||
> :warning: 支持,但可能不再提供修复
|
||||
>
|
||||
> :heavy_check_mark: 支持
|
||||
>
|
||||
> :x: 不支持
|
||||
|
||||
| PHP Version | Status | Comment |
|
||||
|-------------|--------------------|------------------------------|
|
||||
| 7.2 | :x: | |
|
||||
| 7.3 | :warning: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
|
||||
| 7.4 | :warning: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
|
||||
| 8.0 | :heavy_check_mark: | PHP 官方已停止 8.0 的维护 |
|
||||
| 8.1 | :heavy_check_mark: | |
|
||||
| 8.2 | :heavy_check_mark: | |
|
||||
| 8.3 | :heavy_check_mark: | |
|
||||
|
||||
### 支持的扩展
|
||||
|
||||
@@ -106,10 +125,16 @@ curl -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-a
|
||||
curl -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-x86_64
|
||||
# macOS aarch64 (Apple)
|
||||
curl -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-aarch64
|
||||
# Windows (x86_64, win10 build 17063 or later)
|
||||
curl.exe -o spc.exe https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe
|
||||
|
||||
# add x perm
|
||||
# Add execute perm (Linux and macOS only)
|
||||
chmod +x ./spc
|
||||
|
||||
# Run (Linux and macOS)
|
||||
./spc --version
|
||||
# Run (Windows powershell)
|
||||
.\spc.exe --version
|
||||
```
|
||||
|
||||
自托管 `spc` 由 GitHub Actions 构建,你也可以从 Actions 直接下载:[此处](https://github.com/crazywhalecc/static-php-cli/actions/workflows/release-build.yml)。
|
||||
@@ -148,14 +173,16 @@ bin/spc --version
|
||||
# 拉取所有依赖库
|
||||
./bin/spc download --all
|
||||
# 只拉取编译指定扩展需要的所有依赖(推荐)
|
||||
./bin/spc download --for-extensions=openssl,pcntl,mbstring,pdo_sqlite
|
||||
./bin/spc download --for-extensions="openssl,pcntl,mbstring,pdo_sqlite"
|
||||
# 下载编译不同版本的 PHP (--with-php=x.y,推荐 7.3 ~ 8.3)
|
||||
./bin/spc download --for-extensions=openssl,curl,mbstring --with-php=8.1
|
||||
./bin/spc download --for-extensions="openssl,curl,mbstring" --with-php=8.1
|
||||
|
||||
# 构建包含 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
|
||||
# 编译线程安全版本 (--enable-zts)
|
||||
./bin/spc build curl,phar --enable-zts --build-cli
|
||||
./bin/spc build "curl,phar" --enable-zts --build-cli
|
||||
# 编译后使用 UPX 减小可执行文件体积 (--with-upx-pack) (至少压缩至原来的 30~50%)
|
||||
./bin/spc build "curl,phar" --enable-zts --build-cli --with-upx-pack
|
||||
```
|
||||
|
||||
其中,目前支持构建 cli,micro,fpm 和 embed,使用以下参数的一个或多个来指定编译的 SAPI:
|
||||
@@ -169,7 +196,7 @@ bin/spc --version
|
||||
如果出现了任何错误,可以使用 `--debug` 参数来展示完整的输出日志,以供排查错误:
|
||||
|
||||
```bash
|
||||
./bin/spc build openssl,pcntl,mbstring --debug --build-all
|
||||
./bin/spc build "openssl,pcntl,mbstring" --debug --build-all
|
||||
./bin/spc download --all --debug
|
||||
```
|
||||
|
||||
@@ -248,7 +275,7 @@ bin/spc micro:combine my-app.phar -I "memory_limit=4G" -I "disable_functions=sys
|
||||
|
||||
## 赞助本项目
|
||||
|
||||
你可以在 [我的个人赞助页](https://github.com/crazywhalecc/crazywhalecc/blob/master/FUNDING.md) 支持我和我的项目。
|
||||
你可以在 [我的个人赞助页](https://github.com/crazywhalecc/crazywhalecc/blob/master/FUNDING.md) 支持我和我的项目。你捐赠的一部分将会被用于维护 **static-php.dev** 服务器。
|
||||
|
||||
## 开源协议
|
||||
|
||||
|
||||
56
README.md
56
README.md
@@ -27,6 +27,7 @@ static-php-cli (you can call it `spc`) has a lot of features:
|
||||
- :books: Build dependency management
|
||||
- 📦 Provide `spc` own standalone executable (built by spc and [box](https://github.com/box-project/box))
|
||||
- :fire: Support many popular [extensions](https://static-php.dev/en/guide/extensions.html)
|
||||
- :floppy_disk: UPX integration (significantly reduces binary size)
|
||||
|
||||
**Single-file standalone php-cli:**
|
||||
|
||||
@@ -52,16 +53,19 @@ which can be downloaded directly according to your needs.
|
||||
- [Extension-Combination - bulk](https://dl.static-php.dev/static-php-cli/bulk/): `bulk` contains [50+](https://dl.static-php.dev/static-php-cli/bulk/README.txt) extensions and is about 70MB in size.
|
||||
- [Extension-Combination - minimal](https://dl.static-php.dev/static-php-cli/minimal/): `minimal` contains [5](https://dl.static-php.dev/static-php-cli/minimal/README.txt) extensions and is about 6MB in size.
|
||||
|
||||
For Windows systems, there are currently fewer extensions supported,
|
||||
so only `cli` and `micro` that run the minimum extension combination of SPC itself are provided: [Extension-Combination - spc-min](https://dl.static-php.dev/static-php-cli/windows/spc-min/).
|
||||
|
||||
## Build
|
||||
|
||||
### Compilation Requirements
|
||||
|
||||
- PHP >= 8.1 (This is the version required by spc itself, not the build version)
|
||||
- Extension: `mbstring,pcntl,posix,tokenizer,phar`
|
||||
- Supported OS with `curl` and `git` installed
|
||||
|
||||
You can say I made a PHP builder written in PHP, pretty funny.
|
||||
But static-php-cli runtime only requires an environment above PHP 8.1 and `mbstring`, `pcntl` extension.
|
||||
But static-php-cli runtime only requires an environment above PHP 8.1 and extensions mentioned below.
|
||||
|
||||
- PHP >= 8.1 (This is the version required by spc itself, not the build version)
|
||||
- Extension: `mbstring,tokenizer,phar`
|
||||
- Supported OS with `curl` and `git` installed
|
||||
|
||||
Here is the supported OS and arch, where :octocat: represents support for GitHub Action builds,
|
||||
:computer: represents support for local manual builds, and blank represents not currently supported.
|
||||
@@ -73,7 +77,23 @@ Here is the supported OS and arch, where :octocat: represents support for GitHub
|
||||
| Windows | :computer: | |
|
||||
| FreeBSD | :computer: | :computer: |
|
||||
|
||||
Currently supported PHP versions for compilation are: `7.3`, `7.4`, `8.0`, `8.1`, `8.2`, `8.3`.
|
||||
Currently supported PHP versions for compilation:
|
||||
|
||||
> :warning: supported but not maintained
|
||||
>
|
||||
> :heavy_check_mark: supported
|
||||
>
|
||||
> :x: not supported
|
||||
|
||||
| PHP Version | Status | Comment |
|
||||
|-------------|--------------------|---------------------------------------------------|
|
||||
| 7.2 | :x: | |
|
||||
| 7.3 | :warning: | phpmicro and some extensions not supported on 7.x |
|
||||
| 7.4 | :warning: | phpmicro and some extensions not supported on 7.x |
|
||||
| 8.0 | :heavy_check_mark: | PHP official has stopped maintenance of 8.0 |
|
||||
| 8.1 | :heavy_check_mark: | |
|
||||
| 8.2 | :heavy_check_mark: | |
|
||||
| 8.3 | :heavy_check_mark: | |
|
||||
|
||||
### Supported Extensions
|
||||
|
||||
@@ -116,10 +136,16 @@ curl -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-a
|
||||
curl -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-x86_64
|
||||
# macOS aarch64 (Apple)
|
||||
curl -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-aarch64
|
||||
# Windows (x86_64, win10 build 17063 or later)
|
||||
curl.exe -o spc.exe https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe
|
||||
|
||||
# add x perm
|
||||
# Add execute perm (Linux and macOS only)
|
||||
chmod +x ./spc
|
||||
|
||||
# Run (Linux and macOS)
|
||||
./spc --version
|
||||
# Run (Windows powershell)
|
||||
.\spc.exe --version
|
||||
```
|
||||
|
||||
Self-hosted `spc` is built by GitHub Actions, you can also download from Actions artifacts [here](https://github.com/crazywhalecc/static-php-cli/actions/workflows/release-build.yml).
|
||||
@@ -149,7 +175,7 @@ bin/spc --version
|
||||
|
||||
Basic usage for building php with some extensions:
|
||||
|
||||
> If you are using the packaged `spc` binary, you need to replace `bin/spc` with `./spc` in the following commands.
|
||||
> If you are using the packaged standalone `spc` binary, you need to replace `bin/spc` with `./spc` or `.\spc.exe` in the following commands.
|
||||
|
||||
```bash
|
||||
# Check system tool dependencies, auto-fix them if possible
|
||||
@@ -158,14 +184,16 @@ Basic usage for building php with some extensions:
|
||||
# fetch all libraries
|
||||
./bin/spc download --all
|
||||
# only fetch necessary sources by needed extensions (recommended)
|
||||
./bin/spc download --for-extensions=openssl,pcntl,mbstring,pdo_sqlite
|
||||
./bin/spc download --for-extensions="openssl,pcntl,mbstring,pdo_sqlite"
|
||||
# download different PHP version (--with-php=x.y, recommend 7.3 ~ 8.3)
|
||||
./bin/spc download --for-extensions=openssl,curl,mbstring --with-php=8.1
|
||||
./bin/spc download --for-extensions="openssl,curl,mbstring" --with-php=8.1
|
||||
|
||||
# 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
|
||||
./bin/spc build "bcmath,openssl,tokenizer,sqlite3,pdo_sqlite,ftp,curl" --build-cli --build-micro
|
||||
# build thread-safe (ZTS) version (--enable-zts)
|
||||
./bin/spc build curl,phar --enable-zts --build-cli
|
||||
./bin/spc build "curl,phar" --enable-zts --build-cli
|
||||
# build, pack executable with UPX (--with-upx-pack) (reduce binary size for 30~50%)
|
||||
./bin/spc build "curl,phar" --enable-zts --build-cli --with-upx-pack
|
||||
```
|
||||
|
||||
Now we support `cli`, `micro`, `fpm` and `embed` SAPI. You can use one or more of the following parameters to specify the compiled SAPI:
|
||||
@@ -179,7 +207,7 @@ Now we support `cli`, `micro`, `fpm` and `embed` SAPI. You can use one or more o
|
||||
If anything goes wrong, use `--debug` option to display full terminal output:
|
||||
|
||||
```bash
|
||||
./bin/spc build openssl,pcntl,mbstring --debug --build-all
|
||||
./bin/spc build "openssl,pcntl,mbstring" --debug --build-all
|
||||
./bin/spc download --all --debug
|
||||
```
|
||||
|
||||
@@ -272,7 +300,7 @@ Now there is a [static-php](https://github.com/static-php) organization, which i
|
||||
|
||||
## Sponsor this project
|
||||
|
||||
You can sponsor my project on [this page](https://github.com/crazywhalecc/crazywhalecc/blob/master/FUNDING.md).
|
||||
You can sponsor my project on [this page](https://github.com/crazywhalecc/crazywhalecc/blob/master/FUNDING.md). A portion of your donation will be used to maintain the **static-php.dev** server.
|
||||
|
||||
## Open-Source License
|
||||
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
"arg-type": "with",
|
||||
"lib-depends": [
|
||||
"curl"
|
||||
],
|
||||
"ext-depends-windows": [
|
||||
"zlib",
|
||||
"openssl"
|
||||
]
|
||||
},
|
||||
"dba": {
|
||||
@@ -59,8 +63,11 @@
|
||||
"ffi": {
|
||||
"arg-type": "custom",
|
||||
"type": "builtin",
|
||||
"lib-depends": [
|
||||
"lib-depends-unix": [
|
||||
"libffi"
|
||||
],
|
||||
"lib-depends-windows": [
|
||||
"libffi-win"
|
||||
]
|
||||
},
|
||||
"fileinfo": {
|
||||
@@ -93,6 +100,13 @@
|
||||
"freetype"
|
||||
]
|
||||
},
|
||||
"gettext": {
|
||||
"type": "builtin",
|
||||
"arg-type": "with-prefix",
|
||||
"lib-depends": [
|
||||
"gettext"
|
||||
]
|
||||
},
|
||||
"glfw": {
|
||||
"type": "external",
|
||||
"arg-type": "custom",
|
||||
@@ -112,8 +126,12 @@
|
||||
"iconv": {
|
||||
"type": "builtin",
|
||||
"arg-type": "with-prefix",
|
||||
"lib-depends": [
|
||||
"arg-type-windows": "with",
|
||||
"lib-depends-unix": [
|
||||
"libiconv"
|
||||
],
|
||||
"lib-depends-windows": [
|
||||
"libiconv-win"
|
||||
]
|
||||
},
|
||||
"igbinary": {
|
||||
@@ -340,9 +358,11 @@
|
||||
"simplexml": {
|
||||
"type": "builtin",
|
||||
"arg-type": "custom",
|
||||
"arg-type-windows": "with",
|
||||
"lib-depends": [
|
||||
"libxml2"
|
||||
],
|
||||
"ext-depends-windows": [
|
||||
"xml"
|
||||
]
|
||||
},
|
||||
"snappy": {
|
||||
@@ -362,6 +382,9 @@
|
||||
"arg-type": "custom",
|
||||
"lib-depends": [
|
||||
"libxml2"
|
||||
],
|
||||
"ext-depends-windows": [
|
||||
"xml"
|
||||
]
|
||||
},
|
||||
"sockets": {
|
||||
@@ -377,6 +400,7 @@
|
||||
"sqlite3": {
|
||||
"type": "builtin",
|
||||
"arg-type": "with-prefix",
|
||||
"arg-type-windows": "with",
|
||||
"lib-depends": [
|
||||
"sqlite"
|
||||
]
|
||||
@@ -396,8 +420,13 @@
|
||||
"type": "external",
|
||||
"source": "ext-ssh2",
|
||||
"arg-type": "with-prefix",
|
||||
"arg-type-windows": "with",
|
||||
"lib-depends": [
|
||||
"libssh2"
|
||||
],
|
||||
"ext-depends-windows": [
|
||||
"openssl",
|
||||
"zlib"
|
||||
]
|
||||
},
|
||||
"swoole": {
|
||||
@@ -472,8 +501,7 @@
|
||||
"unix-only": true
|
||||
},
|
||||
"sysvshm": {
|
||||
"type": "builtin",
|
||||
"unix-only": true
|
||||
"type": "builtin"
|
||||
},
|
||||
"tidy": {
|
||||
"type": "builtin",
|
||||
@@ -518,6 +546,9 @@
|
||||
"arg-type-windows": "with",
|
||||
"lib-depends": [
|
||||
"libxml2"
|
||||
],
|
||||
"ext-depends-windows": [
|
||||
"iconv"
|
||||
]
|
||||
},
|
||||
"xmlreader": {
|
||||
@@ -525,6 +556,10 @@
|
||||
"arg-type": "custom",
|
||||
"lib-depends": [
|
||||
"libxml2"
|
||||
],
|
||||
"ext-depends-windows": [
|
||||
"xml",
|
||||
"dom"
|
||||
]
|
||||
},
|
||||
"xmlwriter": {
|
||||
@@ -532,6 +567,9 @@
|
||||
"arg-type": "custom",
|
||||
"lib-depends": [
|
||||
"libxml2"
|
||||
],
|
||||
"ext-depends-windows": [
|
||||
"xml"
|
||||
]
|
||||
},
|
||||
"xsl": {
|
||||
|
||||
@@ -45,19 +45,21 @@
|
||||
"openssl",
|
||||
"zlib"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"lib-depends-windows": [
|
||||
"openssl",
|
||||
"zlib",
|
||||
"libssh2",
|
||||
"nghttp2"
|
||||
],
|
||||
"lib-suggests-unix": [
|
||||
"libssh2",
|
||||
"brotli",
|
||||
"nghttp2",
|
||||
"zstd"
|
||||
],
|
||||
"lib-suggests-windows": [
|
||||
"zlib",
|
||||
"libssh2",
|
||||
"brotli",
|
||||
"nghttp2",
|
||||
"zstd",
|
||||
"openssl"
|
||||
"zstd"
|
||||
],
|
||||
"frameworks": [
|
||||
"CoreFoundation",
|
||||
@@ -83,6 +85,22 @@
|
||||
"brotli"
|
||||
]
|
||||
},
|
||||
"gettext": {
|
||||
"source": "gettext",
|
||||
"static-libs-unix": [
|
||||
"libintl.a"
|
||||
],
|
||||
"lib-depends": [
|
||||
"libiconv"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"ncurses",
|
||||
"libxml2"
|
||||
],
|
||||
"frameworks": [
|
||||
"CoreFoundation"
|
||||
]
|
||||
},
|
||||
"glfw": {
|
||||
"source": "ext-glfw",
|
||||
"static-libs-unix": [
|
||||
@@ -129,7 +147,8 @@
|
||||
"libpng",
|
||||
"libjpeg",
|
||||
"libwebp",
|
||||
"freetype"
|
||||
"freetype",
|
||||
"libtiff"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"zstd",
|
||||
@@ -215,6 +234,17 @@
|
||||
"ffitarget.h"
|
||||
]
|
||||
},
|
||||
"libffi-win": {
|
||||
"source": "libffi-win",
|
||||
"static-libs-windows": [
|
||||
"libffi.lib"
|
||||
],
|
||||
"headers-windows": [
|
||||
"ffi.h",
|
||||
"ffitarget.h",
|
||||
"fficonfig.h"
|
||||
]
|
||||
},
|
||||
"libiconv": {
|
||||
"source": "libiconv",
|
||||
"static-libs-unix": [
|
||||
@@ -227,6 +257,13 @@
|
||||
"localcharset.h"
|
||||
]
|
||||
},
|
||||
"libiconv-win": {
|
||||
"source": "libiconv-win",
|
||||
"static-libs-windows": [
|
||||
"libiconv.lib",
|
||||
"libiconv_a.lib"
|
||||
]
|
||||
},
|
||||
"libjpeg": {
|
||||
"source": "libjpeg",
|
||||
"static-libs-unix": [
|
||||
@@ -294,6 +331,12 @@
|
||||
"zlib"
|
||||
]
|
||||
},
|
||||
"libtiff": {
|
||||
"source": "libtiff",
|
||||
"static-libs-unix": [
|
||||
"libtiff.a"
|
||||
]
|
||||
},
|
||||
"libuv": {
|
||||
"source": "libuv",
|
||||
"static-libs-unix": [
|
||||
@@ -316,21 +359,25 @@
|
||||
"libxml2.a"
|
||||
],
|
||||
"static-libs-windows": [
|
||||
[
|
||||
"libxml2s.lib",
|
||||
"libxml2_a.lib"
|
||||
]
|
||||
"libxml2s.lib",
|
||||
"libxml2_a.lib"
|
||||
],
|
||||
"headers": [
|
||||
"libxml2"
|
||||
],
|
||||
"lib-depends": [
|
||||
"lib-depends-unix": [
|
||||
"libiconv"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"lib-suggests-unix": [
|
||||
"xz",
|
||||
"icu",
|
||||
"zlib"
|
||||
],
|
||||
"lib-depends-windows": [
|
||||
"libiconv-win"
|
||||
],
|
||||
"lib-suggests-windows": [
|
||||
"zlib"
|
||||
]
|
||||
},
|
||||
"libxslt": {
|
||||
@@ -411,10 +458,8 @@
|
||||
"libonig.a"
|
||||
],
|
||||
"static-libs-windows": [
|
||||
[
|
||||
"onig.lib",
|
||||
"onig_a.lib"
|
||||
]
|
||||
"onig.lib",
|
||||
"onig_a.lib"
|
||||
],
|
||||
"headers": [
|
||||
"oniggnu.h",
|
||||
@@ -491,7 +536,10 @@
|
||||
"static-libs-unix": [
|
||||
"libsqlite3.a"
|
||||
],
|
||||
"headers-unix": [
|
||||
"static-libs-windows": [
|
||||
"libsqlite3_a.lib"
|
||||
],
|
||||
"headers": [
|
||||
"sqlite3.h",
|
||||
"sqlite3ext.h"
|
||||
]
|
||||
|
||||
46
config/pkg.json
Normal file
46
config/pkg.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"musl-toolchain-aarch64-linux": {
|
||||
"type": "url",
|
||||
"url": "https://dl.static-php.dev/static-php-cli/deps/musl-toolchain/aarch64-musl-toolchain.tgz"
|
||||
},
|
||||
"musl-toolchain-x86_64-linux": {
|
||||
"type": "url",
|
||||
"url": "https://dl.static-php.dev/static-php-cli/deps/musl-toolchain/x86_64-musl-toolchain.tgz"
|
||||
},
|
||||
"nasm-x86_64-win": {
|
||||
"type": "url",
|
||||
"url": "https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win64/nasm-2.16.01-win64.zip",
|
||||
"extract-files": {
|
||||
"nasm-2.16.01/nasm.exe": "{php_sdk_path}/bin/nasm.exe",
|
||||
"nasm-2.16.01/ndisasm.exe": "{php_sdk_path}/bin/ndisasm.exe"
|
||||
}
|
||||
},
|
||||
"strawberry-perl-x86_64-win": {
|
||||
"type": "url",
|
||||
"url": "https://github.com/StrawberryPerl/Perl-Dist-Strawberry/releases/download/SP_5380_5361/strawberry-perl-5.38.0.1-64bit-portable.zip"
|
||||
},
|
||||
"upx-aarch64-linux": {
|
||||
"type": "ghrel",
|
||||
"repo": "upx/upx",
|
||||
"match": "upx.+-arm64_linux\\.tar\\.xz",
|
||||
"extract-files": {
|
||||
"upx": "{pkg_root_path}/bin/upx"
|
||||
}
|
||||
},
|
||||
"upx-x86_64-linux": {
|
||||
"type": "ghrel",
|
||||
"repo": "upx/upx",
|
||||
"match": "upx.+-amd64_linux\\.tar\\.xz",
|
||||
"extract-files": {
|
||||
"upx": "{pkg_root_path}/bin/upx"
|
||||
}
|
||||
},
|
||||
"upx-x86_64-win": {
|
||||
"type": "ghrel",
|
||||
"repo": "upx/upx",
|
||||
"match": "upx.+-win64\\.zip",
|
||||
"extract-files": {
|
||||
"upx-*-win64/upx.exe": "{pkg_root_path}/bin/upx.exe"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,6 +129,15 @@
|
||||
"path": "LICENSE.TXT"
|
||||
}
|
||||
},
|
||||
"gettext": {
|
||||
"type": "filelist",
|
||||
"url": "https://ftp.gnu.org/pub/gnu/gettext/",
|
||||
"regex": "/href=\"(?<file>gettext-(?<version>[^\"]+)\\.tar\\.xz)\"/",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
}
|
||||
},
|
||||
"gmp": {
|
||||
"type": "ghtagtar",
|
||||
"repo": "alisw/GMP",
|
||||
@@ -236,6 +245,15 @@
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"libffi-win": {
|
||||
"type": "git",
|
||||
"rev": "master",
|
||||
"url": "https://github.com/static-php/libffi-win.git",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"libiconv": {
|
||||
"type": "filelist",
|
||||
"url": "https://ftp.gnu.org/gnu/libiconv/",
|
||||
@@ -245,6 +263,15 @@
|
||||
"path": "COPYING"
|
||||
}
|
||||
},
|
||||
"libiconv-win": {
|
||||
"type": "git",
|
||||
"rev": "master",
|
||||
"url": "https://github.com/static-php/libiconv-win.git",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "source/COPYING"
|
||||
}
|
||||
},
|
||||
"libjpeg": {
|
||||
"type": "ghtar",
|
||||
"repo": "libjpeg-turbo/libjpeg-turbo",
|
||||
@@ -298,6 +325,15 @@
|
||||
"path": "COPYING"
|
||||
}
|
||||
},
|
||||
"libtiff": {
|
||||
"type": "filelist",
|
||||
"url": "https://download.osgeo.org/libtiff/",
|
||||
"regex": "/href=\"(?<file>tiff-(?<version>[^\"]+)\\.tar\\.xz)\"/",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE.md"
|
||||
}
|
||||
},
|
||||
"libuv": {
|
||||
"type": "ghtar",
|
||||
"repo": "libuv/libuv",
|
||||
@@ -322,7 +358,7 @@
|
||||
},
|
||||
"libxml2": {
|
||||
"type": "url",
|
||||
"url": "https://github.com/GNOME/libxml2/archive/refs/tags/v2.9.14.tar.gz",
|
||||
"url": "https://github.com/GNOME/libxml2/archive/refs/tags/v2.12.5.tar.gz",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "Copyright"
|
||||
@@ -431,7 +467,7 @@
|
||||
},
|
||||
"postgresql": {
|
||||
"type": "url",
|
||||
"url": "https://ftp.postgresql.org/pub/source/v16.1/postgresql-16.1.tar.gz",
|
||||
"url": "https://ftp.postgresql.org/pub/source/v16.2/postgresql-16.2.tar.bz2",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYRIGHT"
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace SPC;
|
||||
|
||||
use SPC\command\BuildCliCommand;
|
||||
use SPC\command\BuildLibsCommand;
|
||||
use SPC\command\DeleteDownloadCommand;
|
||||
use SPC\command\dev\AllExtCommand;
|
||||
use SPC\command\dev\PhpVerCommand;
|
||||
use SPC\command\dev\SortConfigCommand;
|
||||
@@ -13,6 +14,7 @@ use SPC\command\DoctorCommand;
|
||||
use SPC\command\DownloadCommand;
|
||||
use SPC\command\DumpLicenseCommand;
|
||||
use SPC\command\ExtractCommand;
|
||||
use SPC\command\InstallPkgCommand;
|
||||
use SPC\command\MicroCombineCommand;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\HelpCommand;
|
||||
@@ -23,7 +25,7 @@ use Symfony\Component\Console\Command\ListCommand;
|
||||
*/
|
||||
final class ConsoleApplication extends Application
|
||||
{
|
||||
public const VERSION = '2.1.0-beta.3';
|
||||
public const VERSION = '2.1.2';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@@ -35,6 +37,8 @@ final class ConsoleApplication extends Application
|
||||
new BuildLibsCommand(),
|
||||
new DoctorCommand(),
|
||||
new DownloadCommand(),
|
||||
new InstallPkgCommand(),
|
||||
new DeleteDownloadCommand(),
|
||||
new DumpLicenseCommand(),
|
||||
new ExtractCommand(),
|
||||
new MicroCombineCommand(),
|
||||
|
||||
@@ -9,7 +9,7 @@ use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
use SPC\store\SourceExtractor;
|
||||
use SPC\store\SourceManager;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
abstract class BuilderBase
|
||||
@@ -144,15 +144,15 @@ abstract class BuilderBase
|
||||
{
|
||||
CustomExt::loadCustomExt();
|
||||
$this->emitPatchPoint('before-php-extract');
|
||||
SourceExtractor::initSource(sources: ['php-src']);
|
||||
SourceManager::initSource(sources: ['php-src']);
|
||||
$this->emitPatchPoint('after-php-extract');
|
||||
if ($this->getPHPVersionID() >= 80000) {
|
||||
$this->emitPatchPoint('before-micro-extract');
|
||||
SourceExtractor::initSource(sources: ['micro']);
|
||||
SourceManager::initSource(sources: ['micro']);
|
||||
$this->emitPatchPoint('after-micro-extract');
|
||||
}
|
||||
$this->emitPatchPoint('before-exts-extract');
|
||||
SourceExtractor::initSource(exts: $extensions);
|
||||
SourceManager::initSource(exts: $extensions);
|
||||
$this->emitPatchPoint('after-exts-extract');
|
||||
foreach ($extensions as $extension) {
|
||||
$class = CustomExt::getExtClass($extension);
|
||||
|
||||
@@ -185,8 +185,11 @@ class Extension
|
||||
file_get_contents(ROOT_DIR . '/src/globals/tests/' . $this->getName() . '.php')
|
||||
);
|
||||
|
||||
[$ret] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -r "' . trim($test) . '"');
|
||||
[$ret, $out] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -r "' . trim($test) . '"');
|
||||
if ($ret !== 0) {
|
||||
if ($this->builder->getOption('debug')) {
|
||||
var_dump($out);
|
||||
}
|
||||
throw new RuntimeException('extension ' . $this->getName() . ' failed sanity check');
|
||||
}
|
||||
}
|
||||
@@ -209,7 +212,7 @@ class Extension
|
||||
// Trim additional content & escape special characters to allow inline usage
|
||||
$test = str_replace(
|
||||
['<?php', 'declare(strict_types=1);', "\n", '"', '$'],
|
||||
['', '', '', '\"', '\$'],
|
||||
['', '', '', '\"', '$'],
|
||||
file_get_contents(FileSystem::convertPath(ROOT_DIR . '/src/globals/tests/' . $this->getName() . '.php'))
|
||||
);
|
||||
|
||||
|
||||
@@ -14,4 +14,9 @@ class ffi extends Extension
|
||||
{
|
||||
return '--with-ffi --enable-zend-signals';
|
||||
}
|
||||
|
||||
public function getWindowsConfigureArg(): string
|
||||
{
|
||||
return '--with-ffi';
|
||||
}
|
||||
}
|
||||
|
||||
40
src/SPC/builder/extension/gettext.php
Normal file
40
src/SPC/builder/extension/gettext.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?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('gettext')]
|
||||
class gettext extends Extension
|
||||
{
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function patchBeforeBuildconf(): bool
|
||||
{
|
||||
if ($this->builder instanceof MacOSBuilder) {
|
||||
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/gettext/config.m4', 'AC_CHECK_LIB($GETTEXT_CHECK_IN_LIB', 'AC_CHECK_LIB(intl');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws WrongUsageException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function patchBeforeConfigure(): bool
|
||||
{
|
||||
if ($this->builder instanceof MacOSBuilder) {
|
||||
$frameworks = ' ' . $this->builder->getFrameworks(true) . ' ';
|
||||
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/configure', '-lintl', $this->getLibFilesString() . $frameworks);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -31,4 +31,16 @@ class mbregex extends Extension
|
||||
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: compiled php-cli mbstring extension does not contain regex !');
|
||||
}
|
||||
}
|
||||
|
||||
public function runCliCheckWindows(): void
|
||||
{
|
||||
[$ret, $out] = cmd()->execWithResult(BUILD_ROOT_PATH . '/bin/php --ri "mbstring"', false);
|
||||
if ($ret !== 0) {
|
||||
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: compiled php-cli does not contain mbstring !');
|
||||
}
|
||||
$out = implode("\n", $out);
|
||||
if (!str_contains($out, 'regex')) {
|
||||
throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: compiled php-cli mbstring extension does not contain regex !');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ class mbstring extends Extension
|
||||
$arg = '--enable-mbstring';
|
||||
if ($this->builder->getExt('mbregex') === null) {
|
||||
$arg .= ' --disable-mbregex';
|
||||
} else {
|
||||
$arg .= ' --enable-mbregex';
|
||||
}
|
||||
return $arg;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('xml')]
|
||||
@@ -33,4 +34,25 @@ class xml extends Extension
|
||||
$arg .= ' --with-libxml="' . BUILD_ROOT_PATH . '"';
|
||||
return $arg;
|
||||
}
|
||||
|
||||
public function patchBeforeBuildconf(): bool
|
||||
{
|
||||
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/win32/build/config.w32', 'dllmain.c ', '');
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getWindowsConfigureArg(): string
|
||||
{
|
||||
$arg = match ($this->name) {
|
||||
'xml' => '--with-xml',
|
||||
'soap' => '--enable-soap',
|
||||
'xmlreader' => '--enable-xmlreader',
|
||||
'xmlwriter' => '--enable-xmlwriter',
|
||||
'dom' => '--with-dom',
|
||||
'simplexml' => '--with-simplexml',
|
||||
default => throw new RuntimeException('Not accept non-xml extension'),
|
||||
};
|
||||
$arg .= ' --with-libxml';
|
||||
return $arg;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,6 +169,27 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
|
||||
$enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
|
||||
|
||||
// upx pack and strip for micro
|
||||
if ($this->getOption('with-upx-pack', false)) {
|
||||
FileSystem::replaceFileRegex(
|
||||
SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag',
|
||||
'/POST_MICRO_BUILD_COMMANDS=.*/',
|
||||
'POST_MICRO_BUILD_COMMANDS=\$(STRIP) \$(MICRO_STRIP_FLAGS) \$(SAPI_MICRO_PATH) && ' . $this->getOption('upx-exec') . ' --best \$(SAPI_MICRO_PATH)',
|
||||
);
|
||||
} elseif (!$this->getOption('no-strip', false)) {
|
||||
FileSystem::replaceFileRegex(
|
||||
SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag',
|
||||
'/POST_MICRO_BUILD_COMMANDS=.*/',
|
||||
'POST_MICRO_BUILD_COMMANDS=\$(STRIP) \$(MICRO_STRIP_FLAGS) \$(SAPI_MICRO_PATH)',
|
||||
);
|
||||
} else {
|
||||
FileSystem::replaceFileRegex(
|
||||
SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag',
|
||||
'/POST_MICRO_BUILD_COMMANDS=.*/',
|
||||
'POST_MICRO_BUILD_COMMANDS=true',
|
||||
);
|
||||
}
|
||||
|
||||
shell()->cd(SOURCE_PATH . '/php-src')
|
||||
->exec(
|
||||
"{$this->getOption('ld_library_path')} " .
|
||||
@@ -236,7 +257,11 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
->exec('sed -i "s|//lib|/lib|g" Makefile')
|
||||
->exec("make -j{$this->concurrency} {$vars} cli");
|
||||
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
if ($this->getOption('with-upx-pack')) {
|
||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/cli')
|
||||
->exec('strip --strip-all php')
|
||||
->exec($this->getOption('upx-exec') . ' --best php');
|
||||
} elseif (!$this->getOption('no-strip', false)) {
|
||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/cli')->exec('strip --strip-all php');
|
||||
}
|
||||
|
||||
@@ -267,10 +292,6 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
->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) {
|
||||
@@ -291,10 +312,13 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
->exec('sed -i "s|//lib|/lib|g" Makefile')
|
||||
->exec("make -j{$this->concurrency} {$vars} fpm");
|
||||
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
if ($this->getOption('with-upx-pack')) {
|
||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/fpm')
|
||||
->exec('strip --strip-all php-fpm')
|
||||
->exec($this->getOption('upx-exec') . ' --best php-fpm');
|
||||
} elseif (!$this->getOption('no-strip', false)) {
|
||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/fpm')->exec('strip --strip-all php-fpm');
|
||||
}
|
||||
|
||||
$this->deployBinary(BUILD_TARGET_FPM);
|
||||
}
|
||||
|
||||
|
||||
@@ -110,11 +110,7 @@ class SystemUtil
|
||||
public static function getTuneCFlags(string $arch): array
|
||||
{
|
||||
return match ($arch) {
|
||||
'x86_64' => [
|
||||
'-march=corei7',
|
||||
'-mtune=core-avx2',
|
||||
],
|
||||
'arm64', 'aarch64' => [],
|
||||
'x86_64', 'arm64', 'aarch64' => [],
|
||||
default => throw new RuntimeException('unsupported arch: ' . $arch),
|
||||
};
|
||||
}
|
||||
|
||||
12
src/SPC/builder/linux/library/gettext.php
Normal file
12
src/SPC/builder/linux/library/gettext.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
class gettext extends LinuxLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\gettext;
|
||||
|
||||
public const NAME = 'gettext';
|
||||
}
|
||||
12
src/SPC/builder/linux/library/libtiff.php
Normal file
12
src/SPC/builder/linux/library/libtiff.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
class libtiff extends LinuxLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\libtiff;
|
||||
|
||||
public const NAME = 'libtiff';
|
||||
}
|
||||
@@ -18,7 +18,7 @@ class libxml2 extends LinuxLibraryBase
|
||||
*/
|
||||
public function build(): void
|
||||
{
|
||||
$enable_zlib = $this->builder->getLib('zlib') ? 'ON' : 'OFF';
|
||||
$enable_zlib = $this->builder->getLib('zlib') ? ('ON -DZLIB_LIBRARY=' . BUILD_LIB_PATH . '/libz.a -DZLIB_INCLUDE_DIR=' . BUILD_INCLUDE_PATH) : 'OFF';
|
||||
$enable_icu = $this->builder->getLib('icu') ? 'ON' : 'OFF';
|
||||
$enable_xz = $this->builder->getLib('xz') ? 'ON' : 'OFF';
|
||||
|
||||
|
||||
12
src/SPC/builder/macos/library/gettext.php
Normal file
12
src/SPC/builder/macos/library/gettext.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
class gettext extends MacOSLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\gettext;
|
||||
|
||||
public const NAME = 'gettext';
|
||||
}
|
||||
12
src/SPC/builder/macos/library/libtiff.php
Normal file
12
src/SPC/builder/macos/library/libtiff.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
class libtiff extends MacOSLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\libtiff;
|
||||
|
||||
public const NAME = 'libtiff';
|
||||
}
|
||||
@@ -18,7 +18,7 @@ class libxml2 extends MacOSLibraryBase
|
||||
*/
|
||||
protected function build(): void
|
||||
{
|
||||
$enable_zlib = $this->builder->getLib('zlib') ? 'ON' : 'OFF';
|
||||
$enable_zlib = $this->builder->getLib('zlib') ? ('ON -DZLIB_LIBRARY=' . BUILD_LIB_PATH . '/libz.a -DZLIB_INCLUDE_DIR=' . BUILD_INCLUDE_PATH) : 'OFF';
|
||||
$enable_icu = $this->builder->getLib('icu') ? 'ON' : 'OFF';
|
||||
$enable_xz = $this->builder->getLib('xz') ? 'ON' : 'OFF';
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\store\SourceExtractor;
|
||||
use SPC\store\SourceManager;
|
||||
use SPC\util\DependencyUtil;
|
||||
|
||||
abstract class UnixBuilderBase extends BuilderBase
|
||||
@@ -134,7 +134,7 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
$this->emitPatchPoint('before-libs-extract');
|
||||
|
||||
// extract sources
|
||||
SourceExtractor::initSource(libs: $sorted_libraries);
|
||||
SourceManager::initSource(libs: $sorted_libraries);
|
||||
|
||||
$this->emitPatchPoint('after-libs-extract');
|
||||
|
||||
|
||||
28
src/SPC/builder/unix/library/gettext.php
Normal file
28
src/SPC/builder/unix/library/gettext.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
trait gettext
|
||||
{
|
||||
protected function build(): void
|
||||
{
|
||||
$extra = $this->builder->getLib('ncurses') ? ('--with-libncurses-prefix=' . BUILD_ROOT_PATH . ' ') : '';
|
||||
$extra .= $this->builder->getLib('libxml2') ? ('--with-libxml2-prefix=' . BUILD_ROOT_PATH . ' ') : '';
|
||||
shell()->cd($this->source_dir)
|
||||
->exec(
|
||||
'./configure ' .
|
||||
'--enable-static ' .
|
||||
'--disable-shared ' .
|
||||
'--disable-java ' .
|
||||
'--disable-c+ ' .
|
||||
$extra .
|
||||
'--with-libiconv-prefix=' . BUILD_ROOT_PATH . ' ' .
|
||||
'--prefix=' . BUILD_ROOT_PATH
|
||||
)
|
||||
->exec('make clean')
|
||||
->exec("make -j{$this->builder->concurrency}")
|
||||
->exec('make install');
|
||||
}
|
||||
}
|
||||
30
src/SPC/builder/unix/library/libtiff.php
Normal file
30
src/SPC/builder/unix/library/libtiff.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
|
||||
trait libtiff
|
||||
{
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
protected function build(): void
|
||||
{
|
||||
shell()->cd($this->source_dir)
|
||||
->exec(
|
||||
'./configure ' .
|
||||
'--enable-static --disable-shared ' .
|
||||
'--disable-cxx ' .
|
||||
'--prefix='
|
||||
)
|
||||
->exec('make clean')
|
||||
->exec("make -j{$this->builder->concurrency}")
|
||||
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
|
||||
$this->patchPkgconfPrefix(['libtiff-4.pc']);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,8 @@ trait pkgconfig
|
||||
'--disable-shared ' .
|
||||
'--enable-static ' .
|
||||
'--with-internal-glib ' .
|
||||
'--disable-host-tool ' .
|
||||
'--with-pic ' .
|
||||
'--prefix=' . BUILD_ROOT_PATH . ' ' .
|
||||
'--without-sysroot ' .
|
||||
'--without-system-include-path ' .
|
||||
@@ -29,6 +31,7 @@ trait pkgconfig
|
||||
)
|
||||
->exec('make clean')
|
||||
->exec("make -j{$this->builder->concurrency}")
|
||||
->exec('make install');
|
||||
->exec('make install-exec');
|
||||
shell()->exec('strip ' . BUILD_ROOT_PATH . '/bin/pkg-config');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,11 +58,17 @@ trait postgresql
|
||||
|
||||
FileSystem::resetDir($this->source_dir . '/build');
|
||||
|
||||
# 有静态链接配置 参考文件: src/interfaces/libpq/Makefile
|
||||
shell()->cd($this->source_dir . '/build')
|
||||
->exec('sed -i.backup "s/invokes exit\'; exit 1;/invokes exit\';/" ../src/interfaces/libpq/Makefile')
|
||||
->exec('sed -i.backup "278 s/^/# /" ../src/Makefile.shlib')
|
||||
->exec('sed -i.backup "402 s/^/# /" ../src/Makefile.shlib');
|
||||
$version = $this->getVersion();
|
||||
// 16.1 workaround
|
||||
if (version_compare($version, '16.1') >= 0) {
|
||||
# 有静态链接配置 参考文件: src/interfaces/libpq/Makefile
|
||||
shell()->cd($this->source_dir . '/build')
|
||||
->exec('sed -i.backup "s/invokes exit\'; exit 1;/invokes exit\';/" ../src/interfaces/libpq/Makefile')
|
||||
->exec('sed -i.backup "278 s/^/# /" ../src/Makefile.shlib')
|
||||
->exec('sed -i.backup "402 s/^/# /" ../src/Makefile.shlib');
|
||||
} else {
|
||||
throw new RuntimeException('Unsupported version for postgresql: ' . $version . ' !');
|
||||
}
|
||||
|
||||
// configure
|
||||
shell()->cd($this->source_dir . '/build')
|
||||
@@ -101,4 +107,17 @@ trait postgresql
|
||||
->exec("rm -rf {$builddir}/lib/*.so")
|
||||
->exec("rm -rf {$builddir}/lib/*.dylib");
|
||||
}
|
||||
|
||||
private function getVersion(): string
|
||||
{
|
||||
try {
|
||||
$file = FileSystem::readFile($this->source_dir . '/meson.build');
|
||||
if (preg_match("/^\\s+version:\\s?'(.*)'/m", $file, $match)) {
|
||||
return $match[1];
|
||||
}
|
||||
return 'unknown';
|
||||
} catch (FileSystemException) {
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\store\SourceExtractor;
|
||||
use SPC\store\SourceManager;
|
||||
use SPC\store\SourcePatcher;
|
||||
use SPC\util\DependencyUtil;
|
||||
|
||||
@@ -72,6 +72,27 @@ class WindowsBuilder extends BuilderBase
|
||||
|
||||
$zts = $this->zts ? '--enable-zts=yes ' : '--enable-zts=no ';
|
||||
|
||||
// with-upx-pack for phpmicro
|
||||
$makefile = FileSystem::convertPath(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.w32');
|
||||
if ($this->getOption('with-upx-pack', false)) {
|
||||
if (!file_exists($makefile . '.originfile')) {
|
||||
copy($makefile, $makefile . '.originfile');
|
||||
FileSystem::replaceFileStr($makefile, '$(MICRO_SFX):', "_MICRO_UPX = {$this->getOption('upx-exec')} --best $(MICRO_SFX)\n$(MICRO_SFX):");
|
||||
FileSystem::replaceFileStr($makefile, '@$(_MICRO_MT)', "@$(_MICRO_MT)\n\t@$(_MICRO_UPX)");
|
||||
}
|
||||
} elseif (file_exists($makefile . '.originfile')) {
|
||||
copy($makefile . '.originfile', $makefile);
|
||||
unlink($makefile . '.originfile');
|
||||
}
|
||||
|
||||
if (($logo = $this->getOption('with-micro-logo')) !== null) {
|
||||
// realpath
|
||||
$logo = realpath($logo);
|
||||
$micro_logo = '--enable-micro-logo=' . escapeshellarg($logo) . ' ';
|
||||
} else {
|
||||
$micro_logo = '';
|
||||
}
|
||||
|
||||
cmd()->cd(SOURCE_PATH . '\php-src')
|
||||
->exec(
|
||||
"{$this->sdk_prefix} configure.bat --task-args \"" .
|
||||
@@ -81,7 +102,7 @@ class WindowsBuilder extends BuilderBase
|
||||
'--with-extra-includes=' . BUILD_INCLUDE_PATH . ' ' .
|
||||
'--with-extra-libs=' . BUILD_LIB_PATH . ' ' .
|
||||
($enableCli ? '--enable-cli=yes ' : '--enable-cli=no ') .
|
||||
($enableMicro ? '--enable-micro=yes ' : '--enable-micro=no ') .
|
||||
($enableMicro ? ('--enable-micro=yes ' . $micro_logo) : '--enable-micro=no ') .
|
||||
($enableEmbed ? '--enable-embed=yes ' : '--enable-embed=no ') .
|
||||
"{$this->makeExtensionArgs()} " .
|
||||
$zts .
|
||||
@@ -211,7 +232,7 @@ class WindowsBuilder extends BuilderBase
|
||||
}
|
||||
|
||||
// extract sources
|
||||
SourceExtractor::initSource(libs: $sorted_libraries);
|
||||
SourceManager::initSource(libs: $sorted_libraries);
|
||||
|
||||
// build all libs
|
||||
foreach ($this->libs as $lib) {
|
||||
@@ -293,6 +314,12 @@ class WindowsBuilder extends BuilderBase
|
||||
BUILD_TARGET_MICRO => SOURCE_PATH . "\\php-src\\x64\\Release{$ts}\\micro.sfx",
|
||||
default => throw new RuntimeException('Deployment does not accept type ' . $type),
|
||||
};
|
||||
|
||||
// with-upx-pack for cli
|
||||
if ($this->getOption('with-upx-pack', false) && $type === BUILD_TARGET_CLI) {
|
||||
cmd()->exec($this->getOption('upx-exec') . ' --best ' . escapeshellarg($src));
|
||||
}
|
||||
|
||||
logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file');
|
||||
FileSystem::createDir(BUILD_ROOT_PATH . '\bin');
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ use SPC\builder\BuilderBase;
|
||||
use SPC\builder\LibraryBase;
|
||||
use SPC\builder\windows\WindowsBuilder;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
abstract class WindowsLibraryBase extends LibraryBase
|
||||
@@ -22,6 +24,36 @@ abstract class WindowsLibraryBase extends LibraryBase
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public function getStaticLibFiles(string $style = 'autoconf', bool $recursive = true): string
|
||||
{
|
||||
$libs = [$this];
|
||||
if ($recursive) {
|
||||
array_unshift($libs, ...array_values($this->getDependencies(recursive: true)));
|
||||
}
|
||||
|
||||
$sep = match ($style) {
|
||||
'autoconf' => ' ',
|
||||
'cmake' => ';',
|
||||
default => throw new RuntimeException('style only support autoconf and cmake'),
|
||||
};
|
||||
$ret = [];
|
||||
foreach ($libs as $lib) {
|
||||
$libFiles = [];
|
||||
foreach ($lib->getStaticLibs() as $name) {
|
||||
$name = str_replace(' ', '\ ', FileSystem::convertPath(BUILD_LIB_PATH . "/{$name}"));
|
||||
$name = str_replace('"', '\"', $name);
|
||||
$libFiles[] = $name;
|
||||
}
|
||||
array_unshift($ret, implode($sep, $libFiles));
|
||||
}
|
||||
return implode($sep, $ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a nmake wrapper file.
|
||||
*
|
||||
|
||||
40
src/SPC/builder/windows/library/curl.php
Normal file
40
src/SPC/builder/windows/library/curl.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\windows\library;
|
||||
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
class curl extends WindowsLibraryBase
|
||||
{
|
||||
public const NAME = 'curl';
|
||||
|
||||
protected function build(): void
|
||||
{
|
||||
// reset cmake
|
||||
FileSystem::resetDir($this->source_dir . '\build');
|
||||
|
||||
// start build
|
||||
cmd()->cd($this->source_dir)
|
||||
->execWithWrapper(
|
||||
$this->builder->makeSimpleWrapper('cmake'),
|
||||
'-B build ' .
|
||||
'-A x64 ' .
|
||||
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
||||
'-DCMAKE_BUILD_TYPE=Release ' .
|
||||
'-DBUILD_SHARED_LIBS=OFF ' .
|
||||
'-DBUILD_STATIC_LIBS=ON ' .
|
||||
'-DBUILD_CURL_EXE=OFF ' .
|
||||
'-DUSE_ZLIB=ON ' .
|
||||
'-DCURL_USE_OPENSSL=ON ' .
|
||||
'-DCURL_USE_LIBLSSH2=ON ' .
|
||||
'-DUSE_NGHTTP2=ON ' . // php-src with curl needs nghttp2
|
||||
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' '
|
||||
)
|
||||
->execWithWrapper(
|
||||
$this->builder->makeSimpleWrapper('cmake'),
|
||||
"--build build --config Release --target install -j{$this->builder->concurrency}"
|
||||
);
|
||||
}
|
||||
}
|
||||
46
src/SPC/builder/windows/library/libffi_win.php
Normal file
46
src/SPC/builder/windows/library/libffi_win.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\windows\library;
|
||||
|
||||
use SPC\builder\windows\SystemUtil;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
class libffi_win extends WindowsLibraryBase
|
||||
{
|
||||
public const NAME = 'libffi-win';
|
||||
|
||||
protected function build()
|
||||
{
|
||||
$vs_ver_dir = match (SystemUtil::findVisualStudio()['version']) {
|
||||
'vs17' => '/win32/vs17_x64',
|
||||
'vs16' => '/win32/vs16_x64',
|
||||
default => throw new RuntimeException('Current VS version is not supported yet!'),
|
||||
};
|
||||
|
||||
// start build
|
||||
cmd()->cd($this->source_dir . $vs_ver_dir)
|
||||
->execWithWrapper(
|
||||
$this->builder->makeSimpleWrapper('msbuild'),
|
||||
'libffi-msvc.sln /t:Rebuild /p:Configuration=Release /p:Platform=x64'
|
||||
);
|
||||
FileSystem::createDir(BUILD_LIB_PATH);
|
||||
FileSystem::createDir(BUILD_INCLUDE_PATH);
|
||||
copy($this->source_dir . $vs_ver_dir . '\x64\Release\libffi.lib', BUILD_LIB_PATH . '\libffi.lib');
|
||||
copy($this->source_dir . $vs_ver_dir . '\x64\Release\libffi.pdb', BUILD_LIB_PATH . '\libffi.pdb');
|
||||
copy($this->source_dir . '\include\ffi.h', BUILD_INCLUDE_PATH . '\ffi.h');
|
||||
|
||||
FileSystem::replaceFileStr(BUILD_INCLUDE_PATH . '\ffi.h', '#define LIBFFI_H', "#define LIBFFI_H\n#define FFI_BUILDING");
|
||||
copy($this->source_dir . '\src\x86\ffitarget.h', BUILD_INCLUDE_PATH . '\ffitarget.h');
|
||||
copy($this->source_dir . '\fficonfig.h', BUILD_INCLUDE_PATH . '\fficonfig.h');
|
||||
|
||||
// copy($this->source_dir . '\msvc_build\out\static-Release\X64\libffi.lib', BUILD_LIB_PATH . '\libffi.lib');
|
||||
// copy($this->source_dir . '\msvc_build\include\ffi.h', BUILD_INCLUDE_PATH . '\ffi.h');
|
||||
// copy($this->source_dir . '\msvc_build\include\fficonfig.h', BUILD_INCLUDE_PATH . '\fficonfig.h');
|
||||
// copy($this->source_dir . '\src\x86\ffitarget.h', BUILD_INCLUDE_PATH . '\ffitarget.h');
|
||||
|
||||
// FileSystem::replaceFileStr(BUILD_INCLUDE_PATH . '\ffi.h', '..\..\src\x86\ffitarget.h', 'ffitarget.h');
|
||||
}
|
||||
}
|
||||
35
src/SPC/builder/windows/library/libiconv_win.php
Normal file
35
src/SPC/builder/windows/library/libiconv_win.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\windows\library;
|
||||
|
||||
use SPC\builder\windows\SystemUtil;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
class libiconv_win extends WindowsLibraryBase
|
||||
{
|
||||
public const NAME = 'libiconv-win';
|
||||
|
||||
protected function build()
|
||||
{
|
||||
$vs_ver_dir = match (SystemUtil::findVisualStudio()['version']) {
|
||||
'vs17' => '/MSVC17',
|
||||
'vs16' => '/MSVC16',
|
||||
default => throw new RuntimeException('Current VS version is not supported yet!'),
|
||||
};
|
||||
|
||||
// start build
|
||||
cmd()->cd($this->source_dir . $vs_ver_dir)
|
||||
->execWithWrapper(
|
||||
$this->builder->makeSimpleWrapper('msbuild'),
|
||||
'libiconv.sln /t:Rebuild /p:Configuration=Release /p:Platform=x64'
|
||||
);
|
||||
FileSystem::createDir(BUILD_LIB_PATH);
|
||||
FileSystem::createDir(BUILD_INCLUDE_PATH);
|
||||
copy($this->source_dir . $vs_ver_dir . '\x64\lib\libiconv.lib', BUILD_LIB_PATH . '\libiconv.lib');
|
||||
copy($this->source_dir . $vs_ver_dir . '\x64\lib\libiconv_a.lib', BUILD_LIB_PATH . '\libiconv_a.lib');
|
||||
copy($this->source_dir . '\source\include\iconv.h', BUILD_INCLUDE_PATH . '\iconv.h');
|
||||
}
|
||||
}
|
||||
38
src/SPC/builder/windows/library/libssh2.php
Normal file
38
src/SPC/builder/windows/library/libssh2.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\windows\library;
|
||||
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
class libssh2 extends WindowsLibraryBase
|
||||
{
|
||||
public const NAME = 'libssh2';
|
||||
|
||||
protected function build(): void
|
||||
{
|
||||
$zlib = $this->builder->getLib('zlib') ? 'ON' : 'OFF';
|
||||
// reset cmake
|
||||
FileSystem::resetDir($this->source_dir . '\build');
|
||||
|
||||
// start build
|
||||
cmd()->cd($this->source_dir)
|
||||
->execWithWrapper(
|
||||
$this->builder->makeSimpleWrapper('cmake'),
|
||||
'-B build ' .
|
||||
'-A x64 ' .
|
||||
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
||||
'-DCMAKE_BUILD_TYPE=Release ' .
|
||||
'-DBUILD_SHARED_LIBS=OFF ' .
|
||||
'-DBUILD_STATIC_LIBS=ON ' .
|
||||
'-DBUILD_TESTING=OFF ' .
|
||||
"-DENABLE_ZLIB_COMPRESSION={$zlib} " .
|
||||
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' '
|
||||
)
|
||||
->execWithWrapper(
|
||||
$this->builder->makeSimpleWrapper('cmake'),
|
||||
"--build build --config Release --target install -j{$this->builder->concurrency}"
|
||||
);
|
||||
}
|
||||
}
|
||||
44
src/SPC/builder/windows/library/libxml2.php
Normal file
44
src/SPC/builder/windows/library/libxml2.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\windows\library;
|
||||
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
class libxml2 extends WindowsLibraryBase
|
||||
{
|
||||
public const NAME = 'libxml2';
|
||||
|
||||
protected function build(): void
|
||||
{
|
||||
$zlib = $this->builder->getLib('zlib') ? 'ON' : 'OFF';
|
||||
// reset cmake
|
||||
FileSystem::resetDir($this->source_dir . '\build');
|
||||
|
||||
// start build
|
||||
cmd()->cd($this->source_dir)
|
||||
->execWithWrapper(
|
||||
$this->builder->makeSimpleWrapper('cmake'),
|
||||
'-B build ' .
|
||||
'-A x64 ' .
|
||||
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
||||
'-DBUILD_SHARED_LIBS=OFF ' .
|
||||
'-DBUILD_STATIC_LIBS=ON ' .
|
||||
"-DLIBXML2_WITH_ZLIB={$zlib} " .
|
||||
'-DLIBXML2_WITH_PYTHON=OFF ' .
|
||||
'-DLIBXML2_WITH_ICONV=ON ' .
|
||||
'-DIconv_LIBRARY=' . BUILD_LIB_PATH . ' ' .
|
||||
'-DIconv_INCLUDE_DIR=' . BUILD_INCLUDE_PATH . ' ' .
|
||||
'-DLIBXML2_WITH_LZMA=OFF ' . // xz not supported yet
|
||||
'-DLIBXML2_WITH_PROGRAMS=OFF ' .
|
||||
'-DLIBXML2_WITH_TESTS=OFF ' .
|
||||
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' '
|
||||
)
|
||||
->execWithWrapper(
|
||||
$this->builder->makeSimpleWrapper('cmake'),
|
||||
"--build build --config Release --target install -j{$this->builder->concurrency}"
|
||||
);
|
||||
copy(BUILD_LIB_PATH . '\libxml2s.lib', BUILD_LIB_PATH . '\libxml2_a.lib');
|
||||
}
|
||||
}
|
||||
37
src/SPC/builder/windows/library/nghttp2.php
Normal file
37
src/SPC/builder/windows/library/nghttp2.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\windows\library;
|
||||
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
class nghttp2 extends WindowsLibraryBase
|
||||
{
|
||||
public const NAME = 'nghttp2';
|
||||
|
||||
protected function build(): void
|
||||
{
|
||||
// reset cmake
|
||||
FileSystem::resetDir($this->source_dir . '\build');
|
||||
|
||||
// start build
|
||||
cmd()->cd($this->source_dir)
|
||||
->execWithWrapper(
|
||||
$this->builder->makeSimpleWrapper('cmake'),
|
||||
'-B build ' .
|
||||
'-A x64 ' .
|
||||
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
||||
'-DCMAKE_BUILD_TYPE=Release ' .
|
||||
'-DBUILD_SHARED_LIBS=OFF ' .
|
||||
'-DBUILD_STATIC_LIBS=ON ' .
|
||||
'-DENABLE_STATIC_CRT=ON ' .
|
||||
'-DENABLE_LIB_ONLY=ON ' .
|
||||
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' '
|
||||
)
|
||||
->execWithWrapper(
|
||||
$this->builder->makeSimpleWrapper('cmake'),
|
||||
"--build build --config Release --target install -j{$this->builder->concurrency}"
|
||||
);
|
||||
}
|
||||
}
|
||||
37
src/SPC/builder/windows/library/onig.php
Normal file
37
src/SPC/builder/windows/library/onig.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\windows\library;
|
||||
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
class onig extends WindowsLibraryBase
|
||||
{
|
||||
public const NAME = 'onig';
|
||||
|
||||
protected function build(): void
|
||||
{
|
||||
// reset cmake
|
||||
FileSystem::resetDir($this->source_dir . '\build');
|
||||
|
||||
// start build
|
||||
cmd()->cd($this->source_dir)
|
||||
->execWithWrapper(
|
||||
$this->builder->makeSimpleWrapper('cmake'),
|
||||
'-B build ' .
|
||||
'-A x64 ' .
|
||||
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
|
||||
'-DCMAKE_BUILD_TYPE=Release ' .
|
||||
'-DBUILD_SHARED_LIBS=OFF ' .
|
||||
'-DBUILD_STATIC_LIBS=ON ' .
|
||||
'-DMSVC_STATIC_RUNTIME=ON ' .
|
||||
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' '
|
||||
)
|
||||
->execWithWrapper(
|
||||
$this->builder->makeSimpleWrapper('cmake'),
|
||||
"--build build --config Release --target install -j{$this->builder->concurrency}"
|
||||
);
|
||||
copy(BUILD_LIB_PATH . '/onig.lib', BUILD_LIB_PATH . '/onig_a.lib');
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,8 @@ class openssl extends WindowsLibraryBase
|
||||
|
||||
protected function build(): void
|
||||
{
|
||||
$perl = file_exists(BUILD_ROOT_PATH . '\perl\perl\bin\perl.exe') ? (BUILD_ROOT_PATH . '\perl\perl\bin\perl.exe') : SystemUtil::findCommand('perl.exe');
|
||||
$perl_path_native = PKG_ROOT_PATH . '\strawberry-perl-' . arch2gnu(php_uname('m')) . '-win\perl\bin\perl.exe';
|
||||
$perl = file_exists($perl_path_native) ? ($perl_path_native) : SystemUtil::findCommand('perl.exe');
|
||||
if ($perl === null) {
|
||||
throw new RuntimeException('You need to install perl first! (easiest way is using static-php-cli command "doctor")');
|
||||
}
|
||||
|
||||
21
src/SPC/builder/windows/library/sqlite.php
Normal file
21
src/SPC/builder/windows/library/sqlite.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\windows\library;
|
||||
|
||||
class sqlite extends WindowsLibraryBase
|
||||
{
|
||||
public const NAME = 'sqlite';
|
||||
|
||||
public function patchBeforeBuild(): bool
|
||||
{
|
||||
copy(ROOT_DIR . '/src/globals/extra/Makefile-sqlite', $this->source_dir . '/Makefile');
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function build(): void
|
||||
{
|
||||
cmd()->cd($this->source_dir)->execWithWrapper($this->builder->makeSimpleWrapper('nmake'), 'PREFIX=' . BUILD_ROOT_PATH . ' install-static');
|
||||
}
|
||||
}
|
||||
@@ -56,11 +56,6 @@ abstract class BaseCommand extends Command
|
||||
// 如果 return false 则错误会继续递交给 PHP 标准错误处理
|
||||
return true;
|
||||
}, E_ALL | E_STRICT);
|
||||
if ($input->getOption('debug')) {
|
||||
global $ob_logger;
|
||||
$ob_logger = new ConsoleLogger(LogLevel::DEBUG);
|
||||
define('DEBUG_MODE', true);
|
||||
}
|
||||
$version = ConsoleApplication::VERSION;
|
||||
if (!$this->no_motd) {
|
||||
echo " _ _ _ _
|
||||
@@ -83,6 +78,14 @@ abstract class BaseCommand extends Command
|
||||
$this->input = $input;
|
||||
$this->output = $output;
|
||||
|
||||
global $ob_logger;
|
||||
if ($input->getOption('debug')) {
|
||||
$ob_logger = new ConsoleLogger(LogLevel::DEBUG, decorated: !$input->getOption('no-ansi'));
|
||||
define('DEBUG_MODE', true);
|
||||
} else {
|
||||
$ob_logger = new ConsoleLogger(decorated: !$input->getOption('no-ansi'));
|
||||
}
|
||||
|
||||
// windows fallback
|
||||
Prompt::fallbackWhen(PHP_OS_FAMILY === 'Windows');
|
||||
ConfirmPrompt::fallbackUsing(function (ConfirmPrompt $prompt) use ($input, $output) {
|
||||
|
||||
@@ -32,11 +32,13 @@ class BuildCliCommand extends BuildCommand
|
||||
$this->addOption('enable-zts', null, null, 'enable ZTS support');
|
||||
$this->addOption('disable-opcache-jit', null, null, 'disable opcache jit');
|
||||
$this->addOption('with-hardcoded-ini', 'I', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Patch PHP source code, inject hardcoded INI');
|
||||
$this->addOption('with-micro-fake-cli', null, null, 'Enable phpmicro fake cli');
|
||||
$this->addOption('with-micro-fake-cli', null, null, 'Let phpmicro\'s PHP_SAPI use "cli" instead of "micro"');
|
||||
$this->addOption('with-suggested-libs', 'L', null, 'Build with suggested libs for selected exts and libs');
|
||||
$this->addOption('with-suggested-exts', 'E', null, 'Build with suggested extensions for selected exts');
|
||||
$this->addOption('with-added-patch', 'P', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Inject patch script outside');
|
||||
$this->addOption('without-micro-ext-test', null, null, 'Disable phpmicro with extension test code');
|
||||
$this->addOption('with-upx-pack', null, null, 'Compress / pack binary using UPX tool (linux/windows only)');
|
||||
$this->addOption('with-micro-logo', null, InputOption::VALUE_REQUIRED, 'Use custom .ico for micro.sfx (windows only)');
|
||||
}
|
||||
|
||||
public function handle(): int
|
||||
@@ -58,6 +60,39 @@ class BuildCliCommand extends BuildCommand
|
||||
$this->output->writeln("<comment>\t--build-all\tBuild all SAPI: cli, micro, fpm, embed</comment>");
|
||||
return static::FAILURE;
|
||||
}
|
||||
if ($rule === BUILD_TARGET_ALL) {
|
||||
logger()->warning('--build-all option makes `--no-strip` always true, be aware!');
|
||||
}
|
||||
if (($rule & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO && $this->getOption('with-micro-logo')) {
|
||||
$logo = $this->getOption('with-micro-logo');
|
||||
if (!file_exists($logo)) {
|
||||
logger()->error('Logo file ' . $logo . ' not exist !');
|
||||
return static::FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// Check upx
|
||||
$suffix = PHP_OS_FAMILY === 'Windows' ? '.exe' : '';
|
||||
if ($this->getOption('with-upx-pack')) {
|
||||
// only available for linux for now
|
||||
if (!in_array(PHP_OS_FAMILY, ['Linux', 'Windows'])) {
|
||||
logger()->error('UPX is only available on Linux and Windows!');
|
||||
return static::FAILURE;
|
||||
}
|
||||
// need to install this manually
|
||||
if (!file_exists(PKG_ROOT_PATH . '/bin/upx' . $suffix)) {
|
||||
global $argv;
|
||||
logger()->error('upx does not exist, please install it first:');
|
||||
logger()->error('');
|
||||
logger()->error("\t" . $argv[0] . ' install-pkg upx');
|
||||
logger()->error('');
|
||||
return static::FAILURE;
|
||||
}
|
||||
// exclusive with no-strip
|
||||
if ($this->getOption('no-strip')) {
|
||||
logger()->warning('--with-upx-pack conflicts with --no-strip, --no-strip won\'t work!');
|
||||
}
|
||||
}
|
||||
try {
|
||||
// create builder
|
||||
$builder = BuilderProvider::makeBuilderByInput($this->input);
|
||||
@@ -80,6 +115,10 @@ class BuildCliCommand extends BuildCommand
|
||||
if ($this->input->getOption('disable-opcache-jit')) {
|
||||
$indent_texts['Opcache JIT'] = 'disabled';
|
||||
}
|
||||
if ($this->input->getOption('with-upx-pack') && in_array(PHP_OS_FAMILY, ['Linux', 'Windows'])) {
|
||||
$indent_texts['UPX Pack'] = 'enabled';
|
||||
$builder->setOption('upx-exec', FileSystem::convertPath(PKG_ROOT_PATH . '/bin/upx' . $suffix));
|
||||
}
|
||||
try {
|
||||
$ver = $builder->getPHPVersion();
|
||||
$indent_texts['PHP Version'] = $ver;
|
||||
|
||||
86
src/SPC/command/DeleteDownloadCommand.php
Normal file
86
src/SPC/command/DeleteDownloadCommand.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\command;
|
||||
|
||||
use SPC\exception\DownloaderException;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\FileSystem;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
#[AsCommand('del-download', 'Remove locked download source or package using name', ['delete-download', 'del-down'])]
|
||||
class DeleteDownloadCommand extends BaseCommand
|
||||
{
|
||||
public function configure(): void
|
||||
{
|
||||
$this->addArgument('sources', InputArgument::REQUIRED, 'The sources/packages will be deleted, comma separated');
|
||||
$this->addOption('all', 'A', null, 'Delete all downloaded and locked sources/packages');
|
||||
}
|
||||
|
||||
public function initialize(InputInterface $input, OutputInterface $output): void
|
||||
{
|
||||
if ($input->getOption('all')) {
|
||||
$input->setArgument('sources', '');
|
||||
}
|
||||
parent::initialize($input, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
try {
|
||||
// get source list that will be downloaded
|
||||
$sources = array_map('trim', array_filter(explode(',', $this->getArgument('sources'))));
|
||||
if (empty($sources)) {
|
||||
logger()->notice('Removing downloads/ directory ...');
|
||||
FileSystem::removeDir(DOWNLOAD_PATH);
|
||||
logger()->info('Removed downloads/ dir!');
|
||||
return static::SUCCESS;
|
||||
}
|
||||
$chosen_sources = $sources;
|
||||
$lock = json_decode(FileSystem::readFile(DOWNLOAD_PATH . '/.lock.json'), true) ?? [];
|
||||
|
||||
foreach ($chosen_sources as $source) {
|
||||
$source = trim($source);
|
||||
if (!isset($lock[$source])) {
|
||||
logger()->warning("Source/Package [{$source}] not locked or not downloaded, skipped.");
|
||||
continue;
|
||||
}
|
||||
// remove download file/dir if exists
|
||||
if ($lock[$source]['source_type'] === 'archive') {
|
||||
if (file_exists($path = FileSystem::convertPath(DOWNLOAD_PATH . '/' . $lock[$source]['filename']))) {
|
||||
logger()->info('Deleting file ' . $path);
|
||||
unlink($path);
|
||||
} else {
|
||||
logger()->warning("Source/Package [{$source}] file not found, skip deleting file.");
|
||||
}
|
||||
} else {
|
||||
if (is_dir($path = FileSystem::convertPath(DOWNLOAD_PATH . '/' . $lock[$source]['dirname']))) {
|
||||
logger()->info('Deleting dir ' . $path);
|
||||
FileSystem::removeDir($path);
|
||||
} else {
|
||||
logger()->warning("Source/Package [{$source}] directory not found, skip deleting dir.");
|
||||
}
|
||||
}
|
||||
// remove locked sources
|
||||
unset($lock[$source]);
|
||||
}
|
||||
FileSystem::writeFile(DOWNLOAD_PATH . '/.lock.json', json_encode($lock, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
|
||||
logger()->info('Delete success!');
|
||||
return static::SUCCESS;
|
||||
} catch (DownloaderException $e) {
|
||||
logger()->error($e->getMessage());
|
||||
return static::FAILURE;
|
||||
} catch (WrongUsageException $e) {
|
||||
logger()->critical($e->getMessage());
|
||||
return static::FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,11 @@ use SPC\builder\traits\UnixSystemUtilTrait;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\SourceExtractor;
|
||||
use SPC\store\SourceManager;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
|
||||
#[AsCommand('extract', 'Extract required sources')]
|
||||
#[AsCommand('extract', 'Extract required sources', ['extract-source'])]
|
||||
class ExtractCommand extends BaseCommand
|
||||
{
|
||||
use UnixSystemUtilTrait;
|
||||
@@ -34,7 +34,7 @@ class ExtractCommand extends BaseCommand
|
||||
$this->output->writeln('<error>sources cannot be empty, at least contain one !</error>');
|
||||
return static::FAILURE;
|
||||
}
|
||||
SourceExtractor::initSource(sources: $sources);
|
||||
SourceManager::initSource(sources: $sources);
|
||||
logger()->info('Extract done !');
|
||||
return static::SUCCESS;
|
||||
}
|
||||
|
||||
86
src/SPC/command/InstallPkgCommand.php
Normal file
86
src/SPC/command/InstallPkgCommand.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\command;
|
||||
|
||||
use SPC\builder\traits\UnixSystemUtilTrait;
|
||||
use SPC\exception\DownloaderException;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
use SPC\store\PackageManager;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
#[AsCommand('install-pkg', 'Install additional packages', ['i', 'install-package'])]
|
||||
class InstallPkgCommand extends BaseCommand
|
||||
{
|
||||
use UnixSystemUtilTrait;
|
||||
|
||||
public function configure(): void
|
||||
{
|
||||
$this->addArgument('packages', InputArgument::REQUIRED, 'The packages will be installed, comma separated');
|
||||
$this->addOption('shallow-clone', null, null, 'Clone shallow');
|
||||
$this->addOption('custom-url', 'U', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Specify custom source download url, e.g "php-src:https://downloads.php.net/~eric/php-8.3.0beta1.tar.gz"');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
try {
|
||||
// Use shallow-clone can reduce git resource download
|
||||
if ($this->getOption('shallow-clone')) {
|
||||
define('GIT_SHALLOW_CLONE', true);
|
||||
}
|
||||
|
||||
// Process -U options
|
||||
$custom_urls = [];
|
||||
foreach ($this->input->getOption('custom-url') as $value) {
|
||||
[$pkg_name, $url] = explode(':', $value, 2);
|
||||
$custom_urls[$pkg_name] = $url;
|
||||
}
|
||||
|
||||
$chosen_pkgs = array_map('trim', array_filter(explode(',', $this->getArgument('packages'))));
|
||||
|
||||
// Download them
|
||||
f_mkdir(DOWNLOAD_PATH);
|
||||
$ni = 0;
|
||||
$cnt = count($chosen_pkgs);
|
||||
|
||||
foreach ($chosen_pkgs as $pkg) {
|
||||
++$ni;
|
||||
if (isset($custom_urls[$pkg])) {
|
||||
$config = Config::getPkg($pkg);
|
||||
$new_config = [
|
||||
'type' => 'url',
|
||||
'url' => $custom_urls[$pkg],
|
||||
];
|
||||
if (isset($config['extract'])) {
|
||||
$new_config['extract'] = $config['extract'];
|
||||
}
|
||||
if (isset($config['filename'])) {
|
||||
$new_config['filename'] = $config['filename'];
|
||||
}
|
||||
logger()->info("Installing source {$pkg} from custom url [{$ni}/{$cnt}]");
|
||||
PackageManager::installPackage($pkg, $new_config);
|
||||
} else {
|
||||
logger()->info("Fetching package {$pkg} [{$ni}/{$cnt}]");
|
||||
PackageManager::installPackage($pkg, Config::getPkg($pkg));
|
||||
}
|
||||
}
|
||||
$time = round(microtime(true) - START_TIME, 3);
|
||||
logger()->info('Install packages complete, used ' . $time . ' s !');
|
||||
return static::SUCCESS;
|
||||
} catch (DownloaderException $e) {
|
||||
logger()->error($e->getMessage());
|
||||
return static::FAILURE;
|
||||
} catch (WrongUsageException $e) {
|
||||
logger()->critical($e->getMessage());
|
||||
return static::FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,6 +57,15 @@ class SortConfigCommand extends BaseCommand
|
||||
return static::FAILURE;
|
||||
}
|
||||
break;
|
||||
case 'pkg':
|
||||
$file = json_decode(FileSystem::readFile(ROOT_DIR . '/config/pkg.json'), true);
|
||||
ConfigValidator::validatePkgs($file);
|
||||
ksort($file);
|
||||
if (!file_put_contents(ROOT_DIR . '/config/pkg.json', json_encode($file, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n")) {
|
||||
$this->output->writeln('<error>Write file pkg.json failed!</error>');
|
||||
return static::FAILURE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$this->output->writeln("<error>invalid config name: {$name}</error>");
|
||||
return 1;
|
||||
|
||||
@@ -57,7 +57,7 @@ class BSDToolCheckList
|
||||
$prefix = '';
|
||||
}
|
||||
try {
|
||||
shell(true)->exec("ASSUME_ALWAYS_YES=yes {$prefix} pkg install -y " . implode(' ', $missing));
|
||||
shell(true)->exec("ASSUME_ALWAYS_YES=yes {$prefix}pkg install -y " . implode(' ', $missing));
|
||||
} catch (RuntimeException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Downloader;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\store\PackageManager;
|
||||
|
||||
class LinuxMuslCheck
|
||||
{
|
||||
@@ -84,7 +85,6 @@ class LinuxMuslCheck
|
||||
|
||||
/** @noinspection PhpUnused */
|
||||
/**
|
||||
* @throws DownloaderException
|
||||
* @throws FileSystemException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
@@ -98,15 +98,10 @@ class LinuxMuslCheck
|
||||
logger()->warning('Current user is not root, using sudo for running command');
|
||||
}
|
||||
$arch = arch2gnu(php_uname('m'));
|
||||
$musl_compile_source = [
|
||||
'type' => 'url',
|
||||
'url' => "https://dl.static-php.dev/static-php-cli/deps/musl-toolchain/{$arch}-musl-toolchain.tgz",
|
||||
];
|
||||
logger()->info('Downloading ' . $musl_compile_source['url']);
|
||||
Downloader::downloadSource('musl-compile', $musl_compile_source);
|
||||
logger()->info('Extracting musl-cross');
|
||||
FileSystem::extractSource('musl-compile', DOWNLOAD_PATH . "/{$arch}-musl-toolchain.tgz");
|
||||
shell()->exec($prefix . 'cp -rf ' . SOURCE_PATH . '/musl-compile/* /usr/local/musl');
|
||||
PackageManager::installPackage("musl-toolchain-{$arch}-linux");
|
||||
$pkg_root = PKG_ROOT_PATH . "/musl-toolchain-{$arch}-linux";
|
||||
shell()->exec("{$prefix}cp -rf {$pkg_root}/* /usr/local/musl");
|
||||
FileSystem::removeDir($pkg_root);
|
||||
return true;
|
||||
} catch (RuntimeException) {
|
||||
return false;
|
||||
|
||||
@@ -9,8 +9,8 @@ use SPC\doctor\AsCheckItem;
|
||||
use SPC\doctor\AsFixItem;
|
||||
use SPC\doctor\CheckResult;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\store\Downloader;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\store\PackageManager;
|
||||
|
||||
class WindowsToolCheckList
|
||||
{
|
||||
@@ -64,8 +64,9 @@ class WindowsToolCheckList
|
||||
#[AsCheckItem('if perl(strawberry) installed', limit_os: 'Windows', level: 994)]
|
||||
public function checkPerl(): ?CheckResult
|
||||
{
|
||||
if (file_exists(BUILD_ROOT_PATH . '\perl\perl\bin\perl.exe')) {
|
||||
return CheckResult::ok(BUILD_ROOT_PATH . '\perl\perl\bin\perl.exe');
|
||||
$arch = arch2gnu(php_uname('m'));
|
||||
if (file_exists(PKG_ROOT_PATH . '\strawberry-perl-' . $arch . '-win\perl\bin\perl.exe')) {
|
||||
return CheckResult::ok(PKG_ROOT_PATH . '\strawberry-perl-' . $arch . '-win\perl\bin\perl.exe');
|
||||
}
|
||||
if (($path = SystemUtil::findCommand('perl.exe')) === null) {
|
||||
return CheckResult::fail('perl not found in path.', 'install-perl');
|
||||
@@ -91,32 +92,15 @@ class WindowsToolCheckList
|
||||
#[AsFixItem('install-nasm')]
|
||||
public function installNasm(): bool
|
||||
{
|
||||
// The hardcoded version here is to be consistent with the version compiled by `musl-cross-toolchain`.
|
||||
$nasm_ver = '2.16.01';
|
||||
$nasm_dist = "nasm-{$nasm_ver}";
|
||||
$source = [
|
||||
'type' => 'url',
|
||||
'url' => "https://www.nasm.us/pub/nasm/releasebuilds/{$nasm_ver}/win64/{$nasm_dist}-win64.zip",
|
||||
];
|
||||
logger()->info('Downloading ' . $source['url']);
|
||||
Downloader::downloadSource('nasm', $source);
|
||||
FileSystem::extractSource('nasm', DOWNLOAD_PATH . "\\{$nasm_dist}-win64.zip");
|
||||
copy(SOURCE_PATH . "\\nasm\\{$nasm_dist}\\nasm.exe", PHP_SDK_PATH . '\bin\nasm.exe');
|
||||
copy(SOURCE_PATH . "\\nasm\\{$nasm_dist}\\ndisasm.exe", PHP_SDK_PATH . '\bin\ndisasm.exe');
|
||||
PackageManager::installPackage('nasm-x86_64-win');
|
||||
return true;
|
||||
}
|
||||
|
||||
#[AsFixItem('install-perl')]
|
||||
public function installPerl(): bool
|
||||
{
|
||||
$url = 'https://github.com/StrawberryPerl/Perl-Dist-Strawberry/releases/download/SP_5380_5361/strawberry-perl-5.38.0.1-64bit-portable.zip';
|
||||
$source = [
|
||||
'type' => 'url',
|
||||
'url' => $url,
|
||||
];
|
||||
logger()->info("Downloading {$url}");
|
||||
Downloader::downloadSource('strawberry-perl', $source);
|
||||
FileSystem::extractSource('strawberry-perl', DOWNLOAD_PATH . '\strawberry-perl-5.38.0.1-64bit-portable.zip', '../buildroot/perl');
|
||||
$arch = arch2gnu(php_uname('m'));
|
||||
PackageManager::installPackage("strawberry-perl-{$arch}-win");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ use SPC\exception\WrongUsageException;
|
||||
*/
|
||||
class Config
|
||||
{
|
||||
public static ?array $pkg = null;
|
||||
|
||||
public static ?array $source = null;
|
||||
|
||||
public static ?array $lib = null;
|
||||
@@ -31,6 +33,19 @@ class Config
|
||||
return self::$source[$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read pkg from pkg.json
|
||||
*
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public static function getPkg(string $name): ?array
|
||||
{
|
||||
if (self::$pkg === null) {
|
||||
self::$pkg = FileSystem::loadConfigArray('pkg');
|
||||
}
|
||||
return self::$pkg[$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据不同的操作系统分别选择不同的 lib 库依赖项
|
||||
* 如果 key 为 null,那么直接返回整个 meta。
|
||||
|
||||
@@ -246,6 +246,92 @@ class Downloader
|
||||
}*/
|
||||
}
|
||||
|
||||
public static function downloadPackage(string $name, ?array $pkg = null, bool $force = false): void
|
||||
{
|
||||
if ($pkg === null) {
|
||||
$pkg = Config::getPkg($name);
|
||||
}
|
||||
|
||||
if ($pkg === null) {
|
||||
logger()->warning('Package {name} unknown. Skipping.', ['name' => $name]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_dir(DOWNLOAD_PATH)) {
|
||||
FileSystem::createDir(DOWNLOAD_PATH);
|
||||
}
|
||||
|
||||
// load lock file
|
||||
if (!file_exists(DOWNLOAD_PATH . '/.lock.json')) {
|
||||
$lock = [];
|
||||
} else {
|
||||
$lock = json_decode(FileSystem::readFile(DOWNLOAD_PATH . '/.lock.json'), true) ?? [];
|
||||
}
|
||||
// If lock file exists, skip downloading
|
||||
if (isset($lock[$name]) && !$force) {
|
||||
if ($lock[$name]['source_type'] === 'archive' && file_exists(DOWNLOAD_PATH . '/' . $lock[$name]['filename'])) {
|
||||
logger()->notice("Package [{$name}] already downloaded: " . $lock[$name]['filename']);
|
||||
return;
|
||||
}
|
||||
if ($lock[$name]['source_type'] === 'dir' && is_dir(DOWNLOAD_PATH . '/' . $lock[$name]['dirname'])) {
|
||||
logger()->notice("Package [{$name}] already downloaded: " . $lock[$name]['dirname']);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
switch ($pkg['type']) {
|
||||
case 'bitbuckettag': // BitBucket Tag
|
||||
[$url, $filename] = self::getLatestBitbucketTag($name, $pkg);
|
||||
self::downloadFile($name, $url, $filename, $pkg['extract'] ?? null);
|
||||
break;
|
||||
case 'ghtar': // GitHub Release (tar)
|
||||
[$url, $filename] = self::getLatestGithubTarball($name, $pkg);
|
||||
self::downloadFile($name, $url, $filename, $pkg['extract'] ?? null);
|
||||
break;
|
||||
case 'ghtagtar': // GitHub Tag (tar)
|
||||
[$url, $filename] = self::getLatestGithubTarball($name, $pkg, 'tags');
|
||||
self::downloadFile($name, $url, $filename, $pkg['extract'] ?? null);
|
||||
break;
|
||||
case 'ghrel': // GitHub Release (uploaded)
|
||||
[$url, $filename] = self::getLatestGithubRelease($name, $pkg);
|
||||
self::downloadFile($name, $url, $filename, $pkg['extract'] ?? null);
|
||||
break;
|
||||
case 'filelist': // Basic File List (regex based crawler)
|
||||
[$url, $filename] = self::getFromFileList($name, $pkg);
|
||||
self::downloadFile($name, $url, $filename, $pkg['extract'] ?? null);
|
||||
break;
|
||||
case 'url': // Direct download URL
|
||||
$url = $pkg['url'];
|
||||
$filename = $pkg['filename'] ?? basename($pkg['url']);
|
||||
self::downloadFile($name, $url, $filename, $pkg['extract'] ?? null);
|
||||
break;
|
||||
case 'git': // Git repo
|
||||
self::downloadGit($name, $pkg['url'], $pkg['rev'], $pkg['extract'] ?? null);
|
||||
break;
|
||||
case 'custom': // Custom download method, like API-based download or other
|
||||
$classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/store/source', 'SPC\\store\\source');
|
||||
foreach ($classes as $class) {
|
||||
if (is_a($class, CustomSourceBase::class, true) && $class::NAME === $name) {
|
||||
(new $class())->fetch();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new DownloaderException('unknown source type: ' . $pkg['type']);
|
||||
}
|
||||
} catch (RuntimeException $e) {
|
||||
// Because sometimes files downloaded through the command line are not automatically deleted after a failure.
|
||||
// Here we need to manually delete the file if it is detected to exist.
|
||||
if (isset($filename) && file_exists(DOWNLOAD_PATH . '/' . $filename)) {
|
||||
logger()->warning('Deleting download file: ' . $filename);
|
||||
unlink(DOWNLOAD_PATH . '/' . $filename);
|
||||
}
|
||||
throw new DownloaderException('Download failed! ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download source by name and meta.
|
||||
*
|
||||
|
||||
@@ -16,7 +16,7 @@ class FileSystem
|
||||
*/
|
||||
public static function loadConfigArray(string $config, ?string $config_dir = null): array
|
||||
{
|
||||
$whitelist = ['ext', 'lib', 'source'];
|
||||
$whitelist = ['ext', 'lib', 'source', 'pkg'];
|
||||
if (!in_array($config, $whitelist)) {
|
||||
throw new FileSystemException('Reading ' . $config . '.json is not allowed');
|
||||
}
|
||||
@@ -138,6 +138,37 @@ class FileSystem
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public static function extractPackage(string $name, string $filename, ?string $extract_path = null): void
|
||||
{
|
||||
if ($extract_path !== null) {
|
||||
// replace
|
||||
$extract_path = self::replacePathVariable($extract_path);
|
||||
$extract_path = self::isRelativePath($extract_path) ? (WORKING_DIR . '/' . $extract_path) : $extract_path;
|
||||
} else {
|
||||
$extract_path = PKG_ROOT_PATH . '/' . $name;
|
||||
}
|
||||
logger()->info("extracting {$name} package to {$extract_path} ...");
|
||||
$target = self::convertPath($extract_path);
|
||||
|
||||
if (!is_dir($dir = dirname($target))) {
|
||||
self::createDir($dir);
|
||||
}
|
||||
try {
|
||||
self::extractArchive($filename, $target);
|
||||
} catch (RuntimeException $e) {
|
||||
if (PHP_OS_FAMILY === 'Windows') {
|
||||
f_passthru('rmdir /s /q ' . $target);
|
||||
} else {
|
||||
f_passthru('rm -rf ' . $target);
|
||||
}
|
||||
throw new FileSystemException('Cannot extract package ' . $name, $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解压缩下载的资源包到 source 目录
|
||||
*
|
||||
@@ -152,52 +183,26 @@ class FileSystem
|
||||
if (self::$_extract_hook === []) {
|
||||
SourcePatcher::init();
|
||||
}
|
||||
if (!is_dir(SOURCE_PATH)) {
|
||||
self::createDir(SOURCE_PATH);
|
||||
}
|
||||
if ($move_path !== null) {
|
||||
$move_path = SOURCE_PATH . '/' . $move_path;
|
||||
} else {
|
||||
$move_path = SOURCE_PATH . "/{$name}";
|
||||
}
|
||||
$target = self::convertPath($move_path);
|
||||
logger()->info("extracting {$name} source to {$target}" . ' ...');
|
||||
if (!is_dir($dir = dirname($target))) {
|
||||
self::createDir($dir);
|
||||
}
|
||||
logger()->info("extracting {$name} source to " . ($move_path ?? SOURCE_PATH . "/{$name}") . ' ...');
|
||||
try {
|
||||
$target = self::convertPath($move_path ?? (SOURCE_PATH . "/{$name}"));
|
||||
// Git source, just move
|
||||
if (is_dir(self::convertPath($filename))) {
|
||||
self::copyDir(self::convertPath($filename), $target);
|
||||
self::emitSourceExtractHook($name);
|
||||
return;
|
||||
}
|
||||
if (f_mkdir(directory: $target, recursive: true) !== true) {
|
||||
throw new FileSystemException('create ' . $name . 'source dir failed');
|
||||
}
|
||||
|
||||
if (in_array(PHP_OS_FAMILY, ['Darwin', 'Linux', 'BSD'])) {
|
||||
match (self::extname($filename)) {
|
||||
'tar', 'xz', 'txz' => f_passthru("tar -xf {$filename} -C {$target} --strip-components 1"),
|
||||
'tgz', 'gz' => f_passthru("tar -xzf {$filename} -C {$target} --strip-components 1"),
|
||||
'bz2' => f_passthru("tar -xjf {$filename} -C {$target} --strip-components 1"),
|
||||
'zip' => f_passthru("unzip {$filename} -d {$target}"),
|
||||
default => throw new FileSystemException('unknown archive format: ' . $filename),
|
||||
};
|
||||
} elseif (PHP_OS_FAMILY === 'Windows') {
|
||||
// use php-sdk-binary-tools/bin/7za.exe
|
||||
$_7z = self::convertPath(PHP_SDK_PATH . '/bin/7za.exe');
|
||||
f_mkdir(SOURCE_PATH . "/{$name}", recursive: true);
|
||||
match (self::extname($filename)) {
|
||||
'tar' => f_passthru("tar -xf {$filename} -C {$target} --strip-components 1"),
|
||||
'xz', 'txz', 'gz', 'tgz', 'bz2' => f_passthru("\"{$_7z}\" x -so {$filename} | tar -f - -x -C {$target} --strip-components 1"),
|
||||
'zip' => f_passthru("\"{$_7z}\" x {$filename} -o{$target} -y"),
|
||||
default => throw new FileSystemException("unknown archive format: {$filename}"),
|
||||
};
|
||||
}
|
||||
self::extractArchive($filename, $target);
|
||||
self::emitSourceExtractHook($name);
|
||||
} catch (RuntimeException $e) {
|
||||
if (PHP_OS_FAMILY === 'Windows') {
|
||||
f_passthru('rmdir /s /q ' . SOURCE_PATH . "/{$name}");
|
||||
f_passthru('rmdir /s /q ' . $target);
|
||||
} else {
|
||||
f_passthru('rm -r ' . SOURCE_PATH . "/{$name}");
|
||||
f_passthru('rm -rf ' . $target);
|
||||
}
|
||||
throw new FileSystemException('Cannot extract source ' . $name, $e->getCode(), $e);
|
||||
throw new FileSystemException('Cannot extract source ' . $name . ': ' . $e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,6 +219,14 @@ class FileSystem
|
||||
return str_replace('/', DIRECTORY_SEPARATOR, $path);
|
||||
}
|
||||
|
||||
public static function convertWinPathToMinGW(string $path): string
|
||||
{
|
||||
if (preg_match('/^[A-Za-z]:/', $path)) {
|
||||
$path = '/' . strtolower(substr($path, 0, 1)) . '/' . str_replace('\\', '/', substr($path, 2));
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归或非递归扫描目录,可返回相对目录的文件列表或绝对目录的文件列表
|
||||
*
|
||||
@@ -411,6 +424,63 @@ class FileSystem
|
||||
return strlen($path) > 0 && $path[0] !== '/';
|
||||
}
|
||||
|
||||
public static function replacePathVariable(string $path): string
|
||||
{
|
||||
$replacement = [
|
||||
'{pkg_root_path}' => PKG_ROOT_PATH,
|
||||
'{php_sdk_path}' => defined('PHP_SDK_PATH') ? PHP_SDK_PATH : WORKING_DIR . '/php-sdk-binary-tools',
|
||||
'{working_dir}' => WORKING_DIR,
|
||||
'{download_path}' => DOWNLOAD_PATH,
|
||||
'{source_path}' => SOURCE_PATH,
|
||||
];
|
||||
return str_replace(array_keys($replacement), array_values($replacement), $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
private static function extractArchive(string $filename, string $target): void
|
||||
{
|
||||
// Git source, just move
|
||||
if (is_dir(self::convertPath($filename))) {
|
||||
self::copyDir(self::convertPath($filename), $target);
|
||||
return;
|
||||
}
|
||||
// Create base dir
|
||||
if (f_mkdir(directory: $target, recursive: true) !== true) {
|
||||
throw new FileSystemException('create ' . $target . ' dir failed');
|
||||
}
|
||||
if (!file_exists($filename)) {
|
||||
throw new FileSystemException('File not exists');
|
||||
}
|
||||
|
||||
if (in_array(PHP_OS_FAMILY, ['Darwin', 'Linux', 'BSD'])) {
|
||||
match (self::extname($filename)) {
|
||||
'tar', 'xz', 'txz' => f_passthru("tar -xf {$filename} -C {$target} --strip-components 1"),
|
||||
'tgz', 'gz' => f_passthru("tar -xzf {$filename} -C {$target} --strip-components 1"),
|
||||
'bz2' => f_passthru("tar -xjf {$filename} -C {$target} --strip-components 1"),
|
||||
'zip' => f_passthru("unzip {$filename} -d {$target}"),
|
||||
default => throw new FileSystemException('unknown archive format: ' . $filename),
|
||||
};
|
||||
} elseif (PHP_OS_FAMILY === 'Windows') {
|
||||
// use php-sdk-binary-tools/bin/7za.exe
|
||||
$_7z = self::convertPath(PHP_SDK_PATH . '/bin/7za.exe');
|
||||
|
||||
// Windows notes: I hate windows tar.......
|
||||
// When extracting .tar.gz like libxml2, it shows a symlink error and returns code[1].
|
||||
// Related posts: https://answers.microsoft.com/en-us/windows/forum/all/tar-on-windows-fails-to-extract-archive-containing/0ee9a7ea-9b1f-4fef-86a9-5d9dc35cea2f
|
||||
// And MinGW tar.exe cannot work on temporarily storage ??? (GitHub Actions hosted runner)
|
||||
// Yeah, I will be an MS HATER !
|
||||
match (self::extname($filename)) {
|
||||
'tar' => f_passthru("tar -xf {$filename} -C {$target} --strip-components 1"),
|
||||
'xz', 'txz', 'gz', 'tgz', 'bz2' => cmd()->execWithResult("\"{$_7z}\" x -so {$filename} | tar -f - -x -C \"{$target}\" --strip-components 1"),
|
||||
'zip' => f_passthru("\"{$_7z}\" x {$filename} -o{$target} -y"),
|
||||
default => throw new FileSystemException("unknown archive format: {$filename}"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
|
||||
67
src/SPC/store/PackageManager.php
Normal file
67
src/SPC/store/PackageManager.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\store;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
|
||||
class PackageManager
|
||||
{
|
||||
public static function installPackage(string $pkg_name, ?array $config = null, bool $force = false): void
|
||||
{
|
||||
if ($config === null) {
|
||||
$config = Config::getPkg($pkg_name);
|
||||
}
|
||||
if ($config === null) {
|
||||
$arch = arch2gnu(php_uname('m'));
|
||||
$os = match (PHP_OS_FAMILY) {
|
||||
'Linux' => 'linux',
|
||||
'Windows' => 'win',
|
||||
'BSD' => 'freebsd',
|
||||
'Darwin' => 'macos',
|
||||
default => throw new WrongUsageException('Unsupported OS!'),
|
||||
};
|
||||
$config = Config::getPkg("{$pkg_name}-{$arch}-{$os}");
|
||||
}
|
||||
if ($config === null) {
|
||||
throw new WrongUsageException("Package [{$pkg_name}] does not exist, please check the name and correct it !");
|
||||
}
|
||||
|
||||
// Download package
|
||||
Downloader::downloadPackage($pkg_name, $config, $force);
|
||||
// After download, read lock file name
|
||||
$lock = json_decode(FileSystem::readFile(DOWNLOAD_PATH . '/.lock.json'), true);
|
||||
$filename = DOWNLOAD_PATH . '/' . ($lock[$pkg_name]['filename'] ?? $lock[$pkg_name]['dirname']);
|
||||
$extract = $lock[$pkg_name]['move_path'] === null ? (PKG_ROOT_PATH . '/' . $pkg_name) : $lock[$pkg_name]['move_path'];
|
||||
FileSystem::extractPackage($pkg_name, $filename, $extract);
|
||||
|
||||
// if contains extract-files, we just move this file to destination, and remove extract dir
|
||||
if (is_array($config['extract-files'] ?? null) && is_assoc_array($config['extract-files'])) {
|
||||
$scandir = FileSystem::scanDirFiles($extract, true, true);
|
||||
foreach ($config['extract-files'] as $file => $target) {
|
||||
$target = FileSystem::convertPath(FileSystem::replacePathVariable($target));
|
||||
if (!is_dir($dir = dirname($target))) {
|
||||
f_mkdir($dir, 0755, true);
|
||||
}
|
||||
logger()->debug("Moving package [{$pkg_name}] file {$file} to {$target}");
|
||||
// match pattern, needs to scan dir
|
||||
$file = FileSystem::convertPath($file);
|
||||
$found = false;
|
||||
foreach ($scandir as $item) {
|
||||
if (match_pattern($file, $item)) {
|
||||
$file = $item;
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($found === false) {
|
||||
throw new FileSystemException('Unable to find extract-files item: ' . $file);
|
||||
}
|
||||
rename(FileSystem::convertPath($extract . '/' . $file), $target);
|
||||
}
|
||||
FileSystem::removeDir($extract);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
|
||||
class SourceExtractor
|
||||
class SourceManager
|
||||
{
|
||||
/**
|
||||
* @throws WrongUsageException
|
||||
@@ -70,4 +70,12 @@ class ConfigValidator
|
||||
{
|
||||
is_array($data) || throw new ValidationException('ext.json is broken');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public static function validatePkgs(mixed $data): void
|
||||
{
|
||||
is_array($data) || throw new ValidationException('pkg.json is broken');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ define('START_TIME', microtime(true));
|
||||
define('BUILD_ROOT_PATH', FileSystem::convertPath(is_string($a = getenv('BUILD_ROOT_PATH')) ? $a : (WORKING_DIR . '/buildroot')));
|
||||
define('SOURCE_PATH', FileSystem::convertPath(is_string($a = getenv('SOURCE_PATH')) ? $a : (WORKING_DIR . '/source')));
|
||||
define('DOWNLOAD_PATH', FileSystem::convertPath(is_string($a = getenv('DOWNLOAD_PATH')) ? $a : (WORKING_DIR . '/downloads')));
|
||||
define('PKG_ROOT_PATH', FileSystem::convertPath(is_string($a = getenv('PKG_ROOT_PATH')) ? $a : (WORKING_DIR . '/pkgroot')));
|
||||
define('BUILD_BIN_PATH', FileSystem::convertPath(is_string($a = getenv('INSTALL_BIN_PATH')) ? $a : (BUILD_ROOT_PATH . '/bin')));
|
||||
define('BUILD_LIB_PATH', FileSystem::convertPath(is_string($a = getenv('INSTALL_LIB_PATH')) ? $a : (BUILD_ROOT_PATH . '/lib')));
|
||||
define('BUILD_INCLUDE_PATH', FileSystem::convertPath(is_string($a = getenv('INSTALL_INCLUDE_PATH')) ? $a : (BUILD_ROOT_PATH . '/include')));
|
||||
|
||||
69
src/globals/extra/Makefile-sqlite
Normal file
69
src/globals/extra/Makefile-sqlite
Normal file
@@ -0,0 +1,69 @@
|
||||
|
||||
CC=cl.exe /nologo
|
||||
AR=lib.exe /nologo
|
||||
LINK=link.exe /nologo
|
||||
|
||||
!IF "" == "$(MACHINE)"
|
||||
MACHINE=x64
|
||||
!ENDIF
|
||||
|
||||
!IF "" == "$(CRT)"
|
||||
CRT=vc15
|
||||
!ENDIF
|
||||
|
||||
!IF "" == "$(PREFIX)"
|
||||
PREFIX="$(CRT)-$(MACHINE)"
|
||||
!ENDIF
|
||||
|
||||
COMMON_CFLAGS=/D SQLITE_THREADSAFE=1 /DSQLITE_ENABLE_FTS3=1 /D SQLITE_ENABLE_FTS4=1 /D SQLITE_ENABLE_FTS5=1 /D SQLITE_ENABLE_JSON1=1 /D SQLITE_ENABLE_COLUMN_METADATA=1 /D SQLITE_CORE=1
|
||||
!IF "$(DEBUG)"=="1"
|
||||
SQLITE3_STATIC_BASE=libsqlite3_a_debug
|
||||
SQLITE3_DLL_BASE=libsqlite3_debug
|
||||
SQLITE3_EXE_BASE=sqlite3
|
||||
CFLAGS=$(COMMON_CFLAGS) /Zi /MDd /Od /W3
|
||||
LDFLAGS=/DEBUG /GUARD:CF /INCREMENTAL:NO
|
||||
!ELSE
|
||||
SQLITE3_STATIC_BASE=libsqlite3_a
|
||||
SQLITE3_DLL_BASE=libsqlite3
|
||||
SQLITE3_EXE_BASE=sqlite3
|
||||
CFLAGS=$(COMMON_CFLAGS) /Zi /MT /guard:cf /Zc:inline /Qspectre /Ox /W3 /GF /GL /Gw
|
||||
LDFLAGS=/GUARD:CF /INCREMENTAL:NO /NXCOMPAT /DYNAMICBASE
|
||||
!ENDIF
|
||||
|
||||
|
||||
all: $(SQLITE3_STATIC_BASE).lib $(SQLITE3_EXE_BASE).exe $(SQLITE3_DLL_BASE).dll
|
||||
|
||||
install: all
|
||||
if not exist $(PREFIX)\bin mkdir $(PREFIX)\bin
|
||||
if not exist $(PREFIX)\include mkdir $(PREFIX)\include
|
||||
if not exist $(PREFIX)\lib mkdir $(PREFIX)\lib
|
||||
copy /Y sqlite3.h $(PREFIX)\include
|
||||
copy /Y sqlite3ext.h $(PREFIX)\include
|
||||
copy /Y $(SQLITE3_STATIC_BASE).lib $(PREFIX)\lib
|
||||
copy /Y $(SQLITE3_STATIC_BASE).pdb $(PREFIX)\lib
|
||||
copy /Y $(SQLITE3_DLL_BASE).lib $(PREFIX)\lib
|
||||
copy /Y $(SQLITE3_DLL_BASE).pdb $(PREFIX)\bin
|
||||
copy /Y $(SQLITE3_DLL_BASE).dll $(PREFIX)\bin
|
||||
copy /Y $(SQLITE3_EXE_BASE).exe $(PREFIX)\bin
|
||||
copy /Y $(SQLITE3_EXE_BASE).pdb $(PREFIX)\bin
|
||||
|
||||
install-static: $(SQLITE3_STATIC_BASE).lib
|
||||
if not exist $(PREFIX)\include mkdir $(PREFIX)\include
|
||||
if not exist $(PREFIX)\lib mkdir $(PREFIX)\lib
|
||||
copy /Y sqlite3.h $(PREFIX)\include
|
||||
copy /Y sqlite3ext.h $(PREFIX)\include
|
||||
copy /Y $(SQLITE3_STATIC_BASE).lib $(PREFIX)\lib
|
||||
|
||||
clean:
|
||||
del *.obj *.lib *.exe *.pdb *.dll *.exp
|
||||
|
||||
$(SQLITE3_STATIC_BASE).lib: sqlite3.c sqlite3.h
|
||||
$(CC) $(CFLAGS) /Fd$(SQLITE3_STATIC_BASE).pdb /c sqlite3.c
|
||||
$(AR) sqlite3.obj /OUT:$(SQLITE3_STATIC_BASE).lib
|
||||
|
||||
$(SQLITE3_EXE_BASE).exe: shell.c sqlite3.c sqlite3.h
|
||||
$(CC) $(CFLAGS) shell.c sqlite3.c /Fd$(SQLITE3_EXE_BASE).pdb /Fe$(SQLITE3_EXE_BASE).exe
|
||||
|
||||
$(SQLITE3_DLL_BASE).dll: sqlite3.c sqlite3.h
|
||||
$(CC) $(CFLAGS) /DSQLITE_API=__declspec(dllexport) /Fd$(SQLITE3_DLL_BASE).pdb /c sqlite3.c
|
||||
$(LINK) /DLL /OUT:$(SQLITE3_DLL_BASE).dll sqlite3.obj
|
||||
@@ -47,6 +47,13 @@ function arch2gnu(string $arch): string
|
||||
};
|
||||
}
|
||||
|
||||
function match_pattern(string $pattern, string $subject): bool
|
||||
{
|
||||
$pattern = str_replace(['\*', '\\\\.*'], ['.*', '\*'], preg_quote($pattern, '/'));
|
||||
$pattern = '/^' . $pattern . '$/i';
|
||||
return preg_match($pattern, $subject) === 1;
|
||||
}
|
||||
|
||||
function quote(string $str, string $quote = '"'): string
|
||||
{
|
||||
return $quote . $str . $quote;
|
||||
|
||||
@@ -13,13 +13,13 @@ declare(strict_types=1);
|
||||
|
||||
// If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`).
|
||||
$extensions = match (PHP_OS_FAMILY) {
|
||||
'Linux', 'Darwin' => '',
|
||||
'Windows' => 'mbstring',
|
||||
'Linux', 'Darwin' => 'imagick,zstd,bz2,zip,xml,dom',
|
||||
'Windows' => 'mbstring,pdo_sqlite,mbregex,ffi',
|
||||
};
|
||||
|
||||
// If you want to test lib-suggests feature with extension, add them below (comma separated, example `libwebp,libavif`).
|
||||
$with_libs = match (PHP_OS_FAMILY) {
|
||||
'Linux', 'Darwin' => '',
|
||||
'Linux', 'Darwin' => 'xz',
|
||||
'Windows' => '',
|
||||
};
|
||||
|
||||
@@ -27,7 +27,7 @@ $with_libs = match (PHP_OS_FAMILY) {
|
||||
// You can use `common`, `bulk`, `minimal` or `none`.
|
||||
// note: combination is only available for *nix platform. Windows must use `none` combination
|
||||
$base_combination = match (PHP_OS_FAMILY) {
|
||||
'Linux', 'Darwin' => 'common',
|
||||
'Linux', 'Darwin' => 'minimal',
|
||||
'Windows' => 'none',
|
||||
};
|
||||
|
||||
@@ -62,6 +62,7 @@ $final_libs = trim($with_libs, $trim_value);
|
||||
|
||||
if (PHP_OS_FAMILY === 'Windows') {
|
||||
$final_extensions_cmd = '"' . $final_extensions . '"';
|
||||
$final_libs = $final_libs === '' ? '' : ('"' . $final_libs . '"');
|
||||
} else {
|
||||
$final_extensions_cmd = $final_extensions;
|
||||
}
|
||||
@@ -69,7 +70,7 @@ if (PHP_OS_FAMILY === 'Windows') {
|
||||
echo match ($argv[1]) {
|
||||
'extensions' => $final_extensions,
|
||||
'libs' => $final_libs,
|
||||
'libs_cmd' => ($final_libs === '' ? '' : (' --with-libs="' . $final_libs . '"')),
|
||||
'cmd' => $final_extensions_cmd . ($final_libs === '' ? '' : (' --with-libs="' . $final_libs . '"')),
|
||||
'libs_cmd' => ($final_libs === '' ? '' : (' --with-libs=' . $final_libs)),
|
||||
'cmd' => $final_extensions_cmd . ($final_libs === '' ? '' : (' --with-libs=' . $final_libs)),
|
||||
default => '',
|
||||
};
|
||||
|
||||
25
src/globals/tests/gettext.php
Normal file
25
src/globals/tests/gettext.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
assert(function_exists('gettext'));
|
||||
assert(function_exists('bindtextdomain'));
|
||||
assert(function_exists('textdomain'));
|
||||
assert(function_exists('bind_textdomain_codeset'));
|
||||
|
||||
if (!is_dir('locale/en_US/LC_MESSAGES/')) {
|
||||
mkdir('locale/en_US/LC_MESSAGES/', 0755, true);
|
||||
}
|
||||
if (!file_exists('locale/en_US/LC_MESSAGES/test.mo')) {
|
||||
$mo = '3hIElQAAAAACAAAAHAAAACwAAAAFAAAAPAAAAAAAAABQAAAABgAAAFEAAAAXAQAAWAAAAAcAAABwAQAAAQAAAAAAAAAAAAAAAgAAAAAAAAAA56S65L6LAFByb2plY3QtSWQtVmVyc2lvbjogUEFDS0FHRSBWRVJTSU9OClJlcG9ydC1Nc2dpZC1CdWdzLVRvOiAKUE8tUmV2aXNpb24tRGF0ZTogWUVBUi1NTy1EQSBITzpNSStaT05FCkxhc3QtVHJhbnNsYXRvcjogRlVMTCBOQU1FIDxFTUFJTEBBRERSRVNTPgpMYW5ndWFnZS1UZWFtOiBMQU5HVUFHRSA8TExAbGkub3JnPgpMYW5ndWFnZTogCk1JTUUtVmVyc2lvbjogMS4wCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD1VVEYtOApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiA4Yml0CgBFeGFtcGxlAA==';
|
||||
file_put_contents('locale/en_US/LC_MESSAGES/test.mo', base64_decode($mo));
|
||||
}
|
||||
putenv('LANG=en_US');
|
||||
setlocale(LC_ALL, 'en_US');
|
||||
|
||||
$domain = 'test';
|
||||
bindtextdomain($domain, 'locale/');
|
||||
bind_textdomain_codeset($domain, 'UTF-8');
|
||||
textdomain($domain);
|
||||
|
||||
assert(gettext(json_decode('"\u793a\u4f8b"', true)) === 'Example');
|
||||
Reference in New Issue
Block a user