From 625ee2703d7c216bbd9a7bd33890883448a6c645 Mon Sep 17 00:00:00 2001 From: DubbleClick Date: Thu, 19 Jun 2025 22:06:11 +0700 Subject: [PATCH 1/7] uv needs to explicitly link -lpthread on aarch64, fails to pthread_atfork unresolved otherwise. It's a symbols that's in the static library, but not in the shared library --- src/SPC/builder/extension/uv.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/SPC/builder/extension/uv.php b/src/SPC/builder/extension/uv.php index af8798823..67ead54ea 100644 --- a/src/SPC/builder/extension/uv.php +++ b/src/SPC/builder/extension/uv.php @@ -16,4 +16,11 @@ public function validate(): void throw new \RuntimeException('The latest uv extension requires PHP 8.0 or later'); } } + + public function getStaticAndSharedLibs(): array + { + [$static, $shared] = parent::getStaticAndSharedLibs(); + $shared .= ' -lpthread'; + return [$static, $shared]; + } } From 7d454159906373025e2bbf8ae613448190390030 Mon Sep 17 00:00:00 2001 From: DubbleClick Date: Fri, 20 Jun 2025 15:25:07 +0700 Subject: [PATCH 2/7] patch before make for uv --- src/SPC/builder/Extension.php | 14 ++++++++++++++ src/SPC/builder/extension/uv.php | 12 ++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index a457d82ee..d6dde237c 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -208,6 +208,16 @@ public function patchBeforeSharedConfigure(): bool return false; } + /** + * Patch code before shared extension make + * If you need to patch some code, overwrite this + * return true if you patched something, false if not + */ + public function patchBeforeSharedMake(): bool + { + return false; + } + /** * @return string * returns a command line string with all required shared extensions to load @@ -408,6 +418,10 @@ public function buildUnixShared(): void '$1 ' . $staticLibString ); + if ($this->patchBeforeSharedMake()) { + logger()->info('ext [ . ' . $this->getName() . '] patching before shared make'); + } + shell()->cd($this->source_dir) ->setEnv($env) ->exec('make clean') diff --git a/src/SPC/builder/extension/uv.php b/src/SPC/builder/extension/uv.php index 67ead54ea..d3583fe27 100644 --- a/src/SPC/builder/extension/uv.php +++ b/src/SPC/builder/extension/uv.php @@ -5,6 +5,8 @@ namespace SPC\builder\extension; use SPC\builder\Extension; +use SPC\builder\linux\SystemUtil; +use SPC\store\FileSystem; use SPC\util\CustomExt; #[CustomExt('uv')] @@ -17,10 +19,12 @@ public function validate(): void } } - public function getStaticAndSharedLibs(): array + public function patchBeforeSharedMake(): bool { - [$static, $shared] = parent::getStaticAndSharedLibs(); - $shared .= ' -lpthread'; - return [$static, $shared]; + if (SystemUtil::getLibcVersionIfExists() >= '2.17') { + return false; + } + FileSystem::replaceFileRegex($this->source_dir . '/Makefile', '/^(LDFLAGS =.*)$/', '$1 -luv -ldl -lrt -pthread'); + return true; } } From be0b98c467fe80658cca5b1c9888a20e0af3bf3a Mon Sep 17 00:00:00 2001 From: DubbleClick Date: Fri, 20 Jun 2025 15:27:28 +0700 Subject: [PATCH 3/7] patch before make for uv --- src/SPC/builder/extension/uv.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SPC/builder/extension/uv.php b/src/SPC/builder/extension/uv.php index d3583fe27..d8755a891 100644 --- a/src/SPC/builder/extension/uv.php +++ b/src/SPC/builder/extension/uv.php @@ -21,7 +21,7 @@ public function validate(): void public function patchBeforeSharedMake(): bool { - if (SystemUtil::getLibcVersionIfExists() >= '2.17') { + if (PHP_OS_FAMILY !== 'Linux' || php_uname('m') !== 'aarch64' || SystemUtil::getLibcVersionIfExists() > '2.17') { return false; } FileSystem::replaceFileRegex($this->source_dir . '/Makefile', '/^(LDFLAGS =.*)$/', '$1 -luv -ldl -lrt -pthread'); From 3f92df0865e13504ef82209e197e4bcc4ef2fc1e Mon Sep 17 00:00:00 2001 From: DubbleClick Date: Fri, 20 Jun 2025 15:57:16 +0700 Subject: [PATCH 4/7] patch before make for uv fix --- src/SPC/builder/Extension.php | 4 ++-- src/SPC/builder/extension/uv.php | 4 ++-- src/SPC/doctor/item/LinuxToolCheckList.php | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index d6dde237c..f6e3508d2 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -400,7 +400,7 @@ public function buildUnixShared(): void ->exec(BUILD_BIN_PATH . '/phpize'); if ($this->patchBeforeSharedConfigure()) { - logger()->info('ext [ . ' . $this->getName() . '] patching before shared configure'); + logger()->info('ext [' . $this->getName() . '] patching before shared configure'); } shell()->cd($this->source_dir) @@ -419,7 +419,7 @@ public function buildUnixShared(): void ); if ($this->patchBeforeSharedMake()) { - logger()->info('ext [ . ' . $this->getName() . '] patching before shared make'); + logger()->info('ext [' . $this->getName() . '] patching before shared make'); } shell()->cd($this->source_dir) diff --git a/src/SPC/builder/extension/uv.php b/src/SPC/builder/extension/uv.php index d8755a891..ffe92bcc7 100644 --- a/src/SPC/builder/extension/uv.php +++ b/src/SPC/builder/extension/uv.php @@ -21,10 +21,10 @@ public function validate(): void public function patchBeforeSharedMake(): bool { - if (PHP_OS_FAMILY !== 'Linux' || php_uname('m') !== 'aarch64' || SystemUtil::getLibcVersionIfExists() > '2.17') { + if (PHP_OS_FAMILY !== 'Linux' || GNU_ARCH !== 'aarch64') { return false; } - FileSystem::replaceFileRegex($this->source_dir . '/Makefile', '/^(LDFLAGS =.*)$/', '$1 -luv -ldl -lrt -pthread'); + FileSystem::replaceFileRegex($this->source_dir . '/Makefile', '/^(LDFLAGS =.*)$/m', '$1 -luv -ldl -lrt -pthread'); return true; } } diff --git a/src/SPC/doctor/item/LinuxToolCheckList.php b/src/SPC/doctor/item/LinuxToolCheckList.php index 56235b0cf..cd18c26fc 100644 --- a/src/SPC/doctor/item/LinuxToolCheckList.php +++ b/src/SPC/doctor/item/LinuxToolCheckList.php @@ -61,8 +61,7 @@ public function checkCliTools(): ?CheckResult $required = match ($distro['dist']) { 'alpine' => self::TOOLS_ALPINE, - 'redhat' => self::TOOLS_RHEL, - 'centos' => array_merge(self::TOOLS_RHEL, ['perl-IPC-Cmd']), + 'redhat', 'centos' => self::TOOLS_RHEL, 'arch' => self::TOOLS_ARCH, default => self::TOOLS_DEBIAN, }; From 2abbb75f98859e02b913a2cce0d828a59f9b234c Mon Sep 17 00:00:00 2001 From: DubbleClick Date: Fri, 20 Jun 2025 15:58:42 +0700 Subject: [PATCH 5/7] phpstan doesn't like GNU_ARCH there --- src/SPC/builder/extension/uv.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/SPC/builder/extension/uv.php b/src/SPC/builder/extension/uv.php index ffe92bcc7..8c54e007c 100644 --- a/src/SPC/builder/extension/uv.php +++ b/src/SPC/builder/extension/uv.php @@ -5,7 +5,6 @@ namespace SPC\builder\extension; use SPC\builder\Extension; -use SPC\builder\linux\SystemUtil; use SPC\store\FileSystem; use SPC\util\CustomExt; @@ -21,7 +20,7 @@ public function validate(): void public function patchBeforeSharedMake(): bool { - if (PHP_OS_FAMILY !== 'Linux' || GNU_ARCH !== 'aarch64') { + if (PHP_OS_FAMILY !== 'Linux' || arch2gnu(php_uname('m')) !== 'aarch64') { return false; } FileSystem::replaceFileRegex($this->source_dir . '/Makefile', '/^(LDFLAGS =.*)$/m', '$1 -luv -ldl -lrt -pthread'); From 58d979712e723d73946e78f303fc94e9e478b4fe Mon Sep 17 00:00:00 2001 From: DubbleClick Date: Fri, 20 Jun 2025 17:11:52 +0700 Subject: [PATCH 6/7] suggestion --- src/SPC/builder/Extension.php | 10 +++++++--- src/SPC/builder/extension/intl.php | 2 +- src/SPC/command/BuildPHPCommand.php | 2 -- src/SPC/store/SourcePatcher.php | 21 ++++++--------------- 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index f6e3508d2..d1d1ebb89 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -193,7 +193,7 @@ public function patchBeforeMake(): bool * If you need to patch some code, overwrite this * return true if you patched something, false if not */ - public function patchBeforeSharedBuild(): bool + public function patchBeforeSharedPhpize(): bool { return false; } @@ -394,13 +394,17 @@ public function buildUnixShared(): void 'LD_LIBRARY_PATH' => BUILD_LIB_PATH, ]; + if ($this->patchBeforeSharedPhpize()) { + logger()->info("Extension [{$this->getName()}] patched before shared phpize"); + } + // prepare configure args shell()->cd($this->source_dir) ->setEnv($env) ->exec(BUILD_BIN_PATH . '/phpize'); if ($this->patchBeforeSharedConfigure()) { - logger()->info('ext [' . $this->getName() . '] patching before shared configure'); + logger()->info("Extension [{$this->getName()}] patched before shared configure"); } shell()->cd($this->source_dir) @@ -419,7 +423,7 @@ public function buildUnixShared(): void ); if ($this->patchBeforeSharedMake()) { - logger()->info('ext [' . $this->getName() . '] patching before shared make'); + logger()->info("Extension [{$this->getName()}] patched before shared make"); } shell()->cd($this->source_dir) diff --git a/src/SPC/builder/extension/intl.php b/src/SPC/builder/extension/intl.php index 5676a4897..56ce1c617 100644 --- a/src/SPC/builder/extension/intl.php +++ b/src/SPC/builder/extension/intl.php @@ -22,7 +22,7 @@ public function patchBeforeBuildconf(): bool return true; } - public function patchBeforeSharedBuild(): bool + public function patchBeforeSharedPhpize(): bool { return $this->patchBeforeBuildconf(); } diff --git a/src/SPC/command/BuildPHPCommand.php b/src/SPC/command/BuildPHPCommand.php index 8c4c7233b..2604a7b64 100644 --- a/src/SPC/command/BuildPHPCommand.php +++ b/src/SPC/command/BuildPHPCommand.php @@ -207,8 +207,6 @@ public function handle(): int // start to build $builder->buildPHP($rule); - SourcePatcher::patchBeforeSharedBuild($builder); - // build dynamic extensions if needed if (!empty($shared_extensions)) { logger()->info('Building shared extensions ...'); diff --git a/src/SPC/store/SourcePatcher.php b/src/SPC/store/SourcePatcher.php index 113173145..1b5604c3b 100644 --- a/src/SPC/store/SourcePatcher.php +++ b/src/SPC/store/SourcePatcher.php @@ -46,12 +46,12 @@ public static function patchBeforeBuildconf(BuilderBase $builder): void { foreach ($builder->getExts() as $ext) { if ($ext->patchBeforeBuildconf() === true) { - logger()->info('Extension [' . $ext->getName() . '] patched before buildconf'); + logger()->info("Extension [{$ext->getName()}] patched before buildconf"); } } foreach ($builder->getLibs() as $lib) { if ($lib->patchBeforeBuildconf() === true) { - logger()->info('Library [' . $lib->getName() . '] patched before buildconf'); + logger()->info("Library [{$lib->getName()}]patched before buildconf"); } } // patch windows php 8.1 bug @@ -79,15 +79,6 @@ public static function patchBeforeBuildconf(BuilderBase $builder): void } } - public static function patchBeforeSharedBuild(BuilderBase $builder): void - { - foreach ($builder->getExts() as $ext) { - if ($ext->patchBeforeSharedBuild() === true) { - logger()->info('Extension [' . $ext->getName() . '] patched before shared build'); - } - } - } - /** * Source patcher runner before configure * @@ -98,12 +89,12 @@ public static function patchBeforeConfigure(BuilderBase $builder): void { foreach ($builder->getExts() as $ext) { if ($ext->patchBeforeConfigure() === true) { - logger()->info('Extension [' . $ext->getName() . '] patched before configure'); + logger()->info("Extension [{$ext->getName()}] patched before configure"); } } foreach ($builder->getLibs() as $lib) { if ($lib->patchBeforeConfigure() === true) { - logger()->info('Library [' . $lib->getName() . '] patched before configure'); + logger()->info("Library [{$lib->getName()}] patched before configure"); } } // patch capstone @@ -279,12 +270,12 @@ public static function patchBeforeMake(BuilderBase $builder): void // call extension patch before make foreach ($builder->getExts(false) as $ext) { if ($ext->patchBeforeMake() === true) { - logger()->info('Extension [' . $ext->getName() . '] patched before make'); + logger()->info("Extension [{$ext->getName()}] patched before make"); } } foreach ($builder->getLibs() as $lib) { if ($lib->patchBeforeMake() === true) { - logger()->info('Library [' . $lib->getName() . '] patched before make'); + logger()->info("Library [{$lib->getName()}] patched before make"); } } } From 9bfcea6feb6b584fa2e6af970c9d90b9c368f21a Mon Sep 17 00:00:00 2001 From: DubbleClick Date: Fri, 20 Jun 2025 17:13:01 +0700 Subject: [PATCH 7/7] tests --- src/globals/test-extensions.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/globals/test-extensions.php b/src/globals/test-extensions.php index 955d72cc5..990cbdd9f 100644 --- a/src/globals/test-extensions.php +++ b/src/globals/test-extensions.php @@ -21,19 +21,19 @@ // test os (macos-13, macos-14, macos-15, ubuntu-latest, windows-latest are available) $test_os = [ - 'macos-13', + // 'macos-13', // 'macos-14', - 'macos-15', + // 'macos-15', // 'ubuntu-latest', // 'ubuntu-22.04', // 'ubuntu-24.04', - // 'ubuntu-22.04-arm', + 'ubuntu-22.04-arm', // 'ubuntu-24.04-arm', // 'windows-latest', ]; // whether enable thread safe -$zts = false; +$zts = true; $no_strip = false; @@ -54,13 +54,13 @@ // If you want to test shared extensions, add them below (comma separated, example `bcmath,openssl`). $shared_extensions = match (PHP_OS_FAMILY) { - 'Linux' => '', + 'Linux' => 'uv', 'Darwin' => '', 'Windows' => '', }; // If you want to test lib-suggests for all extensions and libraries, set it to true. -$with_suggested_libs = true; +$with_suggested_libs = false; // If you want to test extra libs for extensions, add them below (comma separated, example `libwebp,libavif`). Unnecessary, when $with_suggested_libs is true. $with_libs = match (PHP_OS_FAMILY) {