Compare commits

..

8 Commits

Author SHA1 Message Date
Jerry Ma
5012da96be Update ConsoleApplication.php 2024-02-23 11:42:10 +08:00
Jerry Ma
df0e37cd0f Add mbregex support for windows (#351)
* add mbregex support for windows

* cs fix

* fix curl http2 support
2024-02-23 11:41:35 +08:00
Jerry Ma
4ab7b6bfdc Add sqlite support for Windows (#350)
* add sqlite support

* cs fix
2024-02-23 11:14:51 +08:00
Jerry Ma
f498250001 Add multiple XML related extensions support for Windows (#349)
* update libxml2 version

* use msys2 tar.exe instead of system32/tar.exe

* add iconv, xml, dom, xmlreader, xmlwriter, soap, libxml, simplexml support

* add test

* add sysvshm support

* add quote

* add debug

* use mingw target

* fix windows tar

* fix windows tar

* fix windows tar

* fix windows tar

* fix windows tar [skip ci]
2024-02-23 00:56:28 +08:00
Jerry Ma
3945ac037b Add curl and ssh2 support for windows (#348)
* add curl and ssh2 support for windows

* add curl and ssh2 test for windows

* cs fix

* update README [skip ci]

* update README [skip ci]

* update README [skip ci]

* update README [skip ci]

* update README [skip ci]
2024-02-22 14:37:10 +08:00
crazywhalecc
b0d8b00fcc optimize pkg-config build process 2024-02-20 15:45:00 +08:00
crazywhalecc
62b0bf8af0 fix no-strip not working for linux micro 2024-02-20 10:56:39 +08:00
crazywhalecc
905e080770 fix upx linux build 2024-02-19 15:29:43 +08:00
23 changed files with 576 additions and 61 deletions

View File

@@ -20,7 +20,7 @@ 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) 构建)
@@ -47,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: 代表支持本地构建,空 代表暂不支持。
@@ -64,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: | |
### 支持的扩展
@@ -107,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)。
@@ -149,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
```
其中,目前支持构建 climicrofpm 和 embed使用以下参数的一个或多个来指定编译的 SAPI
@@ -170,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
```

View File

@@ -53,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.
@@ -74,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
@@ -117,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).
@@ -150,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
@@ -159,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:
@@ -180,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
```

View File

@@ -24,6 +24,10 @@
"arg-type": "with",
"lib-depends": [
"curl"
],
"ext-depends-windows": [
"zlib",
"openssl"
]
},
"dba": {
@@ -119,8 +123,12 @@
"iconv": {
"type": "builtin",
"arg-type": "with-prefix",
"lib-depends": [
"arg-type-windows": "with",
"lib-depends-unix": [
"libiconv"
],
"lib-depends-windows": [
"libiconv-win"
]
},
"igbinary": {
@@ -347,9 +355,11 @@
"simplexml": {
"type": "builtin",
"arg-type": "custom",
"arg-type-windows": "with",
"lib-depends": [
"libxml2"
],
"ext-depends-windows": [
"xml"
]
},
"snappy": {
@@ -369,6 +379,9 @@
"arg-type": "custom",
"lib-depends": [
"libxml2"
],
"ext-depends-windows": [
"xml"
]
},
"sockets": {
@@ -384,6 +397,7 @@
"sqlite3": {
"type": "builtin",
"arg-type": "with-prefix",
"arg-type-windows": "with",
"lib-depends": [
"sqlite"
]
@@ -403,8 +417,13 @@
"type": "external",
"source": "ext-ssh2",
"arg-type": "with-prefix",
"arg-type-windows": "with",
"lib-depends": [
"libssh2"
],
"ext-depends-windows": [
"openssl",
"zlib"
]
},
"swoole": {
@@ -479,8 +498,7 @@
"unix-only": true
},
"sysvshm": {
"type": "builtin",
"unix-only": true
"type": "builtin"
},
"tidy": {
"type": "builtin",
@@ -525,6 +543,9 @@
"arg-type-windows": "with",
"lib-depends": [
"libxml2"
],
"ext-depends-windows": [
"iconv"
]
},
"xmlreader": {
@@ -532,6 +553,10 @@
"arg-type": "custom",
"lib-depends": [
"libxml2"
],
"ext-depends-windows": [
"xml",
"dom"
]
},
"xmlwriter": {
@@ -539,6 +564,9 @@
"arg-type": "custom",
"lib-depends": [
"libxml2"
],
"ext-depends-windows": [
"xml"
]
},
"xsl": {

View File

@@ -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",
@@ -243,6 +245,13 @@
"localcharset.h"
]
},
"libiconv-win": {
"source": "libiconv-win",
"static-libs-windows": [
"libiconv.lib",
"libiconv_a.lib"
]
},
"libjpeg": {
"source": "libjpeg",
"static-libs-unix": [
@@ -332,21 +341,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": {
@@ -427,10 +440,8 @@
"libonig.a"
],
"static-libs-windows": [
[
"onig.lib",
"onig_a.lib"
]
"onig.lib",
"onig_a.lib"
],
"headers": [
"oniggnu.h",
@@ -507,7 +518,10 @@
"static-libs-unix": [
"libsqlite3.a"
],
"headers-unix": [
"static-libs-windows": [
"libsqlite3_a.lib"
],
"headers": [
"sqlite3.h",
"sqlite3ext.h"
]

View File

@@ -254,6 +254,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",
@@ -331,7 +340,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"

View File

@@ -25,7 +25,7 @@ use Symfony\Component\Console\Command\ListCommand;
*/
final class ConsoleApplication extends Application
{
public const VERSION = '2.1.0-beta.4';
public const VERSION = '2.1.0';
public function __construct()
{

View File

@@ -212,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'))
);

View File

@@ -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 !');
}
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -180,13 +180,13 @@ class LinuxBuilder extends UnixBuilderBase
FileSystem::replaceFileRegex(
SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag',
'/POST_MICRO_BUILD_COMMANDS=.*/',
'POST_MICRO_BUILD_COMMANDS=true',
'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=\$(STRIP) \$(MICRO_STRIP_FLAGS) \$(SAPI_MICRO_PATH)',
'POST_MICRO_BUILD_COMMANDS=true',
);
}
@@ -257,12 +257,12 @@ 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)) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/cli')->exec('strip --strip-all php');
} elseif ($this->getOption('with-upx-pack')) {
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');
}
$this->deployBinary(BUILD_TARGET_CLI);
@@ -312,14 +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)) {
shell()->cd(SOURCE_PATH . '/php-src/sapi/fpm')->exec('strip --strip-all php-fpm');
} elseif ($this->getOption('with-upx-pack')) {
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);
}

View File

@@ -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');
}
}

View File

@@ -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.
*

View 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}"
);
}
}

View 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');
}
}

View 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}"
);
}
}

View 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');
}
}

View 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}"
);
}
}

View 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');
}
}

View 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');
}
}

View File

@@ -185,9 +185,11 @@ class FileSystem
}
if ($move_path !== null) {
$move_path = SOURCE_PATH . '/' . $move_path;
} else {
$move_path = SOURCE_PATH . "/{$name}";
}
logger()->info("extracting {$name} source to " . ($move_path ?? (SOURCE_PATH . "/{$name}")) . ' ...');
$target = self::convertPath($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);
}
@@ -217,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;
}
/**
* 递归或非递归扫描目录,可返回相对目录的文件列表或绝对目录的文件列表
*
@@ -441,6 +451,9 @@ class FileSystem
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)) {
@@ -453,9 +466,15 @@ class FileSystem
} 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' => f_passthru("\"{$_7z}\" x -so {$filename} | tar -f - -x -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}"),
};

View 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

View File

@@ -14,7 +14,8 @@ 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' => 'event,gettext',
'Windows' => 'mbstring',
'Linux', 'Darwin' => 'event,gettext',
'Windows' => 'mbstring,pdo_sqlite,mbregex',
};
// If you want to test lib-suggests feature with extension, add them below (comma separated, example `libwebp,libavif`).