Compare commits

...

55 Commits

Author SHA1 Message Date
crazywhalecc
f7730735c0 prepare to release rc3 2023-07-27 23:23:57 +08:00
crazywhalecc
752b88f62d prepare to release rc3, add dev:php-ver command 2023-07-27 23:18:44 +08:00
crazywhalecc
6131e1881b enable compile optimization for other libraries 2023-07-27 22:22:47 +08:00
crazywhalecc
980da4ea0f fix mbregex without mbstring failed check (fix #96) 2023-07-27 18:47:09 +08:00
crazywhalecc
b698ae2f50 add strip option (fix #97) 2023-07-27 18:43:18 +08:00
crazywhalecc
50632f6527 fix libpng build bug for linux 2023-07-27 18:17:06 +08:00
crazywhalecc
6d4755d8c9 fix pgsql dependency 2023-07-27 18:16:51 +08:00
crazywhalecc
75b85c26dc add memcached for macOS 2023-07-26 00:13:27 +08:00
crazywhalecc
1c8bbfbbdf fix libevent bug 2023-07-26 00:13:27 +08:00
crazywhalecc
c5a70f101a fix macOS C++ space 2023-07-26 00:13:27 +08:00
crazywhalecc
956c87a657 add memcache support 2023-07-25 21:46:57 +08:00
crazywhalecc
778b0eadcd add default openssl.cnf path for macOS 2023-07-25 00:31:12 +08:00
crazywhalecc
b8e6f9d1be add hasCppExtension check 2023-07-24 23:49:52 +08:00
crazywhalecc
0e024a8c43 change default to docker (some c++ packages needed) 2023-07-23 23:16:18 +08:00
crazywhalecc
65b0bd01c8 add auto-detect icu support for postgresql 2023-07-23 22:56:04 +08:00
crazywhalecc
3745dfc931 fix #75 2023-07-23 22:54:32 +08:00
crazywhalecc
0186ae5ff2 remove build upload downloads.zip, separated workflow instead 2023-07-23 11:30:54 +08:00
crazywhalecc
f1eacac4fd change extension count 2023-07-22 17:34:33 +08:00
crazywhalecc
4abe0064e6 add dev commands 2023-07-22 17:33:38 +08:00
crazywhalecc
cbc3adbec0 fix pgsql env problem 2023-07-22 16:29:46 +08:00
Jerry Ma
0902f80b46 Merge pull request #84 from jingjingxyk/pgsql
添加pgsql 库
2023-07-22 16:19:43 +08:00
crazywhalecc
47101d058b reformat code 2023-07-22 16:12:12 +08:00
crazywhalecc
bc978ecbde add macOS support for pgsql 2023-07-22 15:07:53 +08:00
Jerry
a2cb5165d3 add english tips 2023-07-21 17:09:11 +08:00
Jerry
e582fa8b22 Merge remote-tracking branch 'origin/refactor' into refactor 2023-07-21 16:34:56 +08:00
Jerry
8ec8838634 bold 2023-07-21 16:34:40 +08:00
Jerry Ma
8f259ffed9 Update README-en.md, add branch rename notes 2023-07-21 14:46:45 +08:00
Jerry Ma
74c2cf824b Update README.md, add branch name change notes 2023-07-21 14:46:12 +08:00
Jerry Ma
9ea3b04e82 Update README-en.md 2023-07-21 09:48:28 +08:00
Jerry Ma
99cb8c77b7 Update README.md 2023-07-21 09:47:39 +08:00
Jerry Ma
7056280c57 Update README-en.md 2023-07-20 11:41:15 +08:00
Jerry Ma
c14421c9ca Update README.md 2023-07-20 11:40:57 +08:00
crazywhalecc
97eff64b5b add micro:combine command 2023-07-20 01:15:28 +08:00
crazywhalecc
e522258693 fix libpng mac source bug 2023-07-20 01:15:05 +08:00
crazywhalecc
b84c68fe11 add doctor linux support 2023-07-17 21:44:17 +08:00
crazywhalecc
8505feaa66 fix createDir not working 2023-07-17 21:41:26 +08:00
crazywhalecc
41f49c20ff add --from-zip command to download locally 2023-07-17 21:36:50 +08:00
crazywhalecc
1912ae36e6 separate system tools list 2023-07-17 21:11:06 +08:00
crazywhalecc
08efc81cf0 add --auto-fix option 2023-07-17 21:10:49 +08:00
crazywhalecc
a3b09c69cc correct alpine build commands 2023-07-17 21:05:39 +08:00
crazywhalecc
5cf105c3a5 fix distro 2023-07-17 20:59:59 +08:00
crazywhalecc
7408781d13 add linux-header installer for alpine 2023-07-17 20:58:48 +08:00
crazywhalecc
0afc8ea2c3 add linux tool check 2023-07-17 20:31:42 +08:00
crazywhalecc
67b073776c add linux tool check 2023-07-17 20:29:02 +08:00
crazywhalecc
8b48cf7f70 add linux tool check 2023-07-17 20:28:08 +08:00
crazywhalecc
63287dd9c4 add linux tool check 2023-07-17 20:26:48 +08:00
crazywhalecc
fc7ac921e2 add document contributing guide 2023-07-17 18:39:34 +08:00
crazywhalecc
57e3193a2a add document 2023-07-17 18:01:45 +08:00
crazywhalecc
388f547878 add document 2023-07-17 17:59:44 +08:00
jingjingxyk
085437e925 pgsql 禁用 依赖libzstd icu库 2023-07-01 18:04:42 +08:00
jingjingxyk
fa17a48483 pgsql 禁用 依赖libzstd icu库 2023-07-01 17:31:46 +08:00
jingjingxyk
78c1484570 解决debian 环境下 pgsql 构建共享库报错 2023-07-01 13:01:53 +08:00
jingjingxyk
9c2ea79bec update pgsql config 2023-06-30 21:00:49 +08:00
jingjingxyk
b7ffe3fd1f 添加pgsql 配置 2023-06-30 20:53:18 +08:00
jingjingxyk
dac14ae16e 添加pgsql 库 2023-06-30 20:36:51 +08:00
35 changed files with 783 additions and 164 deletions

View File

@@ -77,10 +77,10 @@ jobs:
# If there's no dependencies cache, fetch sources, with or without debug # If there's no dependencies cache, fetch sources, with or without debug
- if: steps.cache-download.outputs.cache-hit != 'true' - if: steps.cache-download.outputs.cache-hit != 'true'
run: CACHE_API_EXEC=yes ./bin/spc download --with-php=${{ inputs.version }} --all ${{ env.SPC_BUILD_DEBUG }} run: CACHE_API_EXEC=yes ./bin/spc-alpine-docker download --with-php=${{ inputs.version }} --all ${{ env.SPC_BUILD_DEBUG }}
# Run build command # Run build command
- run: ./bin/spc build ${{ inputs.extensions }} ${{ env.SPC_BUILD_DEBUG }} ${{ env.SPC_BUILD_CLI }} ${{ env.SPC_BUILD_MICRO }} ${{ env.SPC_BUILD_FPM }} - run: ./bin/spc-alpine-docker build ${{ inputs.extensions }} ${{ env.SPC_BUILD_DEBUG }} ${{ env.SPC_BUILD_CLI }} ${{ env.SPC_BUILD_MICRO }} ${{ env.SPC_BUILD_FPM }}
# Upload cli executable # Upload cli executable
- if: ${{ inputs.build-cli == true }} - if: ${{ inputs.build-cli == true }}
@@ -115,8 +115,3 @@ jobs:
buildroot/build-extensions.json buildroot/build-extensions.json
buildroot/build-libraries.json buildroot/build-libraries.json
# Upload downloaded files
- uses: actions/upload-artifact@v3
with:
name: download-files
path: downloads/

View File

@@ -115,8 +115,3 @@ jobs:
buildroot/build-extensions.json buildroot/build-extensions.json
buildroot/build-libraries.json buildroot/build-libraries.json
# Upload downloaded files
- uses: actions/upload-artifact@v3
with:
name: download-files
path: downloads/

View File

@@ -11,14 +11,16 @@ This feature is provided by [dixyes/phpmicro](https://github.com/dixyes/phpmicro
<img width="600" alt="截屏2023-05-02 15 52 33" src="https://user-images.githubusercontent.com/20330940/235610318-2ef4e3f1-278b-4ca4-99f4-b38120efc395.png"> <img width="600" alt="截屏2023-05-02 15 52 33" src="https://user-images.githubusercontent.com/20330940/235610318-2ef4e3f1-278b-4ca4-99f4-b38120efc395.png">
[![Version](https://img.shields.io/badge/Version-2.0--rc1-pink.svg?style=flat-square)]() [![Version](https://img.shields.io/badge/Version-2.0--rc3-pink.svg?style=flat-square)]()
[![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)]() [![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)]()
[![](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/build-linux-x86_64.yml?branch=refactor&label=Linux%20Build&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml) [![](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/build-linux-x86_64.yml?branch=refactor&label=Linux%20Build&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml)
[![](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/build-macos-x86_64.yml?branch=refactor&label=macOS%20Build&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml) [![](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/build-macos-x86_64.yml?branch=refactor&label=macOS%20Build&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml)
[![](https://img.shields.io/badge/Extension%20Counter-50+-yellow.svg?style=flat-square)]() [![](https://img.shields.io/badge/Extension%20Counter-55+-yellow.svg?style=flat-square)]()
[![](https://img.shields.io/github/search/crazywhalecc/static-php-cli/TODO?label=TODO%20Counter&style=flat-square)]() [![](https://img.shields.io/github/search/crazywhalecc/static-php-cli/TODO?label=TODO%20Counter&style=flat-square)]()
> The project has renamed the `refactor` branch to the `main` branch, please pay attention to changing the branch name for dependent projects.
## Compilation Requirements ## Compilation Requirements
Yes, this project is written in PHP, pretty funny. Yes, this project is written in PHP, pretty funny.
@@ -37,7 +39,11 @@ Here is the architecture support status, where `CI` represents support for GitHu
Currently supported PHP versions for compilation are: `7.4`, `8.0`, `8.1`, `8.2`. Currently supported PHP versions for compilation are: `7.4`, `8.0`, `8.1`, `8.2`.
## Usage ## Docs
docs here: <https://static-php-cli.zhamao.me>.
## Simple Usage
Please first select the extension you want to compile based on the extension list below. Please first select the extension you want to compile based on the extension list below.
@@ -49,7 +55,7 @@ If you don't compile yourself, you can download pre-compiled artifact from Actio
### Supported Extensions ### Supported Extensions
[Supported Extension List](/ext-support.md) [Supported Extension List](https://static-php-cli.zhamao.me/en/guide/extensions.html)
> If there is no extension you need here, you can submit an issue. > If there is no extension you need here, you can submit an issue.
@@ -100,7 +106,7 @@ Basic usage for building php and micro with some extensions:
cd static-php-cli cd static-php-cli
composer update composer update
chmod +x bin/spc chmod +x bin/spc
# Check system tool dependencies, fix them automatically (only support macOS) (TODO: Linux distro support) # Check system tool dependencies, fix them automatically
./bin/spc doctor ./bin/spc doctor
# fetch all libraries # fetch all libraries
./bin/spc fetch --all ./bin/spc fetch --all
@@ -217,6 +223,13 @@ The basic principles for contributing are as follows:
camelCase and underscore formats should be followed, and mixing within the same module is prohibited. camelCase and underscore formats should be followed, and mixing within the same module is prohibited.
- When compiling external libraries and creating patches, compatibility with different operating systems should be considered. - When compiling external libraries and creating patches, compatibility with different operating systems should be considered.
If you want to contribute document content, please go to [crazywhalecc/static-php-cli-docs](https://github.com/crazywhalecc/static-php-cli-docs).
Part of the English document is written by me, and part is translated by Google,
and there may be inaccurate descriptions, strange or offensive expressions.
If you are a native English speaker, some corrections to the documentation are welcome.
## Sponsor this project ## 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).
@@ -238,6 +251,6 @@ and comply with the corresponding project's LICENSE.
## Advanced ## Advanced
This project is pure open source project, and some modules are separated for developing. The refactoring branch of this project is written modularly.
If you are interested in this project and want to join the development,
This section will be improved after refactor version released. you can refer to the [Contribution Guide](https://static-php-cli.zhamao.me) of the documentation to contribute code or documentation. (TODO)

View File

@@ -2,7 +2,7 @@
Compile A Statically Linked PHP With Swoole and other Extensions. Compile A Statically Linked PHP With Swoole and other Extensions.
If you are using English, see [English README](README-en.md). **If you are using English, see [English README](README-en.md).**
编译纯静态的 PHP Binary 二进制文件,带有各种扩展,让 PHP-cli 应用变得更便携cli SAPI 编译纯静态的 PHP Binary 二进制文件,带有各种扩展,让 PHP-cli 应用变得更便携cli SAPI
@@ -12,13 +12,15 @@ If you are using English, see [English README](README-en.md).
<img width="600" alt="截屏2023-05-02 15 52 33" src="https://user-images.githubusercontent.com/20330940/235610318-2ef4e3f1-278b-4ca4-99f4-b38120efc395.png"> <img width="600" alt="截屏2023-05-02 15 52 33" src="https://user-images.githubusercontent.com/20330940/235610318-2ef4e3f1-278b-4ca4-99f4-b38120efc395.png">
[![Version](https://img.shields.io/badge/Version-2.0--rc1-pink.svg?style=flat-square)]() [![Version](https://img.shields.io/badge/Version-2.0--rc3-pink.svg?style=flat-square)]()
[![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)]() [![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)]()
[![](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/build-linux-x86_64.yml?branch=refactor&label=Linux%20Build&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml) [![](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/build-linux-x86_64.yml?branch=refactor&label=Linux%20Build&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml)
[![](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/build-macos-x86_64.yml?branch=refactor&label=macOS%20Build&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml) [![](https://img.shields.io/github/actions/workflow/status/crazywhalecc/static-php-cli/build-macos-x86_64.yml?branch=refactor&label=macOS%20Build&style=flat-square)](https://github.com/crazywhalecc/static-php-cli/actions/workflows/build.yml)
[![](https://img.shields.io/badge/Extension%20Counter-50+-yellow.svg?style=flat-square)]() [![](https://img.shields.io/badge/Extension%20Counter-55+-yellow.svg?style=flat-square)]()
[![](https://img.shields.io/github/search/crazywhalecc/static-php-cli/TODO?label=TODO%20Counter&style=flat-square)]() [![](https://img.shields.io/github/search/crazywhalecc/static-php-cli/TODO?label=TODO%20Counter&style=flat-square)]()
> 项目已重命名 `refactor` 分支为 `main` 分支,请依赖的项目注意更改分支名称。
## 编译环境需求 ## 编译环境需求
是的,本项目采用 PHP 编写,编译前需要一个 PHP 环境,比较滑稽。 是的,本项目采用 PHP 编写,编译前需要一个 PHP 环境,比较滑稽。
@@ -36,6 +38,10 @@ If you are using English, see [English README](README-en.md).
目前支持编译的 PHP 版本为:`7.4``8.0``8.1``8.2` 目前支持编译的 PHP 版本为:`7.4``8.0``8.1``8.2`
## 文档
点击这里查看文档:<https://static-php-cli.zhamao.me>。
## 使用 ## 使用
请先根据下方扩展列表选择你要编译的扩展。 请先根据下方扩展列表选择你要编译的扩展。
@@ -48,7 +54,7 @@ If you are using English, see [English README](README-en.md).
### 支持的扩展情况 ### 支持的扩展情况
[扩展支持列表](/ext-support.md) [扩展支持列表](https://static-php-cli.zhamao.me/zh/guide/extensions.html)
> 如果这里没有你需要的扩展,可以提交 Issue。 > 如果这里没有你需要的扩展,可以提交 Issue。
@@ -94,7 +100,7 @@ chmod +x bin/setup-runtime
cd static-php-cli cd static-php-cli
composer update composer update
chmod +x bin/spc chmod +x bin/spc
# 检查环境依赖,并根据提示的命令安装缺失的编译工具(目前仅支持 macOSLinux 后续会支持) # 检查环境依赖,并根据提示的命令安装缺失的编译工具
./bin/spc doctor ./bin/spc doctor
# 拉取所有依赖库 # 拉取所有依赖库
./bin/spc fetch --all ./bin/spc fetch --all
@@ -200,6 +206,8 @@ cat micro.sfx code.php > single-app && chmod +x single-app
另外,添加新扩展的贡献方式,可以参考下方 `进阶` 另外,添加新扩展的贡献方式,可以参考下方 `进阶`
如果你想贡献文档内容,请到项目仓库 [crazywhalecc/static-php-cli-docs](https://github.com/crazywhalecc/static-php-cli-docs) 贡献。
## 赞助本项目 ## 赞助本项目
你可以在 [我的个人赞助页](https://github.com/crazywhalecc/crazywhalecc/blob/master/FUNDING.md) 支持我和我的项目。 你可以在 [我的个人赞助页](https://github.com/crazywhalecc/crazywhalecc/blob/master/FUNDING.md) 支持我和我的项目。
@@ -216,6 +224,4 @@ cat micro.sfx code.php > single-app && chmod +x single-app
## 进阶 ## 进阶
本项目重构分支为模块化编写。 本项目重构分支为模块化编写。如果你对本项目感兴趣,想加入开发,可以参照文档的 [贡献指南](https://static-php-cli.zhamao.me) 贡献代码或文档。TODO
TODO这部分将在基础功能完成后编写完成。

View File

@@ -53,6 +53,19 @@
"sockets" "sockets"
] ]
}, },
"memcached": {
"type": "external",
"source": "memcached",
"arg-type": "custom",
"cpp-extension": true,
"lib-depends": [
"libmemcached"
],
"ext-depends": [
"session",
"zlib"
]
},
"exif": { "exif": {
"type": "builtin" "type": "builtin"
}, },
@@ -138,6 +151,7 @@
}, },
"intl": { "intl": {
"type": "builtin", "type": "builtin",
"cpp-extension": true,
"lib-depends": [ "lib-depends": [
"icu" "icu"
] ]
@@ -151,8 +165,9 @@
}, },
"mbregex": { "mbregex": {
"type": "builtin", "type": "builtin",
"lib-depends": [ "arg-type": "custom",
"onig" "ext-depends": [
"mbstring"
] ]
}, },
"mbstring": { "mbstring": {
@@ -162,6 +177,17 @@
"onig" "onig"
] ]
}, },
"memcache": {
"type": "external",
"source": "ext-memcache",
"arg-type": "custom",
"lib-depends": [
"zlib"
],
"ext-depends": [
"session"
]
},
"mongodb": { "mongodb": {
"type": "external", "type": "external",
"source": "mongodb", "source": "mongodb",
@@ -211,12 +237,13 @@
}, },
"pdo_pgsql": { "pdo_pgsql": {
"type": "builtin", "type": "builtin",
"arg-type": "with", "arg-type": "with-prefix",
"ext-depends": [ "ext-depends": [
"pdo" "pdo",
"pgsql"
], ],
"lib-depends": [ "lib-depends": [
"pq" "postgresql"
] ]
}, },
"pdo_sqlite": { "pdo_sqlite": {
@@ -230,6 +257,13 @@
"sqlite" "sqlite"
] ]
}, },
"pgsql": {
"type": "builtin",
"arg-type": "with-prefix",
"lib-depends": [
"postgresql"
]
},
"phar": { "phar": {
"type": "builtin", "type": "builtin",
"ext-depends": [ "ext-depends": [
@@ -320,6 +354,7 @@
"type": "external", "type": "external",
"source": "swoole", "source": "swoole",
"arg-type": "custom", "arg-type": "custom",
"cpp-extension": true,
"lib-depends": [ "lib-depends": [
"openssl" "openssl"
], ],

View File

@@ -381,7 +381,19 @@
"postgresql": { "postgresql": {
"source": "postgresql", "source": "postgresql",
"static-libs-unix": [ "static-libs-unix": [
"libpg.a" "libpq.a",
"libpgport.a",
"libpgcommon.a"
],
"lib-depends": [
"libiconv",
"libxml2",
"openssl",
"zlib",
"readline"
],
"lib-suggests": [
"icu"
] ]
}, },
"pthreads4w": { "pthreads4w": {
@@ -450,6 +462,13 @@
"zconf.h" "zconf.h"
] ]
}, },
"libmemcached": {
"source": "libmemcached",
"static-libs-unix": [
"libmemcached.a",
"libmemcachedutil.a"
]
},
"zstd": { "zstd": {
"source": "zstd", "source": "zstd",
"static-libs-unix": [ "static-libs-unix": [

View File

@@ -16,6 +16,25 @@
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"memcached": {
"type": "url",
"url": "https://pecl.php.net/get/memcached",
"path": "php-src/ext/memcached",
"filename": "memcached.tgz",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"libmemcached": {
"type": "git",
"url": "https://github.com/crazywhalecc/libmemcached-macos.git",
"rev": "master",
"license": {
"type": "file",
"path": "COPYING"
}
},
"brotli": { "brotli": {
"type": "ghtar", "type": "ghtar",
"repo": "google/brotli", "repo": "google/brotli",
@@ -61,6 +80,16 @@
"path": "LICENSE" "path": "LICENSE"
} }
}, },
"ext-memcache": {
"type": "url",
"url": "https://pecl.php.net/get/memcache",
"path": "php-src/ext/memcache",
"filename": "memcache.tgz",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"ext-ssh2": { "ext-ssh2": {
"type": "url", "type": "url",
"url": "https://pecl.php.net/get/ssh2", "url": "https://pecl.php.net/get/ssh2",
@@ -318,7 +347,8 @@
} }
}, },
"postgresql": { "postgresql": {
"type": "custom", "type": "url",
"url": "https://ftp.postgresql.org/pub/source/v15.1/postgresql-15.1.tar.gz",
"license": { "license": {
"type": "file", "type": "file",
"path": "COPYRIGHT" "path": "COPYRIGHT"

View File

@@ -1,112 +1,3 @@
# Extension List # Extension List
> - yes: supported and tested See: [Docs - Extensions](https://static-php-cli.zhamao.me/en/guide/extensions.html)
> - untested: supported, but not tested
> - empty: not supported yet
> - no with issue link: not supported yet due to issue
> - partial with issue link: supported but not perfect due to issue
| | Linux | macOS | Windows |
|-----------------|---------------------------------------------------------------------|----------------------------------------------------------------|---------|
| apcu | yes, untested | yes, untested | |
| bcmath | yes | yes | |
| bz2 | yes | yes | |
| calendar | yes | yes | |
| ctype | yes | yes | |
| curl | yes | yes | |
| dba | yes | yes | |
| dom | yes | yes | |
| enchant | | | |
| event | yes | yes | |
| exif | yes | yes | |
| ffi | | yes, [docs]() | |
| filter | yes | yes | |
| fileinfo | yes | yes | |
| ftp | yes | yes | |
| gd | yes | yes | |
| gettext | | | |
| gmp | yes | yes | |
| iconv | yes | yes | |
| imagick | yes | yes | |
| inotify | yes | yes | |
| intl | [partial](https://github.com/crazywhalecc/static-php-cli/issues/66) | yes | |
| mbstring | yes | yes | |
| mbregex | yes | yes | |
| mcrypt | | [no](https://github.com/crazywhalecc/static-php-cli/issues/32) | |
| mongodb | yes | yes | |
| mysqli | yes | yes | |
| mysqlnd | yes | yes | |
| opcache | yes | yes | |
| openssl | yes | yes | |
| password-argon2 | | | |
| pcntl | yes | yes | |
| pdo | yes | yes | |
| pdo_mysql | yes | yes | |
| pdo_sqlite | yes | yes | |
| pdo_pgsql | | | |
| phar | yes | yes | |
| posix | yes | yes | |
| protobuf | yes | yes | |
| readline | yes, untested | yes, untested | |
| redis | yes | yes | |
| session | yes | yes | |
| shmop | yes | yes | |
| simplexml | yes | yes | |
| soap | yes | yes | |
| sockets | yes | yes | |
| sodium | yes | yes | |
| sqlite3 | yes | yes | |
| ssh2 | yes, untested | yes, untested | |
| swow | yes | yes | |
| swoole | [partial](https://github.com/crazywhalecc/static-php-cli/issues/51) | yes | |
| tokenizer | yes | yes | |
| xlswriter | yes | yes | |
| xml | yes | yes | |
| xmlreader | yes, untested | yes, untested | |
| xmlwriter | yes, untested | yes, untested | |
| zip | yes, untested | yes, untested | |
| zlib | yes | yes | |
| zstd | yes | yes | |
## Additional Requirements
- phpmicro requires PHP >= 8.0
- swoole >= 5.0 requires PHP >= 8.0
- swow requires PHP >= 8.0
## Typical Extension List Example
Here are some extension list example for different use.
- For general use: `"bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,ftp,filter,gd,iconv,xml,mbstring,mysqlnd,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,redis,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip"`
- For static-php-cli self: `"posix,pcntl,phar,tokenizer,iconv,zlib"`
- For static-php-cli self (with dev dependencies): `"posix,pcntl,phar,tokenizer,iconv,zlib,xml,dom,xmlwriter,xmlreader,fileinfo"`
- Minimum, with no extension: `""`
Compile with all supported extensions (exclude `swow`, `swoole`, because these will change the default behavior of php):
```bash
bin/spc build --build-all bcmath,bz2,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,ftp,gd,gmp,iconv,mbregex,mbstring,mongodb,mysqli,mysqlnd,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,protobuf,redis,session,shmop,simplexml,soap,sockets,sqlite3,tokenizer,xml,xmlreader,xmlwriter,yaml,zip,zlib,zstd --with-libs=libjpeg,freetype,libwebp,libavif --debug
```
## Additional Libraries
Some extensions have soft dependencies, you can enable extra features by adding these libs using `--with-libs`.
For example, to compile with gd extension, with `libwebp, libgif, libavif, libjpeg, freetype` extra features:
```bash
bin/spc build gd --with-libs=libjpeg,freetype,libwebp,libavif --build-cli
```
> If you don't add them, your compilation will not enable these features.
## Limitations
- swow and swoole cannot be compiled at the same time.
- openssl needs manual configuration for ssl certificate. (TODO: I will write a wiki about it)
- some extensions need system configuration, e.g. `curl` and `openssl` will search ssl certificate on your system.
## Bugs and TODOs
See [#32](https://github.com/crazywhalecc/static-php-cli/issues/32).

View File

@@ -16,7 +16,7 @@ use Symfony\Component\Console\Command\ListCommand;
*/ */
class ConsoleApplication extends Application class ConsoleApplication extends Application
{ {
public const VERSION = '2.0-rc2'; public const VERSION = '2.0-rc3';
/** /**
* @throws \ReflectionException * @throws \ReflectionException

View File

@@ -140,6 +140,37 @@ abstract class BuilderBase
return $this->exts[$name] ?? null; return $this->exts[$name] ?? null;
} }
/**
* 获取所有要编译的扩展对象
*
* @return Extension[]
*/
public function getExts(): array
{
return $this->exts;
}
/**
* 检查 C++ 扩展是否存在
*
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
public function hasCppExtension(): bool
{
// judge cpp-extension
$exts = array_keys($this->getExts());
$cpp = false;
foreach ($exts as $ext) {
if (Config::getExt($ext, 'cpp-extension', false) === true) {
$cpp = true;
break;
}
}
return $cpp;
}
/** /**
* 设置本次 Builder 是否为仅编译库的模式 * 设置本次 Builder 是否为仅编译库的模式
*/ */

View File

@@ -14,4 +14,9 @@ class mbregex extends Extension
{ {
return 'mbstring'; return 'mbstring';
} }
public function getConfigureArg(): string
{
return '';
}
} }

View File

@@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\util\CustomExt;
#[CustomExt('memcache')]
class memcache extends Extension
{
public function getUnixConfigureArg(): string
{
return '--enable-memcache --with-zlib-dir=' . BUILD_ROOT_PATH;
}
}

View File

@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\util\CustomExt;
#[CustomExt('memcached')]
class memcached extends Extension
{
public function getUnixConfigureArg(): string
{
$rootdir = BUILD_ROOT_PATH;
return "--enable-memcached --with-zlib-dir={$rootdir} --with-libmemcached-dir={$rootdir} --disable-memcached-sasl --enable-memcached-json";
}
}

View File

@@ -21,7 +21,7 @@ class LinuxBuilder extends BuilderBase
use UnixBuilderTrait; use UnixBuilderTrait;
/** @var string[] Linux 环境下编译依赖的命令 */ /** @var string[] Linux 环境下编译依赖的命令 */
public const REQUIRED_COMMANDS = ['make', 'bison', 'flex', 'pkg-config', 'git', 'autoconf', 'automake', 'tar', 'unzip', /* 'xz', 好像不需要 */ 'gzip', 'bzip2', 'cmake']; public const REQUIRED_COMMANDS = ['make', 'bison', 'flex', 'git', 'autoconf', 'automake', 'tar', 'unzip', /* 'xz', 好像不需要 */ 'gzip', 'bzip2', 'cmake'];
/** @var string 使用的 libc */ /** @var string 使用的 libc */
public string $libc; public string $libc;
@@ -139,7 +139,8 @@ class LinuxBuilder extends BuilderBase
) )
); );
} }
if ($this->getExt('swoole') || $this->getExt('intl')) {
if ($this->hasCppExtension()) {
$extra_libs .= ' -lstdc++'; $extra_libs .= ' -lstdc++';
} }
if ($this->getExt('imagick')) { if ($this->getExt('imagick')) {

View File

@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\RuntimeException;
/**
* gmp is a template library class for unix
*/
class libmemcached extends LinuxLibraryBase
{
public const NAME = 'libmemcached';
public function build()
{
throw new RuntimeException('libmemcached is currently not supported on Linux platform');
}
}

View File

@@ -45,6 +45,7 @@ class libpng extends LinuxLibraryBase
shell()->cd($this->source_dir) shell()->cd($this->source_dir)
->exec('chmod +x ./configure') ->exec('chmod +x ./configure')
->exec('chmod +x ./install-sh')
->exec( ->exec(
"{$this->builder->configure_env} ./configure " . "{$this->builder->configure_env} ./configure " .
"--host={$this->builder->gnu_arch}-unknown-linux " . "--host={$this->builder->gnu_arch}-unknown-linux " .

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux\library;
class postgresql extends LinuxLibraryBase
{
use \SPC\builder\unix\library\postgresql;
public const NAME = 'postgresql';
}

View File

@@ -54,7 +54,7 @@ class MacOSBuilder extends BuilderBase
'PKG_CONFIG_PATH="' . BUILD_LIB_PATH . '/pkgconfig/" ' . 'PKG_CONFIG_PATH="' . BUILD_LIB_PATH . '/pkgconfig/" ' .
"CC='{$this->cc}' " . "CC='{$this->cc}' " .
"CXX='{$this->cxx}' " . "CXX='{$this->cxx}' " .
"CFLAGS='{$this->arch_c_flags} -Wimplicit-function-declaration'"; "CFLAGS='{$this->arch_c_flags} -Wimplicit-function-declaration -Os'";
// 创立 pkg-config 和放头文件的目录 // 创立 pkg-config 和放头文件的目录
f_mkdir(BUILD_LIB_PATH . '/pkgconfig', recursive: true); f_mkdir(BUILD_LIB_PATH . '/pkgconfig', recursive: true);
@@ -118,12 +118,15 @@ class MacOSBuilder extends BuilderBase
} }
/** /**
* @throws RuntimeException * @param int $build_target build target
* @param bool $bloat just raw add all lib files
* @throws FileSystemException * @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/ */
public function buildPHP(int $build_target = BUILD_TARGET_NONE, bool $bloat = false): void public function buildPHP(int $build_target = BUILD_TARGET_NONE, bool $bloat = false): void
{ {
$extra_libs = $this->getFrameworks(true) . ' ' . ($this->getExt('swoole') || $this->getExt('intl') ? '-lc++ ' : ''); $extra_libs = $this->getFrameworks(true) . ' ' . ($this->hasCppExtension() ? '-lc++ ' : '');
if (!$bloat) { if (!$bloat) {
$extra_libs .= implode(' ', $this->getAllStaticLibFiles()); $extra_libs .= implode(' ', $this->getAllStaticLibFiles());
} else { } else {
@@ -209,7 +212,7 @@ class MacOSBuilder extends BuilderBase
public function buildCli(string $extra_libs): void public function buildCli(string $extra_libs): void
{ {
$shell = shell()->cd(SOURCE_PATH . '/php-src'); $shell = shell()->cd(SOURCE_PATH . '/php-src');
$shell->exec("make -j{$this->concurrency} EXTRA_CFLAGS=\"-g -Os -fno-ident\" EXTRA_LIBS=\"{$extra_libs} -lresolv\" cli"); $shell->exec("make -j{$this->concurrency} EXTRA_CFLAGS=\"-g -Os\" EXTRA_LIBS=\"{$extra_libs} -lresolv\" cli");
if ($this->strip) { if ($this->strip) {
$shell->exec('dsymutil -f sapi/cli/php')->exec('strip sapi/cli/php'); $shell->exec('dsymutil -f sapi/cli/php')->exec('strip sapi/cli/php');
} }

View File

@@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace SPC\builder\macos\library;
/**
* gmp is a template library class for unix
*/
class libmemcached extends MacOSLibraryBase
{
public const NAME = 'libmemcached';
public function build()
{
$rootdir = BUILD_ROOT_PATH;
shell()->cd($this->source_dir)
->exec('chmod +x configure')
->exec(
"{$this->builder->configure_env} ./configure " .
'--enable-static --disable-shared ' .
'--disable-sasl ' .
"--prefix={$rootdir}"
)
->exec('make clean')
->exec('sed -ie "s/-Werror//g" ' . $this->source_dir . '/Makefile')
->exec("make -j{$this->builder->concurrency}")
->exec('make install');
}
}

View File

@@ -40,6 +40,7 @@ class libpng extends MacOSLibraryBase
}; };
shell()->cd($this->source_dir) shell()->cd($this->source_dir)
->exec('chmod +x ./configure') ->exec('chmod +x ./configure')
->exec('chmod +x ./install-sh')
->exec( ->exec(
"{$this->builder->configure_env} ./configure " . "{$this->builder->configure_env} ./configure " .
"--host={$this->builder->gnu_arch}-apple-darwin " . "--host={$this->builder->gnu_arch}-apple-darwin " .

View File

@@ -31,18 +31,16 @@ class libxml2 extends MacOSLibraryBase
'-DBUILD_SHARED_LIBS=OFF ' . '-DBUILD_SHARED_LIBS=OFF ' .
'-DLIBXML2_WITH_ICONV=ON ' . '-DLIBXML2_WITH_ICONV=ON ' .
"-DLIBXML2_WITH_ZLIB={$enable_zlib} " . "-DLIBXML2_WITH_ZLIB={$enable_zlib} " .
"-DLIBXML2_WITH_ICU={$enable_icu} " . '-DLIBXML2_WITH_ICU=OFF ' .
"-DLIBXML2_WITH_LZMA={$enable_xz} " . "-DLIBXML2_WITH_LZMA={$enable_xz} " .
'-DLIBXML2_WITH_PYTHON=OFF ' . '-DLIBXML2_WITH_PYTHON=OFF ' .
'-DLIBXML2_WITH_PROGRAMS=OFF ' . '-DLIBXML2_WITH_PROGRAMS=OFF ' .
'-DLIBXML2_WITH_TESTS=OFF ' . '-DLIBXML2_WITH_TESTS=OFF ' .
'-DCMAKE_INSTALL_PREFIX=/ ' . "-DCMAKE_INSTALL_PREFIX={$destdir} " .
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
'..' '..'
) )
->exec("cmake --build . -j {$this->builder->concurrency}") ->exec("cmake --build . -j {$this->builder->concurrency}")
->exec("make install DESTDIR={$destdir}"); ->exec('make install');
} }
} }

View File

@@ -42,6 +42,7 @@ class openssl extends MacOSLibraryBase
"{$this->builder->configure_env} ./Configure no-shared {$extra} " . "{$this->builder->configure_env} ./Configure no-shared {$extra} " .
'--prefix=/ ' . // use prefix=/ '--prefix=/ ' . // use prefix=/
"--libdir={$lib} " . "--libdir={$lib} " .
'--openssldir=/System/Library/OpenSSL ' .
"darwin64-{$this->builder->arch}-cc" "darwin64-{$this->builder->arch}-cc"
) )
->exec('make clean') ->exec('make clean')

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace SPC\builder\macos\library;
class postgresql extends MacOSLibraryBase
{
use \SPC\builder\unix\library\postgresql;
public const NAME = 'postgresql';
}

View File

@@ -22,6 +22,7 @@ trait libevent
'-DEVENT__LIBRARY_TYPE=STATIC ' . '-DEVENT__LIBRARY_TYPE=STATIC ' .
'-DEVENT__DISABLE_BENCHMARK=ON ' . '-DEVENT__DISABLE_BENCHMARK=ON ' .
'-DEVENT__DISABLE_THREAD_SUPPORT=ON ' . '-DEVENT__DISABLE_THREAD_SUPPORT=ON ' .
'-DEVENT__DISABLE_MBEDTLS=ON ' .
'-DEVENT__DISABLE_TESTS=ON ' . '-DEVENT__DISABLE_TESTS=ON ' .
'-DEVENT__DISABLE_SAMPLES=ON ' . '-DEVENT__DISABLE_SAMPLES=ON ' .
'..' '..'

View File

@@ -0,0 +1,89 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\builder\macos\library\MacOSLibraryBase;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
trait postgresql
{
/**
* @throws RuntimeException
* @throws FileSystemException
*/
protected function build()
{
$builddir = BUILD_ROOT_PATH;
$env = $this->builder->configure_env;
$envs = $env;
$packages = 'openssl zlib readline libxml-2.0'; // icu-uc icu-io icu-i18n libzstd
$pkgconfig_executable = $builddir . '/bin/pkg-config';
$output = shell()->execWithResult($env . " {$pkgconfig_executable} --cflags-only-I --static " . $packages);
if (!empty($output[1][0])) {
$cppflags = $output[1][0];
$envs .= " CPPFLAGS=\"{$cppflags}\"";
}
$output = shell()->execWithResult($env . " {$pkgconfig_executable} --libs-only-L --static " . $packages);
if (!empty($output[1][0])) {
$ldflags = $output[1][0];
$envs .= $this instanceof MacOSLibraryBase ? " LDFLAGS=\"{$ldflags}\" " : " LDFLAGS=\"{$ldflags} -static\" ";
}
$output = shell()->execWithResult($env . " {$pkgconfig_executable} --libs-only-l --static " . $packages);
if (!empty($output[1][0])) {
$libs = $output[1][0];
$envs .= " LIBS=\"{$libs}\" ";
}
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 "293 s/^/#$/" ../src/Makefile.shlib')
->exec('sed -i.backup "441 s/^/#$/" ../src/Makefile.shlib');
// configure
shell()->cd($this->source_dir . '/build')
->exec(
"{$envs} ../configure " .
"--prefix={$builddir} " .
'--disable-thread-safety ' .
'--enable-coverage=no ' .
'--with-ssl=openssl ' .
'--with-readline ' .
'--with-libxml ' .
($this->builder->getLib('icu') ? '--with-icu ' : '--without-icu ') .
'--without-ldap ' .
'--without-libxslt ' .
'--without-lz4 ' .
'--without-zstd ' .
'--without-perl ' .
'--without-python ' .
'--without-pam ' .
'--without-ldap ' .
'--without-bonjour ' .
'--without-tcl '
);
// build
shell()->cd($this->source_dir . '/build')
->exec($envs . ' make -C src/bin/pg_config install')
->exec($envs . ' make -C src/include install')
->exec($envs . ' make -C src/common install')
->exec($envs . ' make -C src/backend/port install')
->exec($envs . ' make -C src/port install')
->exec($envs . ' make -C src/backend/libpq install')
->exec($envs . ' make -C src/interfaces/libpq install');
// remove dynamic libs
shell()->cd($this->source_dir . '/build')
->exec("rm -rf {$builddir}/lib/*.so.*")
->exec("rm -rf {$builddir}/lib/*.so")
->exec("rm -rf {$builddir}/lib/*.dylib");
}
}

View File

@@ -71,7 +71,7 @@ class BuildCliCommand extends BuildCommand
// 执行扩展检测 // 执行扩展检测
$builder->proveExts($extensions); $builder->proveExts($extensions);
// strip // strip
$builder->setStrip(false); $builder->setStrip(!$this->getOption('no-strip'));
// 构建 // 构建
$builder->buildPHP($rule, $this->getOption('bloat')); $builder->buildPHP($rule, $this->getOption('bloat'));
// 统计时间 // 统计时间

View File

@@ -10,11 +10,16 @@ use Symfony\Component\Console\Attribute\AsCommand;
#[AsCommand('doctor', 'Diagnose whether the current environment can compile normally')] #[AsCommand('doctor', 'Diagnose whether the current environment can compile normally')]
class DoctorCommand extends BaseCommand class DoctorCommand extends BaseCommand
{ {
public function configure()
{
$this->addOption('auto-fix', null, null, 'Automatically fix failed items (if possible)');
}
public function handle(): int public function handle(): int
{ {
try { try {
$checker = new CheckListHandler($this->input, $this->output); $checker = new CheckListHandler($this->input, $this->output);
$checker->runCheck(FIX_POLICY_PROMPT); $checker->runCheck($this->input->getOption('auto-fix') ? FIX_POLICY_AUTOFIX : FIX_POLICY_PROMPT);
$this->output->writeln('<info>Doctor check complete !</info>'); $this->output->writeln('<info>Doctor check complete !</info>');
} catch (\Throwable $e) { } catch (\Throwable $e) {
$this->output->writeln('<error>' . $e->getMessage() . '</error>'); $this->output->writeln('<error>' . $e->getMessage() . '</error>');

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace SPC\command; namespace SPC\command;
use SPC\builder\traits\UnixSystemUtilTrait;
use SPC\exception\DownloaderException; use SPC\exception\DownloaderException;
use SPC\exception\FileSystemException; use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException; use SPC\exception\RuntimeException;
@@ -18,6 +19,8 @@ use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand('download', 'Download required sources', ['fetch'])] #[AsCommand('download', 'Download required sources', ['fetch'])]
class DownloadCommand extends BaseCommand class DownloadCommand extends BaseCommand
{ {
use UnixSystemUtilTrait;
protected string $php_major_ver; protected string $php_major_ver;
public function configure() public function configure()
@@ -28,12 +31,13 @@ class DownloadCommand extends BaseCommand
$this->addOption('with-php', null, InputOption::VALUE_REQUIRED, 'version in major.minor format like 8.1', '8.1'); $this->addOption('with-php', null, InputOption::VALUE_REQUIRED, 'version in major.minor format like 8.1', '8.1');
$this->addOption('clean', null, null, 'Clean old download cache and source before fetch'); $this->addOption('clean', null, null, 'Clean old download cache and source before fetch');
$this->addOption('all', 'A', null, 'Fetch all sources that static-php-cli needed'); $this->addOption('all', 'A', null, 'Fetch all sources that static-php-cli needed');
$this->addOption('from-zip', 'Z', InputOption::VALUE_REQUIRED, 'Fetch from zip archive');
} }
public function initialize(InputInterface $input, OutputInterface $output) public function initialize(InputInterface $input, OutputInterface $output)
{ {
// --all 等于 "" "",也就是所有东西都要下载 // --all 等于 "" "",也就是所有东西都要下载
if ($input->getOption('all') || $input->getOption('clean')) { if ($input->getOption('all') || $input->getOption('clean') || $input->getOption('from-zip')) {
$input->setArgument('sources', ''); $input->setArgument('sources', '');
} }
parent::initialize($input, $output); parent::initialize($input, $output);
@@ -66,6 +70,44 @@ class DownloadCommand extends BaseCommand
return 0; return 0;
} }
// --from-zip
if ($path = $this->getOption('from-zip')) {
if (!file_exists($path)) {
logger()->critical('File ' . $path . ' not exist or not a zip archive.');
return 1;
}
// remove old download files first
if (is_dir(DOWNLOAD_PATH)) {
logger()->warning('You are doing some operations that not recoverable: removing directories below');
logger()->warning(DOWNLOAD_PATH);
logger()->alert('I will remove these dir after 5 seconds !');
sleep(5);
f_passthru((PHP_OS_FAMILY === 'Windows' ? 'rmdir /s /q ' : 'rm -rf ') . DOWNLOAD_PATH);
}
// unzip command check
if (PHP_OS_FAMILY !== 'Windows' && !$this->findCommand('unzip')) {
logger()->critical('Missing unzip command, you need to install it first !');
logger()->critical('You can use "bin/spc doctor" command to check and install required tools');
return 1;
}
// create downloads
try {
if (PHP_OS_FAMILY !== 'Windows') {
f_passthru('mkdir ' . DOWNLOAD_PATH . ' && cd ' . DOWNLOAD_PATH . ' && unzip ' . escapeshellarg($path));
}
// Windows TODO
if (!file_exists(DOWNLOAD_PATH . '/.lock.json')) {
throw new RuntimeException('.lock.json not exist in "downloads/"');
}
} catch (RuntimeException $e) {
logger()->critical('Extract failed: ' . $e->getMessage());
return 1;
}
logger()->info('Extract success');
return 0;
}
// Define PHP major version // Define PHP major version
$ver = $this->php_major_ver = $this->getOption('with-php') ?? '8.1'; $ver = $this->php_major_ver = $this->getOption('with-php') ?? '8.1';
define('SPC_BUILD_PHP_VERSION', $ver); define('SPC_BUILD_PHP_VERSION', $ver);

View File

@@ -0,0 +1,116 @@
<?php
declare(strict_types=1);
namespace SPC\command;
use SPC\store\FileSystem;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
#[AsCommand('micro:combine', 'Combine micro.sfx and php code together')]
class MicroCombineCommand extends BaseCommand
{
public function configure()
{
$this->addArgument('file', InputArgument::REQUIRED, 'The php or phar file to be combined');
$this->addOption('with-micro', 'M', InputOption::VALUE_REQUIRED, 'Customize your micro.sfx file');
$this->addOption('with-ini-set', 'I', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'ini to inject into micro.sfx when combining');
$this->addOption('with-ini-file', 'N', InputOption::VALUE_REQUIRED, 'ini file to inject into micro.sfx when combining');
$this->addOption('output', 'O', InputOption::VALUE_REQUIRED, 'Customize your output binary file name');
}
public function handle(): int
{
// 0. Initialize path variables
$internal = FileSystem::convertPath(BUILD_ROOT_PATH . '/bin/micro.sfx');
$micro_file = $this->input->getOption('with-micro');
$file = $this->getArgument('file');
$ini_set = $this->input->getOption('with-ini-set');
$ini_file = $this->input->getOption('with-ini-file');
$target_ini = [];
$output = $this->input->getOption('output') ?? 'my-app';
$ini_part = '';
// 1. Make sure specified micro.sfx file exists
if ($micro_file !== null && !file_exists($micro_file)) {
$this->output->writeln('<error>The micro.sfx file you specified is incorrect or does not exist!</error>');
return 1;
}
// 2. Make sure buildroot/bin/micro.sfx exists
if ($micro_file === null && !file_exists($internal)) {
$this->output->writeln('<error>You haven\'t compiled micro.sfx yet, please use "build" command and "--build-micro" to compile phpmicro first!</error>');
return 1;
}
// 3. Use buildroot/bin/micro.sfx
if ($micro_file === null) {
$micro_file = $internal;
}
// 4. Make sure php or phar file exists
if (!is_file(FileSystem::convertPath($file))) {
$this->output->writeln('<error>The file to combine does not exist!</error>');
return 1;
}
// 5. Confirm ini files (ini-set has higher priority)
if ($ini_file !== null) {
// Check file exist first
if (!file_exists($ini_file)) {
$this->output->writeln('<error>The ini file to combine does not exist! (' . $ini_file . ')</error>');
return 1;
}
$arr = parse_ini_file($ini_file);
if ($arr === false) {
$this->output->writeln('<error>Cannot parse ini file</error>');
return 1;
}
$target_ini = array_merge($target_ini, $arr);
}
// 6. Confirm ini sets
if ($ini_set !== []) {
foreach ($ini_set as $item) {
$arr = parse_ini_string($item);
if ($arr === false) {
$this->output->writeln('<error>--with-ini-set parse failed</error>');
return 1;
}
$target_ini = array_merge($target_ini, $arr);
}
}
// 7. Generate ini injection parts
if (!empty($target_ini)) {
$ini_str = $this->encodeINI($target_ini);
logger()->debug('Injecting ini parts: ' . PHP_EOL . $ini_str);
$ini_part = "\xfd\xf6\x69\xe6";
$ini_part .= pack('N', strlen($ini_str));
$ini_part .= $ini_str;
}
// 8. Combine !
$output = FileSystem::isRelativePath($output) ? (WORKING_DIR . '/' . $output) : $output;
$file_target = file_get_contents($micro_file) . $ini_part . file_get_contents($file);
$result = file_put_contents($output, $file_target);
if ($result === false) {
$this->output->writeln('<error>Combine failed.</error>');
return 1;
}
// 9. chmod +x
chmod($output, 0755);
$this->output->writeln('<info>Combine success! Binary file: ' . $output . '</info>');
return 0;
}
private function encodeINI(array $array): string
{
$res = [];
foreach ($array as $key => $val) {
if (is_array($val)) {
$res[] = "[{$key}]";
foreach ($val as $skey => $sval) {
$res[] = "{$skey}=" . (is_numeric($sval) ? $sval : '"' . $sval . '"');
}
} else {
$res[] = "{$key}=" . (is_numeric($val) ? $val : '"' . $val . '"');
}
}
return implode("\n", $res);
}
}

View File

@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace SPC\command\dev;
use SPC\command\BaseCommand;
use SPC\store\Config;
use Symfony\Component\Console\Attribute\AsCommand;
#[AsCommand('dev:ext-all', 'Dev command')]
class AllExtCommand extends BaseCommand
{
public function configure()
{
}
public function handle(): int
{
$this->output->writeln(implode(',', array_keys(Config::getExts())));
return 0;
}
}

View File

@@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace SPC\command\dev;
use SPC\command\BaseCommand;
use SPC\store\Config;
use SPC\util\DependencyUtil;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputArgument;
#[AsCommand('dev:ext-info', 'Dev command')]
class ExtInfoCommand extends BaseCommand
{
public function configure()
{
$this->addArgument('extensions', InputArgument::REQUIRED, 'The extension name you need to get info');
}
public function handle(): int
{
$extensions = array_map('trim', array_filter(explode(',', $this->getArgument('extensions'))));
// 根据提供的扩展列表获取依赖库列表并编译
foreach ($extensions as $extension) {
$this->output->writeln('<comment>[ ' . $extension . ' ]</comment>');
[, $libraries, $not_included] = DependencyUtil::getExtLibsByDeps([$extension]);
$lib_suggests = Config::getExt($extension, 'lib-suggests', []);
$ext_suggests = Config::getExt($extension, 'ext-suggests', []);
$this->output->writeln("<info>lib-depends:\t" . implode(', ', $libraries) . '</info>');
$this->output->writeln("<info>lib-suggests:\t" . implode(', ', $lib_suggests) . '</info>');
$this->output->writeln("<info>ext-depends:\t" . implode(',', $not_included) . '</info>');
$this->output->writeln("<info>ext-suggests:\t" . implode(', ', $ext_suggests) . '</info>');
if (Config::getExt($extension, 'unix-only', false)) {
$this->output->writeln("<info>Unix only:\ttrue</info>");
}
$this->output->writeln('');
}
return 0;
}
}

View File

@@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace SPC\command\dev;
use SPC\command\BaseCommand;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand('dev:php-ver', 'Dev command')]
class PhpVerCommand extends BaseCommand
{
public function initialize(InputInterface $input, OutputInterface $output)
{
$this->no_motd = true;
parent::initialize($input, $output);
}
public function handle(): int
{
// Find php from source/php-src
$file = SOURCE_PATH . '/php-src/main/php_version.h';
$result = preg_match('/#define PHP_VERSION "(\d+\.\d+\.\d+)"/', file_get_contents($file), $match);
if ($result === false) {
$this->output->writeln('<error>PHP source not found, maybe you need to extract first ?</error>');
return 1;
}
$this->output->writeln('<info>' . $match[1] . '</info>');
return 0;
}
}

View File

@@ -0,0 +1,90 @@
<?php
declare(strict_types=1);
namespace SPC\doctor\item;
use SPC\builder\linux\SystemUtil;
use SPC\builder\traits\UnixSystemUtilTrait;
use SPC\doctor\AsCheckItem;
use SPC\doctor\AsFixItem;
use SPC\doctor\CheckResult;
use SPC\exception\RuntimeException;
class LinuxToolCheckList
{
use UnixSystemUtilTrait;
public const TOOLS_ALPINE = [
'make', 'bison', 'flex',
'git', 'autoconf', 'automake',
'tar', 'unzip', 'gzip',
'bzip2', 'cmake', 'gcc',
'g++', 'patch',
];
public const TOOLS_DEBIAN = [
'make', 'bison', 'flex',
'git', 'autoconf', 'automake',
'tar', 'unzip', 'gzip',
'bzip2', 'cmake', 'patch',
];
#[AsCheckItem('if necessary tools are installed', limit_os: 'Linux')]
public function checkCliTools(): ?CheckResult
{
$distro = SystemUtil::getOSRelease();
$required = match ($distro['dist']) {
'alpine' => self::TOOLS_ALPINE,
default => self::TOOLS_DEBIAN,
};
$missing = [];
foreach ($required as $cmd) {
if ($this->findCommand($cmd) === null) {
$missing[] = $cmd;
}
}
if (!empty($missing)) {
return match ($distro['dist']) {
'ubuntu', 'alpine', 'debian' => CheckResult::fail(implode(', ', $missing) . ' not installed on your system', 'install-linux-tools', [$distro, $missing]),
default => CheckResult::fail(implode(', ', $missing) . ' not installed on your system'),
};
}
return CheckResult::ok();
}
#[AsCheckItem('if necessary packages are installed', limit_os: 'Linux')]
public function checkSystemOSPackages(): ?CheckResult
{
$distro = SystemUtil::getOSRelease();
if ($distro['dist'] === 'alpine') {
// check linux-headers installation
if (!file_exists('/usr/include/linux/mman.h')) {
return CheckResult::fail('linux-headers not installed on your system', 'install-linux-tools', [$distro, ['linux-headers']]);
}
}
return CheckResult::ok();
}
#[AsFixItem('install-linux-tools')]
public function fixBuildTools(array $distro, array $missing): bool
{
$install_cmd = match ($distro['dist']) {
'ubuntu', 'debian' => 'apt install -y',
'alpine' => 'apk add',
default => throw new RuntimeException('Current linux distro is not supported for auto-install musl packages'),
};
$prefix = '';
if (get_current_user() !== 'root') {
$prefix = 'sudo ';
logger()->warning('Current user is not root, using sudo for running command');
}
try {
shell(true)->exec($prefix . $install_cmd . ' ' . implode(' ', $missing));
} catch (RuntimeException) {
return false;
}
return true;
}
}

View File

@@ -439,6 +439,20 @@ class FileSystem
self::$_extract_hook[$name][] = $callback; self::$_extract_hook[$name][] = $callback;
} }
/**
* Check whether the path is a relative path (judging according to whether the first character is "/")
*
* @param string $path Path
*/
public static function isRelativePath(string $path): bool
{
// 适配 Windows 的多盘符目录形式
if (DIRECTORY_SEPARATOR === '\\') {
return !(strlen($path) > 2 && ctype_alpha($path[0]) && $path[1] === ':');
}
return strlen($path) > 0 && $path[0] !== '/';
}
private static function emitSourceExtractHook(string $name) private static function emitSourceExtractHook(string $name)
{ {
foreach ((self::$_extract_hook[$name] ?? []) as $hook) { foreach ((self::$_extract_hook[$name] ?? []) as $hook) {

View File

@@ -48,9 +48,33 @@ class SourcePatcher
file_put_contents(SOURCE_PATH . '/php-src/ext/curl/config.m4', $file1 . "\n" . $files . "\n" . $file2); file_put_contents(SOURCE_PATH . '/php-src/ext/curl/config.m4', $file1 . "\n" . $files . "\n" . $file2);
} }
// if ($builder->getExt('pdo_sqlite')) { if ($builder->getExt('memcache')) {
// FileSystem::replaceFile() FileSystem::replaceFile(
// } SOURCE_PATH . '/php-src/ext/memcache/config9.m4',
REPLACE_FILE_STR,
'if test -d $abs_srcdir/src ; then',
'if test -d $abs_srcdir/main ; then'
);
FileSystem::replaceFile(
SOURCE_PATH . '/php-src/ext/memcache/config9.m4',
REPLACE_FILE_STR,
'export CPPFLAGS="$CPPFLAGS $INCLUDES"',
'export CPPFLAGS="$CPPFLAGS $INCLUDES -I$abs_srcdir/main"'
);
// add for in-tree building
file_put_contents(
SOURCE_PATH . '/php-src/ext/memcache/php_memcache.h',
<<<'EOF'
#ifndef PHP_MEMCACHE_H
#define PHP_MEMCACHE_H
extern zend_module_entry memcache_module_entry;
#define phpext_memcache_ptr &memcache_module_entry
#endif
EOF
);
}
} }
public static function patchSwow(): bool public static function patchSwow(): bool
@@ -88,6 +112,9 @@ class SourcePatcher
if ($ssh2 = $builder->getExt('ssh2')) { if ($ssh2 = $builder->getExt('ssh2')) {
$patch[] = ['ssh2 patch', '/-lssh2/', $ssh2->getLibFilesString()]; $patch[] = ['ssh2 patch', '/-lssh2/', $ssh2->getLibFilesString()];
} }
if ($pgsql = $builder->getExt('pgsql')) {
$patch[] = ['pgsql patch', '/-lpq/', $pgsql->getLibFilesString()];
}
$patch[] = ['disable capstone', '/have_capstone="yes"/', 'have_capstone="no"']; $patch[] = ['disable capstone', '/have_capstone="yes"/', 'have_capstone="no"'];
foreach ($patch as $item) { foreach ($patch as $item) {
logger()->info('Patching configure: ' . $item[0]); logger()->info('Patching configure: ' . $item[0]);