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 <jesse2061@outlook.com>
This commit is contained in:
好吧,你想说啥
2024-01-03 10:31:21 +08:00
committed by GitHub
parent 5c7552f826
commit 31c71f180b
25 changed files with 421 additions and 164 deletions

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\RuntimeException;
use SPC\util\CustomExt;
#[CustomExt('swoole-hook-mysql')]
class swoole_hook_mysql extends Extension
{
public function getUnixConfigureArg(): 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 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, 'mysqlnd')) {
throw new RuntimeException('swoole mysql hook is not enabled correctly.');
}
}
}

View File

@@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\util\CustomExt;
#[CustomExt('swoole-hook-pgsql')]
class swoole_hook_pgsql extends Extension
{
public function getUnixConfigureArg(): string
{
// pdo_pgsql need to be disabled
if ($this->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.');
}
}
}

View File

@@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\util\CustomExt;
#[CustomExt('swoole-hook-sqlite')]
class swoole_hook_sqlite extends Extension
{
public function getUnixConfigureArg(): string
{
// pdo_pgsql need to be disabled
if ($this->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.');
}
}
}

View File

@@ -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}",
];
}
}

View File

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

View File

@@ -1,72 +1,12 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*
* 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']);
}
}

View File

@@ -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'),
];
}
}

View File

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

View File

@@ -20,51 +20,9 @@ declare(strict_types=1);
namespace SPC\builder\macos\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
class nghttp2 extends MacOSLibraryBase
{
use \SPC\builder\unix\library\nghttp2;
public const NAME = 'nghttp2';
/**
* @throws FileSystemException
* @throws RuntimeException
*/
protected 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')}-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']);
}
}

View File

@@ -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);

View File

@@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\exception\RuntimeException;
trait libcares
{
/**
* @throws RuntimeException
*/
protected function build(): void
{
shell()->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');
}
}

View File

@@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
trait nghttp2
{
/**
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
protected 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 ' .
'--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']);
}
}

View File

@@ -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;