diff --git a/config/lib.json b/config/lib.json index 576f1087..78443d0d 100644 --- a/config/lib.json +++ b/config/lib.json @@ -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": { diff --git a/config/source.json b/config/source.json index 3cb97433..81c21cfd 100644 --- a/config/source.json +++ b/config/source.json @@ -714,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", diff --git a/docs/en/guide/extension-notes.md b/docs/en/guide/extension-notes.md index 83c0b787..dc0f1d7a 100644 --- a/docs/en/guide/extension-notes.md +++ b/docs/en/guide/extension-notes.md @@ -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. \ No newline at end of file +3. This is experimental for now, but is recommended in threaded environments. diff --git a/docs/zh/guide/extension-notes.md b/docs/zh/guide/extension-notes.md index 762d2df9..c7b3a8d1 100644 --- a/docs/zh/guide/extension-notes.md +++ b/docs/zh/guide/extension-notes.md @@ -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)。 diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index e38714f1..66604ecb 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -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 ?? []; diff --git a/src/SPC/builder/linux/library/nghttp3.php b/src/SPC/builder/linux/library/nghttp3.php new file mode 100644 index 00000000..b26ef647 --- /dev/null +++ b/src/SPC/builder/linux/library/nghttp3.php @@ -0,0 +1,12 @@ + $arr) { $lib = $this->getLib($libName); + if ($lib === null && str_starts_with($libName, 'lib')) { + $lib = $this->getExt(substr($libName, 3)); + } $arr = $arr ?? []; diff --git a/src/SPC/builder/macos/library/nghttp3.php b/src/SPC/builder/macos/library/nghttp3.php new file mode 100644 index 00000000..9feebb01 --- /dev/null +++ b/src/SPC/builder/macos/library/nghttp3.php @@ -0,0 +1,12 @@ +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 diff --git a/src/SPC/builder/unix/library/nghttp2.php b/src/SPC/builder/unix/library/nghttp2.php index 8f764c2a..dbbb6415 100644 --- a/src/SPC/builder/unix/library/nghttp2.php +++ b/src/SPC/builder/unix/library/nghttp2.php @@ -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=' ) diff --git a/src/SPC/builder/unix/library/nghttp3.php b/src/SPC/builder/unix/library/nghttp3.php new file mode 100644 index 00000000..6f677869 --- /dev/null +++ b/src/SPC/builder/unix/library/nghttp3.php @@ -0,0 +1,45 @@ +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']); + } +} diff --git a/src/SPC/builder/unix/library/ngtcp2.php b/src/SPC/builder/unix/library/ngtcp2.php new file mode 100644 index 00000000..20620499 --- /dev/null +++ b/src/SPC/builder/unix/library/ngtcp2.php @@ -0,0 +1,49 @@ +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']); + } +} diff --git a/src/SPC/builder/windows/library/nghttp3.php b/src/SPC/builder/windows/library/nghttp3.php new file mode 100644 index 00000000..1586a4d8 --- /dev/null +++ b/src/SPC/builder/windows/library/nghttp3.php @@ -0,0 +1,39 @@ +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}" + ); + } +} diff --git a/src/SPC/builder/windows/library/ngtcp2.php b/src/SPC/builder/windows/library/ngtcp2.php new file mode 100644 index 00000000..d0f557b7 --- /dev/null +++ b/src/SPC/builder/windows/library/ngtcp2.php @@ -0,0 +1,39 @@ +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}" + ); + } +}