Files
scriptc/scripts/native-cli-bundle.mjs
T
Chris Tate d1a0bea84e Have the native CLI packages depend on their LLVM helper and runtime pack
Each @scriptc/cli-<platform> package bundled its platform's LLVM helper
and runtime pack, which are also published as @scriptc/llvm-<platform> and
@scriptc/runtime-<platform>. The CLI packages now depend on those packages
at the same version (workspace:*, which pnpm pack writes as the exact
version) and leave them out: cli-linux-x64-gnu goes from 115 MB to 60 MB
packed.

- build-native-cli.mts --platform-packages, which each CLI package's
  build:native passes, writes a manifest without llvm_package, runtime_pack
  and runtime_packs.
- loadNativeToolchain resolves a missing helper or host runtime pack as
  Node resolves the package from the compiler's directory: nested in the
  platform package, beside it (hoisted, or pnpm's virtual store) or higher
  up. It requires the compiler's version, and an absent or mismatched
  package fails with an error that names it.
- installNativeCli records where the package manager put both packages in
  the installed manifest, with the same checks.
- verify-native-cli.mjs requires the exact dependencies of a platform
  package and checks the resolved packages' versions.
- package-native-cli.mjs bundles the helper and runtime pack into the
  standalone archives, which stay self-contained.
- smoke-native-install.mjs installs the helper and runtime pack tarballs
  with the platform package; the bootstrap's exported package drops its
  bundled copies first.
- release.yml publishes the CLI packages only once every helper and
  runtime pack package resolves on npm, and scriptc only once the CLI
  packages resolve, each wait at most 25 minutes. A rerun skips the
  uploads npm already accepted and waits again.
2026-10-26 07:48:11 -05:00

73 lines
3.3 KiB
JavaScript

import { cpSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
import { basename, dirname, join, resolve } from "node:path";
/** Copy release payloads explicitly; development caches and build trees never ship. */
export function copyPackage(source, destination, members) {
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));
}
}
}
/** The LLVM helper and host runtime pack packages a native CLI package
* depends on. */
export function platformPackagesOf(identity) {
const names = Object.keys(identity.dependencies ?? {});
const helper = names.find((name) => name.startsWith("@scriptc/llvm-"));
const runtime = names.find((name) => name.startsWith("@scriptc/runtime-"));
if (helper === undefined || runtime === undefined)
throw new Error(`${identity.name} must depend on its LLVM helper and runtime pack packages`);
return { helper, runtime };
}
/** Copies the helper and runtime pack packages from `packages` (the
* workspace's packages directory) into a distribution's lib directory, as a
* standalone archive needs them, and returns the manifest paths, relative to
* the distribution's bin directory in the target's path style. */
export function bundlePlatformPackages({ packages, distribution, helper, runtime, windows }) {
const short = (name) => name.replace("@scriptc/", "");
copyPackage(join(packages, short(helper)), join(distribution, "lib", "llvm"), ["bin"]);
copyPackage(join(packages, short(runtime)), join(distribution, "lib", short(runtime)), [
"artifacts",
"runtime-pack.json",
]);
const path = (name) => ["..", "lib", name].join(windows ? "\\" : "/");
return { llvm_package: path("llvm"), runtime_pack: path(short(runtime)) };
}
/** The THIRD_PARTY_NOTICES line for the LLVM helper, bundled or as a dependency. */
export function llvmNotice(helper) {
return helper === undefined
? "LLVM licensing and notices: lib/llvm/LICENSE and lib/llvm/THIRD_PARTY_NOTICES."
: `LLVM licensing and notices: LICENSE and THIRD_PARTY_NOTICES in the ${helper} package.`;
}
/** Turns a distribution that bundles its LLVM helper and runtime pack into
* an npm platform package's: removes both from lib and from the manifest at
* `manifestPath`, as `build-native-cli.mts --platform-packages` builds it. */
export function unbundlePlatformPackages(distribution, manifestPath, helper) {
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
for (const path of [manifest.llvm_package, manifest.runtime_pack])
rmSync(resolve(dirname(manifestPath), path.replaceAll("\\", "/")), {
recursive: true,
force: true,
});
delete manifest.llvm_package;
delete manifest.runtime_pack;
delete manifest.runtime_packs;
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n");
const notices = join(distribution, "THIRD_PARTY_NOTICES");
writeFileSync(
notices,
readFileSync(notices, "utf8").replace(llvmNotice(undefined), llvmNotice(helper)),
);
}