Merge pull request #864 from crazywhalecc/swoolehooks

swoole hooks can be compiled if pgsql/sqlite are not compiled in statically
This commit is contained in:
Marc 2025-08-29 03:46:30 +02:00 committed by GitHub
commit 5a30d509e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 879 additions and 475 deletions

View File

@ -65,7 +65,7 @@ jobs:
- sqlsrv - sqlsrv
- ssh2 - ssh2
- swoole - swoole
- swoole,swoole-hook-pgsql,swoole-hook-mysql,swoole-hook-sqlite - swoole,swoole-hook-pgsql,swoole-hook-mysql,swoole-hook-sqlite,swoole-hook-odbc
- swow - swow
- sysvmsg,sysvsem,sysvshm - sysvmsg,sysvsem,sysvshm
- tidy - tidy
@ -82,7 +82,7 @@ jobs:
- zlib - zlib
- zstd - zstd
php-version: php-version:
- "8.5" - "8.4"
operating-system: operating-system:
- "ubuntu-latest" - "ubuntu-latest"
#- "macos-13" #- "macos-13"

View File

@ -842,14 +842,23 @@
"nghttp2", "nghttp2",
"zlib" "zlib"
], ],
"lib-suggests": [
"zstd"
],
"lib-suggests-linux": [
"zstd",
"liburing"
],
"ext-depends": [ "ext-depends": [
"openssl", "openssl",
"curl" "curl"
], ],
"ext-suggests": [ "ext-suggests": [
"sockets",
"swoole-hook-pgsql", "swoole-hook-pgsql",
"swoole-hook-mysql", "swoole-hook-mysql",
"swoole-hook-sqlite" "swoole-hook-sqlite",
"swoole-hook-odbc"
] ]
}, },
"swoole-hook-mysql": { "swoole-hook-mysql": {
@ -859,11 +868,12 @@
}, },
"notes": true, "notes": true,
"type": "addon", "type": "addon",
"arg-type": "custom", "arg-type": "none",
"ext-depends": [ "ext-depends": [
"mysqlnd", "mysqlnd",
"pdo", "pdo",
"pdo_mysql" "pdo_mysql",
"swoole"
], ],
"ext-suggests": [ "ext-suggests": [
"mysqli" "mysqli"
@ -877,10 +887,11 @@
}, },
"notes": true, "notes": true,
"type": "addon", "type": "addon",
"arg-type": "custom", "arg-type": "none",
"ext-depends": [ "ext-depends": [
"pgsql", "pgsql",
"pdo" "pdo",
"swoole"
] ]
}, },
"swoole-hook-sqlite": { "swoole-hook-sqlite": {
@ -890,10 +901,27 @@
}, },
"notes": true, "notes": true,
"type": "addon", "type": "addon",
"arg-type": "custom", "arg-type": "none",
"ext-depends": [ "ext-depends": [
"sqlite3", "sqlite3",
"pdo" "pdo",
"swoole"
]
},
"swoole-hook-odbc": {
"support": {
"Windows": "no",
"BSD": "wip"
},
"notes": true,
"type": "addon",
"arg-type": "none",
"ext-depends": [
"pdo",
"swoole"
],
"lib-depends": [
"unixodbc"
] ]
}, },
"swow": { "swow": {

View File

@ -925,5 +925,20 @@
"zstd.h", "zstd.h",
"zstd_errors.h" "zstd_errors.h"
] ]
},
"liburing": {
"source": "liburing",
"pkg-configs": [
"liburing",
"liburing-ffi"
],
"static-libs-linux": [
"liburing.a",
"liburing-ffi.a"
],
"headers-linux": [
"liburing/",
"liburing.h"
]
} }
} }

View File

@ -1136,5 +1136,14 @@
"type": "file", "type": "file",
"path": "LICENSE" "path": "LICENSE"
} }
},
"liburing": {
"type": "ghtar",
"repo": "axboe/liburing",
"prefer-stable": true,
"license": {
"type": "file",
"path": "COPYING"
}
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -46,6 +46,14 @@ If you use `swoole,swoole-hook-sqlite`, you will enable the coroutine mode of Sw
swoole-hook-sqlite conflicts with the `pdo_sqlite` extension. If you want to use Swoole and `pdo_sqlite`, please delete the pdo_sqlite extension and enable `swoole` and `swoole-hook-sqlite`. swoole-hook-sqlite conflicts with the `pdo_sqlite` extension. If you want to use Swoole and `pdo_sqlite`, please delete the pdo_sqlite extension and enable `swoole` and `swoole-hook-sqlite`.
This extension contains an implementation of the coroutine environment for `pdo_sqlite`. This extension contains an implementation of the coroutine environment for `pdo_sqlite`.
## swoole-hook-odbc
swoole-hook-odbc is not an extension, it's a Hook feature of Swoole.
If you use `swoole,swoole-hook-odbc`, you will enable the coroutine mode of Swoole's `odbc` extension.
swoole-hook-odbc conflicts with the `pdo_odbc` extension. If you want to use Swoole and `pdo_odbc`, please delete the `pdo_odbc` extension and enable `swoole` and `swoole-hook-odbc`.
This extension contains an implementation of the coroutine environment for `pdo_odbc`.
## swow ## swow
1. Only PHP 8.0+ is supported. 1. Only PHP 8.0+ is supported.

View File

@ -43,6 +43,14 @@ swoole-hook-sqlite 不是一个扩展,而是 Swoole 的 Hook 特性。
swoole-hook-sqlite 与 `pdo_sqlite` 扩展冲突。如需使用 Swoole 和 `pdo_sqlite`,请删除 pdo_sqlite 扩展,启用 `swoole``swoole-hook-sqlite` 即可。 swoole-hook-sqlite 与 `pdo_sqlite` 扩展冲突。如需使用 Swoole 和 `pdo_sqlite`,请删除 pdo_sqlite 扩展,启用 `swoole``swoole-hook-sqlite` 即可。
该扩展包含了 `pdo_sqlite` 的协程环境的实现。 该扩展包含了 `pdo_sqlite` 的协程环境的实现。
## swoole-hook-odbc
swoole-hook-odbc 不是一个扩展,而是 Swoole 的 Hook 特性。
如果你在编译时添加了 `swoole,swoole-hook-odbc`,你将启用 Swoole 的 `odbc` 扩展的协程模式。
swoole-hook-odbc 与 `pdo_odbc` 扩展冲突。如需使用 Swoole 和 `pdo_odbc`,请删除 `pdo_odbc` 扩展,启用 `swoole``swoole-hook-odbc` 即可。
该扩展包含了 `pdo_odbc` 的协程环境的实现。
## swow ## swow
1. swow 仅支持 PHP 8.0+ 版本。 1. swow 仅支持 PHP 8.0+ 版本。

View File

@ -268,11 +268,11 @@ abstract class BuilderBase
{ {
$ret = []; $ret = [];
foreach ($this->getExts() as $ext) { foreach ($this->getExts() as $ext) {
$arg = $ext->getConfigureArg(); $arg = null;
if ($ext->isBuildShared() && !$ext->isBuildStatic()) { if ($ext->isBuildShared() && !$ext->isBuildStatic()) {
if ( if (
(Config::getExt($ext->getName(), 'type') === 'builtin' && (Config::getExt($ext->getName(), 'type') === 'builtin' &&
!file_exists(SOURCE_PATH . '/php-src/ext/' . $ext->getName() . '/config.m4')) || !file_exists(SOURCE_PATH . '/php-src/ext/' . $ext->getName() . '/config.m4')) ||
Config::getExt($ext->getName(), 'build-with-php') === true Config::getExt($ext->getName(), 'build-with-php') === true
) { ) {
$arg = $ext->getConfigureArg(true); $arg = $ext->getConfigureArg(true);
@ -280,6 +280,7 @@ abstract class BuilderBase
continue; continue;
} }
} }
$arg ??= $ext->getConfigureArg();
logger()->info($ext->getName() . ' is using ' . $arg); logger()->info($ext->getName() . ' is using ' . $arg);
$ret[] = trim($arg); $ret[] = trim($arg);
} }

View File

@ -252,12 +252,15 @@ class Extension
$order = []; $order = [];
$resolve = function ($extension) use (&$resolve, &$loaded, &$order) { $resolve = function ($extension) use (&$resolve, &$loaded, &$order) {
if (!$extension instanceof Extension) {
return;
}
if (isset($loaded[$extension->getName()])) { if (isset($loaded[$extension->getName()])) {
return; return;
} }
$loaded[$extension->getName()] = true; $loaded[$extension->getName()] = true;
foreach ($this->dependencies as $dependency) { foreach ($extension->dependencies as $dependency) {
$resolve($dependency); $resolve($dependency);
} }
@ -269,6 +272,9 @@ class Extension
$ret = ''; $ret = '';
foreach ($order as $ext) { foreach ($order as $ext) {
if ($ext instanceof self && $ext->isBuildShared()) { if ($ext instanceof self && $ext->isBuildShared()) {
if (Config::getExt($ext->getName(), 'type', false) === 'addon') {
continue;
}
if (Config::getExt($ext->getName(), 'zend-extension', false) === true) { if (Config::getExt($ext->getName(), 'zend-extension', false) === true) {
$ret .= " -d \"zend_extension={$ext->getName()}\""; $ret .= " -d \"zend_extension={$ext->getName()}\"";
} else { } else {
@ -350,7 +356,7 @@ class Extension
/** /**
* Build shared extension * Build shared extension
*/ */
public function buildShared(): void public function buildShared(array $visited = []): void
{ {
try { try {
if (Config::getExt($this->getName(), 'type') === 'builtin' || Config::getExt($this->getName(), 'build-with-php') === true) { if (Config::getExt($this->getName(), 'type') === 'builtin' || Config::getExt($this->getName(), 'build-with-php') === true) {
@ -366,17 +372,21 @@ class Extension
} }
if (file_exists(BUILD_MODULES_PATH . '/' . $this->getName() . '.so')) { if (file_exists(BUILD_MODULES_PATH . '/' . $this->getName() . '.so')) {
logger()->info('Shared extension [' . $this->getName() . '] was already built, skipping (' . $this->getName() . '.so)'); logger()->info('Shared extension [' . $this->getName() . '] was already built, skipping (' . $this->getName() . '.so)');
return;
} }
logger()->info('Building extension [' . $this->getName() . '] as shared extension (' . $this->getName() . '.so)'); logger()->info('Building extension [' . $this->getName() . '] as shared extension (' . $this->getName() . '.so)');
foreach ($this->dependencies as $dependency) { foreach ($this->dependencies as $dependency) {
if (!$dependency instanceof Extension) { if (!$dependency instanceof Extension) {
continue; continue;
} }
if (!$dependency->isBuildStatic()) { if (!$dependency->isBuildStatic() && !in_array($dependency->getName(), $visited)) {
logger()->info('extension ' . $this->getName() . ' requires extension ' . $dependency->getName()); logger()->info('extension ' . $this->getName() . ' requires extension ' . $dependency->getName());
$dependency->buildShared(); $dependency->buildShared([...$visited, $this->getName()]);
} }
} }
if (Config::getExt($this->getName(), 'type') === 'addon') {
return;
}
match (PHP_OS_FAMILY) { match (PHP_OS_FAMILY) {
'Darwin', 'Linux' => $this->buildUnixShared(), 'Darwin', 'Linux' => $this->buildUnixShared(),
default => throw new WrongUsageException(PHP_OS_FAMILY . ' build shared extensions is not supported yet'), default => throw new WrongUsageException(PHP_OS_FAMILY . ' build shared extensions is not supported yet'),

View File

@ -12,9 +12,9 @@ class mongodb extends Extension
{ {
public function getUnixConfigureArg(bool $shared = false): string public function getUnixConfigureArg(bool $shared = false): string
{ {
$arg = ' --enable-mongodb '; $arg = ' --enable-mongodb' . ($shared ? '=shared' : '') . ' ';
$arg .= ' --with-mongodb-system-libs=no --with-mongodb-client-side-encryption=no '; $arg .= ' --with-mongodb-system-libs=no --with-mongodb-client-side-encryption=no ';
$arg .= ' --with-mongodb-sasl=no '; $arg .= ' --with-mongodb-sasl=no ';
if ($this->builder->getLib('openssl')) { if ($this->builder->getLib('openssl')) {
$arg .= '--with-mongodb-ssl=openssl'; $arg .= '--with-mongodb-ssl=openssl';
} }
@ -22,6 +22,6 @@ class mongodb extends Extension
$arg .= $this->builder->getLib('zstd') ? ' --with-mongodb-zstd=yes ' : ' --with-mongodb-zstd=no '; $arg .= $this->builder->getLib('zstd') ? ' --with-mongodb-zstd=yes ' : ' --with-mongodb-zstd=no ';
// $arg .= $this->builder->getLib('snappy') ? ' --with-mongodb-snappy=yes ' : ' --with-mongodb-snappy=no '; // $arg .= $this->builder->getLib('snappy') ? ' --with-mongodb-snappy=yes ' : ' --with-mongodb-snappy=no ';
$arg .= $this->builder->getLib('zlib') ? ' --with-mongodb-zlib=yes ' : ' --with-mongodb-zlib=bundled '; $arg .= $this->builder->getLib('zlib') ? ' --with-mongodb-zlib=yes ' : ' --with-mongodb-zlib=bundled ';
return $arg; return clean_spaces($arg);
} }
} }

View File

@ -8,6 +8,7 @@ use SPC\builder\Extension;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
use SPC\store\SourcePatcher; use SPC\store\SourcePatcher;
use SPC\util\CustomExt; use SPC\util\CustomExt;
use SPC\util\SPCTarget;
#[CustomExt('opcache')] #[CustomExt('opcache')]
class opcache extends Extension class opcache extends Extension
@ -46,7 +47,18 @@ class opcache extends Extension
public function getUnixConfigureArg(bool $shared = false): string public function getUnixConfigureArg(bool $shared = false): string
{ {
return '--enable-opcache'; $phpVersionID = $this->builder->getPHPVersionID();
$opcache_jit = ' --enable-opcache-jit';
if ((SPCTarget::getTargetOS() === 'Linux' &&
SPCTarget::getLibc() === 'musl' &&
$this->builder->getOption('enable-zts') &&
arch2gnu(php_uname('m')) === 'x86_64' &&
$phpVersionID < 80500) ||
$this->builder->getOption('disable-opcache-jit')
) {
$opcache_jit = ' --disable-opcache-jit';
}
return '--enable-opcache' . ($shared ? '=shared' : '') . $opcache_jit;
} }
public function getDistName(): string public function getDistName(): string

View File

@ -8,6 +8,8 @@ use SPC\builder\Extension;
use SPC\builder\macos\MacOSBuilder; use SPC\builder\macos\MacOSBuilder;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\util\CustomExt; use SPC\util\CustomExt;
use SPC\util\SPCConfigUtil;
use SPC\util\SPCTarget;
#[CustomExt('swoole')] #[CustomExt('swoole')]
class swoole extends Extension class swoole extends Extension
@ -43,32 +45,40 @@ class swoole extends Extension
public function getUnixConfigureArg(bool $shared = false): string public function getUnixConfigureArg(bool $shared = false): string
{ {
// enable swoole // enable swoole
$arg = '--enable-swoole'; $arg = '--enable-swoole' . ($shared ? '=shared' : '');
// commonly-used feature: coroutine-time, disable-thread-context // commonly used feature: coroutine-time
$arg .= ' --enable-swoole-coro-time --disable-thread-context'; $arg .= ' --enable-swoole-coro-time --with-pic';
// required feature: curl, openssl (but curl hook is buggy for php 8.0) $arg .= $this->builder->getOption('enable-zts') ? ' --enable-swoole-thread --disable-thread-context' : ' --disable-swoole-thread --enable-thread-context';
// required features: curl, openssl (but curl hook is buggy for php 8.0)
$arg .= $this->builder->getPHPVersionID() >= 80100 ? ' --enable-swoole-curl' : ' --disable-swoole-curl'; $arg .= $this->builder->getPHPVersionID() >= 80100 ? ' --enable-swoole-curl' : ' --disable-swoole-curl';
$arg .= ' --enable-openssl'; $arg .= ' --enable-openssl';
// additional feature: c-ares, brotli, nghttp2 (can be disabled, but we enable it by default in config to support full network feature) // additional features that only require libraries
$arg .= $this->builder->getLib('libcares') ? ' --enable-cares' : ''; $arg .= $this->builder->getLib('libcares') ? ' --enable-cares' : '';
if (!$shared) { $arg .= $this->builder->getLib('brotli') ? (' --enable-brotli --with-brotli-dir=' . BUILD_ROOT_PATH) : '';
$arg .= $this->builder->getLib('brotli') ? (' --enable-brotli --with-brotli-dir=' . BUILD_ROOT_PATH) : '';
}
$arg .= $this->builder->getLib('nghttp2') ? (' --with-nghttp2-dir=' . BUILD_ROOT_PATH) : ''; $arg .= $this->builder->getLib('nghttp2') ? (' --with-nghttp2-dir=' . BUILD_ROOT_PATH) : '';
$arg .= $this->builder->getLib('zstd') ? ' --enable-zstd' : '';
$arg .= $this->builder->getLib('liburing') ? ' --enable-iouring' : '';
$arg .= $this->builder->getExt('sockets') ? ' --enable-sockets' : '';
// additional feature: swoole-pgsql, it should depend on lib [postgresql], but it will lack of CFLAGS etc. // enable additional features that require the pdo extension, but conflict with pdo_* extensions
// so this is a tricky way (enable ext [pgsql,pdo] to add postgresql hook and pdo_pgsql support) // to make sure everything works as it should, this is done in fake addon extensions
$arg .= $this->builder->getExt('swoole-hook-pgsql') ? '' : ' --disable-swoole-pgsql'; $arg .= $this->builder->getExt('swoole-hook-pgsql') ? ' --enable-swoole-pgsql' : ' --disable-swoole-pgsql';
$arg .= $this->builder->getExt('swoole-hook-mysql') ? ' --enable-mysqlnd' : ' --disable-mysqlnd';
$arg .= $this->builder->getExt('swoole-hook-sqlite') ? ' --enable-swoole-sqlite' : ' --disable-swoole-sqlite';
// enable this feature , need remove pdo_sqlite if ($this->builder->getExt('swoole-hook-odbc')) {
// more info : https://wenda.swoole.com/detail/109023 $config = (new SPCConfigUtil($this->builder, ['libs_only_deps' => true]))->config([], ['unixodbc']);
$arg .= $this->builder->getExt('swoole-hook-sqlite') ? '' : ' --disable-swoole-sqlite'; $arg .= ' --with-swoole-odbc=unixODBC,' . BUILD_ROOT_PATH . ' SWOOLE_ODBC_LIBS="' . $config['libs'] . '"';
}
if (SPCTarget::getTargetOS() === 'Darwin') {
$arg .= ' ac_cv_lib_pthread_pthread_barrier_init=no';
}
// enable this feature , need stop pdo_*
// $arg .= $this->builder->getLib('unixodbc') ? ' --with-swoole-odbc=unixODBC,' : ' ';
return $arg; return $arg;
} }
} }

View File

@ -16,26 +16,15 @@ class swoole_hook_mysql extends Extension
return 'swoole'; return 'swoole';
} }
public function getUnixConfigureArg(bool $shared = false): string
{
// pdo_mysql doesn't need to be disabled
// enable swoole-hook-mysql will enable mysqli, pdo, pdo_mysql, we don't need to add any additional options
return '';
}
public function runCliCheckUnix(): void public function runCliCheckUnix(): void
{ {
// skip if not enable swoole
if ($this->builder->getExt('swoole') === null) {
return;
}
[$ret, $out] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n' . $this->getSharedExtensionLoadString() . ' --ri "swoole"', false); [$ret, $out] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n' . $this->getSharedExtensionLoadString() . ' --ri "swoole"', false);
$out = implode('', $out); $out = implode('', $out);
if ($ret !== 0) { if ($ret !== 0) {
throw new ValidationException("extension {$this->getName()} failed compile check: php-cli returned {$ret}", validation_module: 'extension swoole_hook_mysql sanity check'); throw new ValidationException("extension {$this->getName()} failed compile check: php-cli returned {$ret}", validation_module: 'extension swoole_hook_mysql sanity check');
} }
if (!str_contains($out, 'mysqlnd')) { if (!str_contains($out, 'mysqlnd')) {
throw new ValidationException('swoole mysql hook is not enabled correctly.', validation_module: 'Extension swoole mysql hook avilability check'); throw new ValidationException('swoole mysql hook is not enabled correctly.', validation_module: 'Extension swoole mysql hook availability check');
} }
} }
} }

View File

@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\ValidationException;
use SPC\exception\WrongUsageException;
use SPC\util\CustomExt;
#[CustomExt('swoole-hook-odbc')]
class swoole_hook_odbc extends Extension
{
public function getDistName(): string
{
return 'swoole';
}
public function validate(): void
{
// pdo_pgsql need to be disabled
if ($this->builder->getExt('pdo_odbc')?->isBuildStatic()) {
throw new WrongUsageException('swoole-hook-odbc provides pdo_odbc, if you enable odbc hook for swoole, you must remove pdo_odbc extension.');
}
}
public function runCliCheckUnix(): void
{
$sharedExtensions = $this->getSharedExtensionLoadString();
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"', false);
$out = implode('', $out);
if ($ret !== 0) {
throw new ValidationException("extension {$this->getName()} failed compile check: php-cli returned {$ret}", validation_module: "Extension {$this->getName()} sanity check");
}
if (!str_contains($out, 'coroutine_odbc')) {
throw new ValidationException('swoole odbc hook is not enabled correctly.', validation_module: 'Extension swoole odbc hook availability check');
}
}
}

View File

@ -20,25 +20,15 @@ class swoole_hook_pgsql extends Extension
public function validate(): void public function validate(): void
{ {
// pdo_pgsql need to be disabled // pdo_pgsql need to be disabled
if ($this->builder->getExt('pdo_pgsql') !== null) { if ($this->builder->getExt('pdo_pgsql')?->isBuildStatic()) {
throw new WrongUsageException('swoole-hook-pgsql provides pdo_pgsql, if you enable pgsql hook for swoole, you must remove pdo_pgsql extension.'); 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(bool $shared = false): string
{
// enable swoole pgsql hook
return '--enable-swoole-pgsql';
}
public function runCliCheckUnix(): void public function runCliCheckUnix(): void
{ {
// skip if not enable swoole
if ($this->builder->getExt('swoole') === null) {
return;
}
$sharedExtensions = $this->getSharedExtensionLoadString(); $sharedExtensions = $this->getSharedExtensionLoadString();
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"'); [$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"', false);
$out = implode('', $out); $out = implode('', $out);
if ($ret !== 0) { if ($ret !== 0) {
throw new ValidationException( throw new ValidationException(

View File

@ -20,25 +20,15 @@ class swoole_hook_sqlite extends Extension
public function validate(): void public function validate(): void
{ {
// pdo_pgsql need to be disabled // pdo_pgsql need to be disabled
if ($this->builder->getExt('pdo_sqlite') !== null) { if ($this->builder->getExt('pdo_sqlite')?->isBuildStatic()) {
throw new WrongUsageException('swoole-hook-sqlite provides pdo_sqlite, if you enable sqlite hook for swoole, you must remove pdo_sqlite extension.'); 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(bool $shared = false): string
{
// enable swoole pgsql hook
return '--enable-swoole-sqlite';
}
public function runCliCheckUnix(): void public function runCliCheckUnix(): void
{ {
// skip if not enable swoole
if ($this->builder->getExt('swoole') === null) {
return;
}
$sharedExtensions = $this->getSharedExtensionLoadString(); $sharedExtensions = $this->getSharedExtensionLoadString();
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"'); [$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"', false);
$out = implode('', $out); $out = implode('', $out);
if ($ret !== 0) { if ($ret !== 0) {
throw new ValidationException("extension {$this->getName()} failed compile check: php-cli returned {$ret}", validation_module: "Extension {$this->getName()} sanity check"); throw new ValidationException("extension {$this->getName()} failed compile check: php-cli returned {$ret}", validation_module: "Extension {$this->getName()} sanity check");

View File

@ -64,10 +64,7 @@ class LinuxBuilder extends UnixBuilderBase
// if opcache_jit is enabled for 8.5 or opcache enabled, // if opcache_jit is enabled for 8.5 or opcache enabled,
// we need to disable undefined behavior sanitizer. // we need to disable undefined behavior sanitizer.
f_putenv('SPC_COMPILER_EXTRA=-fno-sanitize=undefined'); f_putenv('SPC_COMPILER_EXTRA=-fno-sanitize=undefined');
} elseif ($opcache_jit) {
$opcache_jit = false;
} }
$opcache_jit_arg = $opcache_jit ? '--enable-opcache-jit ' : '--disable-opcache-jit ';
if ($this->getOption('enable-zts', false)) { if ($this->getOption('enable-zts', false)) {
$maxExecutionTimers = $phpVersionID >= 80100 ? '--enable-zend-max-execution-timers ' : ''; $maxExecutionTimers = $phpVersionID >= 80100 ? '--enable-zend-max-execution-timers ' : '';
@ -115,7 +112,6 @@ class LinuxBuilder extends UnixBuilderBase
($enableMicro ? '--enable-micro=all-static ' : '--disable-micro ') . ($enableMicro ? '--enable-micro=all-static ' : '--disable-micro ') .
$config_file_path . $config_file_path .
$config_file_scan_dir . $config_file_scan_dir .
$opcache_jit_arg .
$json_74 . $json_74 .
$zts . $zts .
$maxExecutionTimers . $maxExecutionTimers .

View File

@ -0,0 +1,59 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\builder\linux\SystemUtil;
use SPC\store\FileSystem;
use SPC\util\executor\UnixAutoconfExecutor;
use SPC\util\SPCTarget;
class liburing extends LinuxLibraryBase
{
public const NAME = 'liburing';
public function patchBeforeBuild(): bool
{
if (!SystemUtil::isMuslDist()) {
return false;
}
FileSystem::replaceFileStr($this->source_dir . '/configure', 'realpath -s', 'realpath');
return true;
}
protected function build(): void
{
$use_libc = SPCTarget::getLibc() !== 'glibc' || version_compare(SPCTarget::getLibcVersion(), '2.30', '>=');
$make = UnixAutoconfExecutor::create($this);
if (!$use_libc) {
$make->appendEnv([
'CC' => 'gcc', // libc-less version fails to compile with clang or zig
'CXX' => 'g++',
'AR' => 'ar',
'LD' => 'ld',
]);
} else {
$make->appendEnv([
'CFLAGS' => '-D_GNU_SOURCE',
]);
}
$make
->removeConfigureArgs(
'--disable-shared',
'--enable-static',
'--with-pic',
'--enable-pic',
)
->addConfigureArgs(
$use_libc ? '--use-libc' : '',
)
->configure()
->make('library', with_clean: false)
->exec("rm -rf {$this->getLibDir()}/liburing*.so*");
$this->patchPkgconfPrefix();
}
}

View File

@ -90,13 +90,6 @@ class MacOSBuilder extends UnixBuilderBase
$json_74 = $phpVersionID < 80000 ? '--enable-json ' : ''; $json_74 = $phpVersionID < 80000 ? '--enable-json ' : '';
$zts = $this->getOption('enable-zts', false) ? '--enable-zts --disable-zend-signals ' : ''; $zts = $this->getOption('enable-zts', false) ? '--enable-zts --disable-zend-signals ' : '';
$opcache_jit = !$this->getOption('disable-opcache-jit', false);
// disable opcache jit for PHP < 8.5.0 when opcache is not enabled
if ($opcache_jit && $phpVersionID < 80500 && !$this->getExt('opcache')) {
$opcache_jit = false;
}
$opcache_jit_arg = $opcache_jit ? '--enable-opcache-jit ' : '--disable-opcache-jit ';
$config_file_path = $this->getOption('with-config-file-path', false) ? $config_file_path = $this->getOption('with-config-file-path', false) ?
('--with-config-file-path=' . $this->getOption('with-config-file-path') . ' ') : ''; ('--with-config-file-path=' . $this->getOption('with-config-file-path') . ' ') : '';
$config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ? $config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ?
@ -131,7 +124,6 @@ class MacOSBuilder extends UnixBuilderBase
($enableFpm ? '--enable-fpm ' : '--disable-fpm ') . ($enableFpm ? '--enable-fpm ' : '--disable-fpm ') .
($enableEmbed ? "--enable-embed={$embed_type} " : '--disable-embed ') . ($enableEmbed ? "--enable-embed={$embed_type} " : '--disable-embed ') .
($enableMicro ? '--enable-micro ' : '--disable-micro ') . ($enableMicro ? '--enable-micro ' : '--disable-micro ') .
$opcache_jit_arg .
$config_file_path . $config_file_path .
$config_file_scan_dir . $config_file_scan_dir .
$json_74 . $json_74 .

View File

@ -19,6 +19,9 @@ trait UnixSystemUtilTrait
if (!$paths) { if (!$paths) {
$paths = explode(PATH_SEPARATOR, getenv('PATH')); $paths = explode(PATH_SEPARATOR, getenv('PATH'));
} }
if (str_starts_with($name, '/')) {
return file_exists($name) ? $name : null;
}
foreach ($paths as $path) { foreach ($paths as $path) {
if (file_exists($path . DIRECTORY_SEPARATOR . $name)) { if (file_exists($path . DIRECTORY_SEPARATOR . $name)) {
return $path . DIRECTORY_SEPARATOR . $name; return $path . DIRECTORY_SEPARATOR . $name;

View File

@ -13,6 +13,8 @@ use SPC\store\CurlHook;
use SPC\store\Downloader; use SPC\store\Downloader;
use SPC\store\FileSystem; use SPC\store\FileSystem;
use SPC\store\pkg\GoXcaddy; use SPC\store\pkg\GoXcaddy;
use SPC\toolchain\GccNativeToolchain;
use SPC\toolchain\ToolchainManager;
use SPC\util\DependencyUtil; use SPC\util\DependencyUtil;
use SPC\util\GlobalEnvManager; use SPC\util\GlobalEnvManager;
use SPC\util\SPCConfigUtil; use SPC\util\SPCConfigUtil;
@ -259,7 +261,6 @@ abstract class UnixBuilderBase extends BuilderBase
logger()->warning('caddy-cbrotli module is enabled, but brotli library is not built. Disabling caddy-cbrotli.'); logger()->warning('caddy-cbrotli module is enabled, but brotli library is not built. Disabling caddy-cbrotli.');
$xcaddyModules = str_replace('--with github.com/dunglas/caddy-cbrotli', '', $xcaddyModules); $xcaddyModules = str_replace('--with github.com/dunglas/caddy-cbrotli', '', $xcaddyModules);
} }
$lrt = PHP_OS_FAMILY === 'Linux' ? '-lrt' : '';
$releaseInfo = json_decode(Downloader::curlExec( $releaseInfo = json_decode(Downloader::curlExec(
'https://api.github.com/repos/php/frankenphp/releases/latest', 'https://api.github.com/repos/php/frankenphp/releases/latest',
hooks: [[CurlHook::class, 'setupGithubToken']], hooks: [[CurlHook::class, 'setupGithubToken']],
@ -280,10 +281,20 @@ abstract class UnixBuilderBase extends BuilderBase
} }
$config = (new SPCConfigUtil($this))->config($this->ext_list, $this->lib_list); $config = (new SPCConfigUtil($this))->config($this->ext_list, $this->lib_list);
$cflags = "{$this->arch_c_flags} {$config['cflags']} " . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS');
$libs = $config['libs'];
$libs .= PHP_OS_FAMILY === 'Linux' ? ' -lrt' : '';
// Go's gcc driver doesn't automatically link against -lgcov or -lrt. Ugly, but necessary fix.
if ((str_contains((string) getenv('SPC_DEFAULT_C_FLAGS'), '-fprofile') ||
str_contains((string) getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), '-fprofile')) &&
ToolchainManager::getToolchainClass() === GccNativeToolchain::class) {
$cflags .= ' -Wno-error=missing-profile';
$libs .= ' -lgcov';
}
$env = [ $env = [
'CGO_ENABLED' => '1', 'CGO_ENABLED' => '1',
'CGO_CFLAGS' => $this->arch_c_flags . ' ' . $config['cflags'], 'CGO_CFLAGS' => clean_spaces($cflags),
'CGO_LDFLAGS' => "{$this->arch_ld_flags} {$staticFlags} {$config['ldflags']} {$config['libs']} {$lrt}", 'CGO_LDFLAGS' => "{$this->arch_ld_flags} {$staticFlags} {$config['ldflags']} {$libs}",
'XCADDY_GO_BUILD_FLAGS' => '-buildmode=pie ' . 'XCADDY_GO_BUILD_FLAGS' => '-buildmode=pie ' .
'-ldflags \"-linkmode=external ' . $extLdFlags . ' ' . $debugFlags . '-ldflags \"-linkmode=external ' . $extLdFlags . ' ' . $debugFlags .
'-X \'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ' . '-X \'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ' .

View File

@ -252,7 +252,7 @@ class BuildPHPCommand extends BuildCommand
$path = FileSystem::convertPath("{$build_root_path}/modules/{$ext}.so"); $path = FileSystem::convertPath("{$build_root_path}/modules/{$ext}.so");
if (file_exists(BUILD_MODULES_PATH . "/{$ext}.so")) { if (file_exists(BUILD_MODULES_PATH . "/{$ext}.so")) {
logger()->info("Shared extension [{$ext}] path{$fixed}: {$path}"); logger()->info("Shared extension [{$ext}] path{$fixed}: {$path}");
} else { } elseif (Config::getExt($ext, 'type') !== 'addon') {
logger()->warning("Shared extension [{$ext}] not found, please check!"); logger()->warning("Shared extension [{$ext}] not found, please check!");
} }
} }

View File

@ -40,7 +40,7 @@ class LinuxToolCheckList
'tar', 'unzip', 'gzip', 'gcc', 'tar', 'unzip', 'gzip', 'gcc',
'bzip2', 'cmake', 'patch', 'which', 'bzip2', 'cmake', 'patch', 'which',
'xz', 'libtool', 'gettext-devel', 'xz', 'libtool', 'gettext-devel',
'perl', 'patchelf', 'patchelf',
]; ];
public const TOOLS_ARCH = [ public const TOOLS_ARCH = [
@ -48,10 +48,12 @@ class LinuxToolCheckList
]; ];
private const PROVIDED_COMMAND = [ private const PROVIDED_COMMAND = [
'perl' => '/usr/share/perl5/FindBin.pm',
'binutils-gold' => 'ld.gold', 'binutils-gold' => 'ld.gold',
'base-devel' => 'automake', 'base-devel' => 'automake',
'gettext-devel' => 'gettextize', 'gettext-devel' => 'gettextize',
'gettext-dev' => 'gettextize', 'gettext-dev' => 'gettextize',
'perl-IPC-Cmd' => '/usr/share/doc/perl-IPC-Cmd',
]; ];
/** @noinspection PhpUnused */ /** @noinspection PhpUnused */

View File

@ -30,6 +30,7 @@ class SourcePatcher
FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchImapLicense']); FileSystem::addSourceExtractHook('php-src', [__CLASS__, 'patchImapLicense']);
FileSystem::addSourceExtractHook('ext-imagick', [__CLASS__, 'patchImagickWith84']); FileSystem::addSourceExtractHook('ext-imagick', [__CLASS__, 'patchImagickWith84']);
FileSystem::addSourceExtractHook('libaom', [__CLASS__, 'patchLibaomForAlpine']); FileSystem::addSourceExtractHook('libaom', [__CLASS__, 'patchLibaomForAlpine']);
FileSystem::addSourceExtractHook('pkg-config', [__CLASS__, 'patchPkgConfigForGcc15']);
FileSystem::addSourceExtractHook('attr', [__CLASS__, 'patchAttrForAlpine']); FileSystem::addSourceExtractHook('attr', [__CLASS__, 'patchAttrForAlpine']);
FileSystem::addSourceExtractHook('gmssl', [__CLASS__, 'patchGMSSL']); FileSystem::addSourceExtractHook('gmssl', [__CLASS__, 'patchGMSSL']);
} }
@ -155,6 +156,7 @@ class SourcePatcher
$spc_micro_patches = getenv('SPC_MICRO_PATCHES'); $spc_micro_patches = getenv('SPC_MICRO_PATCHES');
$spc_micro_patches = $spc_micro_patches === false ? [] : explode(',', $spc_micro_patches); $spc_micro_patches = $spc_micro_patches === false ? [] : explode(',', $spc_micro_patches);
} }
$spc_micro_patches = array_filter($spc_micro_patches, fn ($item) => trim((string) $item) !== '');
$patch_list = $spc_micro_patches; $patch_list = $spc_micro_patches;
$patches = []; $patches = [];
$serial = ['80', '81', '82', '83', '84', '85']; $serial = ['80', '81', '82', '83', '84', '85'];
@ -269,7 +271,12 @@ class SourcePatcher
if ($version === '5.1.3') { if ($version === '5.1.3') {
self::patchFile('spc_fix_swoole_50513.patch', SOURCE_PATH . '/php-src/ext/swoole'); self::patchFile('spc_fix_swoole_50513.patch', SOURCE_PATH . '/php-src/ext/swoole');
} }
self::patchFile('swoole_fix_date_time.patch', SOURCE_PATH . '/php-src/ext/swoole'); if (version_compare($version, '6.0.0', '>=') && version_compare($version, '6.1.0', '<')) {
// remove when https://github.com/swoole/swoole-src/pull/5848 is merged
self::patchFile('swoole_fix_date_time.patch', SOURCE_PATH . '/php-src/ext/swoole');
// remove when https://github.com/swoole/swoole-src/pull/5847 is merged
self::patchFile('swoole_fix_odbclibs.patch', SOURCE_PATH . '/php-src/ext/swoole');
}
return true; return true;
} }
@ -493,6 +500,12 @@ class SourcePatcher
return true; return true;
} }
public static function patchPkgConfigForGcc15(): bool
{
self::patchFile('pkg-config_gcc15.patch', SOURCE_PATH . '/pkg-config');
return true;
}
public static function patchLibaomForAlpine(): bool public static function patchLibaomForAlpine(): bool
{ {
if (PHP_OS_FAMILY === 'Linux' && SystemUtil::isMuslDist()) { if (PHP_OS_FAMILY === 'Linux' && SystemUtil::isMuslDist()) {

View File

@ -52,6 +52,15 @@ class SPCConfigUtil
*/ */
public function config(array $extensions = [], array $libraries = [], bool $include_suggest_ext = false, bool $include_suggest_lib = false): array public function config(array $extensions = [], array $libraries = [], bool $include_suggest_ext = false, bool $include_suggest_lib = false): array
{ {
$extra_exts = [];
foreach ($extensions as $ext) {
$extra_exts = array_merge($extra_exts, Config::getExt($ext, 'ext-suggests', []));
}
foreach ($extra_exts as $ext) {
if ($this->builder?->getExt($ext) && !in_array($ext, $extensions)) {
$extensions[] = $ext;
}
}
[$extensions, $libraries] = DependencyUtil::getExtsAndLibs($extensions, $libraries, $include_suggest_ext, $include_suggest_lib); [$extensions, $libraries] = DependencyUtil::getExtsAndLibs($extensions, $libraries, $include_suggest_ext, $include_suggest_lib);
ob_start(); ob_start();

View File

@ -100,6 +100,10 @@ class SPCTarget
public static function getLibcVersion(): ?string public static function getLibcVersion(): ?string
{ {
if (PHP_OS_FAMILY === 'Linux') { if (PHP_OS_FAMILY === 'Linux') {
$target = (string) getenv('SPC_TARGET');
if (str_contains($target, '-gnu.2.')) {
return preg_match('/-gnu\.(2\.\d+)/', $target, $matches) ? $matches[1] : null;
}
$libc = self::getLibc(); $libc = self::getLibc();
return SystemUtil::getLibcVersionIfExists($libc); return SystemUtil::getLibcVersionIfExists($libc);
} }

View File

@ -0,0 +1,22 @@
diff --git a/glib/glib/goption.c b/glib/glib/goption.c
index 0a22f6f..f439fd4 100644
--- a/glib/glib/goption.c
+++ b/glib/glib/goption.c
@@ -166,7 +166,7 @@ typedef struct
gpointer arg_data;
union
{
- gboolean bool;
+ gboolean boolean;
gint integer;
gchar *str;
gchar **array;
@@ -1600,7 +1600,7 @@ free_changes_list (GOptionContext *context,
switch (change->arg_type)
{
case G_OPTION_ARG_NONE:
- *(gboolean *)change->arg_data = change->prev.bool;
+ *(gboolean *)change->arg_data = change->prev.boolean;
break;
case G_OPTION_ARG_INT:
*(gint *)change->arg_data = change->prev.integer;

View File

@ -0,0 +1,90 @@
From d4942a590a301a2552f8885962640f38d60de27b Mon Sep 17 00:00:00 2001
From: DubbleClick <m@pyc.ac>
Date: Tue, 26 Aug 2025 00:08:32 +0700
Subject: [PATCH] add SWOOLE_ODBC_LIBC variable if the odbc library needs more
than to link against a single library
---
config.m4 | 57 ++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 44 insertions(+), 13 deletions(-)
diff --git a/config.m4 b/config.m4
index 1583cb81c8..683d8891af 100644
--- a/config.m4
+++ b/config.m4
@@ -641,31 +641,62 @@ EOF
AC_MSG_ERROR([Cannot find header file(s) for pdo_odbc])
fi
+ if test -n "$SWOOLE_ODBC_LIBS"; then
+ ODBC_LIBS="$SWOOLE_ODBC_LIBS"
+ else
+ ODBC_LIBS="-l$pdo_odbc_def_lib"
+ fi
+
PDO_ODBC_INCLUDE="$pdo_odbc_def_cflags -I$PDO_ODBC_INCDIR -DPDO_ODBC_TYPE=\\\"$pdo_odbc_flavour\\\""
- PDO_ODBC_LDFLAGS="$pdo_odbc_def_ldflags -L$PDO_ODBC_LIBDIR -l$pdo_odbc_def_lib"
+ PDO_ODBC_LDFLAGS="$pdo_odbc_def_ldflags -L$PDO_ODBC_LIBDIR $ODBC_LIBS"
PHP_EVAL_LIBLINE([$PDO_ODBC_LDFLAGS], [SWOOLE_SHARED_LIBADD])
EXTRA_CFLAGS="$EXTRA_CFLAGS -I$pdo_cv_inc_path $PDO_ODBC_INCLUDE"
dnl Check first for an ODBC 1.0 function to assert that the libraries work
- PHP_CHECK_LIBRARY($pdo_odbc_def_lib, SQLBindCol,
- [
- dnl And now check for an ODBC 3.0 function to assert that they are *good*
- dnl libraries.
- PHP_CHECK_LIBRARY($pdo_odbc_def_lib, SQLAllocHandle,
- [], [
- AC_MSG_ERROR([
+ save_LIBS="$LIBS"
+ LIBS="$LIBS $PDO_ODBC_LDFLAGS"
+
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <sql.h>
+ #include <sqlext.h>]],
+ [[
+ SQLLEN ind = 0;
+ char buf[1];
+ SQLBindCol((SQLHSTMT)0, (SQLUSMALLINT)1, (SQLSMALLINT)SQL_C_CHAR,
+ (SQLPOINTER)buf, (SQLLEN)sizeof(buf), &ind);
+ return 0;
+ ]])],
+ [
+ dnl And now check for an ODBC 3.0 function to assert that they are *good*
+ dnl libraries.
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <sql.h>
+ #include <sqlext.h>]],
+ [[
+ SQLHANDLE out = SQL_NULL_HANDLE;
+ SQLAllocHandle((SQLSMALLINT)SQL_HANDLE_ENV,
+ (SQLHANDLE)SQL_NULL_HANDLE, &out);
+ return 0;
+ ]])],
+ [],
+ [AC_MSG_ERROR([
Your ODBC library does not appear to be ODBC 3 compatible.
You should consider using iODBC or unixODBC instead, and loading your
libraries as a driver in that environment; it will emulate the
functions required for PDO support.
- ])], $PDO_ODBC_LDFLAGS)
- ],[
- AC_MSG_ERROR([Your ODBC library does not exist or there was an error. Check config.log for more information])
- ], $PDO_ODBC_LDFLAGS)
+ ])]
+ )
+ ],
+ [AC_MSG_ERROR([Your ODBC library does not exist or there was an error. Check config.log for more information])]
+ )
+
+ LIBS="$save_LIBS"
- AC_DEFINE(SW_USE_ODBC, 1, [do we enable swoole-odbc coro support])
+ AC_DEFINE(SW_USE_ODBC, 1, [do we enable swoole-odbc coro support])
fi
dnl odbc end

View File

@ -13,21 +13,21 @@ declare(strict_types=1);
// test php version (8.1 ~ 8.4 available, multiple for matrix) // test php version (8.1 ~ 8.4 available, multiple for matrix)
$test_php_version = [ $test_php_version = [
// '8.1', '8.1',
// '8.2', '8.2',
// '8.3', '8.3',
'8.4', '8.4',
// '8.5', // '8.5',
'git', // 'git',
]; ];
// test os (macos-13, macos-14, macos-15, ubuntu-latest, windows-latest are available) // test os (macos-13, macos-14, macos-15, ubuntu-latest, windows-latest are available)
$test_os = [ $test_os = [
// 'macos-13', // bin/spc for x86_64 'macos-13', // bin/spc for x86_64
// 'macos-14', // bin/spc for arm64 // 'macos-14', // bin/spc for arm64
// 'macos-15', // bin/spc for arm64 'macos-15', // bin/spc for arm64
'ubuntu-latest', // bin/spc-alpine-docker for x86_64 'ubuntu-latest', // bin/spc-alpine-docker for x86_64
// 'ubuntu-22.04', // bin/spc-gnu-docker for x86_64 'ubuntu-22.04', // bin/spc-gnu-docker for x86_64
'ubuntu-24.04', // bin/spc for x86_64 'ubuntu-24.04', // bin/spc for x86_64
'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64 'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64
'ubuntu-24.04-arm', // bin/spc for arm64 'ubuntu-24.04-arm', // bin/spc for arm64
@ -50,7 +50,7 @@ $prefer_pre_built = false;
// If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`). // If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`).
$extensions = match (PHP_OS_FAMILY) { $extensions = match (PHP_OS_FAMILY) {
'Linux', 'Darwin' => 'bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,iconv,xml,mbstring,mbregex,mysqlnd,openssl,pdo,pdo_mysql,pdo_sqlite,phar,session,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip', 'Linux', 'Darwin' => 'swoole,swoole-hook-mysql,swoole-hook-pgsql,swoole-hook-sqlite,swoole-hook-odbc,apcu,bcmath,bz2,calendar,ctype,curl,dba,dom,event,exif,fileinfo,filter,ftp,gd,gmp,iconv,imagick,intl,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pgsql,phar,posix,protobuf,readline,redis,session,shmop,simplexml,soap,sockets,sodium,sqlite3,swoole,sysvmsg,sysvsem,sysvshm,tokenizer,xml,xmlreader,xmlwriter,xsl,zip,zlib',
'Windows' => 'bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,iconv,xml,mbstring,mbregex,mysqlnd,openssl,pdo,pdo_mysql,pdo_sqlite,phar,session,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip', 'Windows' => 'bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,iconv,xml,mbstring,mbregex,mysqlnd,openssl,pdo,pdo_mysql,pdo_sqlite,phar,session,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip',
}; };
@ -62,7 +62,7 @@ $shared_extensions = match (PHP_OS_FAMILY) {
}; };
// If you want to test lib-suggests for all extensions and libraries, set it to true. // If you want to test lib-suggests for all extensions and libraries, set it to true.
$with_suggested_libs = false; $with_suggested_libs = true;
// If you want to test extra libs for extensions, add them below (comma separated, example `libwebp,libavif`). Unnecessary, when $with_suggested_libs is true. // If you want to test extra libs for extensions, add them below (comma separated, example `libwebp,libavif`). Unnecessary, when $with_suggested_libs is true.
$with_libs = match (PHP_OS_FAMILY) { $with_libs = match (PHP_OS_FAMILY) {