mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-30 07:14:39 +08:00
The bootstrap test builds its own seed when CI shares none, and that build still applied the committed function layout, so its LLVM listed functions in a different order from the native compiler's own emission. Both seed builds now share one environment, which leaves the layout out.
80 lines
2.9 KiB
JavaScript
80 lines
2.9 KiB
JavaScript
import { execFileSync } from "node:child_process";
|
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
import { join, resolve } from "node:path";
|
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
|
const root = fileURLToPath(new URL("../", import.meta.url));
|
|
const metadataName = "bootstrap-seed.json";
|
|
|
|
/** Artifacts are scoped to one workflow revision and instrumentation lane.
|
|
* The directory must stay fixed: FFI manifests and IR include absolute paths. */
|
|
export function verifyBootstrapSeed(directory, revision, sanitize) {
|
|
const expected = { schema: 1, revision, sanitize, directory: resolve(directory) };
|
|
const metadata = JSON.parse(readFileSync(join(directory, metadataName), "utf8"));
|
|
if (!revision || Object.entries(expected).some(([key, value]) => metadata[key] !== value)) {
|
|
throw new Error("bootstrap seed identity does not match this checkout, lane, or directory");
|
|
}
|
|
for (const path of [
|
|
"distribution/bin/scriptc",
|
|
"distribution/bin/scriptc.json",
|
|
".scriptc/distribution-seed/cli.ir.json",
|
|
".scriptc/distribution-seed/cli.ll",
|
|
".scriptc/distribution-seed/compiler.ffi.json",
|
|
]) {
|
|
if (!existsSync(join(directory, path))) throw new Error(`bootstrap seed is missing ${path}`);
|
|
}
|
|
}
|
|
|
|
/** The environment a bootstrap seed builds with, over the inherited one. The
|
|
* bootstrap compares the seed's LLVM with the native compiler's own emission,
|
|
* which has no function layout. The layout only orders the functions, so the
|
|
* seed is built without it. */
|
|
export function seedBuildEnvironment(sanitize) {
|
|
return {
|
|
SCRIPTC_SAN: sanitize ? "1" : "",
|
|
SCRIPTC_NATIVE_EMIT_IR: "1",
|
|
SCRIPTC_NATIVE_OPTIMIZATION: sanitize ? "dev" : "release",
|
|
SCRIPTC_NATIVE_LAYOUT: "",
|
|
};
|
|
}
|
|
|
|
async function main() {
|
|
const directory = process.env.SCRIPTC_BOOTSTRAP_SEED_DIRECTORY;
|
|
const revision = process.env.GITHUB_SHA;
|
|
if (!directory || !revision)
|
|
throw new Error("bootstrap seed directory and revision are required");
|
|
if (process.platform !== "linux" || process.arch !== "x64") {
|
|
throw new Error("shared bootstrap seeds require the Linux x64 CI host");
|
|
}
|
|
const sanitize = process.env.SCRIPTC_SAN === "1";
|
|
mkdirSync(directory, { recursive: true });
|
|
execFileSync(
|
|
process.execPath,
|
|
[
|
|
"--max-old-space-size=8192",
|
|
"--import",
|
|
"tsx",
|
|
join(root, "scripts/build-native-cli.mts"),
|
|
join(directory, "distribution"),
|
|
],
|
|
{
|
|
cwd: root,
|
|
stdio: "inherit",
|
|
env: { ...process.env, ...seedBuildEnvironment(sanitize) },
|
|
},
|
|
);
|
|
writeFileSync(
|
|
join(directory, metadataName),
|
|
JSON.stringify({
|
|
schema: 1,
|
|
revision,
|
|
sanitize,
|
|
directory: resolve(directory),
|
|
}) + "\n",
|
|
);
|
|
verifyBootstrapSeed(directory, revision, sanitize);
|
|
}
|
|
|
|
if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href)
|
|
await main();
|