diff --git a/AGENTS.md b/AGENTS.md index 1bad0f6..734599b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,7 +20,10 @@ Guidelines for AI agents working in this Bun monorepo. ```bash bun dev # Start all apps in dev mode bun build # Build all apps -bun compile # Compile server to standalone binary (depends on build) +bun compile # Compile server to standalone binary (current platform, depends on build) +bun compile:linux # Compile server for Linux x64 +bun compile:mac # Compile server for macOS arm64 +bun compile:win # Compile server for Windows x64 bun dist # Full packaging pipeline: server build → compile → desktop distributable (current platform) bun dist:linux # Full pipeline → Linux distributable bun dist:mac # Full pipeline → macOS distributable @@ -33,7 +36,10 @@ bun typecheck # TypeScript check across monorepo ```bash bun dev # Vite dev server (localhost:3000) bun build # Production build -> .output/ -bun compile # Compile to standalone binary +bun compile # Compile to standalone binary (current platform) +bun compile:linux # Compile for Linux x64 +bun compile:mac # Compile for macOS arm64 +bun compile:win # Compile for Windows x64 bun fix # Biome auto-fix bun typecheck # TypeScript check diff --git a/apps/desktop/AGENTS.md b/apps/desktop/AGENTS.md index 59fc762..88dfb5e 100644 --- a/apps/desktop/AGENTS.md +++ b/apps/desktop/AGENTS.md @@ -61,7 +61,7 @@ bun typecheck # TypeScript check From monorepo root, run `bun dist` to execute the full pipeline automatically (via Turbo task dependencies): 1. **Build server**: `apps/server` → `vite build` → `.output/` -2. **Compile server**: `apps/server` → `bun compile.ts` → `out/server-{platform}` +2. **Compile server**: `apps/server` → `bun compile.ts` → `out/server-{os}-{arch}` 3. **Package desktop**: `apps/desktop` → `electron-vite build` + `electron-builder` → distributable The `electron-builder.yml` `extraResources` config reads binaries directly from `../server/out/`, no manual copy needed. diff --git a/apps/desktop/electron-builder.yml b/apps/desktop/electron-builder.yml index 16bf91c..d654f18 100644 --- a/apps/desktop/electron-builder.yml +++ b/apps/desktop/electron-builder.yml @@ -1,14 +1,15 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/electron-userland/electron-builder/refs/heads/master/packages/app-builder-lib/scheme.json appId: com.furtherverse.app productName: Furtherverse directories: buildResources: build files: - - '!**/.vscode/*' - - '!src/*' - - '!electron.vite.config.{js,ts,mjs,cjs}' - - '!{.env,.env.*,bun.lock}' - - '!{tsconfig.json,tsconfig.node.json}' - - '!{AGENTS.md,README.md,CHANGELOG.md}' + - "!**/.vscode/*" + - "!src/*" + - "!electron.vite.config.{js,ts,mjs,cjs}" + - "!{.env,.env.*,bun.lock}" + - "!{tsconfig.json,tsconfig.node.json}" + - "!{AGENTS.md,README.md,CHANGELOG.md}" asarUnpack: - resources/** win: diff --git a/apps/server/AGENTS.md b/apps/server/AGENTS.md index 355dac3..2ec9c51 100644 --- a/apps/server/AGENTS.md +++ b/apps/server/AGENTS.md @@ -25,8 +25,10 @@ bun db:studio # Drizzle Studio GUI # Build bun build # Production build → .output/ -bun compile # Compile to standalone binary (depends on build) - # Also triggered automatically by root `bun dist` +bun compile # Compile to standalone binary (current platform, depends on build) +bun compile:linux # Compile for Linux x64 +bun compile:mac # Compile for macOS arm64 +bun compile:win # Compile for Windows x64 # Code Quality bun fix # Biome auto-fix diff --git a/apps/server/compile.ts b/apps/server/compile.ts index 6bd2d7f..1704ae2 100644 --- a/apps/server/compile.ts +++ b/apps/server/compile.ts @@ -1,111 +1,66 @@ import { rm } from 'node:fs/promises' -import path from 'node:path' import process from 'node:process' -const ALL_TARGETS = [ +const ENTRYPOINT = '.output/server/index.mjs' +const OUTDIR = 'out' + +const VALID_TARGETS = [ 'bun-windows-x64', 'bun-darwin-arm64', - 'bun-darwin-x64', 'bun-linux-x64', 'bun-linux-arm64', ] as const -type BunTarget = (typeof ALL_TARGETS)[number] +type Target = (typeof VALID_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 HOST_MAP: Record = { + 'win32-x64': 'bun-windows-x64', + 'darwin-arm64': 'bun-darwin-arm64', + 'linux-x64': 'bun-linux-x64', + 'linux-arm64': 'bun-linux-arm64', } -const buildOne = async (target: BunTarget) => { - const suffix = suffixFor(target) - const outfile = `${OUTFILE_BASE}-${suffix}` +const resolveTarget = (): Target => { + const idx = process.argv.indexOf('--target') + if (idx !== -1) { + const value = process.argv[idx + 1] + if (!value || !VALID_TARGETS.includes(value as Target)) { + throw new Error( + `Invalid target: ${value}\nAllowed: ${VALID_TARGETS.join(', ')}`, + ) + } + return value as Target + } + + const key = `${process.platform}-${process.arch}` + const target = HOST_MAP[key] + if (!target) { + throw new Error(`Unsupported host: ${key}`) + } + return target +} + +const main = async () => { + const target = resolveTarget() + const suffix = target.replace('bun-', '') + const outfile = `server-${suffix}` + + await rm(OUTDIR, { recursive: true, force: true }) const result = await Bun.build({ entrypoints: [ENTRYPOINT], outdir: OUTDIR, - compile: { - outfile, - target, - }, + compile: { outfile, target }, }) if (!result.success) { - throw new Error( - `Build failed for ${target}:\n${result.logs.map(String).join('\n')}`, - ) + throw new Error(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}`) - } - } + console.log(`✓ ${target} → ${OUTDIR}/${outfile}`) } main().catch((err) => { - console.error('\n❌ 构建失败:') - console.error(err instanceof Error ? err.message : err) + console.error('❌', err instanceof Error ? err.message : err) process.exit(1) }) diff --git a/apps/server/package.json b/apps/server/package.json index e97e95e..80277df 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -6,6 +6,9 @@ "scripts": { "build": "vite build", "compile": "bun compile.ts", + "compile:linux": "bun compile.ts --target bun-linux-x64", + "compile:mac": "bun compile.ts --target bun-darwin-arm64", + "compile:win": "bun compile.ts --target bun-windows-x64", "db:generate": "drizzle-kit generate", "db:migrate": "drizzle-kit migrate", "db:push": "drizzle-kit push", diff --git a/apps/server/turbo.json b/apps/server/turbo.json index 8141e85..0d3daf0 100644 --- a/apps/server/turbo.json +++ b/apps/server/turbo.json @@ -8,6 +8,15 @@ }, "compile": { "outputs": ["out/**"] + }, + "compile:linux": { + "outputs": ["out/**"] + }, + "compile:mac": { + "outputs": ["out/**"] + }, + "compile:win": { + "outputs": ["out/**"] } } } diff --git a/package.json b/package.json index 0131ea9..073073f 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,9 @@ "scripts": { "build": "turbo run build", "compile": "turbo run compile", + "compile:linux": "turbo run compile:linux", + "compile:mac": "turbo run compile:mac", + "compile:win": "turbo run compile:win", "dev": "turbo run dev", "dist": "turbo run dist", "dist:linux": "turbo run dist:linux", diff --git a/turbo.json b/turbo.json index 86ef30e..55fbbd1 100644 --- a/turbo.json +++ b/turbo.json @@ -9,6 +9,15 @@ "compile": { "dependsOn": ["build"] }, + "compile:linux": { + "dependsOn": ["build"] + }, + "compile:mac": { + "dependsOn": ["build"] + }, + "compile:win": { + "dependsOn": ["build"] + }, "dist": {}, "dist:linux": {}, "dist:mac": {}, @@ -17,13 +26,13 @@ "dependsOn": ["@furtherverse/server#compile"] }, "@furtherverse/desktop#dist:linux": { - "dependsOn": ["@furtherverse/server#compile"] + "dependsOn": ["@furtherverse/server#compile:linux"] }, "@furtherverse/desktop#dist:mac": { - "dependsOn": ["@furtherverse/server#compile"] + "dependsOn": ["@furtherverse/server#compile:mac"] }, "@furtherverse/desktop#dist:win": { - "dependsOn": ["@furtherverse/server#compile"] + "dependsOn": ["@furtherverse/server#compile:win"] }, "dev": { "cache": false,