Merge remote-tracking branch 'origin/main' into fix/icurel

This commit is contained in:
DubbleClick 2025-06-06 13:55:00 +07:00
commit 300723419b
20 changed files with 370 additions and 5 deletions

View File

@ -330,6 +330,18 @@
"openssl" "openssl"
] ]
}, },
"lz4": {
"support": {
"Windows": "wip",
"BSD": "wip"
},
"type": "external",
"source": "ext-lz4",
"arg-type": "custom",
"lib-depends": [
"liblz4"
]
},
"libxml": { "libxml": {
"support": { "support": {
"BSD": "wip" "BSD": "wip"

View File

@ -86,6 +86,8 @@
"libssh2", "libssh2",
"brotli", "brotli",
"nghttp2", "nghttp2",
"nghttp3",
"ngtcp2",
"zstd", "zstd",
"libcares" "libcares"
], ],
@ -615,7 +617,44 @@
"openssl" "openssl"
], ],
"lib-suggests": [ "lib-suggests": [
"libxml2" "libxml2",
"nghttp3",
"ngtcp2"
]
},
"nghttp3": {
"source": "nghttp3",
"static-libs-unix": [
"libnghttp3.a"
],
"static-libs-windows": [
"nghttp3.lib"
],
"headers": [
"nghttp3"
],
"lib-depends": [
"openssl"
],
"lib-suggests": [
"ngtcp2"
]
},
"ngtcp2": {
"source": "ngtcp2",
"static-libs-unix": [
"libngtcp2.a",
"libngtcp2_crypto_ossl.a"
],
"static-libs-windows": [
"ngtcp2.lib",
"ngtcp2_crypto_ossl.lib"
],
"headers": [
"ngtcp2"
],
"lib-depends": [
"openssl"
] ]
}, },
"onig": { "onig": {

View File

@ -172,6 +172,17 @@
] ]
} }
}, },
"ext-lz4": {
"type": "ghtagtar",
"repo": "kjdev/php-ext-lz4",
"path": "php-src/ext/lz4",
"license": {
"type": "file",
"path": [
"LICENSE"
]
}
},
"ext-memcache": { "ext-memcache": {
"type": "url", "type": "url",
"url": "https://pecl.php.net/get/memcache", "url": "https://pecl.php.net/get/memcache",
@ -724,6 +735,26 @@
"path": "COPYING" "path": "COPYING"
} }
}, },
"nghttp3": {
"type": "ghrel",
"repo": "ngtcp2/nghttp3",
"match": "nghttp3.+\\.tar\\.xz",
"prefer-stable": true,
"license": {
"type": "file",
"path": "COPYING"
}
},
"ngtcp2": {
"type": "ghrel",
"repo": "ngtcp2/ngtcp2",
"match": "ngtcp2.+\\.tar\\.xz",
"prefer-stable": true,
"license": {
"type": "file",
"path": "COPYING"
}
},
"onig": { "onig": {
"type": "ghrel", "type": "ghrel",
"repo": "kkos/oniguruma", "repo": "kkos/oniguruma",

View File

@ -6,6 +6,8 @@ which will be listed one by one here.
## curl ## curl
HTTP3 support is not enabled by default, compile with `--with-libs="nghttp2,nghttp3,ngtcp2"` to enable HTTP3 support for PHP >= 8.4.
When using curl to request HTTPS, there may be an `error:80000002:system library::No such file or directory` error. When using curl to request HTTPS, there may be an `error:80000002:system library::No such file or directory` error.
For details on the solution, see [FAQ - Unable to use ssl](../faq/#unable-to-use-ssl). For details on the solution, see [FAQ - Unable to use ssl](../faq/#unable-to-use-ssl).

View File

@ -4,6 +4,8 @@
## curl ## curl
HTTP3 支持默认未启用,需在编译时添加 `--with-libs="nghttp2,nghttp3,ngtcp2"` 以启用 PHP 8.4 及以上版本的 HTTP3 支持。
使用 curl 请求 HTTPS 时,可能存在 `error:80000002:system library::No such file or directory` 错误, 使用 curl 请求 HTTPS 时,可能存在 `error:80000002:system library::No such file or directory` 错误,
解决办法详见 [FAQ - 无法使用 ssl](../faq/#无法使用-ssl)。 解决办法详见 [FAQ - 无法使用 ssl](../faq/#无法使用-ssl)。

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\util\CustomExt;
#[CustomExt('lz4')]
class lz4 extends Extension
{
public function getUnixConfigureArg(bool $shared = false): string
{
return '--enable-lz4' . ($shared ? '=shared' : '') . ' --with-lz4-includedir=' . BUILD_ROOT_PATH;
}
public function getWindowsConfigureArg(): string
{
return '--enable-lz4';
}
}

View File

@ -80,6 +80,9 @@ class LinuxBuilder extends UnixBuilderBase
$ret = ''; $ret = '';
foreach ($libSpecs as $libName => $arr) { foreach ($libSpecs as $libName => $arr) {
$lib = $this->getLib($libName); $lib = $this->getLib($libName);
if ($lib === null && str_starts_with($libName, 'lib')) {
$lib = $this->getExt(substr($libName, 3));
}
$arr = $arr ?? []; $arr = $arr ?? [];

View File

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

View File

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

View File

@ -55,6 +55,9 @@ class MacOSBuilder extends UnixBuilderBase
$ret = ''; $ret = '';
foreach ($lib_specs as $libName => $arr) { foreach ($lib_specs as $libName => $arr) {
$lib = $this->getLib($libName); $lib = $this->getLib($libName);
if ($lib === null && str_starts_with($libName, 'lib')) {
$lib = $this->getExt(substr($libName, 3));
}
$arr = $arr ?? []; $arr = $arr ?? [];

View File

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

View File

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

View File

@ -47,6 +47,24 @@ trait curl
} else { } else {
$extra .= '-DUSE_NGHTTP2=OFF '; $extra .= '-DUSE_NGHTTP2=OFF ';
} }
// lib:nghttp3
if ($nghttp3 = $this->builder->getLib('nghttp3')) {
$extra .= '-DUSE_NGHTTP3=ON ' .
/* @phpstan-ignore-next-line */
'-DNGHTTP3_LIBRARY="' . $nghttp3->getStaticLibFiles(style: 'cmake') . '" ' .
'-DNGHTTP3_INCLUDE_DIR="' . BUILD_INCLUDE_PATH . '" ';
} else {
$extra .= '-DUSE_NGHTTP3=OFF ';
}
// lib:ngtcp2
if ($ngtcp2 = $this->builder->getLib('ngtcp2')) {
$extra .= '-DUSE_NGTCP2=ON ' .
/* @phpstan-ignore-next-line */
'-DNGTCP2_LIBRARY="' . $ngtcp2->getStaticLibFiles(style: 'cmake') . '" ' .
'-DNGTCP2_INCLUDE_DIR="' . BUILD_INCLUDE_PATH . '" ';
} else {
$extra .= '-DUSE_NGTCP2=OFF ';
}
// lib:ldap // lib:ldap
$extra .= $this->builder->getLib('ldap') ? '-DCURL_DISABLE_LDAP=OFF ' : '-DCURL_DISABLE_LDAP=ON '; $extra .= $this->builder->getLib('ldap') ? '-DCURL_DISABLE_LDAP=OFF ' : '-DCURL_DISABLE_LDAP=ON ';
// lib:zstd // lib:zstd

View File

@ -30,7 +30,6 @@ trait nghttp2
'jansson' => null, 'jansson' => null,
'jemalloc' => null, 'jemalloc' => null,
'systemd' => null, 'systemd' => null,
'cunit' => null,
]); ]);
[,,$destdir] = SEPARATED_PATH; [,,$destdir] = SEPARATED_PATH;
@ -47,7 +46,6 @@ trait nghttp2
'--disable-shared ' . '--disable-shared ' .
'--with-pic ' . '--with-pic ' .
'--enable-lib-only ' . '--enable-lib-only ' .
'--with-boost=no ' .
$args . ' ' . $args . ' ' .
'--prefix=' '--prefix='
) )

View File

@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
trait nghttp3
{
/**
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
protected function build(): void
{
$args = $this->builder->makeAutoconfArgs(static::NAME, [
'zlib' => null,
'openssl' => null,
]);
shell()->cd($this->source_dir)
->setEnv([
'CFLAGS' => $this->getLibExtraCFlags(),
'LDFLAGS' => $this->getLibExtraLdFlags(),
'LIBS' => $this->getLibExtraLibs(),
])
->execWithEnv(
'./configure ' .
'--enable-static ' .
'--disable-shared ' .
'--with-pic ' .
'--enable-lib-only ' .
$args . ' ' .
'--prefix='
)
->execWithEnv('make clean')
->execWithEnv("make -j{$this->builder->concurrency}")
->execWithEnv('make install DESTDIR=' . BUILD_ROOT_PATH);
$this->patchPkgconfPrefix(['libnghttp3.pc']);
}
}

View File

@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
trait ngtcp2
{
/**
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
protected function build(): void
{
$args = $this->builder->makeAutoconfArgs(static::NAME, [
'zlib' => null,
'openssl' => null,
'libxml2' => null,
'libev' => null,
'jemalloc' => null,
]);
shell()->cd($this->source_dir)
->setEnv([
'CFLAGS' => $this->getLibExtraCFlags(),
'LDFLAGS' => $this->getLibExtraLdFlags(),
'LIBS' => $this->getLibExtraLibs(),
])
->execWithEnv(
'./configure ' .
'--enable-static ' .
'--disable-shared ' .
'--with-pic ' .
'--enable-lib-only ' .
$args . ' ' .
'--prefix='
)
->execWithEnv('make clean')
->execWithEnv("make -j{$this->builder->concurrency}")
->execWithEnv('make install DESTDIR=' . BUILD_ROOT_PATH);
$this->patchPkgconfPrefix(['libngtcp2.pc']);
$this->patchPkgconfPrefix(['libngtcp2_crypto_ossl.pc']);
}
}

View File

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace SPC\builder\windows\library;
use SPC\store\FileSystem;
class nghttp3 extends WindowsLibraryBase
{
public const NAME = 'nghttp3';
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 ' .
'-DENABLE_SHARED_LIB=OFF ' .
'-DENABLE_STATIC_LIB=ON ' .
'-DBUILD_STATIC_LIBS=ON ' .
'-DBUILD_SHARED_LIBS=OFF ' .
'-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,39 @@
<?php
declare(strict_types=1);
namespace SPC\builder\windows\library;
use SPC\store\FileSystem;
class ngtcp2 extends WindowsLibraryBase
{
public const NAME = 'ngtcp2';
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 ' .
'-DENABLE_SHARED_LIB=OFF ' .
'-DENABLE_STATIC_LIB=ON ' .
'-DBUILD_STATIC_LIBS=ON ' .
'-DBUILD_SHARED_LIBS=OFF ' .
'-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,15 @@
<?php
declare(strict_types=1);
assert(function_exists('lz4_compress'));
assert(function_exists('lz4_uncompress'));
$input = str_repeat('The quick brown fox jumps over the lazy dog. ', 10);
$compressed = lz4_compress($input);
assert(is_string($compressed));
assert(strlen($compressed) < strlen($input));
$uncompressed = lz4_uncompress($compressed);
assert(is_string($uncompressed));
assert($uncompressed === $input);

View File

@ -51,7 +51,7 @@ $extensions = match (PHP_OS_FAMILY) {
// If you want to test shared extensions, add them below (comma separated, example `bcmath,openssl`). // If you want to test shared extensions, add them below (comma separated, example `bcmath,openssl`).
$shared_extensions = match (PHP_OS_FAMILY) { $shared_extensions = match (PHP_OS_FAMILY) {
'Linux' => 'amqp,brotli,bz2,dio,ds,ev,event,ffi,ftp,gd,gettext,gmp,gmssl,igbinary,imagick,inotify,intl,ldap,memcache,mongodb,msgpack,odbc,opentelemetry,parallel,pdo_odbc,pdo_pgsql,pdo_sqlsrv,pgsql,protobuf,rar,redis,rdkafka,shmop,sqlsrv,ssh2,swoole,sysvmsg,sysvsem,sysvshm,tidy,uuid,uv,xdebug,xhprof,xlswriter,xsl,xz,yac,yaml,zstd,spx', 'Linux' => 'amqp,brotli,bz2,dio,ds,ev,event,ffi,ftp,gd,gettext,gmp,gmssl,igbinary,imagick,inotify,intl,ldap,lz4,memcache,mongodb,msgpack,odbc,opentelemetry,parallel,pdo_odbc,pdo_pgsql,pdo_sqlsrv,pgsql,protobuf,rar,redis,rdkafka,shmop,sqlsrv,ssh2,swoole,sysvmsg,sysvsem,sysvshm,tidy,uuid,uv,xdebug,xhprof,xlswriter,xsl,xz,yac,yaml,zstd,spx',
'Windows', 'Darwin' => '', 'Windows', 'Darwin' => '',
}; };