simplify common zig code paths

This commit is contained in:
henderkes
2026-05-23 16:14:02 +07:00
parent e7fb1e203f
commit 1ae989df59
8 changed files with 73 additions and 19 deletions

View File

@@ -73,7 +73,7 @@ class llvm_compiler_rt
{ {
$sourceDir ??= SOURCE_PATH . '/llvm-compiler-rt'; $sourceDir ??= SOURCE_PATH . '/llvm-compiler-rt';
$triple ??= SystemTarget::getCanonicalTriple(); $triple ??= SystemTarget::getCanonicalTriple();
$libDir = PKG_ROOT_PATH . '/zig/lib/' . $triple; $libDir = zig::path() . '/lib/' . $triple;
if ($this->isBuilt($libDir)) { if ($this->isBuilt($libDir)) {
return; return;
} }
@@ -101,7 +101,10 @@ class llvm_compiler_rt
private function detectZigLlvmVersion(): ?string private function detectZigLlvmVersion(): ?string
{ {
[$rc, $out] = shell()->execWithResult('zig cc --version', false); if (!zig::isInstalled()) {
return null;
}
[$rc, $out] = shell()->execWithResult(escapeshellarg(zig::binary()) . ' cc --version', false);
if ($rc !== 0) { if ($rc !== 0) {
return null; return null;
} }

View File

@@ -102,8 +102,8 @@ class llvm_tools
'-DLLVM_BUILD_LLVM_DYLIB=OFF', '-DLLVM_BUILD_LLVM_DYLIB=OFF',
'-DLLVM_LINK_LLVM_DYLIB=OFF', '-DLLVM_LINK_LLVM_DYLIB=OFF',
'-DBUILD_SHARED_LIBS=OFF', '-DBUILD_SHARED_LIBS=OFF',
'-DCMAKE_C_COMPILER=' . PKG_ROOT_PATH . '/zig/zig-cc', '-DCMAKE_C_COMPILER=' . zig::binary('zig-cc'),
'-DCMAKE_CXX_COMPILER=' . PKG_ROOT_PATH . '/zig/zig-c++', '-DCMAKE_CXX_COMPILER=' . zig::binary('zig-c++'),
'-DCMAKE_INSTALL_PREFIX=' . $installDir, '-DCMAKE_INSTALL_PREFIX=' . $installDir,
])); ]));
$jobs = ApplicationContext::get(PackageBuilder::class)->concurrency; $jobs = ApplicationContext::get(PackageBuilder::class)->concurrency;
@@ -137,11 +137,10 @@ class llvm_tools
private function detectLlvmVersion(): ?string private function detectLlvmVersion(): ?string
{ {
$zig = PKG_ROOT_PATH . '/zig/zig'; if (!zig::isInstalled()) {
if (!is_file($zig)) {
return null; return null;
} }
[$rc, $out] = shell()->execWithResult(escapeshellarg($zig) . ' cc --version', false); [$rc, $out] = shell()->execWithResult(escapeshellarg(zig::binary()) . ' cc --version', false);
if ($rc !== 0) { if ($rc !== 0) {
return null; return null;
} }

View File

@@ -15,6 +15,23 @@ use StaticPHP\Runtime\SystemTarget;
class zig class zig
{ {
/** Directory zig extracts into. */
public static function path(): string
{
return PKG_ROOT_PATH . '/zig';
}
/** Path to a binary inside the zig install dir (zig, zig-cc, zig-c++, zig-ar, …). */
public static function binary(string $name = 'zig'): string
{
return self::path() . '/' . $name;
}
public static function isInstalled(): bool
{
return is_file(self::binary());
}
#[CustomBinary('zig', [ #[CustomBinary('zig', [
'linux-x86_64', 'linux-x86_64',
'linux-aarch64', 'linux-aarch64',

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace StaticPHP\Doctor\Item; namespace StaticPHP\Doctor\Item;
use Package\Artifact\llvm_compiler_rt; use Package\Artifact\llvm_compiler_rt;
use Package\Artifact\zig;
use StaticPHP\Attribute\Doctor\CheckItem; use StaticPHP\Attribute\Doctor\CheckItem;
use StaticPHP\Attribute\Doctor\FixItem; use StaticPHP\Attribute\Doctor\FixItem;
use StaticPHP\Attribute\Doctor\OptionalCheck; use StaticPHP\Attribute\Doctor\OptionalCheck;
@@ -27,7 +28,7 @@ class LlvmCompilerRtCheck
#[CheckItem('if llvm-compiler-rt is built for current target', level: 799)] #[CheckItem('if llvm-compiler-rt is built for current target', level: 799)]
public function checkLlvmCompilerRt(): CheckResult public function checkLlvmCompilerRt(): CheckResult
{ {
$libDir = PKG_ROOT_PATH . '/zig/lib/' . SystemTarget::getCanonicalTriple(); $libDir = zig::dir() . '/lib/' . SystemTarget::getCanonicalTriple();
if (new llvm_compiler_rt()->isBuilt($libDir)) { if (new llvm_compiler_rt()->isBuilt($libDir)) {
return CheckResult::ok($libDir); return CheckResult::ok($libDir);
} }
@@ -41,7 +42,7 @@ class LlvmCompilerRtCheck
$installer->addInstallPackage('llvm-compiler-rt'); $installer->addInstallPackage('llvm-compiler-rt');
$installer->run(true); $installer->run(true);
new llvm_compiler_rt()->buildForTriple(); new llvm_compiler_rt()->buildForTriple();
$libDir = PKG_ROOT_PATH . '/zig/lib/' . SystemTarget::getCanonicalTriple(); $libDir = zig::dir() . '/lib/' . SystemTarget::getCanonicalTriple();
return new llvm_compiler_rt()->isBuilt($libDir); return new llvm_compiler_rt()->isBuilt($libDir);
} }
} }

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace StaticPHP\Doctor\Item; namespace StaticPHP\Doctor\Item;
use Package\Artifact\zig;
use StaticPHP\Attribute\Doctor\CheckItem; use StaticPHP\Attribute\Doctor\CheckItem;
use StaticPHP\Attribute\Doctor\FixItem; use StaticPHP\Attribute\Doctor\FixItem;
use StaticPHP\Attribute\Doctor\OptionalCheck; use StaticPHP\Attribute\Doctor\OptionalCheck;
@@ -26,7 +27,7 @@ class ZigCheck
public function checkZig(): CheckResult public function checkZig(): CheckResult
{ {
if (new PackageInstaller()->addInstallPackage('zig')->isPackageInstalled('zig')) { if (new PackageInstaller()->addInstallPackage('zig')->isPackageInstalled('zig')) {
return CheckResult::ok(PKG_ROOT_PATH . '/zig/zig'); return CheckResult::ok(zig::binary());
} }
return CheckResult::fail('zig is not installed', 'install-zig'); return CheckResult::fail('zig is not installed', 'install-zig');
} }

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace StaticPHP\Runtime; namespace StaticPHP\Runtime;
use StaticPHP\Toolchain\ZigToolchain;
use StaticPHP\Util\System\LinuxUtil; use StaticPHP\Util\System\LinuxUtil;
/** /**
@@ -16,7 +17,7 @@ class SystemTarget
*/ */
public static function getLibc(): ?string public static function getLibc(): ?string
{ {
if ($target = getenv('SPC_TARGET')) { if ($target = self::target()) {
if (str_contains($target, '-gnu')) { if (str_contains($target, '-gnu')) {
return 'glibc'; return 'glibc';
} }
@@ -57,7 +58,7 @@ class SystemTarget
public static function getLibcVersion(): ?string public static function getLibcVersion(): ?string
{ {
if (PHP_OS_FAMILY === 'Linux') { if (PHP_OS_FAMILY === 'Linux') {
$target = (string) getenv('SPC_TARGET'); $target = self::target();
if (str_contains($target, '-gnu.2.')) { if (str_contains($target, '-gnu.2.')) {
return preg_match('/-gnu\.(2\.\d+)/', $target, $matches) ? $matches[1] : null; return preg_match('/-gnu\.(2\.\d+)/', $target, $matches) ? $matches[1] : null;
} }
@@ -75,7 +76,7 @@ class SystemTarget
*/ */
public static function getTargetOS(): string public static function getTargetOS(): string
{ {
$target = (string) getenv('SPC_TARGET'); $target = self::target();
return match (true) { return match (true) {
str_contains($target, '-linux') => 'Linux', str_contains($target, '-linux') => 'Linux',
str_contains($target, '-macos') => 'Darwin', str_contains($target, '-macos') => 'Darwin',
@@ -91,7 +92,7 @@ class SystemTarget
*/ */
public static function getTargetArch(): string public static function getTargetArch(): string
{ {
$target = (string) getenv('SPC_TARGET'); $target = self::target();
return match (true) { return match (true) {
str_contains($target, 'x86_64') || str_contains($target, 'amd64') => 'x86_64', str_contains($target, 'x86_64') || str_contains($target, 'amd64') => 'x86_64',
str_contains($target, 'aarch64') || str_contains($target, 'arm64') => 'aarch64', str_contains($target, 'aarch64') || str_contains($target, 'arm64') => 'aarch64',
@@ -136,7 +137,7 @@ class SystemTarget
*/ */
public static function getCanonicalTriple(): string public static function getCanonicalTriple(): string
{ {
$target = (string) getenv('SPC_TARGET'); $target = self::target();
if ($target !== '' && !str_contains($target, 'native')) { if ($target !== '' && !str_contains($target, 'native')) {
$cleaned = (string) preg_replace('/(-gnu|-musl)\.[\d.]+/', '$1', $target); $cleaned = (string) preg_replace('/(-gnu|-musl)\.[\d.]+/', '$1', $target);
$cleaned = preg_split('/\s+/', trim($cleaned))[0] ?? ''; $cleaned = preg_split('/\s+/', trim($cleaned))[0] ?? '';
@@ -161,7 +162,7 @@ class SystemTarget
*/ */
public static function getAutoconfHostTriple(): ?string public static function getAutoconfHostTriple(): ?string
{ {
$target = (string) getenv('SPC_TARGET'); $target = self::target();
if ($target === '' || str_contains($target, 'native')) { if ($target === '' || str_contains($target, 'native')) {
return null; return null;
} }
@@ -183,4 +184,14 @@ class SystemTarget
} }
return $cleaned; return $cleaned;
} }
/** native toolchains ignore SPC_TARGET */
private static function target(): string
{
$tc = (string) getenv('SPC_TOOLCHAIN');
if ($tc !== '' && $tc !== ZigToolchain::class) {
return '';
}
return (string) getenv('SPC_TARGET');
}
} }

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace StaticPHP\Toolchain; namespace StaticPHP\Toolchain;
use Package\Artifact\llvm_compiler_rt; use Package\Artifact\llvm_compiler_rt;
use Package\Artifact\zig;
use StaticPHP\DI\ApplicationContext; use StaticPHP\DI\ApplicationContext;
use StaticPHP\Package\PackageBuilder; use StaticPHP\Package\PackageBuilder;
use StaticPHP\Package\PackageInstaller; use StaticPHP\Package\PackageInstaller;
@@ -56,7 +57,7 @@ class ZigToolchain implements UnixToolchainInterface
GlobalEnvManager::putenv("SPC_DEFAULT_CXXFLAGS={$cxxflags}"); GlobalEnvManager::putenv("SPC_DEFAULT_CXXFLAGS={$cxxflags}");
GlobalEnvManager::putenv("SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS={$extraCflags}"); GlobalEnvManager::putenv("SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS={$extraCflags}");
GlobalEnvManager::putenv('RANLIB=zig-ranlib'); GlobalEnvManager::putenv('RANLIB=zig-ranlib');
GlobalEnvManager::putenv('SPC_COMPILER_RT_DIR=' . PKG_ROOT_PATH . '/zig/lib/' . SystemTarget::getCanonicalTriple()); GlobalEnvManager::putenv('SPC_COMPILER_RT_DIR=' . zig::path() . '/lib/' . SystemTarget::getCanonicalTriple());
GlobalEnvManager::putenv('OBJCOPY=' . PKG_ROOT_PATH . '/llvm-tools/bin/llvm-objcopy'); GlobalEnvManager::putenv('OBJCOPY=' . PKG_ROOT_PATH . '/llvm-tools/bin/llvm-objcopy');
$extra_libs = getenv('SPC_EXTRA_LIBS') ?: ''; $extra_libs = getenv('SPC_EXTRA_LIBS') ?: '';
if (!str_contains($extra_libs, '-lunwind')) { if (!str_contains($extra_libs, '-lunwind')) {
@@ -112,9 +113,12 @@ class ZigToolchain implements UnixToolchainInterface
private function ensureCompilerRt(): void private function ensureCompilerRt(): void
{ {
if (!zig::isInstalled()) {
return;
}
$rt = new llvm_compiler_rt(); $rt = new llvm_compiler_rt();
$triple = SystemTarget::getCanonicalTriple(); $triple = SystemTarget::getCanonicalTriple();
$libDir = PKG_ROOT_PATH . '/zig/lib/' . $triple; $libDir = zig::path() . '/lib/' . $triple;
if ($rt->isBuilt($libDir)) { if ($rt->isBuilt($libDir)) {
return; return;
} }
@@ -154,6 +158,6 @@ class ZigToolchain implements UnixToolchainInterface
private function getPath(): string private function getPath(): string
{ {
return PKG_ROOT_PATH . '/zig'; return zig::path();
} }
} }

View File

@@ -123,6 +123,24 @@ class GlobalEnvManager
} }
} }
/** Re-substitute env.ini's CC=${SPC_DEFAULT_CC} bindings after a toolchain swap. */
public static function reapplyOsIni(): void
{
$ini = self::readIniFile();
$os_ini = match (PHP_OS_FAMILY) {
'Windows' => $ini['windows'] ?? [],
'Darwin' => $ini['macos'] ?? [],
'Linux' => $ini['linux'] ?? [],
'BSD' => $ini['freebsd'] ?? [],
default => [],
};
foreach (['CC', 'CXX', 'AR', 'RANLIB', 'LD'] as $k) {
if (isset($os_ini[$k])) {
self::putenv("{$k}={$os_ini[$k]}");
}
}
}
/** /**
* Initialize the toolchain after the environment variables are set. * Initialize the toolchain after the environment variables are set.
* The toolchain or environment availability check is done here. * The toolchain or environment availability check is done here.