294d41bd3b
Bun 1.3.14 stopped exposing `--compile` extras through every filesystem-style API: `fs.existsSync`, `Bun.file().exists()`, `Bun.resolveSync`, and `await import()` on `/$bunfs/...` or `file:///$bunfs/...` all fail; only `/$bunfs/root/<binary-name>` itself answers. The pre-existing legacy-pi rewrite emitted `file:///$bunfs/...` URLs that Bun then could not load, so every legacy extension that imported `@oh-my-pi/pi-*` or `@sinclair/typebox` failed on the `omp-darwin-arm64` release binary. `legacy-pi-compat.ts` now keeps a JS-heap reference to every bundled pi-* surface in a lazy-loaded sibling `legacy-pi-bundled-registry.ts` and serves them through an `omp-legacy-pi-bundled:` virtual namespace whose `Bun.plugin().onLoad` synthesizes a re-export module — no bunfs path ever leaves the module in compiled mode. Dev / source-link / installed-package modes keep the historical `file://` rewrite (source files exist on disk). The matching `--compile` extras in `scripts/build-binary.ts` are gone; `BUNFS_PACKAGE_ROOT`, `bunfsPath`, `__computeBunfsPackageRoot`, and `__joinBunfsPath` are deleted as dead code. `scripts/smoke-3423.ts` compiles a tiny binary that loads a fixture extension end-to-end through the new path. Fixes #3423
116 lines
4.4 KiB
TypeScript
116 lines
4.4 KiB
TypeScript
#!/usr/bin/env bun
|
|
|
|
import { createRequire } from "node:module";
|
|
import * as path from "node:path";
|
|
|
|
const packageDir = path.join(import.meta.dir, "..");
|
|
const repoRoot = path.join(packageDir, "..", "..");
|
|
// Optional cross-compile target, e.g. CROSS_TARGET=linux-arm64 → bun build
|
|
// --target=bun-linux-arm64, embeds the matching native, outputs dist/omp-<target>.
|
|
const crossTarget = Bun.env.CROSS_TARGET || null;
|
|
const [crossPlatform, crossArch] = crossTarget ? crossTarget.split("-") : [null, null];
|
|
// x64 uses the baseline bun runtime so it runs under Rosetta / pre-AVX2 CPUs
|
|
// (the modern bun-linux-x64 target SIGILLs under Apple-Silicon Rosetta).
|
|
const bunTarget = crossTarget ? (crossTarget === "linux-x64" ? "bun-linux-x64-baseline" : `bun-${crossTarget}`) : null;
|
|
const outName = crossTarget ? `omp-${crossTarget}` : "omp";
|
|
const outputPath = path.join(packageDir, "dist", outName);
|
|
|
|
// Transformers.js is an optional, native-heavy dependency that is never bundled
|
|
// into the binary; the tiny-model worker `bun install`s it into a runtime cache
|
|
// on first use. The `catalog:` spec cannot be resolved from inside the compiled
|
|
// bunfs (issue #1763), so embed the concrete installed version here for the
|
|
// worker to pin its runtime install against.
|
|
const transformersVersion = (
|
|
createRequire(import.meta.url)("@huggingface/transformers/package.json") as { version: string }
|
|
).version;
|
|
|
|
function shouldAdhocSignDarwinBinary(): boolean {
|
|
return process.platform === "darwin" && !crossTarget;
|
|
}
|
|
|
|
async function runCommand(
|
|
command: string[],
|
|
env: NodeJS.ProcessEnv = Bun.env,
|
|
cwd: string = packageDir,
|
|
): Promise<void> {
|
|
const proc = Bun.spawn(command, {
|
|
cwd,
|
|
env,
|
|
stdout: "inherit",
|
|
stderr: "inherit",
|
|
});
|
|
const exitCode = await proc.exited;
|
|
if (exitCode !== 0) {
|
|
throw new Error(`Command failed with exit code ${exitCode}: ${command.join(" ")}`);
|
|
}
|
|
}
|
|
|
|
async function main(): Promise<void> {
|
|
// Generate inside the try so the finally always restores the empty checked-in
|
|
// placeholders (stats client archive, docs index) even on failure.
|
|
try {
|
|
await runCommand(["bun", "--cwd=../stats", "scripts/generate-client-bundle.ts", "--generate"]);
|
|
await runCommand(["bun", "scripts/generate-docs-index.ts", "--generate"]);
|
|
await runCommand(
|
|
["bun", "--cwd=../natives", "run", "embed:native"],
|
|
crossTarget
|
|
? { ...Bun.env, TARGET_PLATFORM: crossPlatform as string, TARGET_ARCH: crossArch as string }
|
|
: Bun.env,
|
|
);
|
|
await runCommand(["bun", "scripts/embed-mupdf-wasm.ts", "--generate"]);
|
|
try {
|
|
const buildEnv = shouldAdhocSignDarwinBinary() ? { ...Bun.env, BUN_NO_CODESIGN_MACHO_BINARY: "1" } : Bun.env;
|
|
await runCommand(
|
|
[
|
|
"bun",
|
|
"build",
|
|
"--compile",
|
|
...(bunTarget ? ["--target", bunTarget] : []),
|
|
"--no-compile-autoload-bunfig",
|
|
"--no-compile-autoload-dotenv",
|
|
"--no-compile-autoload-tsconfig",
|
|
"--no-compile-autoload-package-json",
|
|
"--keep-names",
|
|
"--define",
|
|
'process.env.PI_COMPILED="true"',
|
|
"--define",
|
|
`process.env.PI_TINY_TRANSFORMERS_VERSION=${JSON.stringify(transformersVersion)}`,
|
|
"--external",
|
|
"fastembed",
|
|
"--external",
|
|
"onnxruntime-node",
|
|
"--root",
|
|
".",
|
|
"./packages/coding-agent/src/cli.ts",
|
|
// Legacy pi-* extension compat surfaces (host packages + shims)
|
|
// were previously listed as explicit `--compile` entries so the
|
|
// rewrite path could emit `/$bunfs/root/...` URLs against them.
|
|
// Bun 1.3.14 made bunfs files unreachable at runtime (issue
|
|
// #3423), so `legacy-pi-compat.ts` now serves them through a
|
|
// virtual namespace backed by `legacy-pi-bundled-registry.ts`,
|
|
// which static-imports each surface — the bundler already
|
|
// includes them via the main module graph, so no `--compile`
|
|
// extras are required.
|
|
"--outfile",
|
|
`packages/coding-agent/dist/${outName}`,
|
|
],
|
|
buildEnv,
|
|
repoRoot,
|
|
);
|
|
|
|
// Bun 1.3.12 emits a truncated Mach-O signature on darwin builds.
|
|
if (shouldAdhocSignDarwinBinary()) {
|
|
await runCommand(["codesign", "--force", "--sign", "-", outputPath]);
|
|
}
|
|
} finally {
|
|
await runCommand(["bun", "scripts/embed-mupdf-wasm.ts", "--reset"]);
|
|
await runCommand(["bun", "--cwd=../natives", "run", "embed:native", "--reset"]);
|
|
}
|
|
} finally {
|
|
await runCommand(["bun", "--cwd=../stats", "scripts/generate-client-bundle.ts", "--reset"]);
|
|
await runCommand(["bun", "scripts/generate-docs-index.ts", "--reset"]);
|
|
}
|
|
}
|
|
|
|
await main();
|