From f09c18e78f694a0a0653effbe5a59a6364426591 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Thu, 6 Nov 2025 16:24:59 +0800 Subject: [PATCH] Use separated deploy functions --- src/SPC/builder/Extension.php | 7 + src/SPC/builder/freebsd/BSDBuilder.php | 6 +- src/SPC/builder/linux/LinuxBuilder.php | 95 ++++++++++---- src/SPC/builder/macos/MacOSBuilder.php | 8 +- src/SPC/builder/unix/UnixBuilderBase.php | 143 ++++++++++++--------- src/SPC/builder/windows/WindowsBuilder.php | 49 +++++-- src/globals/test-extensions.php | 8 +- 7 files changed, 201 insertions(+), 115 deletions(-) diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index c9cd0657..32153764 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -448,6 +448,13 @@ class Extension ->exec('make clean') ->exec('make -j' . $this->builder->concurrency) ->exec('make install'); + + // process *.so file + $soFile = BUILD_MODULES_PATH . '/' . $this->getName() . '.so'; + if (!file_exists($soFile)) { + throw new ValidationException("extension {$this->getName()} build failed: {$soFile} not found", validation_module: "Extension {$this->getName()} build"); + } + $this->builder->deployBinary($soFile, $soFile, false); } /** diff --git a/src/SPC/builder/freebsd/BSDBuilder.php b/src/SPC/builder/freebsd/BSDBuilder.php index 0c1d1ee4..b746dff5 100644 --- a/src/SPC/builder/freebsd/BSDBuilder.php +++ b/src/SPC/builder/freebsd/BSDBuilder.php @@ -153,7 +153,7 @@ class BSDBuilder extends UnixBuilderBase if (!$this->getOption('no-strip', false)) { $shell->exec('strip sapi/cli/php'); } - $this->deployBinary(BUILD_TARGET_CLI); + $this->deploySAPIBinary(BUILD_TARGET_CLI); } /** @@ -184,7 +184,7 @@ class BSDBuilder extends UnixBuilderBase if (!$this->getOption('no-strip', false)) { shell()->cd(SOURCE_PATH . '/php-src/sapi/micro')->exec('strip --strip-unneeded micro.sfx'); } - $this->deployBinary(BUILD_TARGET_MICRO); + $this->deploySAPIBinary(BUILD_TARGET_MICRO); if ($this->phar_patched) { SourcePatcher::unpatchMicroPhar(); @@ -206,7 +206,7 @@ class BSDBuilder extends UnixBuilderBase if (!$this->getOption('no-strip', false)) { $shell->exec('strip sapi/fpm/php-fpm'); } - $this->deployBinary(BUILD_TARGET_FPM); + $this->deploySAPIBinary(BUILD_TARGET_FPM); } /** diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index 5ffa6a4d..3f5d3b3c 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace SPC\builder\linux; use SPC\builder\unix\UnixBuilderBase; +use SPC\exception\PatchException; use SPC\exception\WrongUsageException; use SPC\store\Config; use SPC\store\FileSystem; @@ -193,7 +194,7 @@ class LinuxBuilder extends UnixBuilderBase SourcePatcher::patchFile('musl_static_readline.patch', SOURCE_PATH . '/php-src', true); } - $this->deployBinary(BUILD_TARGET_CLI); + $this->deploySAPIBinary(BUILD_TARGET_CLI); } protected function buildCgi(): void @@ -204,7 +205,7 @@ class LinuxBuilder extends UnixBuilderBase ->exec('sed -i "s|//lib|/lib|g" Makefile') ->exec("make {$concurrency} {$vars} cgi"); - $this->deployBinary(BUILD_TARGET_CGI); + $this->deploySAPIBinary(BUILD_TARGET_CGI); } /** @@ -233,7 +234,11 @@ class LinuxBuilder extends UnixBuilderBase ->exec('sed -i "s|//lib|/lib|g" Makefile') ->exec("make {$concurrency} {$vars} micro"); - $this->deployBinary(BUILD_TARGET_MICRO); + // deploy micro.sfx + $dst = $this->deploySAPIBinary(BUILD_TARGET_MICRO); + + // patch after UPX-ed micro.sfx + $this->processUpxedMicroSfx($dst); } finally { if ($this->phar_patched) { SourcePatcher::unpatchMicroPhar(); @@ -252,7 +257,7 @@ class LinuxBuilder extends UnixBuilderBase ->exec('sed -i "s|//lib|/lib|g" Makefile') ->exec("make {$concurrency} {$vars} fpm"); - $this->deployBinary(BUILD_TARGET_FPM); + $this->deploySAPIBinary(BUILD_TARGET_FPM); } /** @@ -272,10 +277,48 @@ class LinuxBuilder extends UnixBuilderBase ->exec('sed -i "s|^EXTENSION_DIR = .*|EXTENSION_DIR = /' . basename(BUILD_MODULES_PATH) . '|" Makefile') ->exec("make {$concurrency} INSTALL_ROOT=" . BUILD_ROOT_PATH . " {$vars} install-sapi {$install_modules} install-build install-headers install-programs"); + // process libphp.so for shared embed + $libphpSo = BUILD_LIB_PATH . '/libphp.so'; + if (file_exists($libphpSo)) { + // deploy libphp.so + $this->deployBinary($libphpSo, $libphpSo, false); + // post actions: rename libphp.so to libphp-.so if -release is set in LDFLAGS + $this->processLibphpSoFile($libphpSo); + } + + // process libphp.a for static embed + if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'static') { + $AR = getenv('AR') ?: 'ar'; + f_passthru("{$AR} -t " . BUILD_LIB_PATH . "/libphp.a | grep '\\.a$' | xargs -n1 {$AR} d " . BUILD_LIB_PATH . '/libphp.a'); + // export dynamic symbols + SystemUtil::exportDynamicSymbols(BUILD_LIB_PATH . '/libphp.a'); + } + + // patch embed php scripts + $this->patchPhpScripts(); + } + + /** + * Return extra variables for php make command. + */ + private function getMakeExtraVars(): array + { + $config = (new SPCConfigUtil($this, ['libs_only_deps' => true, 'absolute_libs' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs')); + $static = SPCTarget::isStatic() ? '-all-static' : ''; + $lib = BUILD_LIB_PATH; + return array_filter([ + 'EXTRA_CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), + 'EXTRA_LIBS' => $config['libs'], + 'EXTRA_LDFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'), + 'EXTRA_LDFLAGS_PROGRAM' => "-L{$lib} {$static} -pie", + ]); + } + + private function processLibphpSoFile(string $libphpSo): void + { $ldflags = getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS') ?: ''; $libDir = BUILD_LIB_PATH; $modulesDir = BUILD_MODULES_PATH; - $libphpSo = "{$libDir}/libphp.so"; $realLibName = 'libphp.so'; $cwd = getcwd(); @@ -337,33 +380,29 @@ class LinuxBuilder extends UnixBuilderBase } } } - - if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'static') { - $AR = getenv('AR') ?: 'ar'; - f_passthru("{$AR} -t " . BUILD_LIB_PATH . "/libphp.a | grep '\\.a$' | xargs -n1 {$AR} d " . BUILD_LIB_PATH . '/libphp.a'); - // export dynamic symbols - SystemUtil::exportDynamicSymbols(BUILD_LIB_PATH . '/libphp.a'); - } - - if (!$this->getOption('no-strip', false) && file_exists(BUILD_LIB_PATH . '/' . $realLibName)) { - shell()->cd(BUILD_LIB_PATH)->exec("strip --strip-unneeded {$realLibName}"); - } - $this->patchPhpScripts(); } /** - * Return extra variables for php make command. + * Patch micro.sfx after UPX compression. + * micro needs special section handling in LinuxBuilder. + * The micro.sfx does not support UPX directly, but we can remove UPX + * info segment to adapt. + * This will also make micro.sfx with upx-packed more like a malware fore antivirus */ - private function getMakeExtraVars(): array + private function processUpxedMicroSfx(string $dst): void { - $config = (new SPCConfigUtil($this, ['libs_only_deps' => true, 'absolute_libs' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs')); - $static = SPCTarget::isStatic() ? '-all-static' : ''; - $lib = BUILD_LIB_PATH; - return array_filter([ - 'EXTRA_CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), - 'EXTRA_LIBS' => $config['libs'], - 'EXTRA_LDFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'), - 'EXTRA_LDFLAGS_PROGRAM' => "-L{$lib} {$static} -pie", - ]); + if ($this->getOption('with-upx-pack') && version_compare($this->getMicroVersion(), '0.2.0') >= 0) { + // strip first + // cut binary with readelf + [$ret, $out] = shell()->execWithResult("readelf -l {$dst} | awk '/LOAD|GNU_STACK/ {getline; print \$1, \$2, \$3, \$4, \$6, \$7}'"); + $out[1] = explode(' ', $out[1]); + $offset = $out[1][0]; + if ($ret !== 0 || !str_starts_with($offset, '0x')) { + throw new PatchException('phpmicro UPX patcher', 'Cannot find offset in readelf output'); + } + $offset = hexdec($offset); + // remove upx extra wastes + file_put_contents($dst, substr(file_get_contents($dst), 0, $offset)); + } } } diff --git a/src/SPC/builder/macos/MacOSBuilder.php b/src/SPC/builder/macos/MacOSBuilder.php index d3bc5d19..204a712d 100644 --- a/src/SPC/builder/macos/MacOSBuilder.php +++ b/src/SPC/builder/macos/MacOSBuilder.php @@ -189,7 +189,7 @@ class MacOSBuilder extends UnixBuilderBase $shell = shell()->cd(SOURCE_PATH . '/php-src'); $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; $shell->exec("make {$concurrency} {$vars} cli"); - $this->deployBinary(BUILD_TARGET_CLI); + $this->deploySAPIBinary(BUILD_TARGET_CLI); } protected function buildCgi(): void @@ -199,7 +199,7 @@ class MacOSBuilder extends UnixBuilderBase $shell = shell()->cd(SOURCE_PATH . '/php-src'); $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; $shell->exec("make {$concurrency} {$vars} cgi"); - $this->deployBinary(BUILD_TARGET_CGI); + $this->deploySAPIBinary(BUILD_TARGET_CGI); } /** @@ -229,7 +229,7 @@ class MacOSBuilder extends UnixBuilderBase $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; $shell->exec("make {$concurrency} {$vars} micro"); - $this->deployBinary(BUILD_TARGET_MICRO); + $this->deploySAPIBinary(BUILD_TARGET_MICRO); } finally { if ($this->phar_patched) { SourcePatcher::unpatchMicroPhar(); @@ -247,7 +247,7 @@ class MacOSBuilder extends UnixBuilderBase $shell = shell()->cd(SOURCE_PATH . '/php-src'); $concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : ''; $shell->exec("make {$concurrency} {$vars} fpm"); - $this->deployBinary(BUILD_TARGET_FPM); + $this->deploySAPIBinary(BUILD_TARGET_FPM); } /** diff --git a/src/SPC/builder/unix/UnixBuilderBase.php b/src/SPC/builder/unix/UnixBuilderBase.php index 4c90ebdb..570d8093 100644 --- a/src/SPC/builder/unix/UnixBuilderBase.php +++ b/src/SPC/builder/unix/UnixBuilderBase.php @@ -6,7 +6,6 @@ namespace SPC\builder\unix; use SPC\builder\BuilderBase; use SPC\builder\linux\SystemUtil as LinuxSystemUtil; -use SPC\exception\PatchException; use SPC\exception\SPCException; use SPC\exception\SPCInternalException; use SPC\exception\ValidationException; @@ -79,6 +78,82 @@ abstract class UnixBuilderBase extends BuilderBase $this->lib_list = $sorted_libraries; } + /** + * Strip unneeded symbols from binary file. + */ + public function stripBinary(string $binary_path): void + { + shell()->exec(match (PHP_OS_FAMILY) { + 'Darwin' => "strip -S {$binary_path}", + 'Linux' => "strip --strip-unneeded {$binary_path}", + default => throw new SPCInternalException('stripBinary is only supported on Linux and macOS'), + }); + } + + /** + * Extract debug information from binary file. + * + * @param string $binary_path the path to the binary file, including executables, shared libraries, etc + */ + public function extractDebugInfo(string $binary_path): string + { + $target_dir = BUILD_ROOT_PATH . '/debug'; + FileSystem::createDir($target_dir); + $basename = basename($binary_path); + $debug_file = "{$target_dir}/{$basename}" . (PHP_OS_FAMILY === 'Darwin' ? '.dwarf' : '.debug'); + shell()->exec(match (PHP_OS_FAMILY) { + 'Darwin' => "dsymutil -f {$binary_path} -o {$debug_file}", + 'Linux' => "objcopy ---only-keep-debug {$binary_path} {$debug_file}", + default => throw new SPCInternalException('extractDebugInfo is only supported on Linux and macOS'), + }); + return $debug_file; + } + + /** + * Deploy the binary file from src to dst. + */ + public function deployBinary(string $src, string $dst, bool $executable = true): string + { + // UPX for linux + $upx_option = (bool) $this->getOption('with-upx-pack', false); + + // file must exists + if (!file_exists($src)) { + throw new SPCInternalException("Deploy failed. Cannot find file: {$src}"); + } + // dst dir must exists + FileSystem::createDir(dirname($dst)); + + // ignore copy to self + if (realpath($src) !== realpath($dst)) { + shell()->exec('cp ' . escapeshellarg($src) . ' ' . escapeshellarg($dst)); + } + + // file exist + if (!file_exists($dst)) { + throw new SPCInternalException("Deploy failed. Cannot find file after copy: {$dst}"); + } + + // extract debug info + $this->extractDebugInfo($dst); + + // strip + if (!$this->getOption('no-strip', false)) { + $this->stripBinary($dst); + } + + // Compress binary with UPX if needed (only for Linux) + if ($upx_option && PHP_OS_FAMILY === 'Linux' && $executable) { + if ($this->getOption('no-strip', false)) { + logger()->warning('UPX compression is not recommended when --no-strip is enabled.'); + } + logger()->info("Compressing {$dst} with UPX"); + shell()->exec(getenv('UPX_EXEC') . " --best {$dst}"); + } + + return $dst; + } + /** * Sanity check after build complete. */ @@ -209,14 +284,10 @@ abstract class UnixBuilderBase extends BuilderBase } /** - * Deploy the binary file to the build bin path. - * - * @param int $type Type integer, one of BUILD_TARGET_CLI, BUILD_TARGET_MICRO, BUILD_TARGET_FPM, BUILD_TARGET_CGI, BUILD_TARGET_FRANKENPHP + * Deploy binaries that produces executable SAPI */ - protected function deployBinary(int $type): void + protected function deploySAPIBinary(int $type): string { - FileSystem::createDir(BUILD_BIN_PATH); - $copy_files = []; $src = match ($type) { BUILD_TARGET_CLI => SOURCE_PATH . '/php-src/sapi/cli/php', BUILD_TARGET_MICRO => SOURCE_PATH . '/php-src/sapi/micro/micro.sfx', @@ -225,60 +296,8 @@ abstract class UnixBuilderBase extends BuilderBase BUILD_TARGET_FRANKENPHP => BUILD_BIN_PATH . '/frankenphp', default => throw new SPCInternalException("Deployment does not accept type {$type}"), }; - $no_strip_option = (bool) $this->getOption('no-strip', false); - $upx_option = (bool) $this->getOption('with-upx-pack', false); - - // Generate debug symbols if needed - $copy_files[] = $src; - if (!$no_strip_option && PHP_OS_FAMILY === 'Darwin') { - shell() - ->exec("dsymutil -f {$src}") // generate .dwarf file - ->exec("strip -S {$src}"); // strip unneeded symbols - $copy_files[] = "{$src}.dwarf"; - } elseif (!$no_strip_option && PHP_OS_FAMILY === 'Linux') { - shell() - ->exec("objcopy --only-keep-debug {$src} {$src}.debug") // extract debug symbols - ->exec("objcopy --add-gnu-debuglink={$src}.debug {$src}") // link debug symbols - ->exec("strip --strip-unneeded {$src}"); // strip unneeded symbols - $copy_files[] = "{$src}.debug"; - } - - // Compress binary with UPX if needed (only for Linux) - if ($upx_option && PHP_OS_FAMILY === 'Linux') { - if ($no_strip_option) { - logger()->warning('UPX compression is not recommended when --no-strip is enabled.'); - } - logger()->info("Compressing {$src} with UPX"); - shell()->exec(getenv('UPX_EXEC') . " --best {$src}"); - - // micro needs special section handling in LinuxBuilder. - // The micro.sfx does not support UPX directly, but we can remove UPX-info segment to adapt. - // This will also make micro.sfx with upx-packed more like a malware fore antivirus :( - if ($type === BUILD_TARGET_MICRO && version_compare($this->getMicroVersion(), '0.2.0') >= 0) { - // strip first - // cut binary with readelf - [$ret, $out] = shell()->execWithResult("readelf -l {$src} | awk '/LOAD|GNU_STACK/ {getline; print \$1, \$2, \$3, \$4, \$6, \$7}'"); - $out[1] = explode(' ', $out[1]); - $offset = $out[1][0]; - if ($ret !== 0 || !str_starts_with($offset, '0x')) { - throw new PatchException('phpmicro UPX patcher', 'Cannot find offset in readelf output'); - } - $offset = hexdec($offset); - // remove upx extra wastes - file_put_contents($src, substr(file_get_contents($src), 0, $offset)); - } - } - - // Copy files - foreach ($copy_files as $file) { - if (!file_exists($file)) { - throw new SPCInternalException("Deploy failed. Cannot find file: {$file}"); - } - // ignore copy to self - if (realpath($file) !== realpath(BUILD_BIN_PATH . '/' . basename($file))) { - shell()->exec('cp ' . escapeshellarg($file) . ' ' . escapeshellarg(BUILD_BIN_PATH . '/')); - } - } + $dst = BUILD_BIN_PATH . '/' . basename($src); + return $this->deployBinary($src, $dst); } /** @@ -379,7 +398,7 @@ abstract class UnixBuilderBase extends BuilderBase ->setEnv($env) ->exec("xcaddy build --output frankenphp {$xcaddyModules}"); - $this->deployBinary(BUILD_TARGET_FRANKENPHP); + $this->deploySAPIBinary(BUILD_TARGET_FRANKENPHP); } /** diff --git a/src/SPC/builder/windows/WindowsBuilder.php b/src/SPC/builder/windows/WindowsBuilder.php index 35b1623d..e4f1578c 100644 --- a/src/SPC/builder/windows/WindowsBuilder.php +++ b/src/SPC/builder/windows/WindowsBuilder.php @@ -161,7 +161,7 @@ class WindowsBuilder extends BuilderBase cmd()->cd(SOURCE_PATH . '\php-src')->exec("{$this->sdk_prefix} nmake_cli_wrapper.bat --task-args php.exe"); - $this->deployBinary(BUILD_TARGET_CLI); + $this->deploySAPIBinary(BUILD_TARGET_CLI); } public function buildCgi(): void @@ -186,7 +186,7 @@ class WindowsBuilder extends BuilderBase cmd()->cd(SOURCE_PATH . '\php-src')->exec("{$this->sdk_prefix} nmake_cgi_wrapper.bat --task-args php-cgi.exe"); - $this->deployBinary(BUILD_TARGET_CGI); + $this->deploySAPIBinary(BUILD_TARGET_CGI); } public function buildEmbed(): void @@ -243,7 +243,7 @@ class WindowsBuilder extends BuilderBase } } - $this->deployBinary(BUILD_TARGET_MICRO); + $this->deploySAPIBinary(BUILD_TARGET_MICRO); } public function proveLibs(array $sorted_libraries): void @@ -357,8 +357,18 @@ class WindowsBuilder extends BuilderBase * * @param int $type Deploy type */ - public function deployBinary(int $type): void + public function deploySAPIBinary(int $type): void { + logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file'); + + $debug_dir = BUILD_ROOT_PATH . '\debug'; + $bin_path = BUILD_BIN_PATH; + + // create dirs + FileSystem::createDir($debug_dir); + FileSystem::createDir($bin_path); + + // determine source path for different SAPI $rel_type = 'Release'; // TODO: Debug build support $ts = $this->zts ? '_TS' : ''; $src = match ($type) { @@ -368,21 +378,32 @@ class WindowsBuilder extends BuilderBase default => throw new SPCInternalException("Deployment does not accept type {$type}"), }; + $src = "{$src[0]}\\{$src[1]}"; + $dst = BUILD_BIN_PATH . '\\' . basename($src); + + // file must exists + if (!file_exists($src)) { + throw new SPCInternalException("Deploy failed. Cannot find file: {$src}"); + } + // dst dir must exists + FileSystem::createDir(dirname($dst)); + + // copy file + if (realpath($src) !== realpath($dst)) { + cmd()->exec('copy ' . escapeshellarg($src) . ' ' . escapeshellarg($dst)); + } + + // extract debug info in buildroot/debug + if ($this->getOption('no-strip', false) && file_exists("{$src[0]}\\{$src[2]}")) { + cmd()->exec('copy ' . escapeshellarg("{$src[0]}\\{$src[2]}") . ' ' . escapeshellarg($debug_dir)); + } + // with-upx-pack for cli and micro if ($this->getOption('with-upx-pack', false)) { if ($type === BUILD_TARGET_CLI || $type === BUILD_TARGET_CGI || ($type === BUILD_TARGET_MICRO && version_compare($this->getMicroVersion(), '0.2.0') >= 0)) { - cmd()->exec(getenv('UPX_EXEC') . ' --best ' . escapeshellarg("{$src[0]}\\{$src[1]}")); + cmd()->exec(getenv('UPX_EXEC') . ' --best ' . escapeshellarg($dst)); } } - - logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file'); - FileSystem::createDir(BUILD_BIN_PATH); - - cmd()->exec('copy ' . escapeshellarg("{$src[0]}\\{$src[1]}") . ' ' . escapeshellarg(BUILD_BIN_PATH . '\\')); - if ($this->getOption('no-strip', false) && file_exists("{$src[0]}\\{$src[2]}")) { - logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' debug symbols'); - cmd()->exec('copy ' . escapeshellarg("{$src[0]}\\{$src[2]}") . ' ' . escapeshellarg(BUILD_BIN_PATH . '\\')); - } } /** diff --git a/src/globals/test-extensions.php b/src/globals/test-extensions.php index 43ce5d15..2caf56b0 100644 --- a/src/globals/test-extensions.php +++ b/src/globals/test-extensions.php @@ -31,7 +31,7 @@ $test_os = [ 'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64 'ubuntu-24.04-arm', // bin/spc for arm64 // 'windows-2022', // .\bin\spc.ps1 - // 'windows-2025', + 'windows-2025', ]; // whether enable thread safe @@ -51,13 +51,13 @@ $prefer_pre_built = false; // If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`). $extensions = match (PHP_OS_FAMILY) { 'Linux', 'Darwin' => 'rdkafka', - 'Windows' => 'bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,iconv,xml,mbstring,mbregex,mysqlnd,openssl,pdo,pdo_mysql,pdo_sqlite,phar,session,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip', + 'Windows' => 'bcmath,bz2,calendar,ctype,zlib,zip', }; // If you want to test shared extensions, add them below (comma separated, example `bcmath,openssl`). $shared_extensions = match (PHP_OS_FAMILY) { - 'Linux' => '', - 'Darwin' => '', + 'Linux' => 'snmp', + 'Darwin' => 'snmp', 'Windows' => '', };