README 写 Rust 1.85+ 而 toolchain 钉的是 1.95:四条版本门槛的两层口径

2026-08-10

如果你打算从源码构建 CC Switch,第一件事大概是照着 README 的「环境要求」把工具链装齐。README_ZH.md 的第 447 到 450 行给了四条:Node.js 18+、pnpm 8+、Rust 1.85+、Tauri CLI 2.8+。

问题是,这四条在同一个仓库里各自还有第二个出处——.node-versionpackage.jsonpackageManagerrust-toolchain.tomlsrc-tauri/Cargo.toml。逐个比对下来,四条里有三条两层口径对不上,其中 Rust 那一条最反直觉:它在仓库内部就存在两个不同的数,差了十个小版本。

以下全部基于我们本地 clone 的 cc-switch 仓库快照 c39c903(提交日期 2026-08-10),仓库内版本号 3.19.2。我们只读源码文本,没有安装、没有运行、也没有编译过这个项目

四条门槛,两层口径

工具README「环境要求」仓库里的另一处出处两层是否一致
Node.js18+22.12.0.node-version:1不一致
pnpm8+pnpm@10.12.3package.json:21packageManager不一致
Rust1.85+rust-version = "1.85.0" / channel "1.95"src-tauri/Cargo.toml:9 / rust-toolchain.toml:2仓库内部两处不同
Tauri CLI2.8+@tauri-apps/cli^2.8.0package.json:23一致

这张表的读法是:「README『环境要求』」那一列是声明层(写给人看的最低要求);「仓库里的另一处」加「出处」这两列合起来是落盘层(会被工具真正读取的固定值,以及它所在的文件与行)。四条里只有 Tauri CLI 那一条两层能对上。

反直觉的那一处:Rust 在同一个仓库里有两个数

Node 和 pnpm 那两条其实好理解——README 给的是「最低多少以上」,仓库文件给的是「实际钉在哪一版」,一个宽一个窄,方向一致。Rust 这条不一样,它的两个数都在仓库里,而且不同:

  • src-tauri/Cargo.toml:8-9edition = "2021"rust-version = "1.85.0"
  • rust-toolchain.toml:1-4channel = "1.95"components = ["rustfmt", "clippy"]profile = "minimal"

Cargo.toml 那个 1.85.0 与 README 的「Rust 1.85+」是同一个口径,两处对得上。而 rust-toolchain.toml 钉的 1.95 比它高了十个小版本。

这两个文件在 Rust 生态里的分工不是一回事(以下是通用生态语义,不是该项目文档里写的内容,具体行为请以官方文档为准):Cargo.tomlrust-version 是包声明的最低支持版本,属于兼容性元数据;rust-toolchain.toml 是工具链管理器读取的固定工具链声明,落在仓库根目录,作用范围是这个目录下的构建。所以你在这个仓库里执行构建命令时,环境里究竟起作用的是哪一版,跟你照着 README 装了哪一版可能不是一回事。

按纪律,说到这里就停:我们不推断哪个数「才是对的」,也不推断为什么会有两个数。我们没有在本机编译过这个仓库,因此也不能告诉你 Rust 1.85 到底能不能把它编过去——这个问题只能你自己在自己的环境里试。

同一个 rust-toolchain.toml 里另外两行也顺带说明了这个文件想管什么:components 明确要求装 rustfmtclippyprofile = "minimal" 则把默认组件集合压到最小。这两条和版本数无关,只是同在这个文件里一并声明,我们不推断作者为什么这么写。

pnpm 那一条,CHANGELOG 里有个补充

pnpm 的两层差异(README 8+ 对 package.jsonpnpm@10.12.3)不止是个数字差,CHANGELOG 里记了一条与它直接相关的变更。

CHANGELOG.md:52(属于 ## [3.19.2] - 2026-08-06 这一条目下的 Internal 段)记录:CI 改为通过 Corepack 安装 pnpm,遵循 package.json 里的 packageManager 固定版本。这条记录我们只照抄,不替它补充「所以本地也该怎么装」——CHANGELOG 那一行说的是 CI,本地怎么装是另一回事,卡里没有的我们不写。

也就是说,pnpm 这一条的落盘层是 CI 与本地都会读的那个 pin,而 README 的「8+」是另一层的表述。两层各说各的,我们只陈述这个差异本身。

Node 那一条我们没有找到类似的补充记录:.node-version 里就孤零零一行 22.12.0,README 写 18+,两处并列。

Tauri 那一条别搞混:CLI 不是那个 crate

Tauri CLI 是四条里唯一两层一致的:README 写「Tauri CLI 2.8+」,package.json:23 的 devDependency @tauri-apps/cli^2.8.0,对得上。

容易搞混的是仓库里还有两个带 Tauri 字样的版本号,它们不是 CLI:

  • src-tauri/Cargo.toml:30tauri = "2.8.2",features 为 tray-icon / protocol-asset / image-png
  • src-tauri/Cargo.toml:23tauri-build = "2.4.0"

这两个是 Rust 侧的库依赖与构建依赖,跟你装的那个命令行工具是不同的东西。看到 2.4.0 别以为 README 的「2.8+」写错了——它俩根本不在同一个坐标系里。顺带一提,SQLite 是通过 rusqlite = "0.31" 引入的,features 为 bundled / backup / hookssrc-tauri/Cargo.toml:76)。这三个 feature 名我们照抄自 Cargo.toml,它们各自具体意味着什么属于 rusqlite 的通用 feature 约定、不是该项目文档里写的内容,请以官方文档为准。

可复现的核查动作

这一篇的所有结论都能在两分钟内自己核一遍。在仓库根目录依次看这四个文件:

cat rust-toolchain.toml
cat .node-version
sed -n '1,10p;22,24p' src-tauri/Cargo.toml
sed -n '18,24p' package.json

然后打开 README_ZH.md 翻到「环境要求」小节(四条要求在 README_ZH.md:447-450),把上面四个文件里的数逐条对过去。比对的重点是这三组:

  1. .node-version 的一行 对 README 的 Node 条
  2. package.jsonpackageManager 对 README 的 pnpm 条
  3. rust-toolchain.tomlchannelsrc-tauri/Cargo.tomlrust-version 对 README 的 Rust 条(这一组是三处)

以上为按仓库中的文件位置组合的查看示例,我们没有在本机运行过,行号也会随版本变动,以你自己 clone 到的仓库内容为准。

什么时候这几个数才和你有关

这一条得说清楚,否则容易把不相干的读者吓住。

只装成品包的人,完全不受这四条影响。 README 的「环境要求」是开发环境要求,跟安装要求是两套东西:安装侧的口径写在另一处,是 Windows 10 及以上、macOS 12 (Monterey) 及以上、Ubuntu 22.04+ / Debian 11+ / Fedora 34+ 等主流发行版(README_ZH.md:353-355)。你从 Releases 下 msi 或 dmg,跟 Rust 装的是 1.85 还是 1.95 没有任何关系。

要从源码构建或者要提 PR 的人,这四条才是入口。相关的配套信息有两组,一起记下来:

开发脚本在 package.json:6-17pnpm dev 实际是 pnpm tauri devpnpm buildpnpm tauri build,另有 typecheckformatformat:checktest:unittest:unit:watch

提 PR 前的三道门写在 README_ZH.md:582-584pnpm typecheckpnpm format:checkpnpm test:unit 全过。注意 format:check 这道门跟前面 rust-toolchain.toml 里的 components 是两码事——前者是 package.json 里的一个 pnpm 脚本,后者是 rust-toolchain.toml 声明要装的 Rust 组件(rustfmtclippy),两者出处不同;各自具体查什么、装什么,以仓库配置为准。

还有一组固定值虽然不属于「版本门槛」,但同样是被钉死在仓库里、你构建时绕不开的:src-tauri/Cargo.toml:110-117 的 release profile 写了 codegen-units = 1lto = "thin"opt-level = "s"panic = "unwind"strip = "symbols",文件里的注释写明这么设的目的是压小 AppImage 的体积,同时保留 unwind 好让 panic hook 能抓到 backtrace。把它和前面四条放在一起看,你会发现这个仓库对「构建环境长什么样」是有一整套固定声明的,README 的「环境要求」只是其中面向人的那一层摘要。

至于「那我到底该装哪一版」,这个仓库没有给出一句话答案,我们也不替它给。能确定的只有:这几个数分别写在上面那几行里,你照着比对完,就知道自己环境里的每一个工具站在哪一层口径上。

最后重复一遍分寸:四条门槛的两层口径差异是可核实的事实,我们把每一处的文件与行号都标了出来,你可以自己去核。至于哪一处「才算数」、为什么没有同步、这对项目意味着什么,本文不做推断,也不拿它去评价这个项目——对完就停。


本文依据 CC Switch 官方仓库(github.com/farion1231/cc-switch)的 README、docs/ 下的用户手册与发布说明、 src/config/ 的预设定义与 src-tauri/src/ 的后端源码整理,核对日 2026-08-10,对应仓库快照 c39c903。 本文内容为仓库源码与文档口径,我们没有安装或运行过这个桌面应用, 因此不涉及界面外观、操作手感与切换速度的任何描述。 文中出现的阈值与默认值均为源码中的默认配置,不构成对实际运行结果的保证。 该项目仍在快速迭代,版本与默认值随时可能变动,请以仓库最新内容为准。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。