#!/usr/bin/env node // The native usage core is a second implementation of the usage contract, so the repo // checks it like the rest of the code. It lives in its own repository and arrives here as a // submodule, so "not checked out" is a state this script has to name as clearly as a missing // toolchain. A missing toolchain is reported with the pinned version and how to get it rather // than as an unexplained failure. import { execFileSync } from "node:child_process"; import { existsSync } from "node:fs"; import { homedir } from "node:os"; import { dirname, join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; const PINNED = "0.16.0"; const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); const nativeDir = join(repoRoot, "native", "usage"); function findZig() { if (process.env.ZIG) return process.env.ZIG; const candidates = [ "zig", join(homedir(), ".local", "share", "zig", PINNED, "zig"), `/opt/homebrew/bin/zig`, `/usr/local/bin/zig`, ]; for (const candidate of candidates) { try { execFileSync(candidate, ["version"], { stdio: "ignore" }); return candidate; } catch { // try the next candidate } } return undefined; } const zig = findZig(); if (!zig) { console.error( [ `Zig ${PINNED} is required for the native usage core and was not found.`, "", "Install the pinned toolchain (see native/usage/README.md):", " curl -L -o /tmp/zig.tar.xz https://ziglang.org/download/" + PINNED + "/zig-aarch64-macos-" + PINNED + ".tar.xz", " shasum -a 256 /tmp/zig.tar.xz", " mkdir -p ~/.local/share/zig && tar -xJf /tmp/zig.tar.xz -C ~/.local/share/zig", "", "or point ZIG at an existing zig binary.", ].join("\n"), ); process.exit(1); } const version = execFileSync(zig, ["version"], { encoding: "utf8" }).trim(); if (version !== PINNED) { console.error(`Zig ${version} is not the pinned ${PINNED} (native/usage/build.zig.zon); the 0.16 standard library changed args/stdio/fs/clock APIs.`); process.exit(1); } if (!existsSync(join(nativeDir, "build.zig"))) { console.error( [ `The usage core is not checked out at ${nativeDir}.`, "", "It is a submodule (its own repository), so a plain clone leaves it empty:", " git submodule update --init native/usage", ].join("\n"), ); process.exit(1); } try { execFileSync(zig, ["build", "test"], { cwd: nativeDir, stdio: "inherit" }); // The Swift wrapper links the *installed* static library, so the install step has to run before // swift build does; `zig build test` alone leaves zig-out empty. execFileSync(zig, ["build"], { cwd: nativeDir, stdio: "inherit" }); console.log(`Zig ${version} native usage core: tests and C ABI smoke test passed.`); } catch { process.exit(1); } // The Swift wrapper is only checked where a Swift toolchain exists (macOS dev machines). CI is Linux // and skips it, which is honest as long as the skip is printed rather than silent. const swiftDir = join(nativeDir, "swift"); if (existsSync(swiftDir)) { try { execFileSync("swift", ["build", "--package-path", swiftDir], { stdio: "inherit" }); execFileSync("swift", ["run", "--package-path", swiftDir, "usage-smoke", join(nativeDir, "tests", "fixtures")], { cwd: nativeDir, stdio: "inherit" }); console.log("Swift wrapper: built and passed its smoke test."); } catch (error) { if (error && error.code === "ENOENT") { console.log("Swift wrapper: skipped, no swift toolchain on PATH."); } else { process.exit(1); } } }