Merge branch 'main' into ext/rdkafka

# Conflicts:
#	src/globals/test-extensions.php
This commit is contained in:
crazywhalecc
2024-12-13 15:12:05 +08:00
110 changed files with 2868 additions and 859 deletions

View File

@@ -6,6 +6,7 @@ namespace SPC\builder;
use SPC\exception\ExceptionHandler;
use SPC\exception\FileSystemException;
use SPC\exception\InterruptException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\store\Config;
@@ -24,6 +25,12 @@ abstract class BuilderBase
/** @var array<string, Extension> extensions */
protected array $exts = [];
/** @var array<int, string> extension names */
protected array $ext_list = [];
/** @var array<int, string> library names */
protected array $lib_list = [];
/** @var bool compile libs only (just mark it) */
protected bool $libs_only = false;
@@ -160,7 +167,7 @@ abstract class BuilderBase
* @throws FileSystemException
* @throws RuntimeException
* @throws \ReflectionException
* @throws WrongUsageException
* @throws \Throwable|WrongUsageException
* @internal
*/
public function proveExts(array $extensions, bool $skip_check_deps = false): void
@@ -190,6 +197,7 @@ abstract class BuilderBase
foreach ($this->exts as $ext) {
$ext->checkDependency();
}
$this->ext_list = $extensions;
}
/**
@@ -276,7 +284,7 @@ abstract class BuilderBase
return false;
}
}
if (preg_match('/php-(\d+\.\d+\.\d+)/', $file, $match)) {
if (preg_match('/php-(\d+\.\d+\.\d+(?:RC\d+)?)\.tar\.(?:gz|bz2|xz)/', $file, $match)) {
return $match[1];
}
return false;
@@ -407,6 +415,13 @@ abstract class BuilderBase
}
logger()->debug('Running additional patch script: ' . $patch);
require $patch;
} catch (InterruptException $e) {
if ($e->getCode() === 0) {
logger()->notice('Patch script ' . $patch . ' interrupted' . ($e->getMessage() ? (': ' . $e->getMessage()) : '.'));
} else {
logger()->error('Patch script ' . $patch . ' interrupted with error code [' . $e->getCode() . ']' . ($e->getMessage() ? (': ' . $e->getMessage()) : '.'));
}
exit($e->getCode());
} catch (\Throwable $e) {
logger()->critical('Patch script ' . $patch . ' failed to run.');
if ($this->getOption('debug')) {
@@ -414,34 +429,11 @@ abstract class BuilderBase
} else {
logger()->critical('Please check with --debug option to see more details.');
}
throw $e;
}
}
}
/**
* Check if all libs are downloaded.
* If not, throw exception.
*
* @throws RuntimeException
*/
protected function checkLibsSource(): void
{
$not_downloaded = [];
foreach ($this->libs as $lib) {
if (!file_exists($lib->getSourceDir())) {
$not_downloaded[] = $lib::NAME;
}
}
if ($not_downloaded !== []) {
throw new RuntimeException(
'"' . implode(', ', $not_downloaded) .
'" totally ' . count($not_downloaded) .
' source' . (count($not_downloaded) === 1 ? '' : 's') .
' not downloaded, maybe you need to "fetch" ' . (count($not_downloaded) === 1 ? 'it' : 'them') . ' first?'
);
}
}
/**
* Generate micro extension test php code.
*/

View File

@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\builder\macos\MacOSBuilder;
use SPC\builder\windows\WindowsBuilder;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
use SPC\util\GlobalEnvManager;
#[CustomExt('grpc')]
class grpc extends Extension
{
public function patchBeforeBuildconf(): bool
{
// soft link to the grpc source code
if ($this->builder instanceof WindowsBuilder) {
// not support windows yet
throw new \RuntimeException('grpc extension does not support windows yet');
}
if (!is_link(SOURCE_PATH . '/php-src/ext/grpc')) {
shell()->exec('ln -s ' . $this->builder->getLib('grpc')->getSourceDir() . '/src/php/ext/grpc ' . SOURCE_PATH . '/php-src/ext/grpc');
$macos = $this->builder instanceof MacOSBuilder ? "\n" . ' LDFLAGS="$LDFLAGS -framework CoreFoundation"' : '';
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/ext/grpc/config.m4', '/GRPC_LIBDIR=.*$/m', 'GRPC_LIBDIR=' . BUILD_LIB_PATH . $macos);
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/ext/grpc/config.m4', '/SEARCH_PATH=.*$/m', 'SEARCH_PATH="' . BUILD_ROOT_PATH . '"');
return true;
}
return false;
}
public function patchBeforeMake(): bool
{
// add -Wno-strict-prototypes
GlobalEnvManager::putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -Wno-strict-prototypes');
return true;
}
public function getUnixConfigureArg(): string
{
return '--enable-grpc=' . BUILD_ROOT_PATH . '/grpc GRPC_LIB_SUBDIR=' . BUILD_LIB_PATH;
}
}

View File

@@ -6,6 +6,7 @@ namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\WrongUsageException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
#[CustomExt('parallel')]
@@ -17,4 +18,10 @@ class parallel extends Extension
throw new WrongUsageException('ext-parallel must be built with ZTS builds. Use "--enable-zts" option!');
}
}
public function patchBeforeBuildconf(): bool
{
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/ext/parallel/config.m4', '/PHP_VERSION=.*/m', '');
return true;
}
}

View File

@@ -6,6 +6,8 @@ namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\store\FileSystem;
use SPC\util\CustomExt;
@@ -14,6 +16,8 @@ class pgsql extends Extension
{
/**
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
public function patchBeforeConfigure(): bool
{
@@ -24,4 +28,16 @@ class pgsql extends Extension
);
return true;
}
/**
* @throws WrongUsageException
* @throws RuntimeException
*/
public function getUnixConfigureArg(): string
{
if ($this->builder->getPHPVersionID() >= 80400) {
return '--with-pgsql PGSQL_CFLAGS=-I' . BUILD_INCLUDE_PATH . ' PGSQL_LIBS="-L' . BUILD_LIB_PATH . ' -lpq -lpgport -lpgcommon"';
}
return '--with-pgsql=' . BUILD_ROOT_PATH;
}
}

View File

@@ -1,35 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\util\CustomExt;
#[CustomExt('sodium')]
class sodium extends Extension
{
public function patchBeforeBuildconf(): bool
{
// bypass error: unknown warning option '-Wno-logical-op' for macOS
return $this->removeLineContainingString();
}
private function removeLineContainingString(): bool
{
$path = SOURCE_PATH . '/php-src/ext/sodium/config.m4';
$search = '-Wno-logical-op';
if (!file_exists($path)) {
return false;
}
$content = file_get_contents($path);
$lines = preg_split('/\r\n|\n/', $content);
$filteredLines = array_filter($lines, function ($line) use ($search) {
return strpos($line, $search) === false;
});
$newContent = implode("\n", $filteredLines);
file_put_contents($path, $newContent);
return true;
}
}

View File

@@ -12,6 +12,9 @@ class zlib extends Extension
{
public function getUnixConfigureArg(): string
{
if ($this->builder->getPHPVersionID() >= 80400) {
return '--with-zlib';
}
return '--with-zlib --with-zlib-dir="' . BUILD_ROOT_PATH . '"';
}
}

View File

@@ -89,6 +89,11 @@ class BSDBuilder extends UnixBuilderBase
$zts_enable = $this->getPHPVersionID() < 80000 ? '--enable-maintainer-zts --disable-zend-signals' : '--enable-zts --disable-zend-signals';
$zts = $this->getOption('enable-zts', false) ? $zts_enable : '';
$config_file_path = $this->getOption('with-config-file-path', false) ?
('--with-config-file-path=' . $this->getOption('with-config-file-path') . ' ') : '';
$config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ?
('--with-config-file-scan-dir=' . $this->getOption('with-config-file-scan-dir') . ' ') : '';
$enableCli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI;
$enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
@@ -109,6 +114,8 @@ class BSDBuilder extends UnixBuilderBase
($enableFpm ? '--enable-fpm ' : '--disable-fpm ') .
($enableEmbed ? '--enable-embed=static ' : '--disable-embed ') .
($enableMicro ? '--enable-micro ' : '--disable-micro ') .
$config_file_path .
$config_file_scan_dir .
$json_74 .
$zts .
$this->makeExtensionArgs()

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*

View File

@@ -35,7 +35,7 @@ class LinuxBuilder extends UnixBuilderBase
GlobalEnvManager::init($this);
if (str_ends_with(getenv('CC'), 'linux-musl-gcc') && !file_exists("/usr/local/musl/bin/{$arch}-linux-musl-gcc")) {
if (str_ends_with(getenv('CC'), 'linux-musl-gcc') && !file_exists("/usr/local/musl/bin/{$arch}-linux-musl-gcc") && (getenv('SPC_NO_MUSL_PATH') !== 'yes')) {
throw new WrongUsageException('musl-cross-make not installed, please install it first. (You can use `doctor` command to install it)');
}
@@ -134,6 +134,11 @@ class LinuxBuilder extends UnixBuilderBase
}
$disable_jit = $this->getOption('disable-opcache-jit', false) ? '--disable-opcache-jit ' : '';
$config_file_path = $this->getOption('with-config-file-path', false) ?
('--with-config-file-path=' . $this->getOption('with-config-file-path') . ' ') : '';
$config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ?
('--with-config-file-scan-dir=' . $this->getOption('with-config-file-scan-dir') . ' ') : '';
$enable_cli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI;
$enable_fpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
$enable_micro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
@@ -163,6 +168,8 @@ class LinuxBuilder extends UnixBuilderBase
($enable_fpm ? '--enable-fpm ' : '--disable-fpm ') .
($enable_embed ? '--enable-embed=static ' : '--disable-embed ') .
($enable_micro ? '--enable-micro=all-static ' : '--disable-micro ') .
$config_file_path .
$config_file_scan_dir .
$disable_jit .
$json_74 .
$zts .

View File

@@ -6,7 +6,6 @@ namespace SPC\builder\linux;
use SPC\builder\traits\UnixSystemUtilTrait;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
class SystemUtil
{
@@ -83,52 +82,6 @@ class SystemUtil
};
}
/**
* @throws RuntimeException
* @throws WrongUsageException
* @throws WrongUsageException
*/
public static function getArchCFlags(string $cc, string $arch): string
{
if (php_uname('m') === $arch) {
return '';
}
return match (static::getCCType($cc)) {
'clang' => match ($arch) {
'x86_64' => '--target=x86_64-unknown-linux',
'arm64', 'aarch64' => '--target=arm64-unknown-linux',
default => throw new WrongUsageException('unsupported arch: ' . $arch),
},
'gcc' => '',
default => throw new WrongUsageException('cc compiler ' . $cc . ' is not supported'),
};
}
/**
* @throws RuntimeException
*/
public static function getTuneCFlags(string $arch): array
{
return match ($arch) {
'x86_64', 'arm64', 'aarch64' => [],
default => throw new RuntimeException('unsupported arch: ' . $arch),
};
}
public static function checkCCFlags(array $flags, string $cc): array
{
return array_filter($flags, fn ($flag) => static::checkCCFlag($flag, $cc));
}
public static function checkCCFlag(string $flag, string $cc): string
{
[$ret] = shell()->execWithResult("echo | {$cc} -E -x c - {$flag} 2>/dev/null");
if ($ret != 0) {
return '';
}
return $flag;
}
/**
* @throws RuntimeException
* @noinspection PhpUnused

View File

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

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*

View File

@@ -137,6 +137,11 @@ class MacOSBuilder extends UnixBuilderBase
$json_74 = $this->getPHPVersionID() < 80000 ? '--enable-json ' : '';
$zts = $this->getOption('enable-zts', false) ? '--enable-zts --disable-zend-signals ' : '';
$config_file_path = $this->getOption('with-config-file-path', false) ?
('--with-config-file-path=' . $this->getOption('with-config-file-path') . ' ') : '';
$config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ?
('--with-config-file-scan-dir=' . $this->getOption('with-config-file-scan-dir') . ' ') : '';
$enableCli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI;
$enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
@@ -164,6 +169,8 @@ class MacOSBuilder extends UnixBuilderBase
($enableFpm ? '--enable-fpm ' : '--disable-fpm ') .
($enableEmbed ? '--enable-embed=static ' : '--disable-embed ') .
($enableMicro ? '--enable-micro ' : '--disable-micro ') .
$config_file_path .
$config_file_scan_dir .
$json_74 .
$zts .
$this->makeExtensionArgs() . ' ' .

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*

View File

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

View File

@@ -56,7 +56,7 @@ class imap extends MacOSLibraryBase
->exec('chmod +x src/osdep/unix/drivers')
->exec('chmod +x src/osdep/unix/mkauths')
->exec(
"yes | make osx {$ssl_options} EXTRACFLAGS='-Wimplicit-function-declaration -Wno-incompatible-function-pointer-types {$out}'"
"echo y | make osx {$ssl_options} EXTRACFLAGS='-Wno-implicit-function-declaration -Wno-incompatible-function-pointer-types {$out}'"
);
try {
shell()

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*

View File

@@ -12,6 +12,7 @@ use SPC\exception\WrongUsageException;
use SPC\store\Config;
use SPC\store\FileSystem;
use SPC\util\DependencyUtil;
use SPC\util\SPCConfigUtil;
abstract class UnixBuilderBase extends BuilderBase
{
@@ -128,6 +129,7 @@ abstract class UnixBuilderBase extends BuilderBase
foreach ($this->libs as $lib) {
$lib->calcDependency();
}
$this->lib_list = $sorted_libraries;
}
/**
@@ -170,6 +172,32 @@ abstract class UnixBuilderBase extends BuilderBase
}
}
}
// sanity check for embed
if (($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED) {
logger()->info('running embed sanity check');
$sample_file_path = SOURCE_PATH . '/embed-test';
if (!is_dir($sample_file_path)) {
@mkdir($sample_file_path);
}
// copy embed test files
copy(ROOT_DIR . '/src/globals/common-tests/embed.c', $sample_file_path . '/embed.c');
copy(ROOT_DIR . '/src/globals/common-tests/embed.php', $sample_file_path . '/embed.php');
$util = new SPCConfigUtil($this);
$config = $util->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs'));
$lens = "{$config['cflags']} {$config['ldflags']} {$config['libs']}";
if (PHP_OS_FAMILY === 'Linux') {
$lens .= ' -static';
}
[$ret, $out] = shell()->cd($sample_file_path)->execWithResult(getenv('CC') . ' -o embed embed.c ' . $lens);
if ($ret !== 0) {
throw new RuntimeException('embed failed sanity check: build failed. Error message: ' . implode("\n", $out));
}
[$ret, $output] = shell()->cd($sample_file_path)->execWithResult('./embed');
if ($ret !== 0 || trim(implode('', $output)) !== 'hello') {
throw new RuntimeException('embed failed sanity check: run failed. Error message: ' . implode("\n", $output));
}
}
}
/**

View File

@@ -19,6 +19,7 @@ trait gettext
'--disable-java ' .
'--disable-c+ ' .
$extra .
'--with-included-gettext ' .
'--with-libiconv-prefix=' . BUILD_ROOT_PATH . ' ' .
'--prefix=' . BUILD_ROOT_PATH
)

View File

@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\store\FileSystem;
trait grpc
{
protected function build(): void
{
shell()->cd($this->source_dir)
->exec('EXTRA_DEFINES=GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK EMBED_OPENSSL=false CXXFLAGS="-L' . BUILD_LIB_PATH . ' -I' . BUILD_INCLUDE_PATH . '" make static -j' . $this->builder->concurrency);
copy($this->source_dir . '/libs/opt/libgrpc.a', BUILD_LIB_PATH . '/libgrpc.a');
copy($this->source_dir . '/libs/opt/libboringssl.a', BUILD_LIB_PATH . '/libboringssl.a');
if (!file_exists(BUILD_LIB_PATH . '/libcares.a')) {
copy($this->source_dir . '/libs/opt/libcares.a', BUILD_LIB_PATH . '/libcares.a');
}
FileSystem::copyDir($this->source_dir . '/include/grpc', BUILD_INCLUDE_PATH . '/grpc');
FileSystem::copyDir($this->source_dir . '/include/grpc++', BUILD_INCLUDE_PATH . '/grpc++');
FileSystem::copyDir($this->source_dir . '/include/grpcpp', BUILD_INCLUDE_PATH . '/grpcpp');
}
}

View File

@@ -21,7 +21,7 @@ class SystemUtil
if (!$paths) {
$paths = explode(PATH_SEPARATOR, getenv('Path'));
if ($include_sdk_bin) {
$paths[] = PHP_SDK_PATH . '\bin';
$paths[] = getenv('PHP_SDK_PATH') . '\bin';
}
}
foreach ($paths as $path) {

View File

@@ -38,7 +38,7 @@ class WindowsBuilder extends BuilderBase
// ---------- set necessary options ----------
// set sdk (require visual studio 16 or 17)
$vs = SystemUtil::findVisualStudio()['version'];
$this->sdk_prefix = PHP_SDK_PATH . "\\phpsdk-{$vs}-x64.bat -t";
$this->sdk_prefix = getenv('PHP_SDK_PATH') . "\\phpsdk-{$vs}-x64.bat -t";
// set zts
$this->zts = $this->getOption('enable-zts', false);
@@ -103,6 +103,9 @@ class WindowsBuilder extends BuilderBase
$micro_w32 = $this->getOption('enable-micro-win32') ? ' --enable-micro-win32=yes' : '';
$config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ?
('--with-config-file-scan-dir=' . $this->getOption('with-config-file-scan-dir') . ' ') : '';
cmd()->cd(SOURCE_PATH . '\php-src')
->exec(
"{$this->sdk_prefix} configure.bat --task-args \"" .
@@ -114,6 +117,7 @@ class WindowsBuilder extends BuilderBase
($enableCli ? '--enable-cli=yes ' : '--enable-cli=no ') .
($enableMicro ? ('--enable-micro=yes ' . $micro_logo . $micro_w32) : '--enable-micro=no ') .
($enableEmbed ? '--enable-embed=yes ' : '--enable-embed=no ') .
$config_file_scan_dir .
"{$this->makeExtensionArgs()} " .
$zts .
'"'
@@ -244,6 +248,7 @@ class WindowsBuilder extends BuilderBase
foreach ($this->libs as $lib) {
$lib->calcDependency();
}
$this->lib_list = $sorted_libraries;
}
/**

View File

@@ -32,7 +32,7 @@ class xz extends WindowsLibraryBase
);
// copy liblzma.lib to liblzma_a.lib
copy(BUILD_LIB_PATH . '/liblzma.lib', BUILD_LIB_PATH . '/liblzma_a.lib');
copy(BUILD_LIB_PATH . '/lzma.lib', BUILD_LIB_PATH . '/liblzma_a.lib');
// patch lzma.h
FileSystem::replaceFileStr(BUILD_INCLUDE_PATH . '/lzma.h', 'defined(LZMA_API_STATIC)', 'defined(_WIN32)');
}