import { rm } from 'node:fs/promises' import path from 'node:path' import process from 'node:process' const ALL_TARGETS = [ 'bun-windows-x64', 'bun-darwin-arm64', 'bun-darwin-x64', 'bun-linux-x64', 'bun-linux-arm64', ] as const type BunTarget = (typeof ALL_TARGETS)[number] const ENTRYPOINT = '.output/server/index.mjs' const OUTDIR = 'out' const OUTFILE_BASE = 'server' const DEFAULT_TARGETS: BunTarget[] = [ 'bun-windows-x64', 'bun-darwin-arm64', 'bun-linux-x64', ] const suffixFor = (target: BunTarget) => target.replace('bun-', '') const isTarget = (value: string): value is BunTarget => (ALL_TARGETS as readonly string[]).includes(value) const parseTargets = (): BunTarget[] => { const args = process.argv.slice(2) const targets: string[] = [] for (let i = 0; i < args.length; i++) { const arg = args[i] const next = args[i + 1] if (arg === '--target' && next) { targets.push(next) i++ } else if (arg === '--targets' && next) { targets.push(...next.split(',')) i++ } } if (targets.length === 0) return DEFAULT_TARGETS const invalid = targets.filter((t) => !isTarget(t)) if (invalid.length) { throw new Error( `Unknown target(s): ${invalid.join(', ')}\nAllowed: ${ALL_TARGETS.join(', ')}`, ) } return targets as BunTarget[] } const buildOne = async (target: BunTarget) => { const suffix = suffixFor(target) const outfile = `${OUTFILE_BASE}-${suffix}` const result = await Bun.build({ entrypoints: [ENTRYPOINT], outdir: OUTDIR, compile: { outfile, target, }, }) if (!result.success) { throw new Error( `Build failed for ${target}:\n${result.logs.map(String).join('\n')}`, ) } return { target, outputs: result.outputs.map((o) => path.relative('.', o.path)), } } const main = async () => { const targets = parseTargets() await rm(OUTDIR, { recursive: true, force: true }) console.log(`✓ 已清理输出目录: ${OUTDIR}`) // Bun cross-compile 不支持真正并行,逐目标串行构建 const results: Awaited>[] = [] for (const target of targets) { const start = Date.now() process.stdout.write(`🔨 构建 ${target}... `) const result = await buildOne(target) results.push(result) console.log(`完成 (${Date.now() - start}ms)`) } console.log('\n📦 构建完成:') for (const r of results) { console.log(` ${r.target}:`) for (const p of r.outputs) { console.log(` - ${p}`) } } } main().catch((err) => { console.error('\n❌ 构建失败:') console.error(err instanceof Error ? err.message : err) process.exit(1) })