Files
scriptc/scripts/native-cli-assets.mts
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

74 lines
3.9 KiB
TypeScript

import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
import { basename, dirname, join, relative } from "node:path";
import type { NativeTargetSpec } from "../packages/compiler/src/backend/targets.js";
import type { NativeToolchainManifest } from "../packages/compiler/src/native/toolchain.js";
/** Copy release payloads explicitly; development caches and build trees never ship. */
function copyPackage(source: string, destination: string, members: readonly string[]): void {
mkdirSync(destination, { recursive: true });
for (const member of ["package.json", ...members]) {
cpSync(join(source, member), join(destination, member), {
recursive: true,
filter: (path) => ![".cache", "node_modules", ".DS_Store"].includes(basename(path)),
});
}
for (const name of readdirSync(source)) {
if (/^(?:LICENSE|COPYING|NOTICE|SCRIPTC_LICENSE|THIRD_PARTY_NOTICES)(?:\..*)?$/.test(name)) {
cpSync(join(source, name), join(destination, name));
}
}
}
export function stageNativeCliAssets(options: {
repository: string;
output: string;
target: NativeTargetSpec;
ts7: string;
compilerVersion: string;
}): Pick<NativeToolchainManifest, "ts7" | "llvm_package" | "runtime_pack" | "runtime_packs" | "runtime_sources" | "declarations" | "wasi_node_runner"> {
const { repository, output, target } = options;
const bin = join(output, "bin");
const lib = join(output, "lib");
mkdirSync(lib, { recursive: true });
cpSync(join(repository, "LICENSE"), join(output, "LICENSE"));
const helper = join(lib, "llvm");
const runtime = join(lib, target.runtimePackPackage.replace("@scriptc/", ""));
copyPackage(join(repository, "packages", target.helper.packageName.replace("@scriptc/", "")), helper, ["bin"]);
copyPackage(join(repository, "packages", target.runtimePackPackage.replace("@scriptc/", "")), runtime, ["artifacts", "runtime-pack.json"]);
const typescript = join(lib, "typescript");
copyPackage(dirname(dirname(options.ts7)), typescript, ["lib"]);
const sources = join(lib, "runtime-sources");
copyPackage(join(repository, "packages/runtime"), sources, ["src", "vendor"]);
const declarations = join(lib, "declarations");
mkdirSync(declarations, { recursive: true });
for (const name of ["scriptc.d.ts", "scriptc-overrides.d.ts", "scriptc-node-fallback.d.ts"]) {
cpSync(join(repository, "packages/compiler/ambient", name), join(declarations, name));
}
// This optional Node host runs the built WASI module, never the compiler.
const wasi = join(lib, "wasi");
mkdirSync(join(wasi, "cli"), { recursive: true });
writeFileSync(join(wasi, "package.json"), '{"type":"module"}\n');
for (const name of ["wasi-paths.js", "cli/wasi-paths.js", "cli/wasi-runner.js"]) {
const source = join(repository, "packages/compiler/dist", name);
if (!existsSync(source)) throw new Error("build the compiler workspace before packaging its WASI runner");
cpSync(source, join(wasi, name));
}
const identity = JSON.parse(readFileSync(join(typescript, "package.json"), "utf8")) as { version: string };
writeFileSync(join(output, "THIRD_PARTY_NOTICES"), [
`scriptc ${options.compilerVersion} includes the existing TypeScript ${identity.version}, LLVM, and C runtime dependencies.`,
"TypeScript licensing: lib/typescript/LICENSE and lib/typescript/NOTICE.txt.",
"LLVM licensing and notices: lib/llvm/LICENSE and lib/llvm/THIRD_PARTY_NOTICES.",
"Runtime dependency licenses: lib/runtime-sources/vendor/*/LICENSE*.",
"",
].join("\n"));
return {
ts7: relative(bin, join(typescript, "lib", basename(options.ts7))),
llvm_package: relative(bin, helper),
runtime_pack: relative(bin, runtime),
runtime_packs: [{ target: target.name, path: relative(bin, runtime) }],
runtime_sources: relative(bin, sources),
declarations: relative(bin, declarations),
wasi_node_runner: relative(bin, join(wasi, "cli/wasi-runner.js")),
};
}