diff --git a/package.json b/package.json index c5ca3238a..cf2779669 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "@ark/schema": "0.56.2" }, "scripts": { - "setup": "bun install && bun run build:native && bun --cwd=packages/coding-agent link && sh scripts/link-omp.sh", + "setup": "bun scripts/setup.ts", "dev": "bun --cwd=packages/coding-agent src/cli.ts", "dev:timing": "PI_TIMING=x bun --cwd=packages/coding-agent --preload ../utils/src/module-timer.ts src/cli.ts", "stats": "bun --cwd=packages/coding-agent src/cli.ts stats", diff --git a/scripts/bazel-natives.ts b/scripts/bazel-natives.ts index 6183adc5e..8bb0f4c0b 100755 --- a/scripts/bazel-natives.ts +++ b/scripts/bazel-natives.ts @@ -136,6 +136,8 @@ export interface CliOptions { dest: string | null; source: string | null; bazelArgs: string[]; + /** Force the local Cargo/N-API host build path, skipping bazel. Same semantics as `OMP_NATIVE_BUILD_BACKEND=cargo`. */ + cargo: boolean; } /** Parse target names and the mutually exclusive build or artifact source options. */ @@ -143,6 +145,7 @@ export function parseCliArgs(argv: string[]): CliOptions { const targets: string[] = []; let dest: string | null = null; let source: string | null = null; + let cargo = false; const bazelArgs: string[] = []; for (let i = 0; i < argv.length; i++) { const arg = argv[i]; @@ -160,6 +163,10 @@ export function parseCliArgs(argv: string[]): CliOptions { } continue; } + if (arg === "--cargo") { + cargo = true; + continue; + } if (arg.startsWith("-")) { throw new Error(`Unknown flag ${arg} (extra bazel args go after \`--\`)`); } @@ -167,13 +174,19 @@ export function parseCliArgs(argv: string[]): CliOptions { } if (targets.length === 0) { throw new Error( - "Usage: bun scripts/bazel-natives.ts ... [--dest ] [--source ] [-- ]", + "Usage: bun scripts/bazel-natives.ts ... [--cargo] [--dest ] [--source ] [-- ]", ); } if (source && bazelArgs.length > 0) { throw new Error("--source cannot be combined with extra bazel arguments"); } - return { targets, dest, source, bazelArgs }; + if (cargo && source) { + throw new Error("--cargo cannot be combined with --source"); + } + if (cargo && bazelArgs.length > 0) { + throw new Error("--cargo cannot be combined with extra bazel arguments"); + } + return { targets, dest, source, bazelArgs, cargo }; } function resolveBazelBinary(): string | null { @@ -246,7 +259,7 @@ async function main(): Promise { const host: HostInfo = { platform: process.platform, arch: process.arch, avx2: detectHostAvx2Support() }; const destDir = options.dest ? path.resolve(options.dest) : path.join(repoRoot, "packages/natives/native"); - const cargoBackend = Bun.env.OMP_NATIVE_BUILD_BACKEND === "cargo"; + const cargoBackend = options.cargo || Bun.env.OMP_NATIVE_BUILD_BACKEND === "cargo"; if ((host.platform === "win32" || cargoBackend) && !options.source) { if (options.targets.length !== 1 || options.targets[0] !== "host") { if (host.platform === "win32") { @@ -256,7 +269,7 @@ async function main(): Promise { "(local napi build via VS Build Tools), or run this script from WSL/linux for cross targets.", ); } - throw new Error("OMP_NATIVE_BUILD_BACKEND=cargo supports only the host target"); + throw new Error("--cargo / OMP_NATIVE_BUILD_BACKEND=cargo supports only the host target"); } await buildLocalHostAddon(host, destDir); return; diff --git a/scripts/setup.ts b/scripts/setup.ts new file mode 100755 index 000000000..75c710585 --- /dev/null +++ b/scripts/setup.ts @@ -0,0 +1,62 @@ +#!/usr/bin/env bun +/** + * `bun setup` entrypoint. Chains the four setup steps (install → native + * addon build → coding-agent link → omp link) and forwards a single UX flag: + * + * --cargo Build the host native addon via the local Cargo/N-API path + * instead of bazel. Equivalent to + * `OMP_NATIVE_BUILD_BACKEND=cargo` — surfaced as a flag because + * bun/npm can't forward extra args past `&&`-chained scripts. + * + * Any other flags after `--` are appended to the native build invocation. + */ +import * as path from "node:path"; + +const repoRoot = path.join(import.meta.dir, ".."); + +const argv = process.argv.slice(2); +let cargo = false; +const passthrough: string[] = []; +for (let i = 0; i < argv.length; i++) { + const arg = argv[i]; + if (arg === "--") { + passthrough.push(...argv.slice(i + 1)); + break; + } + if (arg === "--cargo") { + cargo = true; + continue; + } + passthrough.push(arg); +} + +const nativeBackendEnv = cargo ? { OMP_NATIVE_BUILD_BACKEND: "cargo" } : {}; + +interface Step { + label: string; + cmd: string[]; + env?: Record; + cwd?: string; +} + +const steps: Step[] = [ + { label: "bun install", cmd: ["bun", "install"] }, + { label: "build:native", cmd: ["bun", "run", "build:native", ...passthrough], env: nativeBackendEnv }, + { label: "coding-agent link", cmd: ["bun", "--cwd=packages/coding-agent", "link"] }, + { label: "link omp", cmd: ["sh", "scripts/link-omp.sh"] }, +]; + +for (const step of steps) { + console.log(`\n▶ ${step.label}`); + const proc = Bun.spawn(step.cmd, { + cwd: step.cwd ?? repoRoot, + env: { ...process.env, ...(step.env ?? {}) }, + stdout: "inherit", + stderr: "inherit", + }); + const exitCode = await proc.exited; + if (exitCode !== 0) { + console.error(`\nsetup step "${step.label}" failed (exit ${exitCode})`); + process.exit(exitCode || 1); + } +}