From 31c71f180b659a276c2e1bc9ab0f411bfdd3bc1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A5=BD=E5=90=A7=EF=BC=8C=E4=BD=A0=E6=83=B3=E8=AF=B4?= =?UTF-8?q?=E5=95=A5?= Date: Wed, 3 Jan 2024 10:31:21 +0800 Subject: [PATCH] Feature perfect swoole extension config (#297) * improve swoole static build config * improve swoole static build config * improve swoole static build config * improve swoole static build config * improve swoole static build config * add cares config * update swoole depend config * update swoole depend config * update cares build config * update workflow tests.yaml config * fix setup-runtime * test with clang build * test with clang build * update cares build config * test * test * test * test * test * test * test * test * test * test * test * test * test * test * update cares license * test build * test build * test build * test build * test add enable libpq * test add enable libpq * test add enable libpq * test add enable libpq * test add enable libpq * test add enable libpq * test add enable libpq * test * test * test * test * test * test * test * test * test * test * test * test * test * test * test * test * test * test * test * test * test * update * update * update * update * update * update * update * update * update * compatible old * fix code format * fix code format * add swoole test case * add swoole test case * add phpstan ignore error * add phpstan ignore error * add phpstan ignore error * add phpstan ignore error * add phpstan ignore error * update phpstan.neon * update swoole extension test case * update swoole test case * adjust config order and depends * revert LinuxBuilder * remove swoole.phpt * re-adjust swoole args * update test-extensions and some PHPDoc * revert: debian and alpine clang doctor install * revert: MacOSBuilder * fix: extract hook for archive not working * revert: build tests * use addon mode to swoole database hook * add hook tests * test minimal * test minimal * sort config --------- Co-authored-by: crazywhalecc --- bin/setup-runtime | 3 +- config/ext.json | 43 +++++++++++-- config/lib.json | 12 ++++ config/source.json | 9 +++ phpstan.neon | 7 +- src/SPC/builder/BuilderBase.php | 2 +- src/SPC/builder/extension/swoole.php | 30 +++++++-- .../builder/extension/swoole_hook_mysql.php | 36 +++++++++++ .../builder/extension/swoole_hook_pgsql.php | 40 ++++++++++++ .../builder/extension/swoole_hook_sqlite.php | 40 ++++++++++++ src/SPC/builder/linux/LinuxBuilder.php | 14 ++-- src/SPC/builder/linux/library/libcares.php | 12 ++++ src/SPC/builder/linux/library/nghttp2.php | 64 +------------------ src/SPC/builder/macos/MacOSBuilder.php | 49 +++++++++----- src/SPC/builder/macos/library/libcares.php | 12 ++++ src/SPC/builder/macos/library/nghttp2.php | 46 +------------ src/SPC/builder/unix/library/brotli.php | 6 +- src/SPC/builder/unix/library/libcares.php | 21 ++++++ src/SPC/builder/unix/library/nghttp2.php | 53 +++++++++++++++ src/SPC/builder/unix/library/postgresql.php | 3 - src/SPC/store/FileSystem.php | 1 + src/SPC/store/SourcePatcher.php | 12 ++++ src/globals/functions.php | 5 +- src/globals/test-extensions.php | 53 +++++++++++---- src/globals/tests/swoole.php | 12 ++++ 25 files changed, 421 insertions(+), 164 deletions(-) create mode 100644 src/SPC/builder/extension/swoole_hook_mysql.php create mode 100644 src/SPC/builder/extension/swoole_hook_pgsql.php create mode 100644 src/SPC/builder/extension/swoole_hook_sqlite.php create mode 100644 src/SPC/builder/linux/library/libcares.php create mode 100644 src/SPC/builder/macos/library/libcares.php create mode 100644 src/SPC/builder/unix/library/libcares.php create mode 100644 src/SPC/builder/unix/library/nghttp2.php create mode 100644 src/globals/tests/swoole.php diff --git a/bin/setup-runtime b/bin/setup-runtime index b914c1ba..86c29c2d 100755 --- a/bin/setup-runtime +++ b/bin/setup-runtime @@ -35,7 +35,6 @@ while [ $# -gt 0 ]; do case "$1" in --mirror) mirror="$2" - shift ;; --*) echo "Illegal option $1" @@ -47,7 +46,7 @@ done case "$mirror" in china) __PHP_RUNTIME_URL__="https://dl.static-php.dev/static-php-cli/bulk/php-8.2.13-cli-${__OS_FIXED__}-${__ARCH__}.tar.gz" - __COMPOSER_URL__="https://mirrors.aliyun.com/composer/composer.phar" + __COMPOSER_URL__="https://mirrors.tencent.com/composer/composer.phar" ;; esac diff --git a/config/ext.json b/config/ext.json index e549724f..c15e162c 100644 --- a/config/ext.json +++ b/config/ext.json @@ -424,17 +424,50 @@ "source": "swoole", "arg-type": "custom", "cpp-extension": true, + "unix-only": true, "lib-depends": [ - "openssl" + "libcares", + "brotli", + "nghttp2", + "zlib" ], "ext-depends": [ - "openssl" + "openssl", + "curl" ], "ext-suggests": [ - "curl", - "pgsql" + "swoole-hook-pgsql", + "swoole-hook-mysql", + "swoole-hook-sqlite" + ] + }, + "swoole-hook-mysql": { + "type": "addon", + "arg-type": "custom", + "ext-depends": [ + "mysqlnd", + "pdo", + "pdo_mysql" ], - "unix-only": true + "ext-suggests": [ + "mysqli" + ] + }, + "swoole-hook-pgsql": { + "type": "addon", + "arg-type": "custom", + "ext-depends": [ + "pgsql", + "pdo" + ] + }, + "swoole-hook-sqlite": { + "type": "addon", + "arg-type": "custom", + "ext-depends": [ + "sqlite3", + "pdo" + ] }, "swow": { "type": "external", diff --git a/config/lib.json b/config/lib.json index 45329c04..25c2c6df 100644 --- a/config/lib.json +++ b/config/lib.json @@ -175,6 +175,18 @@ "libavif.a" ] }, + "libcares": { + "source": "libcares", + "static-libs-unix": [ + "libcares.a" + ], + "headers-unix": [ + "ares.h", + "ares_dns.h", + "ares_nameser.h", + "ares_rules.h" + ] + }, "libevent": { "source": "libevent", "static-libs-unix": [ diff --git a/config/source.json b/config/source.json index b6cb0441..13a196b7 100644 --- a/config/source.json +++ b/config/source.json @@ -209,6 +209,15 @@ "path": "LICENSE" } }, + "libcares": { + "type": "filelist", + "url": "https://c-ares.org/download/", + "regex": "/href=\"\\/download\\/(?c-ares-(?[^\"]+)\\.tar\\.gz)\"/", + "license": { + "type": "file", + "path": "LICENSE.md" + } + }, "libevent": { "type": "ghrel", "repo": "libevent/libevent", diff --git a/phpstan.neon b/phpstan.neon index 3f0ab052..1bdf9125 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -8,5 +8,10 @@ parameters: - '#Unsafe usage of new static#' - '#class Fiber#' - '#Attribute class JetBrains\\PhpStorm\\ArrayShape does not exist#' + - '#Function Swoole\\Coroutine\\run not found.#' dynamicConstantNames: - - PHP_OS_FAMILY \ No newline at end of file + - PHP_OS_FAMILY + excludePaths: + analyseAndScan: + - ./src/globals/tests/swoole.php + - ./src/globals/tests/swoole.phpt \ No newline at end of file diff --git a/src/SPC/builder/BuilderBase.php b/src/SPC/builder/BuilderBase.php index 72db5961..86254869 100644 --- a/src/SPC/builder/BuilderBase.php +++ b/src/SPC/builder/BuilderBase.php @@ -227,7 +227,7 @@ abstract class BuilderBase foreach ($this->exts as $ext) { $ret[] = trim($ext->getConfigureArg()); } - logger()->info('Using configure: ' . implode(' ', $ret)); + logger()->debug('Using configure: ' . implode(' ', $ret)); return implode(' ', $ret); } diff --git a/src/SPC/builder/extension/swoole.php b/src/SPC/builder/extension/swoole.php index 3dd570a1..f9da2005 100644 --- a/src/SPC/builder/extension/swoole.php +++ b/src/SPC/builder/extension/swoole.php @@ -12,13 +12,31 @@ class swoole extends Extension { public function getUnixConfigureArg(): string { + // enable swoole $arg = '--enable-swoole'; - // pgsql hook is buggy for static php - $arg .= ' --disable-swoole-pgsql'; - $arg .= $this->builder->getLib('openssl') ? ' --enable-openssl' : ' --disable-openssl --without-openssl'; - $arg .= $this->builder->getLib('brotli') ? (' --enable-brotli --with-brotli-dir=' . BUILD_ROOT_PATH) : ' --disable-brotli'; - // swoole curl hook is buggy for php 8.0 - $arg .= $this->builder->getExt('curl') && $this->builder->getPHPVersionID() >= 80100 ? ' --enable-swoole-curl' : ' --disable-swoole-curl'; + + // commonly-used feature: coroutine-time, thread-context + $arg .= ' --enable-swoole-coro-time --enable-thread-context'; + + // required feature: curl, openssl (but curl hook is buggy for php 8.0) + $arg .= $this->builder->getPHPVersionID() >= 80100 ? ' --enable-swoole-curl' : ' --disable-swoole-curl'; + $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) + $arg .= $this->builder->getLib('libcares') ? ' --enable-cares' : ''; + $arg .= $this->builder->getLib('brotli') ? (' --with-brotli-dir=' . BUILD_ROOT_PATH) : ''; + $arg .= $this->builder->getLib('nghttp2') ? (' --with-nghttp2-dir=' . BUILD_ROOT_PATH) : ''; + + // additional feature: swoole-pgsql, it should depend on lib [postgresql], but it will lack of CFLAGS etc. + // so this is a tricky way (enable ext [pgsql,pdo] to add postgresql hook and pdo_pgsql support) + $arg .= $this->builder->getExt('swoole-hook-pgsql') ? '' : ' --disable-swoole-pgsql'; + + // enable this feature , need remove pdo_sqlite + // more info : https://wenda.swoole.com/detail/109023 + $arg .= $this->builder->getExt('swoole-hook-sqlite') ? '' : ' --disable-swoole-sqlite'; + + // enable this feature , need stop pdo_* + // $arg .= $this->builder->getLib('unixodbc') ? ' --with-swoole-odbc=unixODBC,' : ' '; return $arg; } } diff --git a/src/SPC/builder/extension/swoole_hook_mysql.php b/src/SPC/builder/extension/swoole_hook_mysql.php new file mode 100644 index 00000000..6a239976 --- /dev/null +++ b/src/SPC/builder/extension/swoole_hook_mysql.php @@ -0,0 +1,36 @@ +builder->getExt('swoole') === null) { + return; + } + [$ret, $out] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php --ri "swoole"', false); + $out = implode('', $out); + if ($ret !== 0) { + throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret); + } + if (!str_contains($out, 'mysqlnd')) { + throw new RuntimeException('swoole mysql hook is not enabled correctly.'); + } + } +} diff --git a/src/SPC/builder/extension/swoole_hook_pgsql.php b/src/SPC/builder/extension/swoole_hook_pgsql.php new file mode 100644 index 00000000..93e6172c --- /dev/null +++ b/src/SPC/builder/extension/swoole_hook_pgsql.php @@ -0,0 +1,40 @@ +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.'); + } + // enable swoole pgsql hook + return '--enable-swoole-pgsql'; + } + + public function runCliCheck(): void + { + // skip if not enable swoole + if ($this->builder->getExt('swoole') === null) { + return; + } + [$ret, $out] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php --ri "swoole"', false); + $out = implode('', $out); + if ($ret !== 0) { + throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret); + } + if (!str_contains($out, 'coroutine_pgsql')) { + throw new RuntimeException('swoole pgsql hook is not enabled correctly.'); + } + } +} diff --git a/src/SPC/builder/extension/swoole_hook_sqlite.php b/src/SPC/builder/extension/swoole_hook_sqlite.php new file mode 100644 index 00000000..714c83b6 --- /dev/null +++ b/src/SPC/builder/extension/swoole_hook_sqlite.php @@ -0,0 +1,40 @@ +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.'); + } + // enable swoole pgsql hook + return '--enable-swoole-sqlite'; + } + + public function runCliCheck(): void + { + // skip if not enable swoole + if ($this->builder->getExt('swoole') === null) { + return; + } + [$ret, $out] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php --ri "swoole"', false); + $out = implode('', $out); + if ($ret !== 0) { + throw new RuntimeException('extension ' . $this->getName() . ' failed compile check: php-cli returned ' . $ret); + } + if (!str_contains($out, 'coroutine_sqlite')) { + throw new RuntimeException('swoole sqlite hook is not enabled correctly.'); + } + } +} diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index a757c661..8fe8010c 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -138,16 +138,15 @@ class LinuxBuilder extends BuilderBase // add libstdc++, some extensions or libraries need it $extra_libs .= (empty($extra_libs) ? '' : ' ') . ($this->hasCpp() ? '-lstdc++ ' : ''); $this->setOption('extra-libs', $extra_libs); - $cflags = $this->arch_c_flags; // prepare build php envs $envs_build_php = SystemUtil::makeEnvVarString([ 'CFLAGS' => $cflags, 'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH, + 'LDFLAGS' => '-L' . BUILD_LIB_PATH, 'LIBS' => '-ldl -lpthread', ]); - SourcePatcher::patchBeforeBuildconf($this); shell()->cd(SOURCE_PATH . '/php-src')->exec('./buildconf --force'); @@ -190,8 +189,8 @@ class LinuxBuilder extends BuilderBase $json_74 . $zts . $maxExecutionTimers . - $this->makeExtensionArgs() . ' ' . - $envs_build_php + $this->makeExtensionArgs() . + ' ' . $envs_build_php . ' ' ); SourcePatcher::patchBeforeMake($this); @@ -323,10 +322,11 @@ class LinuxBuilder extends BuilderBase $cflags = isset($input['EXTRA_CFLAGS']) && $input['EXTRA_CFLAGS'] ? " {$input['EXTRA_CFLAGS']}" : ''; $libs = isset($input['EXTRA_LIBS']) && $input['EXTRA_LIBS'] ? " {$input['EXTRA_LIBS']}" : ''; $ldflags = isset($input['EXTRA_LDFLAGS_PROGRAM']) && $input['EXTRA_LDFLAGS_PROGRAM'] ? " {$input['EXTRA_LDFLAGS_PROGRAM']}" : ''; + $tune_c_flags = implode(' ', array_map(fn ($x) => "-Xcompiler {$x}", $this->tune_c_flags)); return [ - 'EXTRA_CFLAGS' => "{$optimization} -fno-ident -fPIE " . implode(' ', array_map(fn ($x) => "-Xcompiler {$x}", $this->tune_c_flags)) . $cflags, - 'EXTRA_LIBS' => $this->getOption('extra-libs', '') . $libs, - 'EXTRA_LDFLAGS_PROGRAM' => "{$use_lld} -all-static" . $ldflags, + 'EXTRA_CFLAGS' => "{$optimization} -fno-ident -fPIE {$tune_c_flags}{$cflags}", + 'EXTRA_LIBS' => "{$this->getOption('extra-libs', '')} {$libs}", + 'EXTRA_LDFLAGS_PROGRAM' => "{$use_lld} -all-static{$ldflags}", ]; } } diff --git a/src/SPC/builder/linux/library/libcares.php b/src/SPC/builder/linux/library/libcares.php new file mode 100644 index 00000000..ef3801da --- /dev/null +++ b/src/SPC/builder/linux/library/libcares.php @@ -0,0 +1,12 @@ + - * - * 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); namespace SPC\builder\linux\library; -use SPC\exception\FileSystemException; -use SPC\exception\RuntimeException; -use SPC\exception\WrongUsageException; - class nghttp2 extends LinuxLibraryBase { + use \SPC\builder\unix\library\nghttp2; + public const NAME = 'nghttp2'; - - /** - * @throws FileSystemException - * @throws RuntimeException - * @throws WrongUsageException - */ - public function build(): void - { - $args = $this->builder->makeAutoconfArgs(static::NAME, [ - 'zlib' => null, - 'openssl' => null, - 'libxml2' => null, - 'libev' => null, - 'libcares' => null, - 'libngtcp2' => null, - 'libnghttp3' => null, - 'libbpf' => null, - 'libevent-openssl' => null, - 'jansson' => null, - 'jemalloc' => null, - 'systemd' => null, - 'cunit' => null, - ]); - - [,,$destdir] = SEPARATED_PATH; - - shell()->cd($this->source_dir) - ->exec( - './configure ' . - '--enable-static ' . - '--disable-shared ' . - "--host={$this->builder->getOption('gnu-arch')}-unknown-linux " . - '--enable-lib-only ' . - '--with-boost=no ' . - $args . ' ' . - '--prefix=' - ) - ->exec('make clean') - ->exec("make -j{$this->builder->concurrency}") - ->exec("make install DESTDIR={$destdir}"); - $this->patchPkgconfPrefix(['libnghttp2.pc']); - } } diff --git a/src/SPC/builder/macos/MacOSBuilder.php b/src/SPC/builder/macos/MacOSBuilder.php index 5330e8a2..6a60b33d 100644 --- a/src/SPC/builder/macos/MacOSBuilder.php +++ b/src/SPC/builder/macos/MacOSBuilder.php @@ -155,6 +155,21 @@ class MacOSBuilder extends BuilderBase $enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO; $enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED; + // prepare build php envs + $envs_build_php = SystemUtil::makeEnvVarString([ + 'CFLAGS' => " {$this->arch_c_flags} -Werror=unknown-warning-option ", + 'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH, + 'LDFLAGS' => '-L' . BUILD_LIB_PATH, + ]); + + if ($this->getLib('postgresql')) { + shell() + ->cd(SOURCE_PATH . '/php-src') + ->exec( + 'sed -i.backup "s/ac_cv_func_explicit_bzero\" = xyes/ac_cv_func_explicit_bzero\" = x_fake_yes/" ./configure' + ); + } + shell()->cd(SOURCE_PATH . '/php-src') ->exec( './configure ' . @@ -162,8 +177,6 @@ class MacOSBuilder extends BuilderBase '--with-valgrind=no ' . // Not detect memory leak '--enable-shared=no ' . '--enable-static=yes ' . - "CFLAGS='{$this->arch_c_flags} -Werror=unknown-warning-option' " . - "CPPFLAGS='-I" . BUILD_INCLUDE_PATH . "' " . '--disable-all ' . '--disable-cgi ' . '--disable-phpdbg ' . @@ -173,7 +186,8 @@ class MacOSBuilder extends BuilderBase ($enableMicro ? '--enable-micro ' : '--disable-micro ') . $json_74 . $zts . - $this->makeExtensionArgs() + $this->makeExtensionArgs() . ' ' . + $envs_build_php ); SourcePatcher::patchBeforeMake($this); @@ -213,10 +227,7 @@ class MacOSBuilder extends BuilderBase */ public function buildCli(): void { - $vars = SystemUtil::makeEnvVarString([ - 'EXTRA_CFLAGS' => '-g -Os', // with debug information, but optimize for size - 'EXTRA_LIBS' => "{$this->getOption('extra-libs')} -lresolv", // link resolv library (macOS needs it) - ]); + $vars = SystemUtil::makeEnvVarString($this->getBuildVars()); $shell = shell()->cd(SOURCE_PATH . '/php-src'); $shell->exec("make -j{$this->concurrency} {$vars} cli"); @@ -247,9 +258,8 @@ class MacOSBuilder extends BuilderBase $vars = [ // with debug information, optimize for size, remove identifiers, patch fake cli for micro 'EXTRA_CFLAGS' => '-g -Os -fno-ident' . $enable_fake_cli, - // link resolv library (macOS needs it) - 'EXTRA_LIBS' => "{$this->getOption('extra-libs')} -lresolv", ]; + $vars = $this->getBuildVars($vars); if (!$this->getOption('no-strip', false)) { $vars['STRIP'] = 'dsymutil -f '; } @@ -272,10 +282,7 @@ class MacOSBuilder extends BuilderBase */ public function buildFpm(): void { - $vars = SystemUtil::makeEnvVarString([ - 'EXTRA_CFLAGS' => '-g -Os', // with debug information, but optimize for size - 'EXTRA_LIBS' => "{$this->getOption('extra-libs')} -lresolv", // link resolv library (macOS needs it) - ]); + $vars = SystemUtil::makeEnvVarString($this->getBuildVars()); $shell = shell()->cd(SOURCE_PATH . '/php-src'); $shell->exec("make -j{$this->concurrency} {$vars} fpm"); @@ -292,10 +299,7 @@ class MacOSBuilder extends BuilderBase */ public function buildEmbed(): void { - $vars = SystemUtil::makeEnvVarString([ - 'EXTRA_CFLAGS' => '-g -Os', // with debug information, but optimize for size - 'EXTRA_LIBS' => "{$this->getOption('extra-libs')} -lresolv", // link resolv library (macOS needs it) - ]); + $vars = SystemUtil::makeEnvVarString($this->getBuildVars()); shell() ->cd(SOURCE_PATH . '/php-src') @@ -309,4 +313,15 @@ class MacOSBuilder extends BuilderBase ->exec('ar rcs ' . BUILD_ROOT_PATH . '/lib/libphp.a *.o') ->exec('rm -Rf ' . BUILD_ROOT_PATH . '/lib/php-o'); } + + private function getBuildVars($input = []): array + { + $optimization = $this->getOption('no-strip', false) ? '-g -O0' : '-g0 -Os'; + $cflags = isset($input['EXTRA_CFLAGS']) && $input['EXTRA_CFLAGS'] ? " {$input['EXTRA_CFLAGS']}" : ''; + $libs = isset($input['EXTRA_LIBS']) && $input['EXTRA_LIBS'] ? " {$input['EXTRA_LIBS']}" : ''; + return [ + 'EXTRA_CFLAGS' => "{$optimization} {$cflags} " . $this->getOption('x-extra-cflags'), + 'EXTRA_LIBS' => "{$this->getOption('extra-libs')} -lresolv {$libs} " . $this->getOption('x-extra-libs'), + ]; + } } diff --git a/src/SPC/builder/macos/library/libcares.php b/src/SPC/builder/macos/library/libcares.php new file mode 100644 index 00000000..6eb92ec0 --- /dev/null +++ b/src/SPC/builder/macos/library/libcares.php @@ -0,0 +1,12 @@ +builder->makeAutoconfArgs(static::NAME, [ - 'zlib' => null, - 'openssl' => null, - 'libxml2' => null, - 'libev' => null, - 'libcares' => null, - 'libngtcp2' => null, - 'libnghttp3' => null, - 'libbpf' => null, - 'libevent-openssl' => null, - 'jansson' => null, - 'jemalloc' => null, - 'systemd' => null, - 'cunit' => null, - ]); - - [,,$destdir] = SEPARATED_PATH; - - shell()->cd($this->source_dir) - ->exec( - './configure ' . - '--enable-static ' . - '--disable-shared ' . - "--host={$this->builder->getOption('gnu-arch')}-apple-darwin " . - '--enable-lib-only ' . - '--with-boost=no ' . - $args . ' ' . - '--prefix=' - ) - ->exec('make clean') - ->exec("make -j{$this->builder->concurrency}") - ->exec("make install DESTDIR={$destdir}"); - $this->patchPkgconfPrefix(['libnghttp2.pc']); - } } diff --git a/src/SPC/builder/unix/library/brotli.php b/src/SPC/builder/unix/library/brotli.php index 92c04de4..1b783ad0 100644 --- a/src/SPC/builder/unix/library/brotli.php +++ b/src/SPC/builder/unix/library/brotli.php @@ -28,9 +28,9 @@ trait brotli ->exec('make install DESTDIR=' . BUILD_ROOT_PATH); $this->patchPkgconfPrefix(['libbrotlicommon.pc', 'libbrotlidec.pc', 'libbrotlienc.pc']); shell()->cd(BUILD_ROOT_PATH . '/lib') - ->exec('ln -s libbrotlicommon.a libbrotlicommon-static.a') - ->exec('ln -s libbrotlidec.a libbrotlidec-static.a') - ->exec('ln -s libbrotlienc.a libbrotlienc-static.a'); + ->exec('ln -sf libbrotlicommon.a libbrotlicommon-static.a') + ->exec('ln -sf libbrotlidec.a libbrotlidec-static.a') + ->exec('ln -sf libbrotlienc.a libbrotlienc-static.a'); foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) { if (str_starts_with($filename, 'libbrotli') && (str_contains($filename, '.so') || str_ends_with($filename, '.dylib'))) { unlink(BUILD_ROOT_PATH . '/lib/' . $filename); diff --git a/src/SPC/builder/unix/library/libcares.php b/src/SPC/builder/unix/library/libcares.php new file mode 100644 index 00000000..6d570174 --- /dev/null +++ b/src/SPC/builder/unix/library/libcares.php @@ -0,0 +1,21 @@ +cd($this->source_dir) + ->exec('./configure --prefix=' . BUILD_ROOT_PATH . ' --enable-static --disable-shared --disable-tests') + ->exec("make -j {$this->builder->concurrency}") + ->exec('make install'); + } +} diff --git a/src/SPC/builder/unix/library/nghttp2.php b/src/SPC/builder/unix/library/nghttp2.php new file mode 100644 index 00000000..0334beba --- /dev/null +++ b/src/SPC/builder/unix/library/nghttp2.php @@ -0,0 +1,53 @@ +builder->makeAutoconfArgs(static::NAME, [ + 'zlib' => null, + 'openssl' => null, + 'libxml2' => null, + 'libev' => null, + 'libcares' => null, + 'libngtcp2' => null, + 'libnghttp3' => null, + 'libbpf' => null, + 'libevent-openssl' => null, + 'jansson' => null, + 'jemalloc' => null, + 'systemd' => null, + 'cunit' => null, + ]); + + [,,$destdir] = SEPARATED_PATH; + + shell()->cd($this->source_dir) + ->exec( + './configure ' . + '--enable-static ' . + '--disable-shared ' . + '--enable-lib-only ' . + '--with-boost=no ' . + $args . ' ' . + '--prefix=' + ) + ->exec('make clean') + ->exec("make -j{$this->builder->concurrency}") + ->exec("make install DESTDIR={$destdir}"); + $this->patchPkgconfPrefix(['libnghttp2.pc']); + } +} diff --git a/src/SPC/builder/unix/library/postgresql.php b/src/SPC/builder/unix/library/postgresql.php index 2448f656..4061f13e 100644 --- a/src/SPC/builder/unix/library/postgresql.php +++ b/src/SPC/builder/unix/library/postgresql.php @@ -28,9 +28,6 @@ trait postgresql 'icu' => 'icu-i18n', ]; - f_putenv('PKG_CONFIG=' . BUILD_ROOT_PATH . '/bin/pkg-config'); - f_putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig'); - foreach ($optional_packages as $lib => $pkg) { if ($this->getBuilder()->getLib($lib)) { $packages .= ' ' . $pkg; diff --git a/src/SPC/store/FileSystem.php b/src/SPC/store/FileSystem.php index 0480ff14..c08a09bb 100644 --- a/src/SPC/store/FileSystem.php +++ b/src/SPC/store/FileSystem.php @@ -233,6 +233,7 @@ class FileSystem throw new FileSystemException("unknown archive format: {$filename}"); } } + self::emitSourceExtractHook($name); } catch (RuntimeException $e) { if (PHP_OS_FAMILY === 'Windows') { f_passthru('rmdir /s /q ' . SOURCE_PATH . "/{$name}"); diff --git a/src/SPC/store/SourcePatcher.php b/src/SPC/store/SourcePatcher.php index 426f978a..fc3e69d4 100644 --- a/src/SPC/store/SourcePatcher.php +++ b/src/SPC/store/SourcePatcher.php @@ -16,6 +16,7 @@ class SourcePatcher // FileSystem::addSourceExtractHook('swow', [SourcePatcher::class, 'patchSwow']); FileSystem::addSourceExtractHook('micro', [SourcePatcher::class, 'patchMicro']); FileSystem::addSourceExtractHook('openssl', [SourcePatcher::class, 'patchOpenssl11Darwin']); + FileSystem::addSourceExtractHook('swoole', [SourcePatcher::class, 'patchSwoole']); } /** @@ -159,6 +160,17 @@ class SourcePatcher return false; } + public static function patchSwoole(): bool + { + // swoole hook needs pdo/pdo.h + FileSystem::replaceFileStr( + SOURCE_PATH . '/php-src/ext/swoole/config.m4', + 'PHP_ADD_INCLUDE([$ext_srcdir])', + "PHP_ADD_INCLUDE( [\$ext_srcdir] )\n PHP_ADD_INCLUDE([\$abs_srcdir/ext])" + ); + return true; + } + /** * @throws FileSystemException */ diff --git a/src/globals/functions.php b/src/globals/functions.php index afadf3a4..e48eaeeb 100644 --- a/src/globals/functions.php +++ b/src/globals/functions.php @@ -3,6 +3,7 @@ declare(strict_types=1); use Psr\Log\LoggerInterface; +use SPC\exception\RuntimeException; use SPC\exception\WrongUsageException; use SPC\util\UnixShell; use SPC\util\WindowsCmd; @@ -69,7 +70,7 @@ function osfamily2dir(): string /** * Execute the shell command, and the output will be directly printed in the terminal. If there is an error, an exception will be thrown * - * @throws \SPC\exception\RuntimeException + * @throws RuntimeException */ function f_passthru(string $cmd): ?bool { @@ -87,7 +88,7 @@ function f_passthru(string $cmd): ?bool } $ret = passthru($cmd, $code); if ($code !== 0) { - throw new \SPC\exception\RuntimeException('Command run failed with code[' . $code . ']: ' . $cmd, $code); + throw new RuntimeException('Command run failed with code[' . $code . ']: ' . $cmd, $code); } return $ret; } diff --git a/src/globals/test-extensions.php b/src/globals/test-extensions.php index e5ef1de2..00d69c0a 100644 --- a/src/globals/test-extensions.php +++ b/src/globals/test-extensions.php @@ -2,24 +2,55 @@ declare(strict_types=1); -# Normal test, contains `common` extension. -$extensions = 'bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,gd,gmp,iconv,xml,mbstring,mbregex,mysqlnd,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,redis,session,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip'; +/** + * This is GitHub Actions automatic test extension args generator. + * You can edit $extensions, $with_libs and $base_combination. + */ -# Normal test, contains gd extra libraries. -$additional_libs = 'libwebp,libavif,libjpeg,freetype'; +// --------------------------------- edit area --------------------------------- -# If you want to test additional extensions, add them below. (comma start) -$extensions .= ',xhprof'; +// If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`). +$extensions = 'swoole,swoole-hook-pgsql,swoole-hook-mysql,swoole-hook-sqlite'; -# If you want to test additional features for extensions, add libs below. (comma start like extensions) -$additional_libs .= ''; +// If you want to test lib-suggests feature with extension, add them below (comma separated, example `libwebp,libavif`). +$with_libs = ''; + +// Please change your test base combination. We recommend testing with `common`. +// You can use `common`, `bulk`, `minimal` or `none`. +$base_combination = 'minimal'; + +// -------------------------- code area, do not modify -------------------------- + +/** + * get combination for tests, do not modify it if not necessary. + */ +function _getCombination(string $type = 'common'): string +{ + return match ($type) { + 'common' => 'bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,gd,gmp,iconv,xml,mbstring,mbregex,' . + 'mysqlnd,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,redis,session,simplexml,soap,sockets,' . + 'sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip', + 'bulk' => 'apcu,bcmath,bz2,calendar,ctype,curl,dba,dom,event,exif,fileinfo,filter,ftp,gd,gmp,iconv,imagick,imap,' . + 'intl,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pdo_pgsql,pdo_sqlite,pgsql,phar,' . + 'posix,protobuf,readline,redis,session,shmop,simplexml,soap,sockets,sodium,sqlite3,swoole,sysvmsg,sysvsem,' . + 'sysvshm,tokenizer,xml,xmlreader,xmlwriter,xsl,zip,zlib', + 'minimal' => 'pcntl,posix,mbstring,tokenizer,phar', + default => '', // none + }; +} if (!isset($argv[1])) { exit("Please use 'extensions', 'cmd' or 'libs' as output type"); } + +$trim_value = "\r\n \t,"; + +$final_extensions = trim(trim($extensions, $trim_value) . ',' . _getCombination($base_combination), $trim_value); +$final_libs = trim($with_libs, $trim_value); + echo match ($argv[1]) { - 'extensions' => $extensions, - 'libs' => $additional_libs, - 'cmd' => $extensions . ' --with-libs=' . $additional_libs, + 'extensions' => $final_extensions, + 'libs' => $final_libs, + 'cmd' => $final_extensions . ($final_libs === '' ? '' : (' --with-libs=' . $final_libs)), default => '', }; diff --git a/src/globals/tests/swoole.php b/src/globals/tests/swoole.php new file mode 100644 index 00000000..9e5752f0 --- /dev/null +++ b/src/globals/tests/swoole.php @@ -0,0 +1,12 @@ +