diff --git a/config/env.ini b/config/env.ini index a8e7a8a6..bf322adb 100644 --- a/config/env.ini +++ b/config/env.ini @@ -56,7 +56,7 @@ SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES="--with github.com/dunglas/frankenphp/cadd [windows] ; build target: win7-static -SPC_TARGET=msvc-static +SPC_TARGET=native ; php-sdk-binary-tools path PHP_SDK_PATH="${WORKING_DIR}\php-sdk-binary-tools" ; upx executable path @@ -75,7 +75,9 @@ SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime ; - musl-static (default): pure static linking, using musl-libc, can run on any linux distro. ; - musl: static linking with dynamic linking to musl-libc, can run on musl-based linux distro. ; - glibc: static linking with dynamic linking to glibc, can run on glibc-based linux distro. -SPC_TARGET=musl-static + +; include PATH for musl libc. +SPC_LIBC=musl ; compiler environments CC=${SPC_LINUX_DEFAULT_CC} CXX=${SPC_LINUX_DEFAULT_CXX} @@ -122,7 +124,7 @@ SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-all-static -Wl,-O1 -pie" [macos] ; build target: macho or macho (possibly we could support macho-universal in the future) ; Currently we do not support universal and cross-compilation for macOS. -SPC_TARGET=macho +SPC_TARGET=native ; compiler environments CC=clang CXX=clang++ diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index 3f63c84b..d00c8de0 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -10,6 +10,7 @@ use SPC\exception\WrongUsageException; use SPC\store\Config; use SPC\store\FileSystem; use SPC\util\SPCConfigUtil; +use SPC\util\SPCTarget; class Extension { @@ -532,6 +533,11 @@ class Extension $sharedLibString .= '-l' . $lib . ' '; } } + // move static libstdc++ to shared if we are on non-full-static build target + if (!SPCTarget::isStaticTarget() && in_array(SPCTarget::getLibc(), SPCTarget::LIBC_LIST)) { + $staticLibString .= ' -lstdc++'; + $sharedLibString = str_replace('-lstdc++', '', $sharedLibString); + } return [trim($staticLibString), trim($sharedLibString)]; } diff --git a/src/SPC/builder/extension/imagick.php b/src/SPC/builder/extension/imagick.php index 8332f832..514e79b3 100644 --- a/src/SPC/builder/extension/imagick.php +++ b/src/SPC/builder/extension/imagick.php @@ -6,7 +6,6 @@ namespace SPC\builder\extension; use SPC\builder\Extension; use SPC\util\CustomExt; -use SPC\util\SPCTarget; #[CustomExt('imagick')] class imagick extends Extension @@ -16,15 +15,4 @@ class imagick extends Extension $disable_omp = ' ac_cv_func_omp_pause_resource_all=no'; return '--with-imagick=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH . $disable_omp; } - - protected function getStaticAndSharedLibs(): array - { - // on centos 7, it will use the symbol _ZTINSt6thread6_StateE, which is not defined in system libstdc++.so.6 - [$static, $shared] = parent::getStaticAndSharedLibs(); - if (SPCTarget::isTarget(SPCTarget::GLIBC)) { - $static .= ' -lstdc++'; - $shared = str_replace('-lstdc++', '', $shared); - } - return [$static, $shared]; - } } diff --git a/src/SPC/builder/linux/SystemUtil.php b/src/SPC/builder/linux/SystemUtil.php index 1e405768..0f6d3578 100644 --- a/src/SPC/builder/linux/SystemUtil.php +++ b/src/SPC/builder/linux/SystemUtil.php @@ -6,7 +6,6 @@ namespace SPC\builder\linux; use SPC\builder\traits\UnixSystemUtilTrait; use SPC\exception\RuntimeException; -use SPC\util\SPCTarget; class SystemUtil { @@ -189,12 +188,12 @@ class SystemUtil /** * Get libc version string from ldd */ - public static function getLibcVersionIfExists(): ?string + public static function getLibcVersionIfExists(string $libc): ?string { if (self::$libc_version !== null) { return self::$libc_version; } - if (SPCTarget::isTarget(SPCTarget::GLIBC)) { + if ($libc === 'glibc') { $result = shell()->execWithResult('ldd --version', false); if ($result[0] !== 0) { return null; @@ -209,7 +208,7 @@ class SystemUtil } return null; } - if (SPCTarget::isTarget(SPCTarget::MUSL_STATIC)) { + if ($libc === 'musl') { if (self::isMuslDist()) { $result = shell()->execWithResult('ldd 2>&1', false); } else { diff --git a/src/SPC/builder/linux/library/icu.php b/src/SPC/builder/linux/library/icu.php index 6fb7e1fc..26b98899 100644 --- a/src/SPC/builder/linux/library/icu.php +++ b/src/SPC/builder/linux/library/icu.php @@ -17,7 +17,7 @@ class icu extends LinuxLibraryBase { $cppflags = 'CPPFLAGS="-DU_CHARSET_IS_UTF8=1 -DU_USING_ICU_NAMESPACE=1 -DU_STATIC_IMPLEMENTATION=1 -DPIC -fPIC"'; $cxxflags = 'CXXFLAGS="-std=c++17 -DPIC -fPIC -fno-ident"'; - $ldflags = SPCTarget::isTarget(SPCTarget::MUSL_STATIC) ? 'LDFLAGS="-static"' : ''; + $ldflags = SPCTarget::isStaticTarget() ? 'LDFLAGS="-static"' : ''; shell()->cd($this->source_dir . '/source')->initializeEnv($this) ->exec( "{$cppflags} {$cxxflags} {$ldflags} " . diff --git a/src/SPC/builder/macos/MacOSBuilder.php b/src/SPC/builder/macos/MacOSBuilder.php index 173ec954..362a68fe 100644 --- a/src/SPC/builder/macos/MacOSBuilder.php +++ b/src/SPC/builder/macos/MacOSBuilder.php @@ -29,6 +29,7 @@ class MacOSBuilder extends UnixBuilderBase // apply global environment variables GlobalEnvManager::init(); + GlobalEnvManager::afterInit(); // ---------- set necessary compile vars ---------- // concurrency diff --git a/src/SPC/builder/unix/UnixBuilderBase.php b/src/SPC/builder/unix/UnixBuilderBase.php index 886eec68..f0e2dba5 100644 --- a/src/SPC/builder/unix/UnixBuilderBase.php +++ b/src/SPC/builder/unix/UnixBuilderBase.php @@ -201,7 +201,7 @@ abstract class UnixBuilderBase extends BuilderBase $util = new SPCConfigUtil($this); $config = $util->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs')); $lens = "{$config['cflags']} {$config['ldflags']} {$config['libs']}"; - if (SPCTarget::isTarget(SPCTarget::MUSL_STATIC)) { + if (SPCTarget::isStaticTarget()) { $lens .= ' -static'; } [$ret, $out] = shell()->cd($sample_file_path)->execWithResult(getenv('CC') . ' -o embed embed.c ' . $lens); @@ -335,7 +335,7 @@ abstract class UnixBuilderBase extends BuilderBase $debugFlags = $this->getOption('no-strip') ? "'-w -s' " : ''; $extLdFlags = "-extldflags '-pie'"; $muslTags = ''; - if (SPCTarget::isTarget(SPCTarget::MUSL_STATIC)) { + if (SPCTarget::isStaticTarget()) { $extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000'"; $muslTags = 'static_build,'; } diff --git a/src/SPC/builder/unix/library/imagemagick.php b/src/SPC/builder/unix/library/imagemagick.php index f126bf30..d8d7e0c9 100644 --- a/src/SPC/builder/unix/library/imagemagick.php +++ b/src/SPC/builder/unix/library/imagemagick.php @@ -6,6 +6,7 @@ namespace SPC\builder\unix\library; use SPC\exception\FileSystemException; use SPC\exception\RuntimeException; +use SPC\exception\WrongUsageException; use SPC\store\FileSystem; use SPC\util\executor\UnixAutoconfExecutor; use SPC\util\SPCTarget; @@ -15,6 +16,7 @@ trait imagemagick /** * @throws RuntimeException * @throws FileSystemException + * @throws WrongUsageException */ protected function build(): void { @@ -36,11 +38,11 @@ trait imagemagick '--without-x', ); - // special: linux musl-static needs `-static` - $ldflags = !SPCTarget::isTarget(SPCTarget::MUSL_STATIC) ? ('-static -ldl') : '-ldl'; + // special: linux-static target needs `-static` + $ldflags = SPCTarget::isStaticTarget() ? ('-static -ldl') : '-ldl'; // special: macOS needs -iconv - $libs = SPCTarget::isTarget(SPCTarget::MACHO) ? '-liconv' : ''; + $libs = SPCTarget::getTargetOS() === 'Darwin' ? '-liconv' : ''; $ac->appendEnv([ 'LDFLAGS' => $ldflags, diff --git a/src/SPC/builder/unix/library/ldap.php b/src/SPC/builder/unix/library/ldap.php index e87310cb..18393e24 100644 --- a/src/SPC/builder/unix/library/ldap.php +++ b/src/SPC/builder/unix/library/ldap.php @@ -12,7 +12,7 @@ trait ldap { public function patchBeforeBuild(): bool { - $extra = SPCTarget::isTarget(SPCTarget::GLIBC) ? '-ldl -lpthread -lm -lresolv -lutil' : ''; + $extra = SPCTarget::getLibc() === 'glibc' ? '-ldl -lpthread -lm -lresolv -lutil' : ''; FileSystem::replaceFileStr($this->source_dir . '/configure', '"-lssl -lcrypto', '"-lssl -lcrypto -lz ' . $extra); return true; } diff --git a/src/SPC/builder/unix/library/mimalloc.php b/src/SPC/builder/unix/library/mimalloc.php index 0808516c..6d89e6df 100644 --- a/src/SPC/builder/unix/library/mimalloc.php +++ b/src/SPC/builder/unix/library/mimalloc.php @@ -14,9 +14,9 @@ trait mimalloc $cmake = UnixCMakeExecutor::create($this) ->addConfigureArgs( '-DMI_BUILD_SHARED=OFF', - '-DMI_INSTALL_TOPLEVEL=ON' + '-DMI_INSTALL_TOPLEVEL=ON', ); - if (SPCTarget::isTarget(SPCTarget::MUSL) || SPCTarget::isTarget(SPCTarget::MUSL_STATIC)) { + if (SPCTarget::getLibc() === 'musl') { $cmake->addConfigureArgs('-DMI_LIBC_MUSL=ON'); } $cmake->build(); diff --git a/src/SPC/builder/unix/library/postgresql.php b/src/SPC/builder/unix/library/postgresql.php index efcfc089..7ca324c2 100644 --- a/src/SPC/builder/unix/library/postgresql.php +++ b/src/SPC/builder/unix/library/postgresql.php @@ -51,7 +51,7 @@ trait postgresql $error_exec_cnt += $output[0] === 0 ? 0 : 1; if (!empty($output[1][0])) { $ldflags = $output[1][0]; - $envs .= SPCTarget::isTarget(SPCTarget::MUSL_STATIC) ? " LDFLAGS=\"{$ldflags} -static\" " : " LDFLAGS=\"{$ldflags}\" "; + $envs .= SPCTarget::isStaticTarget() ? " LDFLAGS=\"{$ldflags} -static\" " : " LDFLAGS=\"{$ldflags}\" "; } $output = shell()->execWithResult("pkg-config --libs-only-l --static {$packages}"); $error_exec_cnt += $output[0] === 0 ? 0 : 1; diff --git a/src/SPC/builder/windows/WindowsBuilder.php b/src/SPC/builder/windows/WindowsBuilder.php index c7450050..25a503eb 100644 --- a/src/SPC/builder/windows/WindowsBuilder.php +++ b/src/SPC/builder/windows/WindowsBuilder.php @@ -34,6 +34,7 @@ class WindowsBuilder extends BuilderBase $this->options = $options; GlobalEnvManager::init(); + GlobalEnvManager::afterInit(); // ---------- set necessary options ---------- // set sdk (require visual studio 16 or 17) diff --git a/src/SPC/command/BuildPHPCommand.php b/src/SPC/command/BuildPHPCommand.php index f9938957..62f4260e 100644 --- a/src/SPC/command/BuildPHPCommand.php +++ b/src/SPC/command/BuildPHPCommand.php @@ -64,8 +64,8 @@ class BuildPHPCommand extends BuildCommand // check dynamic extension build env // linux must build with glibc - if (!empty($shared_extensions) && SPCTarget::isTarget(SPCTarget::MUSL_STATIC)) { - $this->output->writeln('Linux does not support dynamic extension loading with musl-libc full-static build, please build with glibc!'); + if (!empty($shared_extensions) && SPCTarget::isStaticTarget()) { + $this->output->writeln('Linux does not support dynamic extension loading with musl-libc full-static build, please build with shared target!'); return static::FAILURE; } $static_and_shared = array_intersect($static_extensions, $shared_extensions); diff --git a/src/SPC/command/DownloadCommand.php b/src/SPC/command/DownloadCommand.php index 35529f5e..1e895bdb 100644 --- a/src/SPC/command/DownloadCommand.php +++ b/src/SPC/command/DownloadCommand.php @@ -4,7 +4,6 @@ declare(strict_types=1); namespace SPC\command; -use SPC\builder\linux\SystemUtil; use SPC\builder\traits\UnixSystemUtilTrait; use SPC\exception\DownloaderException; use SPC\exception\FileSystemException; @@ -224,12 +223,8 @@ class DownloadCommand extends BaseCommand '{name}' => $source, '{arch}' => arch2gnu(php_uname('m')), '{os}' => strtolower(PHP_OS_FAMILY), - '{libc}' => match (getenv('SPC_TARGET')) { - SPCTarget::MUSL_STATIC, SPCTarget::MUSL => 'musl', - SPCTarget::GLIBC => 'glibc', - default => 'default', - }, - '{libcver}' => PHP_OS_FAMILY === 'Linux' ? (SystemUtil::getLibcVersionIfExists() ?? 'default') : 'default', + '{libc}' => SPCTarget::getLibc() ?? 'default', + '{libcver}' => SPCTarget::getLibcVersion() ?? 'default', ]; $find = str_replace(array_keys($replace), array_values($replace), Config::getPreBuilt('match-pattern')); // find filename in asset list diff --git a/src/SPC/command/dev/PackLibCommand.php b/src/SPC/command/dev/PackLibCommand.php index 29a22353..e51cdb17 100644 --- a/src/SPC/command/dev/PackLibCommand.php +++ b/src/SPC/command/dev/PackLibCommand.php @@ -6,7 +6,6 @@ namespace SPC\command\dev; use SPC\builder\BuilderProvider; use SPC\builder\LibraryBase; -use SPC\builder\linux\SystemUtil; use SPC\command\BuildCommand; use SPC\exception\ExceptionHandler; use SPC\exception\FileSystemException; @@ -77,12 +76,8 @@ class PackLibCommand extends BuildCommand '{name}' => $lib->getName(), '{arch}' => arch2gnu(php_uname('m')), '{os}' => strtolower(PHP_OS_FAMILY), - '{libc}' => match (getenv('SPC_TARGET')) { - SPCTarget::MUSL_STATIC, SPCTarget::MUSL => 'musl', - SPCTarget::GLIBC => 'glibc', - default => 'default', - }, - '{libcver}' => SystemUtil::getLibcVersionIfExists() ?? 'default', + '{libc}' => SPCTarget::getLibc() ?? 'default', + '{libcver}' => SPCTarget::getLibcVersion() ?? 'default', ]; // detect suffix, for proper tar option $tar_option = $this->getTarOptionFromSuffix(Config::getPreBuilt('match-pattern')); diff --git a/src/SPC/store/Downloader.php b/src/SPC/store/Downloader.php index 050cd88d..f031d73a 100644 --- a/src/SPC/store/Downloader.php +++ b/src/SPC/store/Downloader.php @@ -4,7 +4,6 @@ declare(strict_types=1); namespace SPC\store; -use SPC\builder\linux\SystemUtil; use SPC\exception\DownloaderException; use SPC\exception\FileSystemException; use SPC\exception\RuntimeException; @@ -594,12 +593,8 @@ class Downloader { $os_family = PHP_OS_FAMILY; $gnu_arch = getenv('GNU_ARCH') ?: 'unknown'; - $libc = match (getenv('SPC_TARGET')) { - SPCTarget::MUSL_STATIC, SPCTarget::MUSL => 'musl', - SPCTarget::GLIBC => 'glibc', - default => 'default', - }; - $libc_version = SystemUtil::getLibcVersionIfExists() ?? 'default'; + $libc = SPCTarget::getLibc(); + $libc_version = SPCTarget::getLibcVersion() ?? 'default'; return "{$source}-{$os_family}-{$gnu_arch}-{$libc}-{$libc_version}"; } diff --git a/src/SPC/store/SourcePatcher.php b/src/SPC/store/SourcePatcher.php index 69d3a649..fe7d5333 100644 --- a/src/SPC/store/SourcePatcher.php +++ b/src/SPC/store/SourcePatcher.php @@ -11,6 +11,7 @@ use SPC\builder\unix\UnixBuilderBase; use SPC\exception\FileSystemException; use SPC\exception\RuntimeException; use SPC\exception\WrongUsageException; +use SPC\util\SPCTarget; class SourcePatcher { @@ -456,7 +457,7 @@ class SourcePatcher public static function patchFfiCentos7FixO3strncmp(): bool { - if (PHP_OS_FAMILY !== 'Linux' || SystemUtil::getLibcVersionIfExists() > '2.17') { + if (!($ver = SPCTarget::getLibcVersion()) || version_compare($ver, '2.17', '>')) { return false; } if (!file_exists(SOURCE_PATH . '/php-src/main/php_version.h')) { diff --git a/src/SPC/store/pkg/GoXcaddy.php b/src/SPC/store/pkg/GoXcaddy.php index e0c7c5b9..8dc1cf2d 100644 --- a/src/SPC/store/pkg/GoXcaddy.php +++ b/src/SPC/store/pkg/GoXcaddy.php @@ -7,7 +7,6 @@ namespace SPC\store\pkg; use SPC\store\Downloader; use SPC\store\FileSystem; use SPC\store\LockFile; -use SPC\util\GlobalEnvManager; class GoXcaddy extends CustomPackage { @@ -62,7 +61,6 @@ class GoXcaddy extends CustomPackage FileSystem::extractPackage($name, $source_type, $filename, $extract); - GlobalEnvManager::init(); // install xcaddy shell() ->appendEnv([ diff --git a/src/SPC/util/toolchain/ClangNativeToolchain.php b/src/SPC/toolchain/ClangNativeToolchain.php similarity index 77% rename from src/SPC/util/toolchain/ClangNativeToolchain.php rename to src/SPC/toolchain/ClangNativeToolchain.php index ac93513a..c5186521 100644 --- a/src/SPC/util/toolchain/ClangNativeToolchain.php +++ b/src/SPC/toolchain/ClangNativeToolchain.php @@ -2,30 +2,25 @@ declare(strict_types=1); -namespace SPC\util\toolchain; +namespace SPC\toolchain; use SPC\builder\freebsd\SystemUtil as FreeBSDSystemUtil; use SPC\builder\linux\SystemUtil as LinuxSystemUtil; use SPC\builder\macos\SystemUtil as MacOSSystemUtil; use SPC\exception\WrongUsageException; use SPC\util\GlobalEnvManager; -use SPC\util\SPCTarget; class ClangNativeToolchain implements ToolchainInterface { - public function initEnv(string $target): void + public function initEnv(): void { - // native toolchain does not support versioning - if (SPCTarget::getTargetSuffix() !== null) { - throw new WrongUsageException('Clang native toolchain does not support versioning.'); - } GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_CC=clang'); GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_CXX=clang++'); GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_AR=ar'); GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_LD=ld'); } - public function afterInit(string $target): void + public function afterInit(): void { // check clang exists match (PHP_OS_FAMILY) { diff --git a/src/SPC/util/toolchain/GccNativeToolchain.php b/src/SPC/toolchain/GccNativeToolchain.php similarity index 77% rename from src/SPC/util/toolchain/GccNativeToolchain.php rename to src/SPC/toolchain/GccNativeToolchain.php index 2547334a..bd8cc868 100644 --- a/src/SPC/util/toolchain/GccNativeToolchain.php +++ b/src/SPC/toolchain/GccNativeToolchain.php @@ -2,30 +2,25 @@ declare(strict_types=1); -namespace SPC\util\toolchain; +namespace SPC\toolchain; use SPC\builder\freebsd\SystemUtil as FreeBSDSystemUtil; use SPC\builder\linux\SystemUtil as LinuxSystemUtil; use SPC\builder\macos\SystemUtil as MacOSSystemUtil; use SPC\exception\WrongUsageException; use SPC\util\GlobalEnvManager; -use SPC\util\SPCTarget; class GccNativeToolchain implements ToolchainInterface { - public function initEnv(string $target): void + public function initEnv(): void { - // native toolchain does not support versioning - if (SPCTarget::getTargetSuffix() !== null) { - throw new WrongUsageException('gcc native toolchain does not support versioning.'); - } GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_CC=gcc'); GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_CXX=g++'); GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_AR=ar'); GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_LD=ld.gold'); } - public function afterInit(string $target): void + public function afterInit(): void { // check gcc exists match (PHP_OS_FAMILY) { diff --git a/src/SPC/toolchain/MSVCToolchain.php b/src/SPC/toolchain/MSVCToolchain.php new file mode 100644 index 00000000..567cff38 --- /dev/null +++ b/src/SPC/toolchain/MSVCToolchain.php @@ -0,0 +1,12 @@ + MuslToolchain::class, // use musl toolchain by default, after zig pr merged, change this to ZigToolchain::class + 'Windows' => MSVCToolchain::class, + 'Darwin' => ClangNativeToolchain::class, + 'BSD' => ClangNativeToolchain::class, + ]; + + /** + * @throws WrongUsageException + */ + public static function initToolchain(): void + { + $libc = getenv('SPC_LIBC'); + if ($libc !== false) { + // uncomment this when zig pr is merged + // logger()->warning('SPC_LIBC is deprecated, please use SPC_TARGET instead.'); + $toolchain = match ($libc) { + 'musl' => SystemUtil::isMuslDist() ? GccNativeToolchain::class : MuslToolchain::class, + 'glibc' => !SystemUtil::isMuslDist() ? GccNativeToolchain::class : throw new WrongUsageException('SPC_TARGET must be musl-static or musl for musl dist.'), + default => throw new WrongUsageException('Unsupported SPC_LIBC value: ' . $libc), + }; + } else { + $toolchain = self::OS_DEFAULT_TOOLCHAIN[PHP_OS_FAMILY]; + } + $toolchainClass = $toolchain; + /* @var ToolchainInterface $toolchainClass */ + (new $toolchainClass())->initEnv(); + GlobalEnvManager::putenv("SPC_TOOLCHAIN={$toolchain}"); + } + + public static function afterInitToolchain(): void + { + if (!getenv('SPC_TOOLCHAIN')) { + throw new WrongUsageException('SPC_TOOLCHAIN not set'); + } + $toolchain = getenv('SPC_TOOLCHAIN'); + /* @var ToolchainInterface $toolchain */ + (new $toolchain())->afterInit(); + } +} diff --git a/src/SPC/toolchain/ZigToolchain.php b/src/SPC/toolchain/ZigToolchain.php new file mode 100644 index 00000000..3922fecb --- /dev/null +++ b/src/SPC/toolchain/ZigToolchain.php @@ -0,0 +1,12 @@ +warning('SPC_LIBC is deprecated, please use SPC_TARGET instead.'); - $target = match (getenv('SPC_LIBC')) { - 'musl' => SPCTarget::MUSL_STATIC, - 'musl-shared' => SPCTarget::MUSL, - 'glibc' => SPCTarget::GLIBC, - default => throw new WrongUsageException('Unsupported SPC_LIBC value: ' . getenv('SPC_LIBC')), - }; - self::putenv("SPC_TARGET={$target}"); - self::putenv('SPC_LIBC'); - } - - // auto-select toolchain based on target and OS temporarily - // TODO: use 'zig' instead of 'gcc-native' when ZigToolchain is implemented - $toolchain = match (SPCTarget::getTargetName()) { - SPCTarget::MUSL_STATIC, SPCTarget::MUSL => SystemUtil::isMuslDist() ? 'gcc-native' : 'musl', - SPCTarget::MACHO => 'clang-native', - SPCTarget::MSVC_STATIC => 'msvc', - SPCTarget::GLIBC => !SystemUtil::isMuslDist() ? 'gcc-native' : throw new WrongUsageException('SPC_TARGET must be musl-static or musl for musl dist.'), - default => throw new WrongUsageException('Unknown SPC_TARGET: ' . getenv('SPC_TARGET')), - }; - - SPCTarget::initTargetForToolchain($toolchain); + ToolchainManager::initToolchain(); // apply second time $ini2 = self::readIniFile(); @@ -123,9 +100,15 @@ class GlobalEnvManager } } + /** + * Initialize the toolchain after the environment variables are set. + * The toolchain or environment availability check is done here. + * + * @throws WrongUsageException + */ public static function afterInit(): void { - SPCTarget::afterInitTargetForToolchain(); + ToolchainManager::afterInitToolchain(); } /** diff --git a/src/SPC/util/SPCConfigUtil.php b/src/SPC/util/SPCConfigUtil.php index 9335e88d..fec3c089 100644 --- a/src/SPC/util/SPCConfigUtil.php +++ b/src/SPC/util/SPCConfigUtil.php @@ -55,7 +55,7 @@ class SPCConfigUtil ob_get_clean(); $ldflags = $this->getLdflagsString(); $libs = $this->getLibsString($libraries, $with_dependencies); - if (SPCTarget::isTarget(SPCTarget::MACHO)) { + if (SPCTarget::getTargetOS() === 'Darwin') { $libs .= " {$this->getFrameworksString($extensions)}"; } $cflags = $this->getIncludesString(); diff --git a/src/SPC/util/SPCTarget.php b/src/SPC/util/SPCTarget.php index 265c3d51..5f091a8e 100644 --- a/src/SPC/util/SPCTarget.php +++ b/src/SPC/util/SPCTarget.php @@ -4,13 +4,8 @@ declare(strict_types=1); namespace SPC\util; +use SPC\builder\linux\SystemUtil; use SPC\exception\WrongUsageException; -use SPC\util\toolchain\ClangNativeToolchain; -use SPC\util\toolchain\GccNativeToolchain; -use SPC\util\toolchain\MSVCToolchain; -use SPC\util\toolchain\MuslToolchain; -use SPC\util\toolchain\ToolchainInterface; -use SPC\util\toolchain\ZigToolchain; /** * SPC build target constants and toolchain initialization. @@ -18,86 +13,75 @@ use SPC\util\toolchain\ZigToolchain; */ class SPCTarget { - public const MUSL = 'musl'; - - public const MUSL_STATIC = 'musl-static'; - - public const GLIBC = 'glibc'; - - public const MACHO = 'macho'; - - public const MSVC_STATIC = 'msvc-static'; - - public const TOOLCHAIN_LIST = [ - 'musl' => MuslToolchain::class, - 'gcc-native' => GccNativeToolchain::class, - 'clang-native' => ClangNativeToolchain::class, - 'msvc' => MSVCToolchain::class, - 'zig' => ZigToolchain::class, + public const array LIBC_LIST = [ + 'musl', + 'glibc', ]; - public static function isTarget(string $target): bool - { - $env = getenv('SPC_TARGET'); - if ($env === false) { - return false; - } - $env = strtolower($env); - // ver - $env = explode('@', $env)[0]; - return $env === $target; - } - + /** + * Returns whether the target is a full-static target. + */ public static function isStaticTarget(): bool { $env = getenv('SPC_TARGET'); - if ($env === false) { - return false; + $libc = getenv('SPC_LIBC'); + // if SPC_LIBC is set, it means the target is static, remove it when 3.0 is released + if ($libc === 'musl') { + return true; } - $env = strtolower($env); - // ver - $env = explode('@', $env)[0]; - return str_ends_with($env, '-static'); + // TODO: add zig target parser here + return false; } - public static function initTargetForToolchain(string $toolchain): void + /** + * Returns the libc type if set, for other OS, it will always return null. + */ + public static function getLibc(): ?string + { + $env = getenv('SPC_TARGET'); + $libc = getenv('SPC_LIBC'); + if ($libc !== false) { + return $libc; + } + // TODO: zig target parser + return null; + } + + /** + * Returns the libc version if set, for other OS, it will always return null. + */ + public static function getLibcVersion(): ?string + { + $env = getenv('SPC_TARGET'); + $libc = getenv('SPC_LIBC'); + if ($libc !== false) { + // legacy method: get a version from system + return SystemUtil::getLibcVersionIfExists($libc); + } + // TODO: zig target parser + + return null; + } + + /** + * Returns the target OS family, e.g. Linux, Darwin, Windows, BSD. + * Currently, we only support native building. + * + * @return 'BSD'|'Darwin'|'Linux'|'Windows' + * @throws WrongUsageException + */ + public static function getTargetOS(): string { $target = getenv('SPC_TARGET'); - $toolchain = strtolower($toolchain); - if (isset(self::TOOLCHAIN_LIST[$toolchain])) { - $toolchainClass = self::TOOLCHAIN_LIST[$toolchain]; - /* @var ToolchainInterface $toolchainClass */ - (new $toolchainClass())->initEnv($target); + if ($target === false) { + return PHP_OS_FAMILY; } - GlobalEnvManager::putenv("SPC_TOOLCHAIN={$toolchain}"); - } - - public static function afterInitTargetForToolchain() - { - if (!getenv('SPC_TOOLCHAIN')) { - throw new WrongUsageException('SPC_TOOLCHAIN not set'); - } - $toolchain = getenv('SPC_TOOLCHAIN'); - if (!isset(self::TOOLCHAIN_LIST[$toolchain])) { - throw new WrongUsageException("Unknown toolchain: {$toolchain}"); - } - $toolchainClass = self::TOOLCHAIN_LIST[$toolchain]; - (new $toolchainClass())->afterInit(getenv('SPC_TARGET')); - } - - public static function getTargetName(): ?string - { - $target = getenv('SPC_TARGET'); - $target = strtolower($target); - // ver - return explode('@', $target)[0]; - } - - public static function getTargetSuffix(): ?string - { - $target = getenv('SPC_TARGET'); - $target = strtolower($target); - // ver - return explode('@', $target)[1] ?? null; + // TODO: zig target parser like below? + return match (true) { + str_contains($target, 'linux') => 'Linux', + str_contains($target, 'macos') => 'Darwin', + str_contains($target, 'windows') => 'Windows', + default => throw new WrongUsageException('Cannot parse target.'), + }; } } diff --git a/src/SPC/util/toolchain/MSVCToolchain.php b/src/SPC/util/toolchain/MSVCToolchain.php deleted file mode 100644 index 2ec8111c..00000000 --- a/src/SPC/util/toolchain/MSVCToolchain.php +++ /dev/null @@ -1,12 +0,0 @@ -