Compare commits

...

18 Commits

Author SHA1 Message Date
Jerry Ma
5d2bd93bd7 Remove dll before sanity check (#459) 2024-05-21 18:09:41 +08:00
Jerry Ma
4ba92b08ca Add extension version and env check method (#458) 2024-05-21 14:56:54 +08:00
Jerry Ma
11076b1355 Add comomand: switch-php-version (#457)
* add switch-php-version command

* update README direct download description
2024-05-21 14:54:08 +08:00
Jerry Ma
71770a0a5f Add xattr command to prevent macOS GateKeeper block (#453)
* Add xattr command to prevent macOS GateKeeper block

* test

* test

* test: disable build tests

* test

* test

* test

* update

* update
2024-05-17 19:41:02 +08:00
crazywhalecc
98d3766fe8 Add xattr command to prevent macOS GateKeeper block 2024-05-17 16:42:26 +08:00
Jerry Ma
1fdb6b439e Add compression for spc.phar and spc.exe (#452) 2024-05-17 16:34:59 +08:00
Jerry Ma
3136d6edc1 Put extension and library compatibility checks before compilation (#451) 2024-05-16 13:01:11 +08:00
Jerry Ma
3e84becf77 Fix php74 upx bug (#450)
* fix php74 cannot compile with no-strip or with-upx-pack (including lint some code)

* use captainhook installer instead of plugin composer

* use captainhook installer instead of plugin composer

* add [no build test] flag

* update actions/cache version [no build test]

* test update actions/cache version

* test update actions/cache version

* test update actions/cache version
2024-05-16 10:51:31 +08:00
Jerry Ma
1632c25223 Add extension parallel support (#444)
* Add extension parallel support

* add parallel windows support

* add parallel test

* add zts limit for parallel

* sort config

* add parallel test

* add dev-php test

* use macos-13 instead of macos-latest

* revert dev-php tests
2024-05-11 14:46:36 +08:00
crazywhalecc
e6c308c242 imap ext fix 2024-05-06 15:52:55 +08:00
crazywhalecc
3fcb7ebf03 update spc binary php version 2024-05-06 14:25:24 +08:00
Jerry Ma
7416b8079b Fix dependency util suggest calculate bug (#441)
* fix dependency util suggest calculate bug

* fix dependency util suggest calculate bug
2024-05-06 14:23:32 +08:00
Jerry Ma
bde18054e5 Fix micro upx compress bug (#440)
* triple compression for micro with upx

* place debug info first
2024-05-06 14:12:40 +08:00
Jerry Ma
954f8f4ddc fix ncurses 6.5 build (#439) 2024-05-06 14:11:50 +08:00
Jerry Ma
0fee628842 Fix xz build on macOS and Linux (#438)
* fix xz build

* add xz tests
2024-05-06 12:55:38 +08:00
Jerry Ma
69e6d82e83 add linux env var: SPC_NO_MUSL_PATH (#437) 2024-05-06 12:32:43 +08:00
crazywhalecc
e1e6270d86 update README 2024-05-06 12:08:35 +08:00
Simon Hamp
30af182aff Windows build GitHub Action (#420)
* Create build-windows-x86_64.yml

* Update build-windows-x86_64.yml

* Fix CLI param

* Fix env writing in Powershell

* Run doctor first, per docs

* Fix file paths

* Generate an acceptable cache key

* Change shell

* Improve cache key generation

* Update upload-artifact action

* Update actions

* Attempt to fix cache key storage

* Remove FPM build option
2024-05-06 11:59:02 +08:00
45 changed files with 1840 additions and 721 deletions

View File

@@ -0,0 +1,108 @@
name: CI on x86_64 Windows
on:
workflow_dispatch:
inputs:
version:
required: true
description: php version to compile
default: '8.2'
type: choice
options:
- '8.3'
- '8.2'
- '8.1'
- '8.0'
- '7.4'
build-cli:
description: build cli binary
default: true
type: boolean
build-micro:
description: build phpmicro binary
type: boolean
extensions:
description: extensions to compile (comma separated)
required: true
type: string
debug:
type: boolean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
build:
name: build ${{ inputs.version }} on Windows x86_64
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
# Cache composer dependencies
- id: cache-composer-deps
uses: actions/cache@v4
with:
path: vendor
key: composer-dependencies
# If there's no Composer cache, install dependencies
- if: steps.cache-composer-deps.outputs.cache-hit != 'true'
run: composer update --no-dev --classmap-authoritative
- name: Generate hashed key for download cache
shell: bash
run: |
INPUT_HASH=$(echo "${{ runner.os }}-${{ inputs.version }}-${{ inputs.extensions }}" | sha256sum | awk '{print $1}')
echo "INPUT_HASH=${INPUT_HASH}" >> "$GITHUB_ENV"
# Cache downloaded source
- id: cache-download
uses: actions/cache@v4
with:
path: downloads
key: php-${{ env.INPUT_HASH }}
# With or without debug
- if: inputs.debug == true
run: echo "SPC_BUILD_DEBUG=--debug" >> $env:GITHUB_ENV
# With target select: cli, micro or both
- if: ${{ inputs.build-cli == true }}
run: echo "SPC_BUILD_CLI=--build-cli" >> $env:GITHUB_ENV
- if: ${{ inputs.build-micro == true }}
run: echo "SPC_BUILD_MICRO=--build-micro" >> $env:GITHUB_ENV
- run: ./bin/spc doctor
# If there's no dependencies cache, fetch sources, with or without debug
- if: steps.cache-download.outputs.cache-hit != 'true'
run: ./bin/spc download --with-php="${{ inputs.version }}" --for-extensions="${{ inputs.extensions }}" ${{ env.SPC_BUILD_DEBUG }}
# Run build command
- run: ./bin/spc build "${{ inputs.extensions }}" ${{ env.SPC_BUILD_DEBUG }} ${{ env.SPC_BUILD_CLI }} ${{ env.SPC_BUILD_MICRO }} ${{ env.SPC_BUILD_FPM }}
# Upload cli executable
- if: ${{ inputs.build-cli == true }}
uses: actions/upload-artifact@v4
with:
name: php-${{ inputs.version }}
path: buildroot/bin/php.exe
# Upload micro self-extracted executable
- if: ${{ inputs.build-micro == true }}
uses: actions/upload-artifact@v4
with:
name: micro-${{ inputs.version }}
path: buildroot/bin/micro.sfx
# Upload extensions metadata
- uses: actions/upload-artifact@v4
with:
name: license-files
path: buildroot/license/
- uses: actions/upload-artifact@v4
with:
name: build-meta
path: |
buildroot/build-extensions.json
buildroot/build-libraries.json

View File

@@ -11,13 +11,13 @@ on:
jobs:
build-release-artifacts:
name: "Build SPC Binary"
runs-on: ubuntu-latest
runs-on: macos-14
strategy:
matrix:
php-version:
- "8.2"
micro-version:
- "8.2.16"
- "8.2.18"
operating-system:
- "linux-x86_64"
- "macos-x86_64"
@@ -45,7 +45,7 @@ jobs:
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: "Cache Composer dependencies"
uses: "actions/cache@v3"
uses: "actions/cache@v4"
with:
path: "${{ steps.composer-cache.outputs.dir }}"
key: "php-${{ matrix.php-version }}-locked-composer-${{ hashFiles('**/composer.lock') }}"
@@ -76,6 +76,9 @@ jobs:
else
chmod +x spc
fi
if [ "${{ matrix.operating-system }}" = "macos-aarch64" ] || [ "${{ matrix.operating-system }}" = "macos-x86_64" ]; then
sudo xattr -cr ./spc
fi
- name: "Archive Executable"
run: |
@@ -83,7 +86,7 @@ jobs:
tar -czf spc-${{ matrix.operating-system }}.tar.gz spc
echo "filename=spc-${{ matrix.operating-system }}.tar.gz" >> $GITHUB_ENV
echo "OS=${{ matrix.operating-system }}" >> $GITHUB_ENV
if [ "${{ matrix.operating-system }}" == "linux-x86_64" ]; then
if [ "${{ matrix.operating-system }}" == "macos-aarch64" ]; then
./spc dev:extensions
fi
else
@@ -119,7 +122,7 @@ jobs:
TARGET: ${{ secrets.DEPLOY_SERVER_TARGET_SPC_NIGHTLY }}
- name: "Upload Artifact"
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
path: spc${{ env.SUFFIX }}
name: spc-${{ matrix.operating-system }}${{ env.SUFFIX }}

View File

@@ -48,7 +48,7 @@ jobs:
- name: "Cache Composer packages"
id: composer-cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: vendor
key: ${{ runner.os }}-phpstan-${{ hashFiles('**/composer.lock') }}
@@ -86,7 +86,7 @@ jobs:
- name: "Cache Composer packages"
id: composer-cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: vendor
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
@@ -113,7 +113,7 @@ jobs:
- "8.3"
os:
- ubuntu-latest
- macos-latest
- macos-13
- windows-latest
- macos-14
fail-fast: false
@@ -136,9 +136,9 @@ jobs:
echo "GITHUB_TOKEN=${{ secrets.TEST_GH_TOKEN }}" >> $GITHUB_ENV
fi
- name: "Cache Composer packages"
- name: "Cache composer packages"
id: composer-cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: vendor
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
@@ -168,4 +168,4 @@ jobs:
bin/spc download --for-extensions="$(php src/globals/test-extensions.php extensions)" --for-libs="$(php src/globals/test-extensions.php libs)" --with-php=${{ matrix.php }} --ignore-cache-sources=php-src --debug --retry=3
- name: "Run Build Tests (build)"
run: bin/spc build "$(php src/globals/test-extensions.php extensions)" --with-libs="$(php src/globals/test-extensions.php libs)" --build-cli --build-micro --build-fpm --debug
run: bin/spc build "$(php src/globals/test-extensions.php extensions)" $(php src/globals/test-extensions.php zts) --with-libs="$(php src/globals/test-extensions.php libs)" --build-cli --build-micro --build-fpm --debug

View File

@@ -43,9 +43,12 @@ static-php-cli简称 `spc`)有许多特性:
如果你不想自行编译 PHP可以从本项目现有的示例 Action 下载 Artifact也可以从自托管的服务器下载。
- [扩展组合 - common](https://dl.static-php.dev/static-php-cli/common/)common 组合包含了约 [30+](https://dl.static-php.dev/static-php-cli/common/README.txt) 个常用扩展,体积为 22MB 左右。
- [扩展组合 - 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 左右。
- [扩展组合 - common](https://dl.static-php.dev/static-php-cli/common/)common 组合包含了约 [30+](https://dl.static-php.dev/static-php-cli/common/README.txt) 个常用扩展,体积为 7.5MB 左右。
- [扩展组合 - bulk](https://dl.static-php.dev/static-php-cli/bulk/)bulk 组合包含了 [50+](https://dl.static-php.dev/static-php-cli/bulk/README.txt) 个扩展,体积为 25MB 左右。
- [扩展组合 - minimal](https://dl.static-php.dev/static-php-cli/minimal/)minimal 组合包含了 [5](https://dl.static-php.dev/static-php-cli/minimal/README.txt) 个扩展,体积为 3MB 左右。
> Linux 和 Windows 默认启用了 UPX 压缩,可减小 30~50% 的 PHP 二进制体积。
> macOS 当前不支持 UPX所以上述预编译的 macOS 版本体积可能较大。
对于 Windows 系统,目前支持的扩展较少,故仅提供 SPC 自身运行的最小扩展组合的 `cli``micro`[扩展组合 - spc-min](https://dl.static-php.dev/static-php-cli/windows/spc-min/)。
@@ -66,7 +69,7 @@ static-php-cli简称 `spc`)有许多特性:
|---------|----------------------|----------------------|
| macOS | :octocat: :computer: | :octocat: :computer: |
| Linux | :octocat: :computer: | :octocat: :computer: |
| Windows | :computer: | |
| Windows | :octocat: :computer: | |
| FreeBSD | :computer: | :computer: |
当前支持编译的 PHP 版本:

View File

@@ -49,9 +49,12 @@ If you don't want to build or want to test first, you can download example pre-c
Below are several precompiled static-php binaries with different extension combinations,
which can be downloaded directly according to your needs.
- [Extension-Combination - common](https://dl.static-php.dev/static-php-cli/common/): `common` contains about [30+](https://dl.static-php.dev/static-php-cli/common/README.txt) commonly used extensions, and the size is about 22MB.
- [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.
- [Extension-Combination - common](https://dl.static-php.dev/static-php-cli/common/): `common` contains about [30+](https://dl.static-php.dev/static-php-cli/common/README.txt) commonly used extensions, and the size is about 7.5MB.
- [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 25MB 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 3MB in size.
> Linux and Windows supports UPX compression for binaries, which can reduce the size of the binary by 30% to 50%.
> macOS does not support UPX compression, so the size of the pre-built binaries for mac is larger.
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/).
@@ -74,7 +77,7 @@ Here is the supported OS and arch, where :octocat: represents support for GitHub
|---------|----------------------|----------------------|
| macOS | :octocat: :computer: | :octocat: :computer: |
| Linux | :octocat: :computer: | :octocat: :computer: |
| Windows | :computer: | |
| Windows | :octocat: :computer: | |
| FreeBSD | :computer: | :computer: |
Currently supported PHP versions for compilation:

View File

@@ -4,6 +4,7 @@
"blacklist": [
".github"
],
"compression": "GZ",
"directories": [
"config",
"src",

View File

@@ -16,8 +16,8 @@
"zhamao/logger": "^1.0"
},
"require-dev": {
"captainhook/captainhook": "^5.10",
"captainhook/plugin-composer": "^5.3",
"captainhook/captainhook-phar": "^5.23",
"captainhook/hook-installer": "^1.0",
"friendsofphp/php-cs-fixer": "^3.25",
"humbug/box": "^4.5",
"nunomaduro/collision": "^7.8",
@@ -50,7 +50,9 @@
"config": {
"allow-plugins": {
"phpstan/extension-installer": true,
"captainhook/plugin-composer": true
"captainhook/hook-installer": true,
"captainhook/plugin-composer": true,
"captainhook/captainhook-phar": true
},
"optimize-autoloader": true,
"sort-packages": true

1688
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -173,7 +173,7 @@
"lib-depends": [
"imap"
],
"lib-suggests": [
"ext-suggests": [
"openssl"
]
},
@@ -280,6 +280,14 @@
"zlib"
]
},
"parallel": {
"type": "external",
"source": "parallel",
"arg-type-windows": "with",
"lib-depends-windows": [
"pthreads4w"
]
},
"password-argon2": {
"type": "builtin",
"arg-type": "with-prefix",

View File

@@ -528,6 +528,12 @@
"zstd"
]
},
"pthreads4w": {
"source": "pthreads4w",
"static-libs-windows": [
"libpthreadVC3.lib"
]
},
"qdbm": {
"source": "qdbm",
"static-libs-unix": [

View File

@@ -480,13 +480,9 @@
}
},
"ncurses": {
"alt": {
"type": "filelist",
"url": "https://ftp.gnu.org/pub/gnu/ncurses/",
"regex": "/href=\"(?<file>ncurses-(?<version>[^\"]+)\\.tar\\.gz)\"/"
},
"type": "url",
"url": "https://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.4.tar.gz",
"type": "filelist",
"url": "https://ftp.gnu.org/pub/gnu/ncurses/",
"regex": "/href=\"(?<file>ncurses-(?<version>[^\"]+)\\.tar\\.gz)\"/",
"license": {
"type": "file",
"path": "COPYING"
@@ -519,6 +515,16 @@
"path": "LICENSE.txt"
}
},
"parallel": {
"type": "url",
"url": "https://pecl.php.net/get/parallel",
"path": "php-src/ext/parallel",
"filename": "parallel.tgz",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"pdo_sqlsrv": {
"type": "url",
"url": "https://pecl.php.net/get/pdo_sqlsrv",
@@ -555,6 +561,15 @@
"path": "LICENSE"
}
},
"pthreads4w": {
"type": "git",
"rev": "master",
"url": "https://git.code.sf.net/p/pthreads4w/code",
"license": {
"type": "file",
"path": "LICENSE"
}
},
"qdbm": {
"type": "git",
"url": "https://github.com/static-php/qdbm.git",

View File

@@ -16,16 +16,15 @@ use SPC\command\DumpLicenseCommand;
use SPC\command\ExtractCommand;
use SPC\command\InstallPkgCommand;
use SPC\command\MicroCombineCommand;
use SPC\command\SwitchPhpVersionCommand;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\HelpCommand;
use Symfony\Component\Console\Command\ListCommand;
/**
* static-php-cli console app entry
*/
final class ConsoleApplication extends Application
{
public const VERSION = '2.2.0';
public const VERSION = '2.2.1';
public function __construct()
{
@@ -43,6 +42,7 @@ final class ConsoleApplication extends Application
new DumpLicenseCommand(),
new ExtractCommand(),
new MicroCombineCommand(),
new SwitchPhpVersionCommand(),
// Dev commands
new AllExtCommand(),
@@ -51,9 +51,4 @@ final class ConsoleApplication extends Application
]
);
}
protected function getDefaultCommands(): array
{
return [new HelpCommand(), new ListCommand()];
}
}

View File

@@ -33,7 +33,7 @@ abstract class BuilderBase
protected string $patch_point = '';
/**
* Build libraries
* Convert libraries to class
*
* @param array<string> $sorted_libraries Libraries to build (if not empty, must sort first)
* @throws FileSystemException
@@ -41,7 +41,27 @@ abstract class BuilderBase
* @throws WrongUsageException
* @internal
*/
abstract public function buildLibs(array $sorted_libraries);
abstract public function proveLibs(array $sorted_libraries);
/**
* Build libraries
*
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
public function buildLibs(): void
{
// build all libs
foreach ($this->libs as $lib) {
match ($lib->tryBuild($this->getOption('rebuild', false))) {
BUILD_STATUS_OK => logger()->info('lib [' . $lib::NAME . '] build success'),
BUILD_STATUS_ALREADY => logger()->notice('lib [' . $lib::NAME . '] already built'),
BUILD_STATUS_FAILED => logger()->error('lib [' . $lib::NAME . '] build failed'),
default => logger()->warning('lib [' . $lib::NAME . '] build status unknown'),
};
}
}
/**
* Add library to build.
@@ -335,6 +355,19 @@ abstract class BuilderBase
return $this->patch_point;
}
/**
* Validate libs and exts can be compiled successfully in current environment
*/
public function validateLibsAndExts(): void
{
foreach ($this->libs as $lib) {
$lib->validate();
}
foreach ($this->exts as $ext) {
$ext->validate();
}
}
public function emitPatchPoint(string $point_name): void
{
$this->patch_point = $point_name;

View File

@@ -223,6 +223,11 @@ class Extension
}
}
public function validate(): void
{
// do nothing, just throw wrong usage exception if not valid
}
/**
* @throws RuntimeException
*/

View File

@@ -177,6 +177,11 @@ abstract class LibraryBase
return false;
}
public function validate(): void
{
// do nothing, just throw wrong usage exception if not valid
}
/**
* Get current builder object.
*/

View File

@@ -14,11 +14,15 @@ class imap extends Extension
/**
* @throws WrongUsageException
*/
public function getUnixConfigureArg(): string
public function validate(): void
{
if ($this->builder->getOption('enable-zts')) {
throw new WrongUsageException('ext-imap is not thread safe, do not build it with ZTS builds');
}
}
public function getUnixConfigureArg(): string
{
$arg = '--with-imap=' . BUILD_ROOT_PATH;
if ($this->builder->getLib('openssl') !== null) {
$arg .= ' --with-imap-ssl=' . BUILD_ROOT_PATH;

View File

@@ -16,11 +16,15 @@ class opcache extends Extension
* @throws WrongUsageException
* @throws RuntimeException
*/
public function getUnixConfigureArg(): string
public function validate(): void
{
if ($this->builder->getPHPVersionID() < 80000) {
if ($this->builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') {
throw new WrongUsageException('Statically compiled PHP with Zend Opcache only available for PHP >= 8.0 !');
}
}
public function getUnixConfigureArg(): string
{
return '--enable-opcache';
}

View File

@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\WrongUsageException;
use SPC\util\CustomExt;
#[CustomExt('parallel')]
class parallel extends Extension
{
public function validate(): void
{
if (!$this->builder->getOption('enable-zts')) {
throw new WrongUsageException('ext-parallel must be built with ZTS builds. Use "--enable-zts" option!');
}
}
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\util\CustomExt;
#[CustomExt('protobuf')]
class protobuf extends Extension
{
public function validate(): void
{
if ($this->builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') {
throw new \RuntimeException('The latest protobuf extension requires PHP 8.0 or later');
}
}
}

View File

@@ -17,12 +17,16 @@ class swoole_hook_pgsql extends Extension
return 'swoole';
}
public function getUnixConfigureArg(): string
public function validate(): void
{
// pdo_pgsql need to be disabled
if ($this->builder->getExt('pdo_pgsql') !== null) {
throw new WrongUsageException('swoole-hook-pgsql provides pdo_pgsql, if you enable pgsql hook for swoole, you must remove pdo_pgsql extension.');
}
}
public function getUnixConfigureArg(): string
{
// enable swoole pgsql hook
return '--enable-swoole-pgsql';
}

View File

@@ -17,12 +17,16 @@ class swoole_hook_sqlite extends Extension
return 'swoole';
}
public function getUnixConfigureArg(): string
public function validate(): void
{
// pdo_pgsql need to be disabled
if ($this->builder->getExt('pdo_sqlite') !== null) {
throw new WrongUsageException('swoole-hook-sqlite provides pdo_sqlite, if you enable sqlite hook for swoole, you must remove pdo_sqlite extension.');
}
}
public function getUnixConfigureArg(): string
{
// enable swoole pgsql hook
return '--enable-swoole-sqlite';
}

View File

@@ -11,6 +11,13 @@ use SPC\util\CustomExt;
#[CustomExt('swow')]
class swow extends Extension
{
public function validate(): void
{
if ($this->builder->getPHPVersionID() < 80000 && getenv('SPC_SKIP_PHP_VERSION_CHECK') !== 'yes') {
throw new RuntimeException('The latest swow extension requires PHP 8.0 or later');
}
}
public function getUnixConfigureArg(): string
{
$arg = '--enable-swow';

View File

@@ -28,7 +28,7 @@ class BSDBuilder extends UnixBuilderBase
// ---------- set necessary options ----------
// set C Compiler (default: clang)
f_putenv('CC=' . $this->getOption('cc', 'clang'));
// set C++ Composer (default: clang++)
// set C++ Compiler (default: clang++)
f_putenv('CXX=' . $this->getOption('cxx', 'clang++'));
// set PATH
f_putenv('PATH=' . BUILD_ROOT_PATH . '/bin:' . getenv('PATH'));
@@ -86,7 +86,8 @@ class BSDBuilder extends UnixBuilderBase
SourcePatcher::patchBeforeConfigure($this);
$json_74 = $this->getPHPVersionID() < 80000 ? '--enable-json ' : '';
$zts = $this->getOption('enable-zts', false) ? '--enable-zts --disable-zend-signals ' : '';
$zts_enable = $this->getPHPVersionID() < 80000 ? '--enable-maintainer-zts --disable-zend-signals' : '--enable-zts --disable-zend-signals';
$zts = $this->getOption('enable-zts', false) ? $zts_enable : '';
$enableCli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI;
$enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;

View File

@@ -92,6 +92,9 @@ class LinuxBuilder extends UnixBuilderBase
}
/**
* Build PHP from source.
*
* @param int $build_target Build target, use `BUILD_TARGET_*` constants
* @throws RuntimeException
* @throws FileSystemException
* @throws WrongUsageException
@@ -131,10 +134,10 @@ class LinuxBuilder extends UnixBuilderBase
}
$disable_jit = $this->getOption('disable-opcache-jit', false) ? '--disable-opcache-jit ' : '';
$enableCli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI;
$enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
$enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
$enable_cli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI;
$enable_fpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
$enable_micro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
$enable_embed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
// prepare build php envs
$envs_build_php = SystemUtil::makeEnvVarString([
@@ -144,37 +147,18 @@ class LinuxBuilder extends UnixBuilderBase
'LIBS' => getenv('SPC_CMD_VAR_PHP_CONFIGURE_LIBS'),
]);
// upx pack and strip for micro
if ($this->getOption('with-upx-pack', false)) {
// with upx pack always need strip
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) && ' . getenv('UPX_EXEC') . ' --best \$(SAPI_MICRO_PATH)',
);
} elseif (!$this->getOption('no-strip', false)) {
// not-no-strip means strip (default behavior)
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 {
// just no strip
FileSystem::replaceFileRegex(
SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag',
'/POST_MICRO_BUILD_COMMANDS=.*/',
'POST_MICRO_BUILD_COMMANDS=true',
);
// process micro upx patch if micro sapi enabled
if ($enable_micro) {
$this->processMicroUPX();
}
shell()->cd(SOURCE_PATH . '/php-src')
->exec(
getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' .
($enableCli ? '--enable-cli ' : '--disable-cli ') .
($enableFpm ? '--enable-fpm ' : '--disable-fpm ') .
($enableEmbed ? '--enable-embed=static ' : '--disable-embed ') .
($enableMicro ? '--enable-micro=all-static ' : '--disable-micro ') .
($enable_cli ? '--enable-cli ' : '--disable-cli ') .
($enable_fpm ? '--enable-fpm ' : '--disable-fpm ') .
($enable_embed ? '--enable-embed=static ' : '--disable-embed ') .
($enable_micro ? '--enable-micro=all-static ' : '--disable-micro ') .
$disable_jit .
$json_74 .
$zts .
@@ -188,21 +172,21 @@ class LinuxBuilder extends UnixBuilderBase
$this->cleanMake();
if ($enableCli) {
if ($enable_cli) {
logger()->info('building cli');
$this->buildCli();
}
if ($enableFpm) {
if ($enable_fpm) {
logger()->info('building fpm');
$this->buildFpm();
}
if ($enableMicro) {
if ($enable_micro) {
logger()->info('building micro');
$this->buildMicro();
}
if ($enableEmbed) {
if ($enable_embed) {
logger()->info('building embed');
if ($enableMicro) {
if ($enable_micro) {
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/Makefile', 'OVERALL_TARGET =', 'OVERALL_TARGET = libphp.la');
}
$this->buildEmbed();
@@ -318,4 +302,48 @@ class LinuxBuilder extends UnixBuilderBase
'EXTRA_LDFLAGS_PROGRAM' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM'),
];
}
/**
* Apply option --no-strip and --with-upx-pack for micro sapi.
*
* @throws FileSystemException
*/
private function processMicroUPX(): void
{
// upx pack and strip for micro
// but always restore Makefile.frag.bak first
if (file_exists(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.bak')) {
copy(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.bak', SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag');
}
if ($this->getOption('with-upx-pack', false)) {
// judge $(MAKE) micro_2s_objs SFX_FILESIZE=`$(STAT_SIZE) $(SAPI_MICRO_PATH)` count
// if 2, replace src/globals/extra/micro-triple-Makefile.frag file content
if (substr_count(FileSystem::readFile(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag'), '$(MAKE) micro_2s_objs SFX_FILESIZE=`$(STAT_SIZE) $(SAPI_MICRO_PATH)`') === 2) {
// bak first
copy(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag', SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.bak');
// replace Makefile.frag content
FileSystem::writeFile(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag', FileSystem::readFile(ROOT_DIR . '/src/globals/extra/micro-triple-Makefile.frag'));
}
// with upx pack always need strip
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) && ' . getenv('UPX_EXEC') . ' --best \$(SAPI_MICRO_PATH)',
);
} elseif (!$this->getOption('no-strip', false)) {
// not-no-strip means strip (default behavior)
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 {
// just no strip
FileSystem::replaceFileRegex(
SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag',
'/POST_MICRO_BUILD_COMMANDS=.*/',
'POST_MICRO_BUILD_COMMANDS=true',
);
}
}
}

View File

@@ -1,20 +1,4 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*
* lwmbs is licensed under Mulan PSL v2. You can use this
* software according to the terms and conditions of the
* Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
*/
declare(strict_types=1);

View File

@@ -90,7 +90,7 @@ abstract class UnixBuilderBase extends BuilderBase
return $extra;
}
public function buildLibs(array $sorted_libraries): void
public function proveLibs(array $sorted_libraries): void
{
// search all supported libs
$support_lib_list = [];
@@ -137,16 +137,6 @@ abstract class UnixBuilderBase extends BuilderBase
SourceManager::initSource(libs: $sorted_libraries);
$this->emitPatchPoint('after-libs-extract');
// build all libs
foreach ($this->libs as $lib) {
match ($lib->tryBuild($this->getOption('rebuild', false))) {
BUILD_STATUS_OK => logger()->info('lib [' . $lib::NAME . '] build success'),
BUILD_STATUS_ALREADY => logger()->notice('lib [' . $lib::NAME . '] already built'),
BUILD_STATUS_FAILED => logger()->error('lib [' . $lib::NAME . '] build failed'),
default => logger()->warning('lib [' . $lib::NAME . '] build status unknown'),
};
}
}
/**

View File

@@ -17,7 +17,7 @@ trait ncurses
'--with-curses-h ' .
'--enable-pc-files ' .
'--enable-echo ' .
// '--enable-widec ' .
'--disable-widec ' .
'--with-normal ' .
'--with-ticlib ' .
'--without-tests ' .

View File

@@ -20,7 +20,6 @@ trait xz
'./configure ' .
'--enable-static ' .
'--disable-shared ' .
"--host={$this->builder->getOption('gnu-arch')}-unknown-linux " .
'--disable-scripts ' .
'--disable-doc ' .
'--with-libiconv ' .

View File

@@ -205,7 +205,7 @@ class WindowsBuilder extends BuilderBase
$this->deployBinary(BUILD_TARGET_MICRO);
}
public function buildLibs(array $sorted_libraries): void
public function proveLibs(array $sorted_libraries): void
{
// search all supported libs
$support_lib_list = [];
@@ -242,16 +242,6 @@ class WindowsBuilder extends BuilderBase
// extract sources
SourceManager::initSource(libs: $sorted_libraries);
// build all libs
foreach ($this->libs as $lib) {
match ($lib->tryBuild($this->getOption('rebuild', false))) {
BUILD_STATUS_OK => logger()->info('lib [' . $lib::NAME . '] build success'),
BUILD_STATUS_ALREADY => logger()->notice('lib [' . $lib::NAME . '] already built'),
BUILD_STATUS_FAILED => logger()->error('lib [' . $lib::NAME . '] build failed'),
default => logger()->warning('lib [' . $lib::NAME . '] build status unknown'),
};
}
}
/**
@@ -271,6 +261,12 @@ class WindowsBuilder extends BuilderBase
*/
public function sanityCheck(mixed $build_target): void
{
// remove all .dll from `buildroot/bin/`
logger()->debug('Removing all .dll files from buildroot/bin/');
$dlls = glob(BUILD_BIN_PATH . '\*.dll');
foreach ($dlls as $dll) {
@unlink($dll);
}
// sanity check for php-cli
if (($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) {
logger()->info('running cli sanity check');

View File

@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace SPC\builder\windows\library;
class pthreads4w extends WindowsLibraryBase
{
public const NAME = 'pthreads4w';
protected function build(): void
{
cmd()->cd($this->source_dir)
->execWithWrapper(
$this->builder->makeSimpleWrapper(
'nmake /E /nologo /f Makefile ' .
'DESTROOT=' . BUILD_ROOT_PATH . ' ' .
'XCFLAGS="/MT" ' . // no dll
'EHFLAGS="/I. /DHAVE_CONFIG_H /Os /Ob2 /D__PTW32_STATIC_LIB /D__PTW32_BUILD_INLINED"'
),
'pthreadVC3.inlined_static_stamp'
);
copy($this->source_dir . '\libpthreadVC3.lib', BUILD_LIB_PATH . '\libpthreadVC3.lib');
copy($this->source_dir . '\_ptw32.h', BUILD_INCLUDE_PATH . '\_ptw32.h');
copy($this->source_dir . '\pthread.h', BUILD_INCLUDE_PATH . '\pthread.h');
copy($this->source_dir . '\sched.h', BUILD_INCLUDE_PATH . '\sched.h');
copy($this->source_dir . '\semaphore.h', BUILD_INCLUDE_PATH . '\semaphore.h');
}
}

View File

@@ -132,4 +132,14 @@ abstract class BaseCommand extends Command
{
return true;
}
protected function logWithResult(bool $result, string $success_msg, string $fail_msg): int
{
if ($result) {
logger()->info($success_msg);
return static::SUCCESS;
}
logger()->error($fail_msg);
return static::FAILURE;
}
}

View File

@@ -17,7 +17,7 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use ZM\Logger\ConsoleColor;
#[AsCommand('build', 'build PHP')]
#[AsCommand('build', 'build PHP', ['build:php'])]
class BuildCliCommand extends BuildCommand
{
public function configure(): void
@@ -93,6 +93,9 @@ class BuildCliCommand extends BuildCommand
if ($this->getOption('no-strip')) {
logger()->warning('--with-upx-pack conflicts with --no-strip, --no-strip won\'t work!');
}
if (($rule & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO) {
logger()->warning('Some cases micro.sfx cannot be packed via UPX due to dynamic size bug, be aware!');
}
}
try {
// create builder
@@ -131,19 +134,25 @@ class BuildCliCommand extends BuildCommand
if (!empty($not_included)) {
$indent_texts['Extra Exts (' . count($not_included) . ')'] = implode(', ', $not_included);
}
$this->printFormatInfo($indent_texts);
$this->printFormatInfo($this->getDefinedEnvs(), true);
$this->printFormatInfo($indent_texts);
logger()->notice('Build will start after 2s ...');
sleep(2);
// compile libraries
$builder->proveLibs($libraries);
// check extensions
$builder->proveExts($extensions);
// validate libs and exts
$builder->validateLibsAndExts();
// build libraries
$builder->buildLibs();
if ($this->input->getOption('with-clean')) {
logger()->info('Cleaning source dir...');
FileSystem::removeDir(SOURCE_PATH);
}
// compile libraries
$builder->buildLibs($libraries);
// check extensions
$builder->proveExts($extensions);
// Process -I option
$custom_ini = [];

View File

@@ -61,7 +61,11 @@ class BuildLibsCommand extends BuildCommand
$builder->setLibsOnly();
// 编译和检查库完整
$libraries = DependencyUtil::getLibs($libraries);
$builder->buildLibs($libraries);
logger()->info('Building libraries: ' . implode(',', $libraries));
sleep(2);
$builder->proveLibs($libraries);
$builder->validateLibsAndExts();
$builder->buildLibs();
$time = round(microtime(true) - START_TIME, 3);
logger()->info('Build libs complete, used ' . $time . ' s !');

View File

@@ -57,8 +57,11 @@ class DumpLicenseCommand extends BaseCommand
$libraries = DependencyUtil::getLibs($libraries);
$dumper->addLibs($libraries);
$dumper->dump($this->getOption('dump-dir'));
$this->output->writeln('Dump target dir: ' . $this->getOption('dump-dir'));
return static::SUCCESS;
return $this->logWithResult(
$dumper->dump($this->getOption('dump-dir')),
'Dump target dir: ' . $this->getOption('dump-dir'),
'Dump failed!'
);
}
if ($this->getOption('for-sources') !== null) {
$sources = array_map('trim', array_filter(explode(',', $this->getOption('for-sources'))));

View File

@@ -0,0 +1,67 @@
<?php
declare(strict_types=1);
namespace SPC\command;
use SPC\store\Config;
use SPC\store\Downloader;
use SPC\store\FileSystem;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
#[AsCommand('switch-php-version', description: 'Switch downloaded PHP version')]
class SwitchPhpVersionCommand extends BaseCommand
{
public function configure()
{
$this->addArgument(
'php-major-version',
InputArgument::REQUIRED,
'PHP major version (supported: 7.4, 8.0, 8.1, 8.2, 8.3)',
null,
fn () => ['7.4', '8.0', '8.1', '8.2', '8.3']
);
$this->no_motd = true;
$this->addOption('retry', 'R', InputOption::VALUE_REQUIRED, 'Set retry time when downloading failed (default: 0)', '0');
}
public function handle(): int
{
$php_ver = $this->input->getArgument('php-major-version');
if (!in_array($php_ver, ['7.4', '8.0', '8.1', '8.2', '8.3'])) {
$this->output->writeln('<error>Invalid PHP major version ' . $php_ver . ' !</error>');
return static::FAILURE;
}
// detect if downloads/.lock.json exists
$lock_file = DOWNLOAD_PATH . '/.lock.json';
// parse php-src part of lock file
$lock_data = json_decode(file_get_contents($lock_file), true);
// get php-src downloaded file name
$php_src = $lock_data['php-src'];
$file = DOWNLOAD_PATH . '/' . ($php_src['filename'] ?? '.donot.delete.me');
if (file_exists($file)) {
$this->output->writeln('<info>Removing old PHP source...</info>');
unlink($file);
}
// Download new PHP source
$this->output->writeln('<info>Downloading PHP source...</info>');
define('SPC_BUILD_PHP_VERSION', $php_ver);
// retry
$retry = intval($this->getOption('retry'));
f_putenv('SPC_RETRY_TIME=' . $retry);
Downloader::downloadSource('php-src', Config::getSource('php-src'));
// Remove source/php-src dir
FileSystem::removeDir(SOURCE_PATH . '/php-src');
$this->output->writeln('<info>Switched to PHP ' . $php_ver . ' successfully!</info>');
return static::SUCCESS;
}
}

View File

@@ -62,12 +62,17 @@ class DependencyUtil
if ($include_suggested_libs) {
foreach ($dep_list as $name => $obj) {
$del_list = [];
foreach ($obj['suggests'] as $id => $suggest) {
if (!str_starts_with($suggest, 'ext@')) {
$dep_list[$name]['depends'][] = $suggest;
array_splice($dep_list[$name]['suggests'], $id, 1);
$del_list[] = $id;
}
}
foreach ($del_list as $id) {
unset($dep_list[$name]['suggests'][$id]);
}
$dep_list[$name]['suggests'] = array_values($dep_list[$name]['suggests']);
}
}
@@ -93,12 +98,17 @@ class DependencyUtil
if ($include_suggested_exts) {
// check every deps suggests contains ext@
foreach ($dep_list as $name => $obj) {
$del_list = [];
foreach ($obj['suggests'] as $id => $suggest) {
if (str_starts_with($suggest, 'ext@')) {
$dep_list[$name]['depends'][] = $suggest;
array_splice($dep_list[$name]['suggests'], $id, 1);
$del_list[] = $id;
}
}
foreach ($del_list as $id) {
unset($dep_list[$name]['suggests'][$id]);
}
$dep_list[$name]['suggests'] = array_values($dep_list[$name]['suggests']);
}
}
@@ -106,12 +116,17 @@ class DependencyUtil
if ($include_suggested_libs) {
// check every deps suggests
foreach ($dep_list as $name => $obj) {
$del_list = [];
foreach ($obj['suggests'] as $id => $suggest) {
if (!str_starts_with($suggest, 'ext@')) {
$dep_list[$name]['depends'][] = $suggest;
array_splice($dep_list[$name]['suggests'], $id, 1);
$del_list[] = $id;
}
}
foreach ($del_list as $id) {
unset($dep_list[$name]['suggests'][$id]);
}
$dep_list[$name]['suggests'] = array_values($dep_list[$name]['suggests']);
}
}

View File

@@ -51,7 +51,7 @@ class GlobalEnvManager
// Init system-specific env
match (PHP_OS_FAMILY) {
'Windows' => self::initWindowsEnv($builder),
'Windows' => self::initWindowsEnv(),
'Darwin' => self::initDarwinEnv($builder),
'Linux' => self::initLinuxEnv($builder),
'BSD' => 'TODO',
@@ -59,7 +59,7 @@ class GlobalEnvManager
};
}
private static function initWindowsEnv(BuilderBase $builder): void
private static function initWindowsEnv(): void
{
// Windows need php-sdk binary tools
self::initIfNotExists('PHP_SDK_PATH', WORKING_DIR . DIRECTORY_SEPARATOR . 'php-sdk-binary-tools');
@@ -69,7 +69,7 @@ class GlobalEnvManager
private static function initLinuxEnv(BuilderBase $builder): void
{
// Init C Compiler and C++ Compiler (alpine)
if (\SPC\builder\linux\SystemUtil::isMuslDist()) {
if (LinuxSystemUtil::isMuslDist()) {
self::initIfNotExists('CC', 'gcc');
self::initIfNotExists('CXX', 'g++');
self::initIfNotExists('AR', 'ar');
@@ -80,7 +80,9 @@ class GlobalEnvManager
self::initIfNotExists('CXX', "{$arch}-linux-musl-g++");
self::initIfNotExists('AR', "{$arch}-linux-musl-ar");
self::initIfNotExists('LD', 'ld.gold');
self::putenv("PATH=/usr/local/musl/bin:/usr/local/musl/{$arch}-linux-musl/bin:" . getenv('PATH'));
if (getenv('SPC_NO_MUSL_PATH') !== 'yes') {
self::putenv("PATH=/usr/local/musl/bin:/usr/local/musl/{$arch}-linux-musl/bin:" . getenv('PATH'));
}
}
// Init arch-specific cflags
@@ -106,12 +108,11 @@ class GlobalEnvManager
'SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS' => getenv('SPC_DEFAULT_C_FLAGS'),
'SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH,
'SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS' => '-L' . BUILD_LIB_PATH,
'SPC_CMD_VAR_PHP_CONFIGURE_LIBS' => '-ldl -lpthread',
'SPC_CMD_VAR_PHP_CONFIGURE_LIBS' => '-ldl -lpthread -lm',
'SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS' => $php_extra_cflags_optimize . ' -fno-ident -fPIE',
'SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS' => '',
'SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM' => $clang_use_lld . '-all-static',
];
foreach ($init_spc_cmd_maps as $name => $value) {
self::initIfNotExists($name, $value);
}

View File

@@ -10,6 +10,9 @@ use SPC\exception\WrongUsageException;
use SPC\store\Config;
use SPC\store\FileSystem;
/**
* License dumper, dump source license files to target directory
*/
class LicenseDumper
{
private array $exts = [];
@@ -37,6 +40,10 @@ class LicenseDumper
}
/**
* Dump source licenses to target directory
*
* @param string $target_dir Target directory
* @return bool Success or not
* @throws WrongUsageException
* @throws FileSystemException
* @throws RuntimeException
@@ -55,20 +62,29 @@ class LicenseDumper
$source_name = Config::getExt($ext, 'source');
foreach ($this->getSourceLicenses($source_name) as $index => $license) {
file_put_contents("{$target_dir}/ext_{$ext}_{$index}.txt", $license);
$result = file_put_contents("{$target_dir}/ext_{$ext}_{$index}.txt", $license);
if ($result === false) {
return false;
}
}
}
foreach ($this->libs as $lib) {
$source_name = Config::getLib($lib, 'source');
foreach ($this->getSourceLicenses($source_name) as $index => $license) {
file_put_contents("{$target_dir}/lib_{$lib}_{$index}.txt", $license);
$result = file_put_contents("{$target_dir}/lib_{$lib}_{$index}.txt", $license);
if ($result === false) {
return false;
}
}
}
foreach ($this->sources as $source) {
foreach ($this->getSourceLicenses($source) as $index => $license) {
file_put_contents("{$target_dir}/src_{$source}_{$index}.txt", $license);
$result = file_put_contents("{$target_dir}/src_{$source}_{$index}.txt", $license);
if ($result === false) {
return false;
}
}
}
return true;

View File

@@ -1,38 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\util;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
class Patcher
{
/**
* @throws FileSystemException
* @throws RuntimeException
*/
public static function patchLinuxConfigHeader(string $libc): void
{
switch ($libc) {
case 'musl_wrapper':
// bad checks
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/main/php_config.h', '/^#define HAVE_STRLCPY 1$/m', '');
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/main/php_config.h', '/^#define HAVE_STRLCAT 1$/m', '');
// no break
case 'musl':
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/main/php_config.h', '/^#define HAVE_FUNC_ATTRIBUTE_IFUNC 1$/m', '');
break;
case 'glibc':
// avoid lcrypt dependency
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/main/php_config.h', '/^#define HAVE_CRYPT 1$/m', '');
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/main/php_config.h', '/^#define HAVE_CRYPT_R 1$/m', '');
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/main/php_config.h', '/^#define HAVE_CRYPT_H 1$/m', '');
break;
default:
throw new RuntimeException('not implemented');
}
}
}

View File

@@ -15,6 +15,9 @@ class UnixShell
private array $env = [];
/**
* @throws RuntimeException
*/
public function __construct(?bool $debug = null)
{
if (PHP_OS_FAMILY === 'Windows') {

View File

@@ -15,6 +15,9 @@ class WindowsCmd
private array $env = [];
/**
* @throws RuntimeException
*/
public function __construct(?bool $debug = null)
{
if (PHP_OS_FAMILY !== 'Windows') {

View File

@@ -0,0 +1,51 @@
micro: $(SAPI_MICRO_PATH)
micro_2s_objs:
rm $(MICRO_2STAGE_OBJS) || :
$(MAKE) $(MICRO_2STAGE_OBJS)
EXTRA_MICRO_BUILD_COMMANDS=
POST_MICRO_BUILD_COMMANDS=$(STRIP) $(MICRO_STRIP_FLAGS) $(SAPI_MICRO_PATH)
$(SAPI_MICRO_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_MICRO_OBJS)
$(MAKE) micro_2s_objs SFX_FILESIZE=0xcafebabe
$(BUILD_MICRO)
$(EXTRA_MICRO_BUILD_COMMANDS)
$(POST_MICRO_BUILD_COMMANDS)
$(MAKE) micro_2s_objs SFX_FILESIZE=`$(STAT_SIZE) $(SAPI_MICRO_PATH)`
$(BUILD_MICRO)
$(EXTRA_MICRO_BUILD_COMMANDS)
$(POST_MICRO_BUILD_COMMANDS)
$(MAKE) micro_2s_objs SFX_FILESIZE=`$(STAT_SIZE) $(SAPI_MICRO_PATH)`
$(BUILD_MICRO)
$(EXTRA_MICRO_BUILD_COMMANDS)
$(POST_MICRO_BUILD_COMMANDS)
$(MAKE) micro_2s_objs SFX_FILESIZE=`$(STAT_SIZE) $(SAPI_MICRO_PATH)`
$(BUILD_MICRO)
$(EXTRA_MICRO_BUILD_COMMANDS)
$(POST_MICRO_BUILD_COMMANDS)
MICRO_EXES = sapi/micro/tests/simpleecho.exe sapi/micro/tests/fakecmd.exe
$(MICRO_EXES): $(SAPI_MICRO_PATH)
@binname=$@;\
cat $(SAPI_MICRO_PATH) $${binname%.exe}.php > $@ || {\
rm $@; \
exit 1; \
}
@chmod 0755 $@
MICRO_FAKECMD=sapi/micro/tests/fakecmd.exe
micro_test: $(SAPI_MICRO_PATH) $(MICRO_EXES)
@[ x"hello world" = "x`sapi/micro/tests/simpleecho.exe nonce world`" ] || {\
echo sanity check for micro.sfx failed, the sfx generated may be corrupt. >&2 ;\
exit 1;\
}
@SKIP_IO_CAPTURE_TESTS=yes \
TEST_PHP_EXECUTABLE=$(MICRO_FAKECMD) \
TEST_PHP_SRCDIR=$(top_srcdir) \
CC="$(CC)" \
$(MICRO_FAKECMD) -n $(PHP_TEST_SETTINGS) $(top_srcdir)/run-tests.php -n $(TESTS); \
exit $$?;

View File

@@ -47,6 +47,13 @@ function arch2gnu(string $arch): string
};
}
/**
* Match pattern function
* Example: match_pattern('*.txt', 'test.txt') will return true.
*
* @param string $pattern Pattern string
* @param string $subject Subject string
*/
function match_pattern(string $pattern, string $subject): bool
{
$pattern = str_replace(['\*', '\\\\.*'], ['.*', '\*'], preg_quote($pattern, '/'));
@@ -54,6 +61,12 @@ function match_pattern(string $pattern, string $subject): bool
return preg_match($pattern, $subject) === 1;
}
/**
* Quote a string with a quote character
*
* @param string $str String to quote
* @param string $quote Quote character, default: `"`
*/
function quote(string $str, string $quote = '"'): string
{
return $quote . $str . $quote;
@@ -61,7 +74,6 @@ function quote(string $str, string $quote = '"'): string
/**
* Get Family name of current OS
*
* @throws WrongUsageException
*/
function osfamily2dir(): string
@@ -76,6 +88,41 @@ function osfamily2dir(): string
};
}
function shell(?bool $debug = null): UnixShell
{
/* @noinspection PhpUnhandledExceptionInspection */
return new UnixShell($debug);
}
function cmd(?bool $debug = null): WindowsCmd
{
/* @noinspection PhpUnhandledExceptionInspection */
return new WindowsCmd($debug);
}
/**
* Get current builder.
*
* @throws WrongUsageException
*/
function builder(): BuilderBase
{
return BuilderProvider::getBuilder();
}
/**
* Get current patch point.
*
* @throws WrongUsageException
*/
function patch_point(): string
{
return BuilderProvider::getBuilder()->getPatchPoint();
}
// ------- function f_* part -------
// f_ means standard function wrapper
/**
* Execute the shell command, and the output will be directly printed in the terminal. If there is an error, an exception will be thrown
*
@@ -126,33 +173,3 @@ function f_putenv(string $env): bool
logger()->debug('Setting env: ' . $env);
return putenv($env);
}
function shell(?bool $debug = null): UnixShell
{
return new UnixShell($debug);
}
function cmd(?bool $debug = null): WindowsCmd
{
return new WindowsCmd($debug);
}
/**
* Get current builder.
*
* @throws WrongUsageException
*/
function builder(): BuilderBase
{
return BuilderProvider::getBuilder();
}
/**
* Get current patch point.
*
* @throws WrongUsageException
*/
function patch_point(): string
{
return BuilderProvider::getBuilder()->getPatchPoint();
}

View File

@@ -11,10 +11,12 @@ declare(strict_types=1);
// --------------------------------- edit area ---------------------------------
$zts = true;
// If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`).
$extensions = match (PHP_OS_FAMILY) {
'Linux', 'Darwin' => 'readline',
'Windows' => 'mbstring,pdo_sqlite,mbregex',
'Linux', 'Darwin' => 'parallel',
'Windows' => 'mbstring,pdo_sqlite,mbregex,parallel',
};
// If you want to test lib-suggests feature with extension, add them below (comma separated, example `libwebp,libavif`).
@@ -71,5 +73,6 @@ echo match ($argv[1]) {
'libs' => $final_libs,
'libs_cmd' => ($final_libs === '' ? '' : (' --with-libs=' . $final_libs)),
'cmd' => $final_extensions_cmd . ($final_libs === '' ? '' : (' --with-libs=' . $final_libs)),
'zts' => $zts ? '--enable-zts' : '',
default => '',
};

View File

@@ -0,0 +1,5 @@
<?php
declare(strict_types=1);
assert(class_exists('\parallel\Runtime'));