2025-06-29 16:00:17 +08:00
< ? php
declare ( strict_types = 1 );
namespace SPC\toolchain ;
use SPC\builder\linux\SystemUtil ;
2025-07-01 18:22:05 +07:00
use SPC\exception\RuntimeException ;
2025-06-29 16:00:17 +08:00
use SPC\exception\WrongUsageException ;
use SPC\util\GlobalEnvManager ;
2025-07-01 18:22:05 +07:00
use SPC\util\SPCTarget ;
2025-06-29 16:00:17 +08:00
class ToolchainManager
{
public const array OS_DEFAULT_TOOLCHAIN = [
2025-07-01 14:01:48 +07:00
'Linux' => ZigToolchain :: class ,
2025-06-29 16:00:17 +08:00
'Windows' => MSVCToolchain :: class ,
'Darwin' => ClangNativeToolchain :: class ,
'BSD' => ClangNativeToolchain :: class ,
];
2025-07-01 14:01:48 +07:00
public static function getToolchainClass () : string
2025-06-29 16:00:17 +08:00
{
$libc = getenv ( 'SPC_LIBC' );
2025-07-01 16:21:57 +07:00
if ( $libc && ! getenv ( 'SPC_TARGET' )) {
2025-07-01 15:05:44 +07:00
// TODO: @crazywhalecc this breaks tests
// logger()->warning('SPC_LIBC is deprecated, please use SPC_TARGET instead.');
2025-07-01 14:01:48 +07:00
return match ( $libc ) {
2025-06-29 16:00:17 +08:00
'musl' => SystemUtil :: isMuslDist () ? GccNativeToolchain :: class : MuslToolchain :: class ,
2025-07-01 14:41:14 +07:00
'glibc' => ! SystemUtil :: isMuslDist () ? GccNativeToolchain :: class : throw new WrongUsageException ( 'SPC_LIBC must be musl for musl dist.' ),
2025-06-29 16:00:17 +08:00
default => throw new WrongUsageException ( 'Unsupported SPC_LIBC value: ' . $libc ),
};
}
2025-07-01 14:01:48 +07:00
return self :: OS_DEFAULT_TOOLCHAIN [ PHP_OS_FAMILY ];
}
/**
* @ throws WrongUsageException
*/
public static function initToolchain () : void
{
$toolchainClass = self :: getToolchainClass ();
2025-06-29 16:00:17 +08:00
/* @var ToolchainInterface $toolchainClass */
( new $toolchainClass ()) -> initEnv ();
2025-07-01 14:01:48 +07:00
GlobalEnvManager :: putenv ( " SPC_TOOLCHAIN= { $toolchainClass } " );
2025-06-29 16:00:17 +08:00
}
public static function afterInitToolchain () : void
{
if ( ! getenv ( 'SPC_TOOLCHAIN' )) {
2025-07-01 18:22:05 +07:00
throw new WrongUsageException ( 'SPC_TOOLCHAIN was not properly set. Please contact the developers.' );
}
if ( SPCTarget :: getLibc () === 'musl' && ! SPCTarget :: isStatic () && ! file_exists ( '/lib/ld-musl-x86_64.so.1' )) {
throw new RuntimeException ( 'You are linking against musl libc dynamically, but musl libc is not installed. Please install it with `sudo dnf install musl-libc` or `sudo apt install musl`' );
}
if ( SPCTarget :: getLibc () === 'glibc' && SystemUtil :: isMuslDist ()) {
throw new RuntimeException ( 'You are linking against glibc libc dynamically, which is only supported on glibc distros.' );
2025-06-29 16:00:17 +08:00
}
$toolchain = getenv ( 'SPC_TOOLCHAIN' );
/* @var ToolchainInterface $toolchain */
( new $toolchain ()) -> afterInit ();
}
}