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
{
2025-07-01 23:01:53 +07:00
if ( $tc = getenv ( 'SPC_TOOLCHAIN' )) {
return $tc ;
}
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-28 14:51:13 +07:00
// trigger_error('Setting SPC_LIBC is deprecated, please use SPC_TARGET instead.', E_USER_DEPRECATED);
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.' );
}
2025-07-05 12:19:26 +07:00
$musl_wrapper_lib = sprintf ( '/lib/ld-musl-%s.so.1' , php_uname ( 'm' ));
if ( SPCTarget :: getLibc () === 'musl' && ! SPCTarget :: isStatic () && ! file_exists ( $musl_wrapper_lib )) {
2025-07-01 18:22:05 +07:00
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 ()) {
2025-07-01 18:23:02 +07:00
throw new RuntimeException ( 'You are linking against glibc dynamically, which is only supported on musl distros.' );
2025-06-29 16:00:17 +08:00
}
$toolchain = getenv ( 'SPC_TOOLCHAIN' );
/* @var ToolchainInterface $toolchain */
( new $toolchain ()) -> afterInit ();
}
}