本节摘要:第 1 章我们说过,OpenCode 的安装会按你的机器挑一份精确匹配的平台二进制。本节讲清这套「挑选」背后的工程:启动脚本(一个纯 Node 脚本)如何探测操作系统、CPU 架构、C 库(libc)、CPU 指令集(AVX2),然后从一个有序的候选包列表里找到第一个存在的包来执行。这套机制解释了「为什么安装后能直接跑」——它不是魔法,而是精确的平台匹配。
先破除一个误解:OpenCode 的启动脚本(命令入口)是纯 Node 脚本,不依赖 Bun。这是个有意的设计——启动脚本要尽可能轻、尽可能兼容,所以用 Node 能跑的最小脚本。它只负责一件事:挑对平台二进制,然后把命令行参数转发给它。
用户敲 opencode 命令 │ ▼ 启动脚本(纯 Node) │ ├─ 探测平台(OS / 架构 / libc / AVX2) ├─ 生成候选包名列表(有序) ├─ 找到第一个存在的包 └─ spawn 那个二进制,转发参数
启动脚本本身跑完后,真正的活儿交给被挑中的平台二进制(那才是 Bun 编译的产物)。
启动脚本探测四个维度,每个都有具体方法:
用 Node 内置的 os.platform() 和 os.arch() 直接拿到。组合有:darwin/linux/windows × x64/arm64/arm。包名前缀就是 opencode-<平台>-<架构>。
AVX2 是一种 SIMD 指令集,OpenCode 在某些本地推理路径上会用它加速。但不是所有 CPU 都支持,所以只对 x64 架构探测:
| 平台 | 探测方法 |
|---|---|
| Linux | 读 /proc/cpuinfo,正则匹配 avx2 标志 |
| macOS | 调 sysctl -n hw.optional.avx2_0 |
| Windows | 调 IsProcessorFeaturePresent(40)(40 = AVX2) |
💡 为什么只对 x64:arm64 架构的 SIMD 是另一套(NEON),且通常都支持,不需要这种「支持/不支持」的探测。x64 因为历史原因,老 CPU 可能不支持 AVX2,所以必须探测。
Linux 有两种主流 C 库:glibc(大多数发行版)和 musl(Alpine 等)。两者编译的二进制不兼容,所以必须区分。探测方法:
/etc/alpine-release 文件是否存在(Alpine 用 musl)。ldd --version 看输出是否含 musl。探测完四个维度,生成一个有序的候选包名列表。顺序很关键——最具体的(如 baseline-musl)排前面,最通用的排后面。以「musl + x64 + baseline」为例,候选列表大致是:
1. opencode-linux-x64-baseline-musl ← 最具体,优先 2. opencode-linux-x64-musl 3. opencode-linux-x64-baseline 4. opencode-linux-x64 ← 最通用,兜底
启动脚本从前往后找,用第一个实际存在的包。
有了候选列表,启动脚本怎么找「哪个包存在」?方法是从当前目录向上遍历 node_modules:
当前目录 └─ node_modules/opencode-linux-x64-baseline-musl ? ← 找 (没有)向上 └─ ../node_modules/... ← 继续找 ... └─ 找到第一个存在的,用它
这种「向上找」保证不管你在项目的哪一层目录启动,都能找到装在顶层的平台包。
⚠️ 环境变量覆盖:有个逃生口——环境变量(如
OPENCODE_BIN_PATH)可以直接指定二进制路径,跳过整个探测。这在调试或特殊部署时有用。
你可能会问:为什么不直接发一个「通用」二进制?三个理由:
这些差异是真实的硬件/系统层面差异,没法用一个二进制覆盖。所以 OpenCode 的做法是:发多个平台包,启动脚本精确挑。这是跨平台二进制工具的常见做法,只是 OpenCode 把维度分得更细(尤其加了 AVX2)。
本节讲的是「挑包」,而「造包」是第 12 章的主题——单文件构建脚本会按一个目标矩阵(共 12 个变体)产出所有平台二进制,每个变体写一份带 os/cpu/libc 字段的包描述,供 npm 按平台分发。挑(本节)和造(第 12 章)是一对:造出 12 个包,挑出 1 个对的。
记住这张表,踩坑时能快速定位:
| 症状 | 最可能原因 | 排查 |
|---|---|---|
| 非法指令(启动即崩) | AVX2 版装到不支持 AVX2 的 CPU | 让脚本重新探测,或强制用 baseline 版 |
| 找不到符号 | musl 版装到 glibc 系统或反之 | 检查 libc 探测,选对 musl/gnu 版 |
| 找不到二进制 | 候选包都没装上 | 重新装,或用环境变量直接指定路径 |
| 架构不匹配 | 装错架构包(如 x64 装到 arm) | 检查架构探测 |
挑包讲完了,下一节讲最常用的「连接枢纽」——serve 模式。