Files
scriptc/packages/compiler/src/backend/native-tools.ts
T
Chris Tate ee9f0d64eb feat: ship the self-hosted native scriptc CLI (#585)
* feat: ship the self-hosted native scriptc CLI

- Run the shared compiler and CLI natively, including library builds and compile-time evaluation.
- Install native platform packages and ship relocatable standalone distributions.
- Preserve program semantics and reuse validated build artifacts for fast rebuilds.

* fix: complete native CLI integration and validation

- Preserve library diagnostics and run recursive compiler work on the main stack.
- Restore packaged helper permissions and exercise native npm and Wasm library builds.
- Recover interrupted Sandbox status probes within the original command deadline.
2026-09-30 02:17:56 -05:00

51 lines
2.4 KiB
TypeScript

/** Native tool invocation without a JavaScript host or shell command construction. */
import { execFileSync } from "node:child_process";
import { readFileSync, statSync } from "node:fs";
import type { NativeHelperSpec, NativeTargetSpec } from "./targets.js";
import { validateNativeCodegenVersion, type NativeCodegenOutputKind } from "./native-codegen-core.js";
export function runNativeTool(executable: string, args: string[], cwd?: string, env?: NodeJS.ProcessEnv): string {
return execFileSync(executable, args, { encoding: "utf8", stdio: "pipe", maxBuffer: 64 * 1024 * 1024,
cwd: cwd ?? process.cwd(), env: env ?? process.env });
}
export function requireNativeArtifact(path: string): void {
const info = statSync(path);
if (!info.isFile() || info.size === 0) throw new Error(`native tool produced no artifact: ${path}`);
}
export function emitNativeObject(options: {
executable: string;
packageRoot: string;
compilerVersion: string;
target: NativeTargetSpec;
helper: NativeHelperSpec;
inputPath: string;
outputPath: string;
sourcePath: string;
optimization: "release" | "dev";
outputKind?: NativeCodegenOutputKind;
}): void {
verifyNativeHelper(options);
runNativeTool(options.executable, [
"emit", "--input", options.inputPath, "--output", options.outputPath, "--filetype", options.outputKind ?? "obj",
"--target", options.target.llvmTriple, "--opt-level", options.optimization === "dev" ? "0" : "2",
"--relocation-model", options.target.relocationModel, "--diagnostic-format", "json",
"--source-path", options.sourcePath,
]);
requireNativeArtifact(options.outputPath);
}
/** Verify installed identity even when a caller can reuse a cached object. */
export function verifyNativeHelper(options: {
executable: string; packageRoot: string; compilerVersion: string;
target: NativeTargetSpec; helper: NativeHelperSpec;
}): void {
const identity = JSON.parse(readFileSync(options.packageRoot + "/package.json", "utf8")) as { name: string; version: string };
if (identity.name !== options.helper.packageName || identity.version !== options.compilerVersion) {
throw new Error(`LLVM helper package mismatch: expected ${options.helper.packageName}@${options.compilerVersion}`);
}
const version = JSON.parse(runNativeTool(options.executable, ["version", "--format=json"])) as Record<string, unknown>;
validateNativeCodegenVersion(version, options.target, options.helper, options.compilerVersion);
}