diff --git a/bin/spc-gnu-docker b/bin/spc-gnu-docker index f619a82b..164697f1 100755 --- a/bin/spc-gnu-docker +++ b/bin/spc-gnu-docker @@ -83,7 +83,8 @@ RUN if [ "$SPC_USE_ARCH" = "aarch64" ]; then \ sed -i 's/mirror.centos.org/vault.centos.org/g' /etc/yum.repos.d/*.repo ; \ fi RUN sed -i 's/^#.*baseurl=http/baseurl=http/g' /etc/yum.repos.d/*.repo && \ - sed -i 's/^mirrorlist=http/#mirrorlist=http/g' /etc/yum.repos.d/*.repo + sed -i 's/^mirrorlist=http/#mirrorlist=http/g' /etc/yum.repos.d/*.repo && \ + sed -i 's|http://|https://|g' /etc/yum.repos.d/*.repo RUN yum update -y && \ yum install -y devtoolset-10-gcc-* diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index 6f6fe15b..6a702416 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -9,9 +9,8 @@ use SPC\exception\RuntimeException; 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; class Extension { @@ -187,16 +186,11 @@ class Extension */ public function patchBeforeMake(): bool { - if ( - PHP_OS_FAMILY === 'Linux' && - $this->isBuildShared() && - ToolchainManager::getToolchainClass() === ZigToolchain::class && - ($extra = (new ZigToolchain())->getExtraRuntimeObjects()) - ) { + if (SPCTarget::getTargetOS() === 'Linux' && $this->isBuildShared() && ($objs = getenv('SPC_EXTRA_RUNTIME_OBJECTS'))) { FileSystem::replaceFileRegex( SOURCE_PATH . '/php-src/Makefile', "/^(shared_objects_{$this->getName()}\\s*=.*)$/m", - "$1 {$extra}", + "$1 {$objs}", ); return true; } @@ -230,15 +224,11 @@ class Extension */ public function patchBeforeSharedMake(): bool { - if ( - PHP_OS_FAMILY === 'Linux' && - ToolchainManager::getToolchainClass() === ZigToolchain::class && - ($extra = (new ZigToolchain())->getExtraRuntimeObjects()) - ) { + if (SPCTarget::getTargetOS() === 'Linux' && ($objs = getenv('SPC_EXTRA_RUNTIME_OBJECTS'))) { FileSystem::replaceFileRegex( $this->source_dir . '/Makefile', "/^(shared_objects_{$this->getName()}\\s*=.*)$/m", - "$1 {$extra}", + "$1 {$objs}", ); return true; } diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index a2078e9d..8983cab7 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -10,8 +10,6 @@ use SPC\exception\RuntimeException; 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\SPCTarget; @@ -62,7 +60,6 @@ class LinuxBuilder extends UnixBuilderBase } // add libstdc++, some extensions or libraries need it $extra_libs .= (empty($extra_libs) ? '' : ' ') . ($this->hasCpp() ? '-lstdc++ ' : ''); - $extra_libs .= (ToolchainManager::getToolchainClass() === ZigToolchain::class ? ' -lunwind' : ''); f_putenv('SPC_EXTRA_LIBS=' . $extra_libs); $cflags = $this->arch_c_flags; f_putenv('CFLAGS=' . $cflags); @@ -109,15 +106,6 @@ class LinuxBuilder extends UnixBuilderBase 'LIBS' => $mimallocLibs . SPCTarget::getRuntimeLibs(), ]); - // process micro upx patch if micro sapi enabled - if ($enableMicro) { - if (version_compare($this->getMicroVersion(), '0.2.0') < 0) { - // for phpmicro 0.1.x - $this->processMicroUPXLegacy(); - } - // micro latest needs do strip and upx pack later (strip, upx, cut binary manually supported) - } - $embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static'; if ($embed_type !== 'static' && SPCTarget::isStatic()) { throw new WrongUsageException( @@ -284,6 +272,7 @@ class LinuxBuilder extends UnixBuilderBase $modulesDir = BUILD_MODULES_PATH; $libphpSo = "{$libDir}/libphp.so"; $realLibName = 'libphp.so'; + $cwd = getcwd(); if (preg_match('/-release\s+(\S+)/', $ldflags, $matches)) { $release = $matches[1]; @@ -325,14 +314,14 @@ class LinuxBuilder extends UnixBuilderBase } } } - chdir(getcwd()); + chdir($cwd); } $target = "{$libDir}/{$realLibName}"; if (file_exists($target)) { [, $output] = shell()->execWithResult('readelf -d ' . escapeshellarg($target)); $output = join("\n", $output); - if (preg_match('/SONAME.*\[(.+)\]/', $output, $sonameMatch)) { + if (preg_match('/SONAME.*\[(.+)]/', $output, $sonameMatch)) { $currentSoname = $sonameMatch[1]; if ($currentSoname !== basename($target)) { shell()->exec(sprintf( @@ -361,49 +350,12 @@ class LinuxBuilder extends UnixBuilderBase } /** - * Apply option --no-strip and --with-upx-pack for micro sapi (only for phpmicro 0.1.x) + * Strip micro.sfx for Linux. + * 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 :( * - * @throws FileSystemException + * @throws RuntimeException */ - private function processMicroUPXLegacy(): void - { - // upx pack and strip for micro - // but always restore Makefile.frag.bak first - if (file_exists(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.bak')) { - copy(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.bak', SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag'); - } - if ($this->getOption('with-upx-pack', false)) { - // judge $(MAKE) micro_2s_objs SFX_FILESIZE=`$(STAT_SIZE) $(SAPI_MICRO_PATH)` count - // if 2, replace src/globals/extra/micro-triple-Makefile.frag file content - if (substr_count(FileSystem::readFile(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag'), '$(MAKE) micro_2s_objs SFX_FILESIZE=`$(STAT_SIZE) $(SAPI_MICRO_PATH)`') === 2) { - // bak first - copy(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag', SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.bak'); - // replace Makefile.frag content - FileSystem::writeFile(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag', FileSystem::readFile(ROOT_DIR . '/src/globals/extra/micro-triple-Makefile.frag')); - } - // with upx pack always need strip - FileSystem::replaceFileRegex( - SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag', - '/POST_MICRO_BUILD_COMMANDS=.*/', - 'POST_MICRO_BUILD_COMMANDS=\$(STRIP) \$(MICRO_STRIP_FLAGS) \$(SAPI_MICRO_PATH) && ' . getenv('UPX_EXEC') . ' --best \$(SAPI_MICRO_PATH)', - ); - } elseif (!$this->getOption('no-strip', false)) { - // not-no-strip means strip (default behavior) - FileSystem::replaceFileRegex( - SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag', - '/POST_MICRO_BUILD_COMMANDS=.*/', - 'POST_MICRO_BUILD_COMMANDS=\$(STRIP) \$(MICRO_STRIP_FLAGS) \$(SAPI_MICRO_PATH)', - ); - } else { - // just no strip - FileSystem::replaceFileRegex( - SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag', - '/POST_MICRO_BUILD_COMMANDS=.*/', - 'POST_MICRO_BUILD_COMMANDS=true', - ); - } - } - private function processMicroUPX(): void { if (version_compare($this->getMicroVersion(), '0.2.0') >= 0 && !$this->getOption('no-strip', false)) { diff --git a/src/SPC/store/pkg/Zig.php b/src/SPC/store/pkg/Zig.php index f819da7a..6f823405 100644 --- a/src/SPC/store/pkg/Zig.php +++ b/src/SPC/store/pkg/Zig.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace SPC\store\pkg; +use SPC\exception\RuntimeException; +use SPC\exception\WrongUsageException; use SPC\store\CurlHook; use SPC\store\Downloader; use SPC\store\FileSystem; @@ -50,14 +52,14 @@ class Zig extends CustomPackage $zig_arch = match ($arch) { 'x86_64', 'aarch64' => $arch, - default => throw new \InvalidArgumentException('Unsupported architecture: ' . $arch), + default => throw new WrongUsageException('Unsupported architecture: ' . $arch), }; $zig_os = match ($os) { 'linux' => 'linux', 'macos' => 'macos', 'win' => 'windows', - default => throw new \InvalidArgumentException('Unsupported OS: ' . $os), + default => throw new WrongUsageException('Unsupported OS: ' . $os), }; $index_json = json_decode(Downloader::curlExec('https://ziglang.org/download/index.json', hooks: [[CurlHook::class, 'setupGithubToken']]), true); @@ -69,14 +71,14 @@ class Zig extends CustomPackage } if (!$latest_version) { - throw new \RuntimeException('Could not determine latest Zig version'); + throw new RuntimeException('Could not determine latest Zig version'); } logger()->info("Installing Zig version {$latest_version}"); $platform_key = "{$zig_arch}-{$zig_os}"; if (!isset($index_json[$latest_version][$platform_key])) { - throw new \RuntimeException("No download available for {$platform_key} in Zig version {$latest_version}"); + throw new RuntimeException("No download available for {$platform_key} in Zig version {$latest_version}"); } $download_info = $index_json[$latest_version][$platform_key]; @@ -119,7 +121,6 @@ class Zig extends CustomPackage { $arch = arch2gnu(php_uname('m')); $os = match (PHP_OS_FAMILY) { - 'Linux' => 'linux', 'Windows' => 'win', 'Darwin' => 'macos', 'BSD' => 'freebsd', @@ -134,11 +135,13 @@ class Zig extends CustomPackage ]; } + /** + * @throws WrongUsageException + */ private static function getPath(): string { $arch = arch2gnu(php_uname('m')); $os = match (PHP_OS_FAMILY) { - 'Linux' => 'linux', 'Windows' => 'win', 'Darwin' => 'macos', 'BSD' => 'freebsd', diff --git a/src/SPC/toolchain/ClangNativeToolchain.php b/src/SPC/toolchain/ClangNativeToolchain.php index fb0bea46..aef844d7 100644 --- a/src/SPC/toolchain/ClangNativeToolchain.php +++ b/src/SPC/toolchain/ClangNativeToolchain.php @@ -10,6 +10,9 @@ use SPC\builder\macos\SystemUtil as MacOSSystemUtil; use SPC\exception\WrongUsageException; use SPC\util\GlobalEnvManager; +/** + * Toolchain implementation for system clang compiler. + */ class ClangNativeToolchain implements ToolchainInterface { public function initEnv(): void @@ -20,6 +23,9 @@ class ClangNativeToolchain implements ToolchainInterface GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_LD=ld'); } + /** + * @throws WrongUsageException + */ public function afterInit(): void { foreach (['CC', 'CXX', 'AR', 'LD'] as $env) { diff --git a/src/SPC/toolchain/ZigToolchain.php b/src/SPC/toolchain/ZigToolchain.php index 59e97469..1447956f 100644 --- a/src/SPC/toolchain/ZigToolchain.php +++ b/src/SPC/toolchain/ZigToolchain.php @@ -17,27 +17,8 @@ class ZigToolchain implements ToolchainInterface GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_CXX=zig-c++'); GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_AR=ar'); GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_LD=ld'); - } - - public function afterInit(): void - { - if (!is_dir(Zig::getEnvironment()['PATH'])) { - throw new WrongUsageException('You are building with zig, but zig is not installed, please install zig first. (You can use `doctor` command to install it)'); - } - GlobalEnvManager::addPathIfNotExists(Zig::getEnvironment()['PATH']); - } - - /** - * Get the extra runtime objects needed for zig toolchain. - * This method searches for `crtbeginS.o` and `crtendS.o` in common GCC library paths. - */ - public function getExtraRuntimeObjects(): string - { - static $cache = null; - if ($cache !== null) { - return $cache; - } + // Generate additional object needed for zig toolchain $paths = ['/usr/lib/gcc', '/usr/local/lib/gcc']; $objects = ['crtbeginS.o', 'crtendS.o']; $found = []; @@ -56,8 +37,24 @@ class ZigToolchain implements ToolchainInterface $found[] = $located; } } + GlobalEnvManager::putenv('SPC_EXTRA_RUNTIME_OBJECTS=' . implode(' ', $found)); - $cache = implode(' ', $found); - return $cache; + $extra_libs = getenv('SPC_EXTRA_LIBS') ?: ''; + if (!str_contains($extra_libs, '-lunwind')) { + // Add unwind library if not already present + $extra_libs = trim($extra_libs . ' -lunwind'); + GlobalEnvManager::putenv("SPC_EXTRA_LIBS={$extra_libs}"); + } + } + + /** + * @throws WrongUsageException + */ + public function afterInit(): void + { + if (!is_dir(Zig::getEnvironment()['PATH'])) { + throw new WrongUsageException('You are building with zig, but zig is not installed, please install zig first. (You can use `doctor` command to install it)'); + } + GlobalEnvManager::addPathIfNotExists(Zig::getEnvironment()['PATH']); } } diff --git a/src/SPC/util/GlobalEnvManager.php b/src/SPC/util/GlobalEnvManager.php index 23ae242d..f5dafea2 100644 --- a/src/SPC/util/GlobalEnvManager.php +++ b/src/SPC/util/GlobalEnvManager.php @@ -15,6 +15,8 @@ class GlobalEnvManager { private static array $env_cache = []; + private static bool $initialized = false; + public static function getInitializedEnv(): array { return self::$env_cache; @@ -28,6 +30,9 @@ class GlobalEnvManager */ public static function init(): void { + if (self::$initialized) { + return; + } // Check pre-defined env vars exists if (getenv('BUILD_ROOT_PATH') === false) { throw new RuntimeException('You must include src/globals/internal-env.php before using GlobalEnvManager'); @@ -85,6 +90,7 @@ class GlobalEnvManager self::putenv("{$k}={$v}"); } } + self::$initialized = true; } public static function putenv(string $val): void diff --git a/src/SPC/util/SPCConfigUtil.php b/src/SPC/util/SPCConfigUtil.php index 83b76b2c..d7ecd368 100644 --- a/src/SPC/util/SPCConfigUtil.php +++ b/src/SPC/util/SPCConfigUtil.php @@ -11,8 +11,6 @@ use SPC\exception\FileSystemException; use SPC\exception\RuntimeException; use SPC\exception\WrongUsageException; use SPC\store\Config; -use SPC\toolchain\ToolchainManager; -use SPC\toolchain\ZigToolchain; use Symfony\Component\Console\Input\ArgvInput; class SPCConfigUtil @@ -71,9 +69,7 @@ class SPCConfigUtil if ($this->builder->hasCpp()) { $libs .= $this->builder instanceof MacOSBuilder ? ' -lc++' : ' -lstdc++'; } - if (ToolchainManager::getToolchainClass() === ZigToolchain::class) { - $libs .= ' -lunwind'; - } + $libs .= ' ' . (getenv('SPC_EXTRA_LIBS') ?: ''); // mimalloc must come first if (str_contains($libs, BUILD_LIB_PATH . '/mimalloc.o')) { $libs = BUILD_LIB_PATH . '/mimalloc.o ' . str_replace(BUILD_LIB_PATH . '/mimalloc.o', '', $libs); diff --git a/src/globals/ext-tests/curl.php b/src/globals/ext-tests/curl.php index eaf4b82e..7c3eecf7 100644 --- a/src/globals/ext-tests/curl.php +++ b/src/globals/ext-tests/curl.php @@ -9,7 +9,7 @@ assert(function_exists('curl_close')); $curl_version = curl_version(); if (stripos($curl_version['ssl_version'], 'schannel') !== false) { $curl = curl_init(); - curl_setopt($curl, CURLOPT_URL, 'https://www.example.com/'); + curl_setopt($curl, CURLOPT_URL, 'https://captive.apple.com/'); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_HEADER, 0); $data = curl_exec($curl); diff --git a/src/globals/ext-tests/openssl.php b/src/globals/ext-tests/openssl.php index 87862e87..0453101a 100644 --- a/src/globals/ext-tests/openssl.php +++ b/src/globals/ext-tests/openssl.php @@ -5,5 +5,5 @@ declare(strict_types=1); assert(function_exists('openssl_digest')); assert(openssl_digest('123456', 'md5') === 'e10adc3949ba59abbe56e057f20f883e'); if (file_exists('/etc/ssl/openssl.cnf')) { - assert(file_get_contents('https://www.example.com/') !== false); + assert(file_get_contents('https://captive.apple.com/') !== false); }