Move extra runtime object to zig toolchain

This commit is contained in:
crazywhalecc 2025-07-05 10:48:56 +08:00
parent 013a19e25b
commit 5f8cd972cd
No known key found for this signature in database
GPG Key ID: 1F4BDD59391F2680
3 changed files with 44 additions and 81 deletions

View File

@ -4,12 +4,13 @@ declare(strict_types=1);
namespace SPC\builder;
use SPC\builder\linux\SystemUtil;
use SPC\exception\FileSystemException;
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;
class Extension
@ -216,16 +217,15 @@ class Extension
*/
public function patchBeforeSharedMake(): bool
{
$extra = SystemUtil::getExtraRuntimeObjects();
if (!$extra) {
return false;
if (ToolchainManager::getToolchainClass() === ZigToolchain::class && ($extra = (new ZigToolchain())->getExtraRuntimeObjects())) {
FileSystem::replaceFileRegex(
$this->source_dir . '/Makefile',
"/^(shared_objects_{$this->getName()}\\s*=.*)$/m",
"$1 {$extra}",
);
return true;
}
FileSystem::replaceFileRegex(
$this->source_dir . '/Makefile',
"/^(shared_objects_{$this->getName()}\\s*=.*)$/m",
"$1 {$extra}",
);
return true;
return false;
}
/**

View File

@ -5,9 +5,6 @@ declare(strict_types=1);
namespace SPC\builder\linux;
use SPC\builder\traits\UnixSystemUtilTrait;
use SPC\exception\RuntimeException;
use SPC\toolchain\ToolchainManager;
use SPC\toolchain\ZigToolchain;
use SPC\util\SPCTarget;
class SystemUtil
@ -16,8 +13,6 @@ class SystemUtil
public static ?string $libc_version = null;
private static ?string $extra_runtime_objects = null;
/** @noinspection PhpMissingBreakStatementInspection */
public static function getOSRelease(): array
{
@ -80,39 +75,6 @@ class SystemUtil
return $ncpu;
}
/**
* @throws RuntimeException
*/
public static function getCCType(?string $cc = null): string
{
$cc ??= getenv('CC');
return match (true) {
str_contains($cc, 'zig') => 'clang',
str_ends_with($cc, 'c++'), str_ends_with($cc, 'cc'), str_ends_with($cc, 'g++'), str_ends_with($cc, 'gcc') => 'gcc',
$cc === 'clang++', $cc === 'clang', str_starts_with($cc, 'musl-clang') => 'clang',
default => throw new RuntimeException("unknown cc type: {$cc}"),
};
}
/**
* @throws RuntimeException
* @noinspection PhpUnused
*/
public static function getCrossCompilePrefix(string $cc, string $arch): string
{
return match (static::getCCType($cc)) {
// guessing clang toolchains
'clang' => match ($arch) {
'x86_64' => 'x86_64-linux-gnu-',
'arm64', 'aarch64' => 'aarch64-linux-gnu-',
default => throw new RuntimeException('unsupported arch: ' . $arch),
},
// remove gcc postfix
'gcc' => str_replace('-cc', '', str_replace('-gcc', '', $cc)) . '-',
default => throw new RuntimeException('unsupported cc'),
};
}
public static function findStaticLib(string $name): ?array
{
$paths = getenv('LIBPATH');
@ -233,37 +195,4 @@ class SystemUtil
}
return null;
}
public static function getExtraRuntimeObjects(): string
{
if (ToolchainManager::getToolchainClass() !== ZigToolchain::class) {
return '';
}
if (self::$extra_runtime_objects !== null) {
return self::$extra_runtime_objects;
}
$paths = ['/usr/lib/gcc', '/usr/local/lib/gcc'];
$objects = ['crtbeginS.o', 'crtendS.o'];
$found = [];
foreach ($objects as $obj) {
$located = null;
foreach ($paths as $base) {
$output = shell_exec("find {$base} -name {$obj} 2>/dev/null | grep -v '/32/' | head -n 1");
$line = trim((string) $output);
if ($line !== '') {
$located = $line;
break;
}
}
if ($located) {
$found[] = $located;
}
}
self::$extra_runtime_objects = implode(' ', $found);
return implode(' ', $found);
}
}

View File

@ -26,4 +26,38 @@ class ZigToolchain implements ToolchainInterface
}
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;
}
$paths = ['/usr/lib/gcc', '/usr/local/lib/gcc'];
$objects = ['crtbeginS.o', 'crtendS.o'];
$found = [];
foreach ($objects as $obj) {
$located = null;
foreach ($paths as $base) {
$output = shell_exec("find {$base} -name {$obj} 2>/dev/null | grep -v '/32/' | head -n 1");
$line = trim((string) $output);
if ($line !== '') {
$located = $line;
break;
}
}
if ($located) {
$found[] = $located;
}
}
$cache = implode(' ', $found);
return $cache;
}
}