Compare commits

...

13 Commits

Author SHA1 Message Date
Marc
f75ab9f428 Merge pull request #743 from crazywhalecc/feat/h3
Feature: add http/3 support to curl.
2025-06-06 13:53:25 +07:00
Marc
856db3df08 Merge pull request #745 from crazywhalecc/feat/lz4
add lz4 extension
2025-06-06 13:28:54 +07:00
DubbleClick
80f63e66c3 check static compilation 2025-06-05 11:48:28 +07:00
DubbleClick
2f25409475 add lz4 test 2025-06-05 11:48:07 +07:00
DubbleClick
67320d3eb3 add to tests 2025-06-05 11:37:36 +07:00
DubbleClick
92aeb2d816 enable shared 2025-06-05 11:35:50 +07:00
DubbleClick
3420f6ca42 add lz4 extension 2025-06-05 11:33:51 +07:00
DubbleClick
8e5efb923f update docs 2025-06-05 10:27:18 +07:00
DubbleClick
8993b3f4f0 add pkgconf prefix patch for ngtcp2 crypto library 2025-06-05 10:06:20 +07:00
DubbleClick
499c281931 cs fix 2025-06-05 09:50:14 +07:00
DubbleClick
bb7e0f6f89 add nghttp3 and ngtcp2 2025-06-05 09:44:03 +07:00
DubbleClick
8919a2fcca goddamn windows 2025-06-04 21:50:28 +07:00
DubbleClick
ba0796c9ea nghttp3 2025-06-04 21:42:44 +07:00
20 changed files with 381 additions and 15 deletions

View File

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

View File

@@ -86,6 +86,8 @@
"libssh2",
"brotli",
"nghttp2",
"nghttp3",
"ngtcp2",
"zstd",
"libcares"
],
@@ -615,7 +617,44 @@
"openssl"
],
"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": {

View File

@@ -161,6 +161,17 @@
]
}
},
"ext-lz4": {
"type": "ghtagtar",
"repo": "kjdev/php-ext-lz4",
"path": "php-src/ext/lz4",
"license": {
"type": "file",
"path": [
"LICENSE"
]
}
},
"ext-memcache": {
"type": "url",
"url": "https://pecl.php.net/get/memcache",
@@ -703,6 +714,26 @@
"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": {
"type": "ghrel",
"repo": "kkos/oniguruma",

View File

@@ -6,6 +6,8 @@ which will be listed one by one here.
## 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.
For details on the solution, see [FAQ - Unable to use ssl](../faq/#unable-to-use-ssl).
@@ -156,4 +158,4 @@ Parallel is only supported on PHP 8.0 ZTS and above.
1. This is not technically an extension, but a library.
2. Building with `--with-libs="mimalloc"` on Linux or macOS will override the default allocator.
3. This is experimental for now, but is recommended in threaded environments.
3. This is experimental for now, but is recommended in threaded environments.

View File

@@ -4,6 +4,8 @@
## curl
HTTP3 支持默认未启用,需在编译时添加 `--with-libs="nghttp2,nghttp3,ngtcp2"` 以启用 PHP 8.4 及以上版本的 HTTP3 支持。
使用 curl 请求 HTTPS 时,可能存在 `error:80000002:system library::No such file or directory` 错误,
解决办法详见 [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 = '';
foreach ($libSpecs as $libName => $arr) {
$lib = $this->getLib($libName);
if ($lib === null && str_starts_with($libName, 'lib')) {
$lib = $this->getExt(substr($libName, 3));
}
$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 = '';
foreach ($lib_specs as $libName => $arr) {
$lib = $this->getLib($libName);
if ($lib === null && str_starts_with($libName, 'lib')) {
$lib = $this->getExt(substr($libName, 3));
}
$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 {
$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
$extra .= $this->builder->getLib('ldap') ? '-DCURL_DISABLE_LDAP=OFF ' : '-DCURL_DISABLE_LDAP=ON ';
// lib:zstd

View File

@@ -30,7 +30,6 @@ trait nghttp2
'jansson' => null,
'jemalloc' => null,
'systemd' => null,
'cunit' => null,
]);
[,,$destdir] = SEPARATED_PATH;
@@ -41,8 +40,8 @@ trait nghttp2
'./configure ' .
'--enable-static ' .
'--disable-shared ' .
'--with-pic ' .
'--enable-lib-only ' .
'--with-boost=no ' .
$args . ' ' .
'--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

@@ -13,22 +13,22 @@ declare(strict_types=1);
// test php version (8.1 ~ 8.4 available, multiple for matrix)
$test_php_version = [
'8.1',
'8.2',
'8.3',
// '8.1',
// '8.2',
// '8.3',
'8.4',
];
// test os (macos-13, macos-14, macos-15, ubuntu-latest, windows-latest are available)
$test_os = [
// 'macos-13',
// 'macos-14',
// 'macos-15',
'macos-13',
'macos-14',
'macos-15',
'ubuntu-latest',
// 'ubuntu-22.04',
// 'ubuntu-24.04',
// 'ubuntu-22.04-arm',
// 'ubuntu-24.04-arm',
'ubuntu-22.04',
'ubuntu-24.04',
'ubuntu-22.04-arm',
'ubuntu-24.04-arm',
// 'windows-latest',
];
@@ -45,7 +45,7 @@ $prefer_pre_built = false;
// If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`).
$extensions = match (PHP_OS_FAMILY) {
'Linux', 'Darwin' => 'xsl,simplexml,xlswriter',
'Linux', 'Darwin' => 'lz4',
'Windows' => 'xlswriter,openssl',
};