diff --git a/src/Package/Artifact/llvm_compiler_rt.php b/src/Package/Artifact/llvm_compiler_rt.php index 166500b9..f39893da 100644 --- a/src/Package/Artifact/llvm_compiler_rt.php +++ b/src/Package/Artifact/llvm_compiler_rt.php @@ -73,7 +73,7 @@ class llvm_compiler_rt { $sourceDir ??= SOURCE_PATH . '/llvm-compiler-rt'; $triple ??= SystemTarget::getCanonicalTriple(); - $libDir = PKG_ROOT_PATH . '/zig/lib/' . $triple; + $libDir = zig::path() . '/lib/' . $triple; if ($this->isBuilt($libDir)) { return; } @@ -101,7 +101,10 @@ class llvm_compiler_rt 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) { return null; } diff --git a/src/Package/Artifact/llvm_tools.php b/src/Package/Artifact/llvm_tools.php index 3be55a93..4a64cbbd 100644 --- a/src/Package/Artifact/llvm_tools.php +++ b/src/Package/Artifact/llvm_tools.php @@ -102,8 +102,8 @@ class llvm_tools '-DLLVM_BUILD_LLVM_DYLIB=OFF', '-DLLVM_LINK_LLVM_DYLIB=OFF', '-DBUILD_SHARED_LIBS=OFF', - '-DCMAKE_C_COMPILER=' . PKG_ROOT_PATH . '/zig/zig-cc', - '-DCMAKE_CXX_COMPILER=' . PKG_ROOT_PATH . '/zig/zig-c++', + '-DCMAKE_C_COMPILER=' . zig::binary('zig-cc'), + '-DCMAKE_CXX_COMPILER=' . zig::binary('zig-c++'), '-DCMAKE_INSTALL_PREFIX=' . $installDir, ])); $jobs = ApplicationContext::get(PackageBuilder::class)->concurrency; @@ -137,11 +137,10 @@ class llvm_tools private function detectLlvmVersion(): ?string { - $zig = PKG_ROOT_PATH . '/zig/zig'; - if (!is_file($zig)) { + if (!zig::isInstalled()) { return null; } - [$rc, $out] = shell()->execWithResult(escapeshellarg($zig) . ' cc --version', false); + [$rc, $out] = shell()->execWithResult(escapeshellarg(zig::binary()) . ' cc --version', false); if ($rc !== 0) { return null; } diff --git a/src/Package/Artifact/zig.php b/src/Package/Artifact/zig.php index 04ae0b1c..123139d9 100644 --- a/src/Package/Artifact/zig.php +++ b/src/Package/Artifact/zig.php @@ -15,6 +15,23 @@ use StaticPHP\Runtime\SystemTarget; 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', [ 'linux-x86_64', 'linux-aarch64', diff --git a/src/StaticPHP/Doctor/Item/LlvmCompilerRtCheck.php b/src/StaticPHP/Doctor/Item/LlvmCompilerRtCheck.php index 368e0267..72f172b8 100644 --- a/src/StaticPHP/Doctor/Item/LlvmCompilerRtCheck.php +++ b/src/StaticPHP/Doctor/Item/LlvmCompilerRtCheck.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace StaticPHP\Doctor\Item; use Package\Artifact\llvm_compiler_rt; +use Package\Artifact\zig; use StaticPHP\Attribute\Doctor\CheckItem; use StaticPHP\Attribute\Doctor\FixItem; use StaticPHP\Attribute\Doctor\OptionalCheck; @@ -27,7 +28,7 @@ class LlvmCompilerRtCheck #[CheckItem('if llvm-compiler-rt is built for current target', level: 799)] 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)) { return CheckResult::ok($libDir); } @@ -41,7 +42,7 @@ class LlvmCompilerRtCheck $installer->addInstallPackage('llvm-compiler-rt'); $installer->run(true); 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); } } diff --git a/src/StaticPHP/Doctor/Item/ZigCheck.php b/src/StaticPHP/Doctor/Item/ZigCheck.php index ec140fd7..0f84263c 100644 --- a/src/StaticPHP/Doctor/Item/ZigCheck.php +++ b/src/StaticPHP/Doctor/Item/ZigCheck.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace StaticPHP\Doctor\Item; +use Package\Artifact\zig; use StaticPHP\Attribute\Doctor\CheckItem; use StaticPHP\Attribute\Doctor\FixItem; use StaticPHP\Attribute\Doctor\OptionalCheck; @@ -26,7 +27,7 @@ class ZigCheck public function checkZig(): CheckResult { 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'); } diff --git a/src/StaticPHP/Runtime/SystemTarget.php b/src/StaticPHP/Runtime/SystemTarget.php index b968dee8..3949443b 100644 --- a/src/StaticPHP/Runtime/SystemTarget.php +++ b/src/StaticPHP/Runtime/SystemTarget.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace StaticPHP\Runtime; +use StaticPHP\Toolchain\ZigToolchain; use StaticPHP\Util\System\LinuxUtil; /** @@ -16,7 +17,7 @@ class SystemTarget */ public static function getLibc(): ?string { - if ($target = getenv('SPC_TARGET')) { + if ($target = self::target()) { if (str_contains($target, '-gnu')) { return 'glibc'; } @@ -57,7 +58,7 @@ class SystemTarget public static function getLibcVersion(): ?string { if (PHP_OS_FAMILY === 'Linux') { - $target = (string) getenv('SPC_TARGET'); + $target = self::target(); if (str_contains($target, '-gnu.2.')) { return preg_match('/-gnu\.(2\.\d+)/', $target, $matches) ? $matches[1] : null; } @@ -75,7 +76,7 @@ class SystemTarget */ public static function getTargetOS(): string { - $target = (string) getenv('SPC_TARGET'); + $target = self::target(); return match (true) { str_contains($target, '-linux') => 'Linux', str_contains($target, '-macos') => 'Darwin', @@ -91,7 +92,7 @@ class SystemTarget */ public static function getTargetArch(): string { - $target = (string) getenv('SPC_TARGET'); + $target = self::target(); return match (true) { str_contains($target, 'x86_64') || str_contains($target, 'amd64') => 'x86_64', str_contains($target, 'aarch64') || str_contains($target, 'arm64') => 'aarch64', @@ -136,7 +137,7 @@ class SystemTarget */ public static function getCanonicalTriple(): string { - $target = (string) getenv('SPC_TARGET'); + $target = self::target(); if ($target !== '' && !str_contains($target, 'native')) { $cleaned = (string) preg_replace('/(-gnu|-musl)\.[\d.]+/', '$1', $target); $cleaned = preg_split('/\s+/', trim($cleaned))[0] ?? ''; @@ -161,7 +162,7 @@ class SystemTarget */ public static function getAutoconfHostTriple(): ?string { - $target = (string) getenv('SPC_TARGET'); + $target = self::target(); if ($target === '' || str_contains($target, 'native')) { return null; } @@ -183,4 +184,14 @@ class SystemTarget } 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'); + } } diff --git a/src/StaticPHP/Toolchain/ZigToolchain.php b/src/StaticPHP/Toolchain/ZigToolchain.php index 7058a845..05819b16 100644 --- a/src/StaticPHP/Toolchain/ZigToolchain.php +++ b/src/StaticPHP/Toolchain/ZigToolchain.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace StaticPHP\Toolchain; use Package\Artifact\llvm_compiler_rt; +use Package\Artifact\zig; use StaticPHP\DI\ApplicationContext; use StaticPHP\Package\PackageBuilder; use StaticPHP\Package\PackageInstaller; @@ -56,7 +57,7 @@ class ZigToolchain implements UnixToolchainInterface GlobalEnvManager::putenv("SPC_DEFAULT_CXXFLAGS={$cxxflags}"); GlobalEnvManager::putenv("SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS={$extraCflags}"); 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'); $extra_libs = getenv('SPC_EXTRA_LIBS') ?: ''; if (!str_contains($extra_libs, '-lunwind')) { @@ -112,9 +113,12 @@ class ZigToolchain implements UnixToolchainInterface private function ensureCompilerRt(): void { + if (!zig::isInstalled()) { + return; + } $rt = new llvm_compiler_rt(); $triple = SystemTarget::getCanonicalTriple(); - $libDir = PKG_ROOT_PATH . '/zig/lib/' . $triple; + $libDir = zig::path() . '/lib/' . $triple; if ($rt->isBuilt($libDir)) { return; } @@ -154,6 +158,6 @@ class ZigToolchain implements UnixToolchainInterface private function getPath(): string { - return PKG_ROOT_PATH . '/zig'; + return zig::path(); } } diff --git a/src/StaticPHP/Util/GlobalEnvManager.php b/src/StaticPHP/Util/GlobalEnvManager.php index 5b4b16b2..eb44112e 100644 --- a/src/StaticPHP/Util/GlobalEnvManager.php +++ b/src/StaticPHP/Util/GlobalEnvManager.php @@ -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. * The toolchain or environment availability check is done here.