diff --git a/config/ext.json b/config/ext.json index 8e02b118..188aea58 100644 --- a/config/ext.json +++ b/config/ext.json @@ -414,9 +414,17 @@ "libmemcached", "fastlz" ], + "lib-suggests": [ + "zstd" + ], "ext-depends": [ "session", "zlib" + ], + "ext-suggests": [ + "igbinary", + "msgpack", + "session" ] }, "mongodb": { diff --git a/config/lib.json b/config/lib.json index bda0baad..37faca3c 100644 --- a/config/lib.json +++ b/config/lib.json @@ -9,17 +9,19 @@ "lib-base", "micro" ], + "lib-depends-macos": [ + "lib-base", + "micro", + "libxml2" + ], "lib-suggests-linux": [ "libacl", "brotli", "watcher" ], - "lib-suggests-unix": [ + "lib-suggests-macos": [ "brotli", "watcher" - ], - "lib-depends-macos": [ - "libxml2" ] }, "micro": { @@ -450,6 +452,7 @@ }, "libmemcached": { "source": "libmemcached", + "cpp-library": true, "static-libs-unix": [ "libmemcached.a", "libmemcachedprotocol.a", @@ -594,7 +597,6 @@ ], "lib-suggests-unix": [ "xz", - "icu", "zlib" ], "lib-depends-windows": [ diff --git a/src/SPC/ConsoleApplication.php b/src/SPC/ConsoleApplication.php index c60ca4b0..023b541e 100644 --- a/src/SPC/ConsoleApplication.php +++ b/src/SPC/ConsoleApplication.php @@ -34,7 +34,7 @@ use Symfony\Component\Console\Application; */ final class ConsoleApplication extends Application { - public const string VERSION = '2.7.3'; + public const string VERSION = '2.7.4'; public function __construct() { diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index 71bbf9d4..ac7efd1e 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -5,11 +5,14 @@ declare(strict_types=1); 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; @@ -418,8 +421,24 @@ class Extension 'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"), 'LD_LIBRARY_PATH' => BUILD_LIB_PATH, ]; - if (ToolchainManager::getToolchainClass() === ZigToolchain::class && SPCTarget::getTargetOS() === 'Linux') { - $env['SPC_COMPILER_EXTRA'] = '-lstdc++'; + 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()) { diff --git a/src/SPC/builder/extension/memcached.php b/src/SPC/builder/extension/memcached.php index a1b88ac6..983b5b64 100644 --- a/src/SPC/builder/extension/memcached.php +++ b/src/SPC/builder/extension/memcached.php @@ -17,6 +17,10 @@ class memcached extends Extension '--with-libmemcached-dir=' . BUILD_ROOT_PATH . ' ' . '--disable-memcached-sasl ' . '--enable-memcached-json ' . + ($this->builder->getLib('zstd') ? '--with-zstd ' : '') . + ($this->builder->getExt('igbinary') ? '--enable-memcached-igbinary ' : '') . + ($this->builder->getExt('session') ? '--enable-memcached-session ' : '') . + ($this->builder->getExt('msgpack') ? '--enable-memcached-msgpack ' : '') . '--with-system-fastlz'; } } diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index c4eb2b05..3525ffb7 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -103,9 +103,8 @@ class LinuxBuilder extends UnixBuilderBase ); } - shell()->cd(SOURCE_PATH . '/php-src') - ->exec( - $php_configure_env . ' ' . + $this->seekPhpSrcLogFileOnException(fn () => shell()->cd(SOURCE_PATH . '/php-src')->exec( + $php_configure_env . ' ' . getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' . ($enableCli ? '--enable-cli ' : '--disable-cli ') . ($enableFpm ? '--enable-fpm ' . ($this->getLib('libacl') !== null ? '--with-fpm-acl ' : '') : '--disable-fpm ') . @@ -118,7 +117,7 @@ class LinuxBuilder extends UnixBuilderBase $zts . $maxExecutionTimers . $this->makeStaticExtensionArgs() . ' ' - ); + )); $this->emitPatchPoint('before-php-make'); SourcePatcher::patchBeforeMake($this); diff --git a/src/SPC/builder/macos/MacOSBuilder.php b/src/SPC/builder/macos/MacOSBuilder.php index 13a978d3..20a2ed13 100644 --- a/src/SPC/builder/macos/MacOSBuilder.php +++ b/src/SPC/builder/macos/MacOSBuilder.php @@ -118,9 +118,8 @@ class MacOSBuilder extends UnixBuilderBase } $embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static'; - shell()->cd(SOURCE_PATH . '/php-src') - ->exec( - getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' . + $this->seekPhpSrcLogFileOnException(fn () => shell()->cd(SOURCE_PATH . '/php-src')->exec( + getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' . ($enableCli ? '--enable-cli ' : '--disable-cli ') . ($enableFpm ? '--enable-fpm ' : '--disable-fpm ') . ($enableEmbed ? "--enable-embed={$embed_type} " : '--disable-embed ') . @@ -132,7 +131,7 @@ class MacOSBuilder extends UnixBuilderBase $zts . $this->makeStaticExtensionArgs() . ' ' . $envs_build_php - ); + )); $this->emitPatchPoint('before-php-make'); SourcePatcher::patchBeforeMake($this); diff --git a/src/SPC/builder/unix/UnixBuilderBase.php b/src/SPC/builder/unix/UnixBuilderBase.php index 6017479d..5942f90c 100644 --- a/src/SPC/builder/unix/UnixBuilderBase.php +++ b/src/SPC/builder/unix/UnixBuilderBase.php @@ -6,6 +6,7 @@ namespace SPC\builder\unix; use SPC\builder\BuilderBase; use SPC\builder\linux\SystemUtil as LinuxSystemUtil; +use SPC\exception\SPCException; use SPC\exception\SPCInternalException; use SPC\exception\ValidationException; use SPC\exception\WrongUsageException; @@ -333,4 +334,20 @@ abstract class UnixBuilderBase extends BuilderBase } } } + + /** + * Seek php-src/config.log when building PHP, add it to exception. + */ + protected function seekPhpSrcLogFileOnException(callable $callback): void + { + try { + $callback(); + } catch (SPCException $e) { + if (file_exists(SOURCE_PATH . '/php-src/config.log')) { + $e->addExtraLogFile('php-src config.log', 'php-src.config.log'); + copy(SOURCE_PATH . '/php-src/config.log', SPC_LOGS_DIR . '/php-src.config.log'); + } + throw $e; + } + } } diff --git a/src/SPC/builder/unix/library/libxml2.php b/src/SPC/builder/unix/library/libxml2.php index 87fbab10..7152c0c4 100644 --- a/src/SPC/builder/unix/library/libxml2.php +++ b/src/SPC/builder/unix/library/libxml2.php @@ -20,17 +20,17 @@ trait libxml2 "-DZLIB_INCLUDE_DIR={$this->getIncludeDir()}", '-DLIBXML2_WITH_ZLIB=OFF', ) - ->optionalLib('icu', ...cmake_boolean_args('LIBXML2_WITH_ICU')) ->optionalLib('xz', ...cmake_boolean_args('LIBXML2_WITH_LZMA')) ->addConfigureArgs( '-DLIBXML2_WITH_ICONV=ON', + '-DLIBXML2_WITH_ICU=OFF', // optional, but discouraged: https://gitlab.gnome.org/GNOME/libxml2/-/blob/master/README.md '-DLIBXML2_WITH_PYTHON=OFF', '-DLIBXML2_WITH_PROGRAMS=OFF', '-DLIBXML2_WITH_TESTS=OFF', ); if ($this instanceof LinuxLibraryBase) { - $cmake->addConfigureArgs('-DIconv_IS_BUILD_IN=OFF'); + $cmake->addConfigureArgs('-DIconv_IS_BUILT_IN=OFF'); } $cmake->build(); diff --git a/src/globals/ext-tests/gettext.php b/src/globals/ext-tests/gettext.php index f34f487a..b5bc901e 100644 --- a/src/globals/ext-tests/gettext.php +++ b/src/globals/ext-tests/gettext.php @@ -4,20 +4,40 @@ declare(strict_types=1); assert(function_exists('gettext')); assert(function_exists('bindtextdomain')); +assert(function_exists('bind_textdomain_codeset')); assert(function_exists('textdomain')); -if (!is_dir('locale/en_US/LC_MESSAGES/')) { - mkdir('locale/en_US/LC_MESSAGES/', 0755, true); +foreach (['en_US', 'en_GB'] as $lc) { + $dir = "locale/{$lc}/LC_MESSAGES"; + if (!is_dir($dir)) { + mkdir($dir, 0755, true); + } + $mo = '3hIElQAAAAACAAAAHAAAACwAAAAFAAAAPAAAAAAAAABQAAAABgAAAFEAAAAXAQAAWAAAAAcAAABwAQAAAQAAAAAAAAAAAAAAAgAAAAAAAAAA56S65L6LAFByb2plY3QtSWQtVmVyc2lvbjogUEFDS0FHRSBWRVJTSU9OClJlcG9ydC1Nc2dpZC1CdWdzLVRvOiAKUE8tUmV2aXNpb24tRGF0ZTogWUVBUi1NTy1EQSBITzpNSytaT05FCkxhc3QtVHJhbnNsYXRvcjogRlVMTCBOQU1FIDxFTUFJTEBBRERSRVNTPgpMYW5ndWFnZS1UZWFtOiBMQU5HVUFHRSA8TExAbGkub3JnPgpMYW5ndWFnZTogCk1JTUUtVmVyc2lvbjogMS4wCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD1VVEYtOApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiA4Yml0CgBFeGFtcGxlAA=='; + $path = "{$dir}/test.mo"; + if (!file_exists($path)) { + file_put_contents($path, base64_decode($mo)); + } } -if (!file_exists('locale/en_US/LC_MESSAGES/test.mo')) { - $mo = '3hIElQAAAAACAAAAHAAAACwAAAAFAAAAPAAAAAAAAABQAAAABgAAAFEAAAAXAQAAWAAAAAcAAABwAQAAAQAAAAAAAAAAAAAAAgAAAAAAAAAA56S65L6LAFByb2plY3QtSWQtVmVyc2lvbjogUEFDS0FHRSBWRVJTSU9OClJlcG9ydC1Nc2dpZC1CdWdzLVRvOiAKUE8tUmV2aXNpb24tRGF0ZTogWUVBUi1NTy1EQSBITzpNSStaT05FCkxhc3QtVHJhbnNsYXRvcjogRlVMTCBOQU1FIDxFTUFJTEBBRERSRVNTPgpMYW5ndWFnZS1UZWFtOiBMQU5HVUFHRSA8TExAbGkub3JnPgpMYW5ndWFnZTogCk1JTUUtVmVyc2lvbjogMS4wCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD1VVEYtOApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiA4Yml0CgBFeGFtcGxlAA=='; - file_put_contents('locale/en_US/LC_MESSAGES/test.mo', base64_decode($mo)); -} -putenv('LANG=en_US'); -assert(setlocale(LC_ALL, 'en_US.utf-8') === 'en_US.utf-8'); + +// Probe for an available English locale +$candidates = [ + 'en_US.UTF-8', 'en_US.utf8', 'en_US.utf-8', 'en_US', + 'en_GB.UTF-8', 'en_GB.utf8', 'en_GB.utf-8', 'en_GB', + 'English_United States.65001', 'English_United States.1252', + 'English_United Kingdom.65001', 'English_United Kingdom.1252', +]; + +$locale = setlocale(LC_ALL, $candidates); +assert($locale !== false); + +putenv('LC_ALL=' . $locale); +putenv('LANG=' . $locale); +putenv('LANGUAGE=' . (stripos($locale, 'US') !== false ? 'en_US:en_GB' : 'en_GB:en_US')); $domain = 'test'; bindtextdomain($domain, 'locale/'); +bind_textdomain_codeset($domain, 'UTF-8'); textdomain($domain); -assert(gettext(json_decode('"\u793a\u4f8b"', true)) === 'Example'); +$src = json_decode('"\u793a\u4f8b"', true); +assert(gettext($src) === 'Example');