cc-haha/desktop/scripts/build-sidecars.ts
程序员阿江(Relakkes) 0e60cadb13 chore(desktop): 构建改进与 UI 完善
- build-sidecars.ts macOS 编译后自动 ad-hoc codesign
- build-macos-arm64.sh 构建流程优化
- tauri.conf.json 配置更新
- i18n 中英文翻译补充
- Settings 页面与 uiStore 调整
2026-04-15 14:18:55 +08:00

184 lines
6.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { mkdir } from 'node:fs/promises'
import path from 'node:path'
const desktopRoot = path.resolve(import.meta.dir, '..')
const repoRoot = path.resolve(desktopRoot, '..')
const binariesDir = path.join(desktopRoot, 'src-tauri', 'binaries')
const targetTriple =
process.env.TAURI_ENV_TARGET_TRIPLE ||
process.env.CARGO_BUILD_TARGET ||
(await detectHostTriple())
const bunTarget = mapTargetTripleToBun(targetTriple)
// 编译前先扫一遍 src/ 把所有缺失的 ant-internal 模块在磁盘上 stub 出来。
// 见 desktop/scripts/scan-missing-imports.ts。
console.log('[build-sidecars] scanning for missing imports...')
const scanProc = Bun.spawn(
['bun', 'run', path.join(desktopRoot, 'scripts/scan-missing-imports.ts')],
{ cwd: repoRoot, stdout: 'inherit', stderr: 'inherit' },
)
const scanExit = await scanProc.exited
if (scanExit !== 0) {
throw new Error(`[build-sidecars] scan-missing-imports failed (exit ${scanExit})`)
}
await mkdir(binariesDir, { recursive: true })
// 单一合并 sidecarserver / cli 共享一份 bun runtime + 共享依赖代码。
// 调用方Tauri lib.rs / conversationService通过第一个 positional 参数
// 选择 'server' 或 'cli' 模式,详见 desktop/sidecars/claude-sidecar.ts。
await compileExecutable({
entrypoint: path.join(desktopRoot, 'sidecars/claude-sidecar.ts'),
outfileBase: path.join(binariesDir, `claude-sidecar-${targetTriple}`),
productName: 'Claude Code Sidecar',
bunTarget,
})
console.log(`[build-sidecars] Built desktop sidecar for ${targetTriple} (${bunTarget})`)
async function detectHostTriple() {
const proc = Bun.spawn(['rustc', '-vV'], {
cwd: repoRoot,
stdout: 'pipe',
stderr: 'pipe',
})
const stdout = await new Response(proc.stdout).text()
const stderr = await new Response(proc.stderr).text()
const exitCode = await proc.exited
if (exitCode !== 0) {
throw new Error(`[build-sidecars] rustc -vV failed: ${stderr || stdout}`)
}
const hostLine = stdout
.split('\n')
.map((line) => line.trim())
.find((line) => line.startsWith('host: '))
if (!hostLine) {
throw new Error('[build-sidecars] Could not detect Rust host triple')
}
return hostLine.replace('host: ', '')
}
function mapTargetTripleToBun(triple: string) {
switch (triple) {
case 'aarch64-apple-darwin':
return 'bun-darwin-arm64'
case 'x86_64-apple-darwin':
return 'bun-darwin-x64'
case 'x86_64-pc-windows-msvc':
return 'bun-windows-x64'
case 'aarch64-pc-windows-msvc':
return 'bun-windows-arm64'
case 'x86_64-unknown-linux-gnu':
return 'bun-linux-x64-baseline'
case 'aarch64-unknown-linux-gnu':
return 'bun-linux-arm64'
case 'x86_64-unknown-linux-musl':
return 'bun-linux-x64-musl'
case 'aarch64-unknown-linux-musl':
return 'bun-linux-arm64-musl'
default:
throw new Error(`[build-sidecars] Unsupported target triple: ${triple}`)
}
}
async function compileExecutable({
entrypoint,
outfileBase,
productName,
bunTarget,
}: {
entrypoint: string
outfileBase: string
productName: string
bunTarget: string
}) {
const result = await Bun.build({
entrypoints: [entrypoint],
// minify whitespace + identifiers + dead-code 大概能省 5-15% 的二进制大小,
// 代价是 stack trace 里的函数名变成短名 —— 终端用户场景可接受。
minify: { whitespace: true, identifiers: true, syntax: true },
sourcemap: 'none',
target: 'bun',
// 可选 npm 包:开 telemetry / 用 sharp 图像 / 用 Bedrock/Vertex 等
// 替代 provider 时才需要,全部不在顶层 package.json 里。标 external
// 让 bun build 跳过解析;运行时 import 在没装时自然失败,由 try/catch
// 或 feature() gate 兜底。
external: [
// OpenTelemetry exporters开 OTEL_* env 时才加载)
'@opentelemetry/exporter-trace-otlp-grpc',
'@opentelemetry/exporter-trace-otlp-http',
'@opentelemetry/exporter-trace-otlp-proto',
'@opentelemetry/exporter-logs-otlp-grpc',
'@opentelemetry/exporter-logs-otlp-http',
'@opentelemetry/exporter-logs-otlp-proto',
'@opentelemetry/exporter-metrics-otlp-grpc',
'@opentelemetry/exporter-metrics-otlp-http',
'@opentelemetry/exporter-metrics-otlp-proto',
'@opentelemetry/exporter-prometheus',
// 替代 LLM provider —— 默认不用,用户自装
'@aws-sdk/client-bedrock',
'@aws-sdk/client-sts',
'@anthropic-ai/bedrock-sdk',
'@anthropic-ai/foundry-sdk',
'@anthropic-ai/vertex-sdk',
'@azure/identity',
// ant-internal / 可选工具
'@anthropic-ai/mcpb',
'fflate',
'turndown',
'sharp',
'react-devtools-core',
],
compile: {
target: bunTarget,
outfile: outfileBase,
autoloadTsconfig: true,
autoloadPackageJson: true,
windows: {
title: productName,
publisher: 'Claude Code',
description: productName,
hideConsole: true,
},
},
})
if (!result.success) {
const logs = result.logs.map((log) => log.message).join('\n')
throw new Error(`[build-sidecars] Failed to compile ${productName}:\n${logs}`)
}
const outputPath = result.outputs[0]?.path ?? outfileBase
console.log(`[build-sidecars] ${productName} -> ${outputPath}`)
// macOS Apple System Policy (ASP) requires valid code signatures on all
// executables. Bun-compiled binaries ship with an invalid/empty signature
// that causes "load code signature error 4" and SIGKILL at launch.
// Fix: strip the broken signature, then ad-hoc sign.
if (process.platform === 'darwin') {
console.log(`[build-sidecars] ad-hoc signing ${outputPath} for macOS ...`)
const strip = Bun.spawn(['codesign', '--remove-signature', outputPath], {
stdout: 'inherit',
stderr: 'inherit',
})
await strip.exited
const sign = Bun.spawn(
['codesign', '--sign', '-', '--force', '--timestamp=none', outputPath],
{ stdout: 'inherit', stderr: 'inherit' },
)
const signExit = await sign.exited
if (signExit !== 0) {
throw new Error(`[build-sidecars] ad-hoc codesign failed for ${outputPath} (exit ${signExit})`)
}
console.log(`[build-sidecars] ad-hoc signed ${outputPath}`)
}
}