From d3ba04fc5b18851ff2846d7dfdb4eb3982dbc98a Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 18 Sep 2025 18:16:03 +0200 Subject: [PATCH 01/36] fix grpc shared build (ignores CXXFLAGS, needs CPPFLAGS) --- config/lib.json | 1 + src/SPC/builder/Extension.php | 39 +++++++++++++++++------------- src/SPC/builder/extension/grpc.php | 6 +++++ 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/config/lib.json b/config/lib.json index 37faca3c4..096e7a429 100644 --- a/config/lib.json +++ b/config/lib.json @@ -202,6 +202,7 @@ "openssl", "libcares" ], + "cpp-library": true, "provide-pre-built": true, "frameworks": [ "CoreFoundation" diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index ac7efd1ec..41c4ae6b5 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -405,22 +405,7 @@ public function buildShared(array $visited = []): void */ public function buildUnixShared(): void { - $config = (new SPCConfigUtil($this->builder))->config( - [$this->getName()], - array_map(fn ($l) => $l->getName(), $this->getLibraryDependencies(recursive: true)), - $this->builder->getOption('with-suggested-exts'), - $this->builder->getOption('with-suggested-libs'), - ); - [$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']); - $preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group '; - $postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group '; - $env = [ - 'CFLAGS' => $config['cflags'], - 'CXXFLAGS' => $config['cflags'], - 'LDFLAGS' => $config['ldflags'], - 'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"), - 'LD_LIBRARY_PATH' => BUILD_LIB_PATH, - ]; + $env = $this->getSharedExtensionEnv(); if (str_contains($env['LIBS'], '-lstdc++') && SPCTarget::getTargetOS() === 'Linux') { if (ToolchainManager::getToolchainClass() === ZigToolchain::class) { $env['SPC_COMPILER_EXTRA'] = '-lstdc++'; @@ -512,6 +497,26 @@ public function isBuildStatic(): bool return $this->build_static; } + protected function getSharedExtensionEnv(): array + { + $config = (new SPCConfigUtil($this->builder))->config( + [$this->getName()], + array_map(fn ($l) => $l->getName(), $this->getLibraryDependencies(recursive: true)), + $this->builder->getOption('with-suggested-exts'), + $this->builder->getOption('with-suggested-libs'), + ); + [$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']); + $preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group '; + $postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group '; + return [ + 'CFLAGS' => $config['cflags'], + 'CXXFLAGS' => $config['cflags'], + 'LDFLAGS' => $config['ldflags'], + 'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"), + 'LD_LIBRARY_PATH' => BUILD_LIB_PATH, + ]; + } + protected function addLibraryDependency(string $name, bool $optional = false): void { $depLib = $this->builder->getLib($name); @@ -570,7 +575,7 @@ protected function splitLibsIntoStaticAndShared(string $allLibs): array return [trim($staticLibString), trim($sharedLibString)]; } - private function getLibraryDependencies(bool $recursive = false): array + protected function getLibraryDependencies(bool $recursive = false): array { $ret = array_filter($this->dependencies, fn ($x) => $x instanceof LibraryBase); if (!$recursive) { diff --git a/src/SPC/builder/extension/grpc.php b/src/SPC/builder/extension/grpc.php index 61af6c04d..fe13a76ad 100644 --- a/src/SPC/builder/extension/grpc.php +++ b/src/SPC/builder/extension/grpc.php @@ -56,4 +56,10 @@ public function patchBeforeMake(): bool GlobalEnvManager::putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -Wno-strict-prototypes'); return true; } + + protected function getSharedExtensionEnv(): array + { + $env = parent::getSharedExtensionEnv(); + $env['CPPFLAGS'] = $env['CXXFLAGS']; + } } From 2e6329bb867b53018a82e93620fa518b2107c278 Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 18 Sep 2025 18:16:23 +0200 Subject: [PATCH 02/36] add cpp-library for imagemagick too --- config/lib.json | 1 + 1 file changed, 1 insertion(+) diff --git a/config/lib.json b/config/lib.json index 096e7a429..392786b2a 100644 --- a/config/lib.json +++ b/config/lib.json @@ -231,6 +231,7 @@ }, "imagemagick": { "source": "imagemagick", + "cpp-library": true, "pkg-configs": [ "Magick++-7.Q16HDRI", "MagickCore-7.Q16HDRI", From d0a9a3a5943b8ea9e2df34f87e2fb4ab81d18664 Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 18 Sep 2025 18:17:48 +0200 Subject: [PATCH 03/36] fix return of array --- src/SPC/builder/extension/grpc.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SPC/builder/extension/grpc.php b/src/SPC/builder/extension/grpc.php index fe13a76ad..f2f36c164 100644 --- a/src/SPC/builder/extension/grpc.php +++ b/src/SPC/builder/extension/grpc.php @@ -61,5 +61,6 @@ protected function getSharedExtensionEnv(): array { $env = parent::getSharedExtensionEnv(); $env['CPPFLAGS'] = $env['CXXFLAGS']; + return $env; } } From b5c7185374dec2109e98941b55c25f974e36fae3 Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 18 Sep 2025 18:20:26 +0200 Subject: [PATCH 04/36] add comment for new method --- src/SPC/builder/Extension.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index 41c4ae6b5..a22f6b7aa 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -497,6 +497,10 @@ public function isBuildStatic(): bool return $this->build_static; } + /** + * Returns the environment variables a shared extension needs to be built. + * CFLAGS, CXXFLAGS, LDFLAGS and so on. + */ protected function getSharedExtensionEnv(): array { $config = (new SPCConfigUtil($this->builder))->config( From fa2e041cc954accab4027ed662cca09fd2e78e7a Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 18 Sep 2025 19:00:38 +0200 Subject: [PATCH 05/36] test shared grpc, imagick --- src/globals/test-extensions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/globals/test-extensions.php b/src/globals/test-extensions.php index 764cfc7d3..749ed3b47 100644 --- a/src/globals/test-extensions.php +++ b/src/globals/test-extensions.php @@ -26,7 +26,7 @@ 'macos-13', // bin/spc for x86_64 // 'macos-14', // bin/spc for arm64 'macos-15', // bin/spc for arm64 - 'ubuntu-latest', // bin/spc-alpine-docker for x86_64 + // 'ubuntu-latest', // bin/spc-alpine-docker for x86_64 'ubuntu-22.04', // bin/spc-gnu-docker for x86_64 // 'ubuntu-24.04', // bin/spc for x86_64 'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64 @@ -56,7 +56,7 @@ // If you want to test shared extensions, add them below (comma separated, example `bcmath,openssl`). $shared_extensions = match (PHP_OS_FAMILY) { - 'Linux' => 'zip', + 'Linux' => 'grpc,imagick', 'Darwin' => '', 'Windows' => '', }; From 40f89d1dcab6bae73c4a7520fa6d61a1166da88a Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 18 Sep 2025 19:44:48 +0200 Subject: [PATCH 06/36] is shared_libadd enough? --- src/SPC/builder/Extension.php | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index a22f6b7aa..3f8d54b80 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -5,16 +5,11 @@ namespace SPC\builder; use SPC\exception\EnvironmentException; -use SPC\exception\FileSystemException; use SPC\exception\SPCException; use SPC\exception\ValidationException; use SPC\exception\WrongUsageException; use SPC\store\Config; use SPC\store\FileSystem; -use SPC\toolchain\ClangNativeToolchain; -use SPC\toolchain\GccNativeToolchain; -use SPC\toolchain\ToolchainManager; -use SPC\toolchain\ZigToolchain; use SPC\util\SPCConfigUtil; use SPC\util\SPCTarget; @@ -226,11 +221,11 @@ public function patchBeforeSharedConfigure(): bool public function patchBeforeSharedMake(): bool { $config = (new SPCConfigUtil($this->builder))->config([$this->getName()], array_map(fn ($l) => $l->getName(), $this->builder->getLibs())); - [$staticLibs] = $this->splitLibsIntoStaticAndShared($config['libs']); + [$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']); FileSystem::replaceFileRegex( $this->source_dir . '/Makefile', '/^(.*_SHARED_LIBADD\s*=.*)$/m', - '$1 ' . trim($staticLibs) + clean_spaces("$1 {$staticLibs} {$sharedLibs}") ); if ($objs = getenv('SPC_EXTRA_RUNTIME_OBJECTS')) { FileSystem::replaceFileRegex( @@ -406,26 +401,6 @@ public function buildShared(array $visited = []): void public function buildUnixShared(): void { $env = $this->getSharedExtensionEnv(); - if (str_contains($env['LIBS'], '-lstdc++') && SPCTarget::getTargetOS() === 'Linux') { - if (ToolchainManager::getToolchainClass() === ZigToolchain::class) { - $env['SPC_COMPILER_EXTRA'] = '-lstdc++'; - } elseif (ToolchainManager::getToolchainClass() === GccNativeToolchain::class || ToolchainManager::getToolchainClass() === ClangNativeToolchain::class) { - try { - $content = FileSystem::readFile($this->source_dir . '/config.m4'); - if ($content && !str_contains($content, 'PHP_ADD_LIBRARY(stdc++')) { - $pattern = '/(PHP_NEW_EXTENSION\(' . $this->name . ',.*\))/m'; - $replacement = "$1\nPHP_ADD_LIBRARY(stdc++, 1, " . strtoupper($this->name) . '_SHARED_LIBADD)'; - FileSystem::replaceFileRegex( - $this->source_dir . '/config.m4', - $pattern, - $replacement - ); - } - } catch (FileSystemException) { - } - } - } - if ($this->patchBeforeSharedPhpize()) { logger()->info("Extension [{$this->getName()}] patched before shared phpize"); } @@ -593,12 +568,12 @@ protected function getLibraryDependencies(bool $recursive = false): array $added = 0; foreach ($ret as $depName => $dep) { foreach ($dep->getDependencies(true) as $depdepName => $depdep) { - if (!in_array($depdepName, array_keys($deps), true)) { + if (!array_key_exists($depdepName, $deps)) { $deps[$depdepName] = $depdep; ++$added; } } - if (!in_array($depName, array_keys($deps), true)) { + if (!array_key_exists($depName, $deps)) { $deps[$depName] = $dep; } } From b0538c09bf4ed384c3eea3ce033ea12537dbb1bd Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 18 Sep 2025 20:09:17 +0200 Subject: [PATCH 07/36] deduplicate those to make it more readable --- src/SPC/builder/Extension.php | 22 +++++++++++++++++----- src/globals/functions.php | 10 ++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index 3f8d54b80..410f04d8a 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -222,11 +222,23 @@ public function patchBeforeSharedMake(): bool { $config = (new SPCConfigUtil($this->builder))->config([$this->getName()], array_map(fn ($l) => $l->getName(), $this->builder->getLibs())); [$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']); - FileSystem::replaceFileRegex( - $this->source_dir . '/Makefile', - '/^(.*_SHARED_LIBADD\s*=.*)$/m', - clean_spaces("$1 {$staticLibs} {$sharedLibs}") - ); + $lstdcpp = str_contains($sharedLibs, '-lstdc++') ? '-lstdc++' : ''; + + $makefileContent = file_get_contents($this->source_dir . '/Makefile'); + + if (preg_match('/^(.*_SHARED_LIBADD\s*=\s*)(.*)$/m', $makefileContent, $matches)) { + $prefix = $matches[1]; + $currentLibs = trim($matches[2]); + $newLibs = trim("{$currentLibs} {$staticLibs} {$lstdcpp}"); + $deduplicatedLibs = deduplicate_flags($newLibs); + + FileSystem::replaceFileRegex( + $this->source_dir . '/Makefile', + '/^(.*_SHARED_LIBADD\s*=.*)$/m', + $prefix . $deduplicatedLibs + ); + } + if ($objs = getenv('SPC_EXTRA_RUNTIME_OBJECTS')) { FileSystem::replaceFileRegex( $this->source_dir . '/Makefile', diff --git a/src/globals/functions.php b/src/globals/functions.php index 711279600..c8c40b68c 100644 --- a/src/globals/functions.php +++ b/src/globals/functions.php @@ -245,6 +245,16 @@ function clean_spaces(string $string): string return trim(preg_replace('/\s+/', ' ', $string)); } +function deduplicate_flags(string $flags): string +{ + $tokens = preg_split('/\s+/', trim($flags)); + + // Reverse, unique, reverse back - keeps last occurrence of duplicates + $deduplicated = array_reverse(array_unique(array_reverse($tokens))); + + return implode(' ', $deduplicated); +} + /** * Register a callback function to handle keyboard interrupts (Ctrl+C). * From 83696e92b757837f8c5dc91f861d48a63488d755 Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 18 Sep 2025 20:12:41 +0200 Subject: [PATCH 08/36] remove whitespace --- src/SPC/builder/Extension.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index 410f04d8a..6b518b061 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -225,7 +225,6 @@ public function patchBeforeSharedMake(): bool $lstdcpp = str_contains($sharedLibs, '-lstdc++') ? '-lstdc++' : ''; $makefileContent = file_get_contents($this->source_dir . '/Makefile'); - if (preg_match('/^(.*_SHARED_LIBADD\s*=\s*)(.*)$/m', $makefileContent, $matches)) { $prefix = $matches[1]; $currentLibs = trim($matches[2]); From 81430e685377d47d7662194e58c8ec12e38d7f8a Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 18 Sep 2025 21:29:46 +0200 Subject: [PATCH 09/36] also use libstdc++.a for grpc? --- src/SPC/builder/Extension.php | 3 ++- src/SPC/builder/extension/grpc.php | 12 +++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index 6b518b061..2b8263de1 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -222,7 +222,8 @@ public function patchBeforeSharedMake(): bool { $config = (new SPCConfigUtil($this->builder))->config([$this->getName()], array_map(fn ($l) => $l->getName(), $this->builder->getLibs())); [$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']); - $lstdcpp = str_contains($sharedLibs, '-lstdc++') ? '-lstdc++' : ''; + $lstdcpp = str_contains($sharedLibs, '-l:libstdc++.a') ? '-l:libstdc++.a' : null; + $lstdcpp ??= str_contains($sharedLibs, '-lstdc++') ? '-lstdc++' : ''; $makefileContent = file_get_contents($this->source_dir . '/Makefile'); if (preg_match('/^(.*_SHARED_LIBADD\s*=\s*)(.*)$/m', $makefileContent, $matches)) { diff --git a/src/SPC/builder/extension/grpc.php b/src/SPC/builder/extension/grpc.php index f2f36c164..3833030e2 100644 --- a/src/SPC/builder/extension/grpc.php +++ b/src/SPC/builder/extension/grpc.php @@ -60,7 +60,17 @@ public function patchBeforeMake(): bool protected function getSharedExtensionEnv(): array { $env = parent::getSharedExtensionEnv(); - $env['CPPFLAGS'] = $env['CXXFLAGS']; + $env['CPPFLAGS'] = $env['CXXFLAGS'] . ' -Wno-attributes'; return $env; } + + protected function splitLibsIntoStaticAndShared(string $allLibs): array + { + [$static, $shared] = parent::splitLibsIntoStaticAndShared($allLibs); + if (str_contains(getenv('PATH'), 'rh/devtoolset') || str_contains(getenv('PATH'), 'rh/gcc-toolset')) { + $static .= ' -l:libstdc++.a'; + $shared = str_replace('-lstdc++', '', $shared); + } + return [clean_spaces($static), clean_spaces($shared)]; + } } From d0b253c3469dcc9021038bbcfe0edc7b546c3b29 Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 18 Sep 2025 21:36:38 +0200 Subject: [PATCH 10/36] not required --- src/SPC/builder/extension/grpc.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/SPC/builder/extension/grpc.php b/src/SPC/builder/extension/grpc.php index 3833030e2..7388eaffd 100644 --- a/src/SPC/builder/extension/grpc.php +++ b/src/SPC/builder/extension/grpc.php @@ -63,14 +63,4 @@ protected function getSharedExtensionEnv(): array $env['CPPFLAGS'] = $env['CXXFLAGS'] . ' -Wno-attributes'; return $env; } - - protected function splitLibsIntoStaticAndShared(string $allLibs): array - { - [$static, $shared] = parent::splitLibsIntoStaticAndShared($allLibs); - if (str_contains(getenv('PATH'), 'rh/devtoolset') || str_contains(getenv('PATH'), 'rh/gcc-toolset')) { - $static .= ' -l:libstdc++.a'; - $shared = str_replace('-lstdc++', '', $shared); - } - return [clean_spaces($static), clean_spaces($shared)]; - } } From e323d7b155cbf3689328f83b9a471ce8b571944a Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 18 Sep 2025 21:41:35 +0200 Subject: [PATCH 11/36] revert to private --- src/SPC/builder/Extension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index 2b8263de1..1ee0e4b94 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -566,7 +566,7 @@ protected function splitLibsIntoStaticAndShared(string $allLibs): array return [trim($staticLibString), trim($sharedLibString)]; } - protected function getLibraryDependencies(bool $recursive = false): array + private function getLibraryDependencies(bool $recursive = false): array { $ret = array_filter($this->dependencies, fn ($x) => $x instanceof LibraryBase); if (!$recursive) { From 927d7f55bac1b3218bc1b1e569d72731aa861b13 Mon Sep 17 00:00:00 2001 From: henderkes Date: Thu, 18 Sep 2025 22:47:01 +0200 Subject: [PATCH 12/36] make sure -ldl is not taken as needed, problem on EL8 --- src/SPC/builder/unix/library/imagemagick.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/SPC/builder/unix/library/imagemagick.php b/src/SPC/builder/unix/library/imagemagick.php index 2d3125498..2e795a0dd 100644 --- a/src/SPC/builder/unix/library/imagemagick.php +++ b/src/SPC/builder/unix/library/imagemagick.php @@ -32,7 +32,10 @@ protected function build(): void ); // special: linux-static target needs `-static` - $ldflags = SPCTarget::isStatic() ? ('-static -ldl') : '-ldl'; + $ldflags = SPCTarget::isStatic() ? '-static -ldl' : '-ldl'; + if (str_contains($this->builder->arch_ld_flags, '-Wl,--as-needed')) { + $ldflags = str_replace('-ldl', '-Wl,--no-as-needed -ldl -Wl,--as-needed', $ldflags); + } // special: macOS needs -iconv $libs = SPCTarget::getTargetOS() === 'Darwin' ? '-liconv' : ''; From 44399cd185c5b418c1fd6ff43832204382b974a4 Mon Sep 17 00:00:00 2001 From: henderkes Date: Fri, 19 Sep 2025 09:21:17 +0200 Subject: [PATCH 13/36] remove -Wl,--as-needed for imagemagick build --- src/SPC/builder/unix/library/imagemagick.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/SPC/builder/unix/library/imagemagick.php b/src/SPC/builder/unix/library/imagemagick.php index 2e795a0dd..42064e2d8 100644 --- a/src/SPC/builder/unix/library/imagemagick.php +++ b/src/SPC/builder/unix/library/imagemagick.php @@ -12,6 +12,11 @@ trait imagemagick { protected function build(): void { + $original_ldflags = $this->builder->arch_ld_flags; + if (str_contains($this->builder->arch_ld_flags, '-Wl,--as-needed')) { + $this->builder->arch_ld_flags = str_replace('-Wl,--as-needed', '', $original_ldflags); + } + $ac = UnixAutoconfExecutor::create($this) ->optionalLib('libzip', ...ac_with_args('zip')) ->optionalLib('libjpeg', ...ac_with_args('jpeg')) @@ -33,9 +38,6 @@ protected function build(): void // special: linux-static target needs `-static` $ldflags = SPCTarget::isStatic() ? '-static -ldl' : '-ldl'; - if (str_contains($this->builder->arch_ld_flags, '-Wl,--as-needed')) { - $ldflags = str_replace('-ldl', '-Wl,--no-as-needed -ldl -Wl,--as-needed', $ldflags); - } // special: macOS needs -iconv $libs = SPCTarget::getTargetOS() === 'Darwin' ? '-liconv' : ''; @@ -48,6 +50,8 @@ protected function build(): void $ac->configure()->make(); + $this->builder->arch_ld_flags = $original_ldflags; + $filelist = [ 'ImageMagick.pc', 'ImageMagick-7.Q16HDRI.pc', From dcbfe1e0abe9728af1119c7aa226c87c864a2f34 Mon Sep 17 00:00:00 2001 From: henderkes Date: Fri, 19 Sep 2025 15:29:49 +0200 Subject: [PATCH 14/36] e-dant/watcher is a c++ library too --- config/lib.json | 1 + src/SPC/builder/unix/UnixBuilderBase.php | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/lib.json b/config/lib.json index 392786b2a..5db911460 100644 --- a/config/lib.json +++ b/config/lib.json @@ -869,6 +869,7 @@ }, "watcher": { "source": "watcher", + "cpp-library": true, "static-libs-unix": [ "libwatcher-c.a" ], diff --git a/src/SPC/builder/unix/UnixBuilderBase.php b/src/SPC/builder/unix/UnixBuilderBase.php index 5942f90c2..0d123d1f0 100644 --- a/src/SPC/builder/unix/UnixBuilderBase.php +++ b/src/SPC/builder/unix/UnixBuilderBase.php @@ -291,11 +291,11 @@ protected function buildFrankenphp(): void } } $debugFlags = $this->getOption('no-strip') ? '-w -s ' : ''; - $extLdFlags = "-extldflags '-pie{$dynamic_exports}'"; + $extLdFlags = "-extldflags '-pie{$dynamic_exports} {$this->arch_ld_flags}'"; $muslTags = ''; $staticFlags = ''; if (SPCTarget::isStatic()) { - $extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000{$dynamic_exports}'"; + $extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000{$dynamic_exports} {$this->arch_ld_flags}'"; $muslTags = 'static_build,'; $staticFlags = '-static-pie'; } @@ -303,7 +303,6 @@ protected function buildFrankenphp(): void $config = (new SPCConfigUtil($this))->config($this->ext_list, $this->lib_list); $cflags = "{$this->arch_c_flags} {$config['cflags']} " . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'); $libs = $config['libs']; - $libs .= PHP_OS_FAMILY === 'Linux' ? ' -lrt' : ''; // Go's gcc driver doesn't automatically link against -lgcov or -lrt. Ugly, but necessary fix. if ((str_contains((string) getenv('SPC_DEFAULT_C_FLAGS'), '-fprofile') || str_contains((string) getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), '-fprofile')) && From fa87149631be7f1110114ded36f402de0bca7be9 Mon Sep 17 00:00:00 2001 From: henderkes Date: Sun, 21 Sep 2025 19:59:11 +0200 Subject: [PATCH 15/36] shallow submodules as well (grpc download goes from 2.9 gb to 900mb) --- src/SPC/command/DownloadCommand.php | 4 ++-- src/SPC/store/Downloader.php | 22 ++++++++++++---------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/SPC/command/DownloadCommand.php b/src/SPC/command/DownloadCommand.php index b9bae6a57..00bcc1948 100644 --- a/src/SPC/command/DownloadCommand.php +++ b/src/SPC/command/DownloadCommand.php @@ -106,7 +106,7 @@ public function handle(): int } // retry - $retry = intval($this->getOption('retry')); + $retry = (int) $this->getOption('retry'); f_putenv('SPC_DOWNLOAD_RETRIES=' . $retry); // Use shallow-clone can reduce git resource download @@ -265,7 +265,7 @@ private function downloadFromZip(string $path): int f_passthru((PHP_OS_FAMILY === 'Windows' ? 'rmdir /s /q ' : 'rm -rf ') . DOWNLOAD_PATH); } // unzip command check - if (PHP_OS_FAMILY !== 'Windows' && !$this->findCommand('unzip')) { + if (PHP_OS_FAMILY !== 'Windows' && !self::findCommand('unzip')) { $this->output->writeln('Missing unzip command, you need to install it first !'); $this->output->writeln('You can use "bin/spc doctor" command to check and install required tools'); return static::FAILURE; diff --git a/src/SPC/store/Downloader.php b/src/SPC/store/Downloader.php index d659253e9..3e50c93d2 100644 --- a/src/SPC/store/Downloader.php +++ b/src/SPC/store/Downloader.php @@ -65,19 +65,19 @@ public static function getLatestGithubTarball(string $name, array $source, strin url: "https://api.github.com/repos/{$source['repo']}/{$type}", hooks: [[CurlHook::class, 'setupGithubToken']], retries: self::getRetryAttempts() - ), true); + ), true, 512, JSON_THROW_ON_ERROR); $url = null; - for ($i = 0; $i < count($data); ++$i) { - if (($data[$i]['prerelease'] ?? false) === true && ($source['prefer-stable'] ?? false)) { + foreach ($data as $rel) { + if (($rel['prerelease'] ?? false) === true && ($source['prefer-stable'] ?? false)) { continue; } if (!($source['match'] ?? null)) { - $url = $data[$i]['tarball_url'] ?? null; + $url = $rel['tarball_url'] ?? null; break; } - if (preg_match('|' . $source['match'] . '|', $data[$i]['tarball_url'])) { - $url = $data[$i]['tarball_url']; + if (preg_match('|' . $source['match'] . '|', $rel['tarball_url'])) { + $url = $rel['tarball_url']; break; } } @@ -232,7 +232,8 @@ public static function downloadGit(string $name, string $url, string $branch, ?a $quiet = !defined('DEBUG_MODE') ? '-q --quiet' : ''; $git = SPC_GIT_EXEC; $shallow = defined('GIT_SHALLOW_CLONE') ? '--depth 1 --single-branch' : ''; - $recursive = ($submodules === null) ? '--recursive' : ''; + $recursive = ($submodules === null && defined('GIT_SHALLOW_CLONE')) ? '--recursive --shallow-submodules' : null; + $recursive ??= $submodules === null ? '--recursive' : ''; try { self::registerCancelEvent(function () use ($download_path) { @@ -243,8 +244,9 @@ public static function downloadGit(string $name, string $url, string $branch, ?a }); f_passthru("{$git} clone {$quiet} --config core.autocrlf=false --branch \"{$branch}\" {$shallow} {$recursive} \"{$url}\" \"{$download_path}\""); if ($submodules !== null) { + $depth_flag = defined('GIT_SHALLOW_CLONE') ? '--depth 1' : ''; foreach ($submodules as $submodule) { - f_passthru("cd \"{$download_path}\" && {$git} submodule update --init " . escapeshellarg($submodule)); + f_passthru("cd \"{$download_path}\" && {$git} submodule update --init {$depth_flag} " . escapeshellarg($submodule)); } } } catch (SPCException $e) { @@ -399,7 +401,7 @@ public static function downloadPackage(string $name, ?array $pkg = null, bool $f * Download source * * @param string $name source name - * @param null|array{ + * @param null|array{ * type: string, * repo: ?string, * url: ?string, @@ -414,7 +416,7 @@ public static function downloadPackage(string $name, ?array $pkg = null, bool $f * path: ?string, * text: ?string * } - * } $source source meta info: [type, path, rev, url, filename, regex, license] + * } $source source meta info: [type, path, rev, url, filename, regex, license] * @param bool $force Whether to force download (default: false) * @param int $download_as Lock source type (default: SPC_LOCK_SOURCE) */ From 35a90f27693226108547a118809f2e7648264f48 Mon Sep 17 00:00:00 2001 From: henderkes Date: Sun, 21 Sep 2025 20:32:47 +0200 Subject: [PATCH 16/36] skip -mcpu or -march=armv8-... flags because zig doesn't support them (stupid grpc build thirdparty hardcode) --- src/SPC/store/scripts/zig-cc.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/SPC/store/scripts/zig-cc.sh b/src/SPC/store/scripts/zig-cc.sh index d4090a0f3..6b340bc1d 100644 --- a/src/SPC/store/scripts/zig-cc.sh +++ b/src/SPC/store/scripts/zig-cc.sh @@ -19,9 +19,15 @@ while [[ $# -gt 0 ]]; do ARG_ABS="$(realpath "$ARG" 2>/dev/null || true)" [[ "$ARG_ABS" == "$BUILDROOT_ABS" ]] && PARSED_ARGS+=("-I$ARG") || PARSED_ARGS+=("-isystem$ARG") ;; - -march=*|-mcpu=*) # replace -march=x86-64 with -march=x86_64 + -march=*|-mcpu=*) OPT_NAME="${1%%=*}" OPT_VALUE="${1#*=}" + # Skip armv8- flags entirely as Zig doesn't support them + if [[ "$OPT_VALUE" == armv8-* ]]; then + shift + continue + fi + # replace -march=x86-64 with -march=x86_64 OPT_VALUE="${OPT_VALUE//-/_}" PARSED_ARGS+=("${OPT_NAME}=${OPT_VALUE}") shift From e02be69e403f7ffca11797fb1a06c818a4485910 Mon Sep 17 00:00:00 2001 From: henderkes Date: Sun, 21 Sep 2025 21:01:07 +0200 Subject: [PATCH 17/36] update grpc from 1.68.x to 1.75.x --- config/source.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/source.json b/config/source.json index 4a0e0fdb5..cab584604 100644 --- a/config/source.json +++ b/config/source.json @@ -324,7 +324,7 @@ }, "grpc": { "type": "git", - "rev": "v1.68.x", + "rev": "v1.75.x", "url": "https://github.com/grpc/grpc.git", "provide-pre-built": true, "license": { From fc90b4ae23dcec71382c17f108bd18af0d90077c Mon Sep 17 00:00:00 2001 From: henderkes Date: Mon, 22 Sep 2025 13:10:48 +0200 Subject: [PATCH 18/36] allow appending pkg_config_path #910 --- src/SPC/util/GlobalEnvManager.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/SPC/util/GlobalEnvManager.php b/src/SPC/util/GlobalEnvManager.php index 9f74d2df7..4ce3384dd 100644 --- a/src/SPC/util/GlobalEnvManager.php +++ b/src/SPC/util/GlobalEnvManager.php @@ -40,7 +40,12 @@ public static function init(): void if (is_unix()) { self::addPathIfNotExists(BUILD_BIN_PATH); self::addPathIfNotExists(PKG_ROOT_PATH . '/bin'); - self::putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig'); + $pkgConfigPath = getenv('PKG_CONFIG_PATH'); + if ($pkgConfigPath !== false) { + self::putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . "/pkgconfig:{$pkgConfigPath}"); + } else { + self::putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig'); + } } $ini = self::readIniFile(); From 8039ea49f9563e0d7fdf82508e09ceb38d004ab1 Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 23 Sep 2025 11:56:12 +0200 Subject: [PATCH 19/36] soap requires libxml and session --- config/ext.json | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/config/ext.json b/config/ext.json index 188aea581..68612fe8a 100644 --- a/config/ext.json +++ b/config/ext.json @@ -759,11 +759,9 @@ }, "type": "builtin", "arg-type": "custom", - "lib-depends": [ - "libxml2" - ], - "ext-depends-windows": [ - "xml" + "ext-depends": [ + "libxml", + "session" ] }, "sockets": { From 8bda4fd31efb70f1ab01c1a005feb9e808c71f32 Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 23 Sep 2025 11:59:30 +0200 Subject: [PATCH 20/36] simdjson requires +evex512 --- src/SPC/builder/extension/simdjson.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/SPC/builder/extension/simdjson.php b/src/SPC/builder/extension/simdjson.php index 71796ebee..29bf54bab 100644 --- a/src/SPC/builder/extension/simdjson.php +++ b/src/SPC/builder/extension/simdjson.php @@ -17,7 +17,7 @@ public function patchBeforeBuildconf(): bool FileSystem::replaceFileRegex( SOURCE_PATH . '/php-src/ext/simdjson/config.m4', '/php_version=(`.*`)$/m', - 'php_version=' . strval($php_ver) + 'php_version=' . $php_ver ); FileSystem::replaceFileStr( SOURCE_PATH . '/php-src/ext/simdjson/config.m4', @@ -31,4 +31,11 @@ public function patchBeforeBuildconf(): bool ); return true; } + + public function getSharedExtensionEnv(): array + { + $env = parent::getSharedExtensionEnv(); + $env['CFLAGS'] = $env['CXXFLAGS'] = $env['CFLAGS'] . ' -Xclang -target-feature -Xclang +evex512'; + return $env; + } } From 59dedbea2cb19e4704762b10f1e5e792e66344aa Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 23 Sep 2025 12:00:15 +0200 Subject: [PATCH 21/36] simdjson requires +evex512 (for zig-cc) --- src/SPC/builder/extension/simdjson.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/SPC/builder/extension/simdjson.php b/src/SPC/builder/extension/simdjson.php index 29bf54bab..939c7b5e9 100644 --- a/src/SPC/builder/extension/simdjson.php +++ b/src/SPC/builder/extension/simdjson.php @@ -6,6 +6,8 @@ use SPC\builder\Extension; use SPC\store\FileSystem; +use SPC\toolchain\ToolchainManager; +use SPC\toolchain\ZigToolchain; use SPC\util\CustomExt; #[CustomExt('simdjson')] @@ -35,7 +37,9 @@ public function patchBeforeBuildconf(): bool public function getSharedExtensionEnv(): array { $env = parent::getSharedExtensionEnv(); - $env['CFLAGS'] = $env['CXXFLAGS'] = $env['CFLAGS'] . ' -Xclang -target-feature -Xclang +evex512'; + if (ToolchainManager::getToolchainClass() === ZigToolchain::class) { + $env['CFLAGS'] = $env['CXXFLAGS'] = $env['CFLAGS'] . ' -Xclang -target-feature -Xclang +evex512'; + } return $env; } } From 93e6dcab1d1a957b1521c13a13a708ff3b170877 Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 23 Sep 2025 12:01:09 +0200 Subject: [PATCH 22/36] cflags and cxxflags separately --- src/SPC/builder/extension/simdjson.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/SPC/builder/extension/simdjson.php b/src/SPC/builder/extension/simdjson.php index 939c7b5e9..19afd0f9d 100644 --- a/src/SPC/builder/extension/simdjson.php +++ b/src/SPC/builder/extension/simdjson.php @@ -38,7 +38,8 @@ public function getSharedExtensionEnv(): array { $env = parent::getSharedExtensionEnv(); if (ToolchainManager::getToolchainClass() === ZigToolchain::class) { - $env['CFLAGS'] = $env['CXXFLAGS'] = $env['CFLAGS'] . ' -Xclang -target-feature -Xclang +evex512'; + $env['CFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512'; + $env['CXXFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512'; } return $env; } From 21149f6807c6f8ea924ab3dbe4b2d27b76ba512c Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 23 Sep 2025 12:42:29 +0200 Subject: [PATCH 23/36] simdjson needs patch --- src/SPC/builder/extension/simdjson.php | 4 ++++ src/SPC/util/SPCConfigUtil.php | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/SPC/builder/extension/simdjson.php b/src/SPC/builder/extension/simdjson.php index 19afd0f9d..914fd674f 100644 --- a/src/SPC/builder/extension/simdjson.php +++ b/src/SPC/builder/extension/simdjson.php @@ -38,6 +38,10 @@ public function getSharedExtensionEnv(): array { $env = parent::getSharedExtensionEnv(); if (ToolchainManager::getToolchainClass() === ZigToolchain::class) { + $extra = getenv('SPC_COMPILER_EXTRA'); + if (!str_contains((string) $extra, '-lstdc++')) { + f_putenv('SPC_COMPILER_EXTRA=' . clean_spaces($extra . ' -lstdc++')); + } $env['CFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512'; $env['CXXFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512'; } diff --git a/src/SPC/util/SPCConfigUtil.php b/src/SPC/util/SPCConfigUtil.php index d19cc8583..49561c5bd 100644 --- a/src/SPC/util/SPCConfigUtil.php +++ b/src/SPC/util/SPCConfigUtil.php @@ -87,7 +87,7 @@ public function config(array $extensions = [], array $libraries = [], bool $incl if (SPCTarget::getTargetOS() === 'Darwin') { $libs .= " {$this->getFrameworksString($extensions)}"; } - if ($this->builder->hasCpp()) { + if ($this->builder->hasCpp() || collect($extensions)->contains(static fn (string $ext) => Config::getExt($ext)['cpp-extension'] ?? false)) { $libcpp = SPCTarget::getTargetOS() === 'Darwin' ? '-lc++' : '-lstdc++'; $libs = str_replace($libcpp, '', $libs) . " {$libcpp}"; } From cac57dbf7985d0efd8b586ee185c1afdf149ec7f Mon Sep 17 00:00:00 2001 From: henderkes Date: Mon, 29 Sep 2025 21:15:18 +0200 Subject: [PATCH 24/36] php 8.5 has beta 3 --- src/SPC/store/source/PhpSource.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SPC/store/source/PhpSource.php b/src/SPC/store/source/PhpSource.php index c33e172f3..2a73368e5 100644 --- a/src/SPC/store/source/PhpSource.php +++ b/src/SPC/store/source/PhpSource.php @@ -16,11 +16,11 @@ public function fetch(bool $force = false, ?array $config = null, int $lock_as = { $major = defined('SPC_BUILD_PHP_VERSION') ? SPC_BUILD_PHP_VERSION : '8.4'; if ($major === '8.5') { - Downloader::downloadSource('php-src', ['type' => 'url', 'url' => 'https://downloads.php.net/~edorian/php-8.5.0beta1.tar.xz'], $force); + Downloader::downloadSource('php-src', ['type' => 'url', 'url' => 'https://downloads.php.net/~edorian/php-8.5.0beta3.tar.xz'], $force); } elseif ($major === 'git') { Downloader::downloadSource('php-src', ['type' => 'git', 'url' => 'https://github.com/php/php-src.git', 'rev' => 'master'], $force); } else { - Downloader::downloadSource('php-src', self::getLatestPHPInfo($major), $force); + Downloader::downloadSource('php-src', $this->getLatestPHPInfo($major), $force); } } From e862bacc8ab7ad2348fe2884efa7901bf30c1536 Mon Sep 17 00:00:00 2001 From: henderkes Date: Mon, 29 Sep 2025 21:15:56 +0200 Subject: [PATCH 25/36] php 8.5 has beta 3 --- src/SPC/store/source/PhpSource.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SPC/store/source/PhpSource.php b/src/SPC/store/source/PhpSource.php index 2a73368e5..377a8e1da 100644 --- a/src/SPC/store/source/PhpSource.php +++ b/src/SPC/store/source/PhpSource.php @@ -33,7 +33,7 @@ public function getLatestPHPInfo(string $major_version): array // 查找最新的小版本号 $info = json_decode(Downloader::curlExec( url: "https://www.php.net/releases/index.php?json&version={$major_version}", - retries: intval(getenv('SPC_DOWNLOAD_RETRIES') ?: 0) + retries: (int) getenv('SPC_DOWNLOAD_RETRIES') ?: 0 ), true); if (!isset($info['version'])) { throw new DownloaderException("Version {$major_version} not found."); From c2813d5736dafa02aebde204ba39725b5abb203b Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 30 Sep 2025 00:12:59 +0200 Subject: [PATCH 26/36] move hasCpp to SPCConfigUtil --- src/SPC/builder/BuilderBase.php | 21 --------------------- src/SPC/util/SPCConfigUtil.php | 27 ++++++++++++++++++++++++++- tests/SPC/builder/BuilderTest.php | 6 ------ 3 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/SPC/builder/BuilderBase.php b/src/SPC/builder/BuilderBase.php index e6e27cda9..fdba936d7 100644 --- a/src/SPC/builder/BuilderBase.php +++ b/src/SPC/builder/BuilderBase.php @@ -128,27 +128,6 @@ public function getExts(bool $including_shared = true): array return array_filter($this->exts, fn ($ext) => $ext->isBuildStatic()); } - /** - * Check if there is a cpp extensions or libraries. - */ - public function hasCpp(): bool - { - // judge cpp-extension - $exts = array_keys($this->getExts(false)); - foreach ($exts as $ext) { - if (Config::getExt($ext, 'cpp-extension', false) === true) { - return true; - } - } - $libs = array_keys($this->getLibs()); - foreach ($libs as $lib) { - if (Config::getLib($lib, 'cpp-library', false) === true) { - return true; - } - } - return false; - } - /** * Set libs only mode. * diff --git a/src/SPC/util/SPCConfigUtil.php b/src/SPC/util/SPCConfigUtil.php index 49561c5bd..edbb9926f 100644 --- a/src/SPC/util/SPCConfigUtil.php +++ b/src/SPC/util/SPCConfigUtil.php @@ -6,6 +6,8 @@ use SPC\builder\BuilderBase; use SPC\builder\BuilderProvider; +use SPC\builder\Extension; +use SPC\builder\LibraryBase; use SPC\exception\WrongUsageException; use SPC\store\Config; use Symfony\Component\Console\Input\ArgvInput; @@ -87,7 +89,7 @@ public function config(array $extensions = [], array $libraries = [], bool $incl if (SPCTarget::getTargetOS() === 'Darwin') { $libs .= " {$this->getFrameworksString($extensions)}"; } - if ($this->builder->hasCpp() || collect($extensions)->contains(static fn (string $ext) => Config::getExt($ext)['cpp-extension'] ?? false)) { + if ($this->hasCpp($extensions, $libraries)) { $libcpp = SPCTarget::getTargetOS() === 'Darwin' ? '-lc++' : '-lstdc++'; $libs = str_replace($libcpp, '', $libs) . " {$libcpp}"; } @@ -123,6 +125,29 @@ public function config(array $extensions = [], array $libraries = [], bool $incl ]; } + private function hasCpp(array $extensions, array $libraries): bool + { + // judge cpp-extension + $builderExtNames = array_keys($this->builder->getExts(false)); + $extNames = array_map(fn (Extension $x) => $x->getName(), $extensions); + $exts = array_unique([...$builderExtNames, ...$extNames]); + + foreach ($exts as $ext) { + if (Config::getExt($ext, 'cpp-extension', false) === true) { + return true; + } + } + $builderLibNames = array_keys($this->builder->getLibs()); + $libNames = array_map(fn (LibraryBase $x) => $x->getName(), $libraries); + $libs = array_unique([...$builderLibNames, ...$libNames]); + foreach ($libs as $lib) { + if (Config::getLib($lib, 'cpp-library', false) === true) { + return true; + } + } + return false; + } + private function getIncludesString(array $libraries): string { $base = BUILD_INCLUDE_PATH; diff --git a/tests/SPC/builder/BuilderTest.php b/tests/SPC/builder/BuilderTest.php index d28bd4d33..b4b6258fd 100644 --- a/tests/SPC/builder/BuilderTest.php +++ b/tests/SPC/builder/BuilderTest.php @@ -62,12 +62,6 @@ public function testGetExtAndGetExts() $this->assertInstanceOf(Extension::class, $this->builder->getExt('mbregex')); } - public function testHasCpp() - { - // mbregex doesn't have cpp - $this->assertFalse($this->builder->hasCpp()); - } - public function testMakeExtensionArgs() { $this->assertStringContainsString('--enable-mbstring', $this->builder->makeStaticExtensionArgs()); From fe09d8c03ec8d895dd8eaa1bbdad52875996b1aa Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 30 Sep 2025 00:17:17 +0200 Subject: [PATCH 27/36] add docstring --- src/globals/functions.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/globals/functions.php b/src/globals/functions.php index c8c40b68c..8127548b8 100644 --- a/src/globals/functions.php +++ b/src/globals/functions.php @@ -245,6 +245,13 @@ function clean_spaces(string $string): string return trim(preg_replace('/\s+/', ' ', $string)); } +/** + * Deduplicate flags in a string. + * + * @param string $flags The string containing flags to deduplicate. Only the last occurence of each flag will be kept. + * E.g. `-lintl -lstdc++ -lphp -lstdc++` becomes `-lintl -lphp -lstdc++` + * @return string the deduplicated string with no duplicate flags + */ function deduplicate_flags(string $flags): string { $tokens = preg_split('/\s+/', trim($flags)); From b0b031afb26147449870fc7cef219870e574eaf7 Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 30 Sep 2025 00:17:17 +0200 Subject: [PATCH 28/36] add docstring --- src/globals/functions.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/globals/functions.php b/src/globals/functions.php index 8127548b8..da2d177f5 100644 --- a/src/globals/functions.php +++ b/src/globals/functions.php @@ -246,10 +246,10 @@ function clean_spaces(string $string): string } /** - * Deduplicate flags in a string. + * Deduplicate flags in a string. Only the last occurence of each flag will be kept. + * E.g. `-lintl -lstdc++ -lphp -lstdc++` becomes `-lintl -lphp -lstdc++` * - * @param string $flags The string containing flags to deduplicate. Only the last occurence of each flag will be kept. - * E.g. `-lintl -lstdc++ -lphp -lstdc++` becomes `-lintl -lphp -lstdc++` + * @param string $flags the string containing flags to deduplicate * @return string the deduplicated string with no duplicate flags */ function deduplicate_flags(string $flags): string From 5b6c923eefca3db68bb2bbe8e7d4ee375373002f Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 30 Sep 2025 00:31:20 +0200 Subject: [PATCH 29/36] snappy is a c++ lib --- config/lib.json | 1 + 1 file changed, 1 insertion(+) diff --git a/config/lib.json b/config/lib.json index 5db911460..ac2c5705e 100644 --- a/config/lib.json +++ b/config/lib.json @@ -824,6 +824,7 @@ }, "snappy": { "source": "snappy", + "cpp-library": true, "static-libs-unix": [ "libsnappy.a" ], From f7744188f4d021b9d36dab840f6d499023221357 Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 30 Sep 2025 00:34:30 +0200 Subject: [PATCH 30/36] fix configutil --- src/SPC/util/SPCConfigUtil.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/SPC/util/SPCConfigUtil.php b/src/SPC/util/SPCConfigUtil.php index edbb9926f..f321ca102 100644 --- a/src/SPC/util/SPCConfigUtil.php +++ b/src/SPC/util/SPCConfigUtil.php @@ -7,7 +7,6 @@ use SPC\builder\BuilderBase; use SPC\builder\BuilderProvider; use SPC\builder\Extension; -use SPC\builder\LibraryBase; use SPC\exception\WrongUsageException; use SPC\store\Config; use Symfony\Component\Console\Input\ArgvInput; @@ -129,8 +128,7 @@ private function hasCpp(array $extensions, array $libraries): bool { // judge cpp-extension $builderExtNames = array_keys($this->builder->getExts(false)); - $extNames = array_map(fn (Extension $x) => $x->getName(), $extensions); - $exts = array_unique([...$builderExtNames, ...$extNames]); + $exts = array_unique([...$builderExtNames, ...$extensions]); foreach ($exts as $ext) { if (Config::getExt($ext, 'cpp-extension', false) === true) { @@ -138,8 +136,7 @@ private function hasCpp(array $extensions, array $libraries): bool } } $builderLibNames = array_keys($this->builder->getLibs()); - $libNames = array_map(fn (LibraryBase $x) => $x->getName(), $libraries); - $libs = array_unique([...$builderLibNames, ...$libNames]); + $libs = array_unique([...$builderLibNames, ...$libraries]); foreach ($libs as $lib) { if (Config::getLib($lib, 'cpp-library', false) === true) { return true; From 2d1a61d18439d73a3d8961a3b98d2a8660caed29 Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 30 Sep 2025 14:00:13 +0200 Subject: [PATCH 31/36] explicitly disable avx512 if zig and march not high enough --- src/SPC/builder/Extension.php | 9 ++++++++- src/SPC/builder/extension/simdjson.php | 16 ---------------- src/SPC/builder/linux/LinuxBuilder.php | 8 ++++++++ 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index 1ee0e4b94..cb5901673 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -10,6 +10,8 @@ use SPC\exception\WrongUsageException; use SPC\store\Config; use SPC\store\FileSystem; +use SPC\toolchain\ToolchainManager; +use SPC\toolchain\ZigToolchain; use SPC\util\SPCConfigUtil; use SPC\util\SPCTarget; @@ -427,13 +429,18 @@ public function buildUnixShared(): void logger()->info("Extension [{$this->getName()}] patched before shared configure"); } + $has_avx512 = str_contains($this->builder->arch_c_flags ?? '', '-mavx512') || + str_contains($this->builder->arch_c_flags ?? '', '-march=x86-64-v3') || + str_contains($this->arch_c_flags ?? '', '-march=x86-64-v4') || + ToolchainManager::getToolchainClass() !== ZigToolchain::class; + shell()->cd($this->source_dir) ->setEnv($env) ->appendEnv($this->getExtraEnv()) ->exec( './configure ' . $this->getUnixConfigureArg(true) . ' --with-php-config=' . BUILD_BIN_PATH . '/php-config ' . - '--enable-shared --disable-static' + '--enable-shared --disable-static' . (!$has_avx512 ? ' php_cv_have_avx512=no ' : '') ); if ($this->patchBeforeSharedMake()) { diff --git a/src/SPC/builder/extension/simdjson.php b/src/SPC/builder/extension/simdjson.php index 914fd674f..1be99eb94 100644 --- a/src/SPC/builder/extension/simdjson.php +++ b/src/SPC/builder/extension/simdjson.php @@ -6,8 +6,6 @@ use SPC\builder\Extension; use SPC\store\FileSystem; -use SPC\toolchain\ToolchainManager; -use SPC\toolchain\ZigToolchain; use SPC\util\CustomExt; #[CustomExt('simdjson')] @@ -33,18 +31,4 @@ public function patchBeforeBuildconf(): bool ); return true; } - - public function getSharedExtensionEnv(): array - { - $env = parent::getSharedExtensionEnv(); - if (ToolchainManager::getToolchainClass() === ZigToolchain::class) { - $extra = getenv('SPC_COMPILER_EXTRA'); - if (!str_contains((string) $extra, '-lstdc++')) { - f_putenv('SPC_COMPILER_EXTRA=' . clean_spaces($extra . ' -lstdc++')); - } - $env['CFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512'; - $env['CXXFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512'; - } - return $env; - } } diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index b1b1ffc57..0eaf86a94 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -9,6 +9,8 @@ use SPC\exception\WrongUsageException; use SPC\store\FileSystem; use SPC\store\SourcePatcher; +use SPC\toolchain\ToolchainManager; +use SPC\toolchain\ZigToolchain; use SPC\util\GlobalEnvManager; use SPC\util\SPCConfigUtil; use SPC\util\SPCTarget; @@ -103,6 +105,11 @@ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void ); } + $has_avx512 = str_contains($this->arch_c_flags, '-mavx512') || + str_contains($this->arch_c_flags, '-march=x86-64-v3') || + str_contains($this->arch_c_flags, '-march=x86-64-v4') || + ToolchainManager::getToolchainClass() !== ZigToolchain::class; + $this->seekPhpSrcLogFileOnException(fn () => shell()->cd(SOURCE_PATH . '/php-src')->exec( $php_configure_env . ' ' . getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' . @@ -116,6 +123,7 @@ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void $json_74 . $zts . $maxExecutionTimers . + (!$has_avx512 ? 'php_cv_have_avx512=no ' : '') . $this->makeStaticExtensionArgs() . ' ' )); From c5316f92315e8a9a6e521b22c3c6d2f8d6b6efb2 Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 30 Sep 2025 14:21:31 +0200 Subject: [PATCH 32/36] -v3 doesn't have avx512 yet --- src/SPC/builder/Extension.php | 3 +-- src/SPC/builder/linux/LinuxBuilder.php | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index cb5901673..0570159fc 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -430,7 +430,6 @@ public function buildUnixShared(): void } $has_avx512 = str_contains($this->builder->arch_c_flags ?? '', '-mavx512') || - str_contains($this->builder->arch_c_flags ?? '', '-march=x86-64-v3') || str_contains($this->arch_c_flags ?? '', '-march=x86-64-v4') || ToolchainManager::getToolchainClass() !== ZigToolchain::class; @@ -440,7 +439,7 @@ public function buildUnixShared(): void ->exec( './configure ' . $this->getUnixConfigureArg(true) . ' --with-php-config=' . BUILD_BIN_PATH . '/php-config ' . - '--enable-shared --disable-static' . (!$has_avx512 ? ' php_cv_have_avx512=no ' : '') + '--enable-shared --disable-static' . (!$has_avx512 ? ' php_cv_have_avx512=no php_cv_have_avx512vbmi=no' : '') ); if ($this->patchBeforeSharedMake()) { diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index 0eaf86a94..d9e0b8051 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -106,7 +106,6 @@ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void } $has_avx512 = str_contains($this->arch_c_flags, '-mavx512') || - str_contains($this->arch_c_flags, '-march=x86-64-v3') || str_contains($this->arch_c_flags, '-march=x86-64-v4') || ToolchainManager::getToolchainClass() !== ZigToolchain::class; @@ -123,7 +122,7 @@ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void $json_74 . $zts . $maxExecutionTimers . - (!$has_avx512 ? 'php_cv_have_avx512=no ' : '') . + (!$has_avx512 ? 'php_cv_have_avx512=no php_cv_have_avx512vbmi ' : '') . $this->makeStaticExtensionArgs() . ' ' )); From 044275d90927479c82f670bb7e54d27fcfbf8457 Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 30 Sep 2025 14:22:38 +0200 Subject: [PATCH 33/36] typo --- src/SPC/builder/linux/LinuxBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index d9e0b8051..6a543ec14 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -122,7 +122,7 @@ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void $json_74 . $zts . $maxExecutionTimers . - (!$has_avx512 ? 'php_cv_have_avx512=no php_cv_have_avx512vbmi ' : '') . + (!$has_avx512 ? 'php_cv_have_avx512=no php_cv_have_avx512vbmi=no ' : '') . $this->makeStaticExtensionArgs() . ' ' )); From 31a4498056434aec4db07bed635adb00c876f031 Mon Sep 17 00:00:00 2001 From: henderkes Date: Tue, 30 Sep 2025 15:07:22 +0200 Subject: [PATCH 34/36] bring back simdjson tests, extension headers do not properly guard for avx512 symbols --- src/SPC/builder/extension/simdjson.php | 16 ++++++++++++++++ src/globals/test-extensions.php | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/SPC/builder/extension/simdjson.php b/src/SPC/builder/extension/simdjson.php index 1be99eb94..914fd674f 100644 --- a/src/SPC/builder/extension/simdjson.php +++ b/src/SPC/builder/extension/simdjson.php @@ -6,6 +6,8 @@ use SPC\builder\Extension; use SPC\store\FileSystem; +use SPC\toolchain\ToolchainManager; +use SPC\toolchain\ZigToolchain; use SPC\util\CustomExt; #[CustomExt('simdjson')] @@ -31,4 +33,18 @@ public function patchBeforeBuildconf(): bool ); return true; } + + public function getSharedExtensionEnv(): array + { + $env = parent::getSharedExtensionEnv(); + if (ToolchainManager::getToolchainClass() === ZigToolchain::class) { + $extra = getenv('SPC_COMPILER_EXTRA'); + if (!str_contains((string) $extra, '-lstdc++')) { + f_putenv('SPC_COMPILER_EXTRA=' . clean_spaces($extra . ' -lstdc++')); + } + $env['CFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512'; + $env['CXXFLAGS'] .= ' -Xclang -target-feature -Xclang +evex512'; + } + return $env; + } } diff --git a/src/globals/test-extensions.php b/src/globals/test-extensions.php index 749ed3b47..954cb4743 100644 --- a/src/globals/test-extensions.php +++ b/src/globals/test-extensions.php @@ -23,8 +23,8 @@ // test os (macos-13, macos-14, macos-15, ubuntu-latest, windows-latest are available) $test_os = [ - 'macos-13', // bin/spc for x86_64 - // 'macos-14', // bin/spc for arm64 + // 'macos-13', // bin/spc for x86_64 + 'macos-14', // bin/spc for arm64 'macos-15', // bin/spc for arm64 // 'ubuntu-latest', // bin/spc-alpine-docker for x86_64 'ubuntu-22.04', // bin/spc-gnu-docker for x86_64 From 018dfae15e16d691ed22bf418d0d18d9c0dd196e Mon Sep 17 00:00:00 2001 From: henderkes Date: Sat, 11 Oct 2025 10:38:51 +0200 Subject: [PATCH 35/36] suggestions --- src/SPC/builder/Extension.php | 8 +------- src/SPC/builder/linux/LinuxBuilder.php | 8 +------- src/SPC/toolchain/ZigToolchain.php | 5 +++++ 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index 0570159fc..9e36aeff5 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -10,8 +10,6 @@ use SPC\exception\WrongUsageException; use SPC\store\Config; use SPC\store\FileSystem; -use SPC\toolchain\ToolchainManager; -use SPC\toolchain\ZigToolchain; use SPC\util\SPCConfigUtil; use SPC\util\SPCTarget; @@ -429,17 +427,13 @@ public function buildUnixShared(): void logger()->info("Extension [{$this->getName()}] patched before shared configure"); } - $has_avx512 = str_contains($this->builder->arch_c_flags ?? '', '-mavx512') || - str_contains($this->arch_c_flags ?? '', '-march=x86-64-v4') || - ToolchainManager::getToolchainClass() !== ZigToolchain::class; - shell()->cd($this->source_dir) ->setEnv($env) ->appendEnv($this->getExtraEnv()) ->exec( './configure ' . $this->getUnixConfigureArg(true) . ' --with-php-config=' . BUILD_BIN_PATH . '/php-config ' . - '--enable-shared --disable-static' . (!$has_avx512 ? ' php_cv_have_avx512=no php_cv_have_avx512vbmi=no' : '') + '--enable-shared --disable-static ' . getenv('SPC_EXTRA_PHP_VARS') ); if ($this->patchBeforeSharedMake()) { diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index 6a543ec14..2a3c89123 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -9,8 +9,6 @@ use SPC\exception\WrongUsageException; use SPC\store\FileSystem; use SPC\store\SourcePatcher; -use SPC\toolchain\ToolchainManager; -use SPC\toolchain\ZigToolchain; use SPC\util\GlobalEnvManager; use SPC\util\SPCConfigUtil; use SPC\util\SPCTarget; @@ -105,10 +103,6 @@ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void ); } - $has_avx512 = str_contains($this->arch_c_flags, '-mavx512') || - str_contains($this->arch_c_flags, '-march=x86-64-v4') || - ToolchainManager::getToolchainClass() !== ZigToolchain::class; - $this->seekPhpSrcLogFileOnException(fn () => shell()->cd(SOURCE_PATH . '/php-src')->exec( $php_configure_env . ' ' . getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' . @@ -122,7 +116,7 @@ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void $json_74 . $zts . $maxExecutionTimers . - (!$has_avx512 ? 'php_cv_have_avx512=no php_cv_have_avx512vbmi=no ' : '') . + getenv('SPC_EXTRA_PHP_VARS') . ' ' . $this->makeStaticExtensionArgs() . ' ' )); diff --git a/src/SPC/toolchain/ZigToolchain.php b/src/SPC/toolchain/ZigToolchain.php index 8f2e261e9..c3da766d8 100644 --- a/src/SPC/toolchain/ZigToolchain.php +++ b/src/SPC/toolchain/ZigToolchain.php @@ -64,6 +64,11 @@ public function afterInit(): void $extra_libs = trim($extra_libs . ' -lunwind'); GlobalEnvManager::putenv("SPC_EXTRA_LIBS={$extra_libs}"); } + $cflags = getenv('SPC_DEFAULT_C_FLAGS') ?: getenv('CFLAGS') ?: ''; + $has_avx512 = str_contains($cflags, '-mavx512') || str_contains($cflags, '-march=x86-64-v4'); + if (!$has_avx512) { + f_putenv('SPC_EXTRA_PHP_VARS=php_cv_have_avx512=no php_cv_have_avx512vbmi=no'); + } } public function getCompilerInfo(): ?string From 897cb003511880c7d05c444e8d369f50dd0684be Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Sun, 12 Oct 2025 16:42:38 +0800 Subject: [PATCH 36/36] Use failsafe for SPC_EXTRA_PHP_VARS --- config/env.ini | 1 + src/SPC/builder/Extension.php | 4 +++- src/SPC/builder/linux/LinuxBuilder.php | 4 +++- src/SPC/toolchain/ZigToolchain.php | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/config/env.ini b/config/env.ini index 4b9f294ad..0fbcd6934 100644 --- a/config/env.ini +++ b/config/env.ini @@ -34,6 +34,7 @@ ; SPC_LINUX_DEFAULT_CC: the default compiler for linux. (For alpine linux: `gcc`, default: `$GNU_ARCH-linux-musl-gcc`) ; SPC_LINUX_DEFAULT_CXX: the default c++ compiler for linux. (For alpine linux: `g++`, default: `$GNU_ARCH-linux-musl-g++`) ; SPC_LINUX_DEFAULT_AR: the default archiver for linux. (For alpine linux: `ar`, default: `$GNU_ARCH-linux-musl-ar`) +; SPC_EXTRA_PHP_VARS: the extra vars for building php, used in `configure` and `make` command. [global] ; Build concurrency for make -jN, default is CPU_COUNT, this value are used in every libs. diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index 9e36aeff5..a8e875191 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -427,13 +427,15 @@ public function buildUnixShared(): void logger()->info("Extension [{$this->getName()}] patched before shared configure"); } + $phpvars = getenv('SPC_EXTRA_PHP_VARS') ?: ''; + shell()->cd($this->source_dir) ->setEnv($env) ->appendEnv($this->getExtraEnv()) ->exec( './configure ' . $this->getUnixConfigureArg(true) . ' --with-php-config=' . BUILD_BIN_PATH . '/php-config ' . - '--enable-shared --disable-static ' . getenv('SPC_EXTRA_PHP_VARS') + "--enable-shared --disable-static {$phpvars}" ); if ($this->patchBeforeSharedMake()) { diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index 2a3c89123..d62e97bd4 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -95,6 +95,8 @@ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void // 'LIBS' => SPCTarget::getRuntimeLibs(), // do not pass static libraries here yet, they may contain polyfills for libc functions! ]); + $phpvars = getenv('SPC_EXTRA_PHP_VARS') ?: ''; + $embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static'; if ($embed_type !== 'static' && SPCTarget::isStatic()) { throw new WrongUsageException( @@ -116,7 +118,7 @@ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void $json_74 . $zts . $maxExecutionTimers . - getenv('SPC_EXTRA_PHP_VARS') . ' ' . + "{$phpvars} " . $this->makeStaticExtensionArgs() . ' ' )); diff --git a/src/SPC/toolchain/ZigToolchain.php b/src/SPC/toolchain/ZigToolchain.php index c3da766d8..bb423db20 100644 --- a/src/SPC/toolchain/ZigToolchain.php +++ b/src/SPC/toolchain/ZigToolchain.php @@ -67,7 +67,7 @@ public function afterInit(): void $cflags = getenv('SPC_DEFAULT_C_FLAGS') ?: getenv('CFLAGS') ?: ''; $has_avx512 = str_contains($cflags, '-mavx512') || str_contains($cflags, '-march=x86-64-v4'); if (!$has_avx512) { - f_putenv('SPC_EXTRA_PHP_VARS=php_cv_have_avx512=no php_cv_have_avx512vbmi=no'); + GlobalEnvManager::putenv('SPC_EXTRA_PHP_VARS=php_cv_have_avx512=no php_cv_have_avx512vbmi=no'); } }