在Windows上把Rust装明白,这句口号听起来不太难,但很多人实际走下来都会卡在同一个地方:link.exe not found。我当年第一次在Windows上编译Rust,输入cargo run后看到这个报错,第一反应是Rust装坏了,后来折腾了半天才明白,问题根本不在Rust,而在Windows缺了一个编译器背后的链接器。这一篇我就把从下载、编译到跑通第一个项目的过程完整拆开,把微软Build Tools、rustup、cargo镜像这些绕不开的细节一次讲清楚。这篇内容既适合刚接触Rust的Windows用户,也适合已经装上rustup但编译总是出问题的朋友。
1. 为什么装完之后第一个hello world就报link.exe not found
1.1 Rust工具链不只是rustc一个文件
安装Rust,本质上安装的是三样东西的组合:rustc是编译器,负责把.rs源码变成目标文件;cargo是构建系统和包管理器,负责调用rustc、下载依赖、链接生成可执行文件;rustup是工具链管理器,负责下载、切换、更新不同版本的rustc和配套组件。
这三者缺一不可,但真正决定你能不能编出.exe的,其实是最后一个环节——链接。源代码经过rustc编译后,生成的是.o目标文件和.rlib静态库,这些文件还不能直接运行,必须经过链接器把它们和Windows系统库粘在一起,才能变成可执行程序。在Windows上,这个链接器默认是微软的link.exe。
问题就出在这里:Rust官方安装包只提供rustc、cargo、rustup,并没有把link.exe一起打包给你。它默认认为你既然用Windows,就应该已經有Visual Studio Build Tools提供的链接器。一旦你没有,cargo build走到链接阶段就会直接罢工,报出那句经典的错误:
error: linker `link.exe` not found | = note: 系统找不到指定的文件。1.2 MSVC和GNU:先搞清楚你是哪条路
Rust在Windows上官方支持两套工具链,一套叫x86_64-pc-windows-msvc,另一套叫x86_64-pc-windows-gnu。安装rustup的时候默认选的是MSVC,因为微软的Visual Studio生态在Windows上是主流。
MSVC工具链依赖微软的Build Tools,里面包含cl.exe编译器、link.exe链接器,以及Windows SDK的导入库。GNU工具链依赖的是MinGW-w64提供的GCC链接器,适合不想装微软那套组件的场景,或者你本来就在MSYS2环境下写C/C++。
很多人的误区是,以为装完rustup就万事大吉,然后发现编译报错时一脸懵。实际上,你选的工具链是谁,决定了谁来做最后一步链接。默认的MSVC路线,就必须把微软的链接器补齐;如果你实在不想装Build Tools,那就得手动切到GNU路线,并准备好MinGW-w64。
1.3 一套完整的排查链路
如果你已经撞上了link.exe not found,不要急着卸载重装,按下面这个顺序排查,能省下不少时间:
- 运行
rustc --version,确认Rust本体安装正常。 - 运行
rustup show,查看当前默认工具链到底是什么。 - 在CMD或PowerShell里执行
where link.exe,如果终端提示"找不到文件",说明系统里确实没有可用的link.exe。 - 打开
C:\Program Files\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC,看是否存在带版本号的目录,不存在就是Build Tools没装。
这一套链路走下来,大概率会在最后一步发现问题。where link.exe查不到,不代表一定没装Build Tools,也有可能只是普通终端的环境变量里没包含它的路径,并不影响rustc通过vswhere机制去查找。重点还是先看Build Tools目录存不存在。
2. 装Build Tools:不是随便点两下就完事的
2.1 下载正确的安装包
要补上链接器,最标准的做法不是去下载某个单独的link.exe,而是安装微软官方的 "Visual Studio Build Tools" 独立安装包。注意,这里说的是Build Tools,不是完整版Visual Studio。如果你只是为了编译Rust,完全没必要装整套IDE,Build Tools直接提供编译器和链接器,轻量得多。
下载入口是微软官网的Visual Studio Downloads页面,往下翻到"下载Visual Studio Tools",选择 "Build Tools for Visual Studio 2022" 的"生成工具"版本。安装器是几百MB的在线引导程序,运行后会让你勾选工作负载,真正的组件是边走边下载的。
2.2 工作负载怎么勾才准确
至少要勾选 "使用C++的桌面开发" 这一项。这个名字看起来很大,实际装完它会把MSVC编译器、Windows SDK、C++标准库这些核心组件一起带下来。Rust真正需要的核心组件有三个:
- MSVC v143 生成工具,里面包含
cl.exe和link.exe - Windows SDK,提供Windows API的头文件和导入库
- 如果后续要做C/C++混合项目,可以顺便勾上"适用于Windows的C++ CMake工具"
装完后磁盘占用大概在5到15GB之间,取决于你勾了多少项。网速正常的情况下,安装时间通常要20到40分钟。期间尽量别关机,偶尔会卡在某个组件上,直接点"继续"让它重试就行。
2.3 装完怎么验证它真的能用了
安装完成后,不要直接回Rust终端跑cargo build,先验证Build Tools本身是不是好的。
打开Windows开始菜单,找到 "x64 Native Tools Command Prompt for VS 2022",这个终端会自动把MSVC工具链的路径注入PATH。在窗口里执行:
cl link如果分别看到cl.exe的版本信息和link.exe的版本信息,说明MSVC工具链已经可用。再检查三个关键路径是否存在:
C:\Program Files\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.x.x,下面有bin\Hostx64\x64\cl.exe和link.exeC:\Program Files\Windows Kits\10\Lib\10.x.x,这是Windows SDK库文件目录- 上述MSVC目录下的
lib\x64,标准库导入库就在这
这三个路径齐全之后,rustc在编译时会自动通过vswhere机制找到Build Tools,不需要你在普通终端里手动配置PATH。怕搞错的话,也可以像我一样再执行一条命令:
vswhere.exe -latest -property installationPath能输出VS或Build Tools的安装路径,说明rustc找它的主要通道是通的。
2.4 已经装了Visual Studio还需要再装吗
很多人电脑上本来就装了Visual Studio 2022,而且勾选了C++开发组件,那就完全不用再安装Build Tools了,rustc会自动识别。要注意版本匹配:VS 2019配套的MSVC v142也能用,Rust官方对版本要求不严。唯一麻烦的是系统里同时有Build Tools和MinGW的情况,PATH里如果出现多个link.exe或gcc.exe,就可能引发工具链混乱,这个具体在第五部分细说。
一个小建议:如果你只是编译Rust,优先选择Build Tools独立安装包,别贪方便把整个Visual Studio也装上。IDE那部分体积大,平时又用不上,纯粹占磁盘。
3. rustup的安装、环境变量与国内镜像提速
3.1 拿到rustup-init.exe
安装Rust本身的入口是rustup.rs。在Windows浏览器打开这个页面,会自动下载rustup-init.exe。不建议从第三方站点下载所谓的一键安装包,版本旧不说,还可能捆绑额外程序。
双击运行之后,安装器会问你要装什么工具链,默认就是stable-x86_64-pc-windows-msvc,直接回车即可。它会创建两个目录:
%USERPROFILE%\.cargo,cargo的安装目录,里面bin文件夹放着cargo.exe和rustc.exe%USERPROFILE%\.rustup,rustup管理的工具链目录,不同版本和目标平台都放在这里
安装完会自动把%USERPROFILE%\.cargo\bin加进当前用户的PATH。记得新开一个终端再验证:
rustup --version cargo --version rustc --version三条命令都能输出版本号,才算装上。
3.2 命令行安装时值得注意的参数
如果你喜欢用命令行,安装阶段可以加几个参数,省得点半天界面:
-y:跳过所有交互式提示,适合脚本化安装--default-toolchain stable:指定默认工具链--profile minimal:只装rustc、cargo、rust-std,不装文档等其他组件,下载量能少一两百MB--default-host x86_64-pc-windows-msvc:显式指定目标平台,防止某些机器默认选了奇怪的目标
完整命令举例:
rustup-init.exe -y --default-toolchain stable --profile minimal --default-host x86_64-pc-windows-msvc普通用户用默认profile就够,真需要补文档时再用rustup component add添加也不迟。
3.3 国内下载慢的镜像配置
rustup和cargo默认从海外服务器下载,国内网络经常慢到想砸键盘。这个问题有两部分:一是rustup下载编译器二进制,二是cargo下载crates.io的索引和依赖包。解决方案都是换成国内镜像。
先给rustup配置下载源,设置两个环境变量:
RUSTUP_DIST_SERVER=https://rsproxy.cn RUSTUP_UPDATE_ROOT=https://rsproxy.cn/rustup设置完必须重开终端,再执行rustup update才会生效。如果下载速度有明显提升,说明源已经切过来了。
再给cargo配置依赖镜像。编辑%USERPROFILE%\.cargo\config.toml,内容如下:
[source.crates-io] replace-with = "rsproxy" [source.rsproxy] registry = "https://rsproxy.cn/crates.io-index" [registries.rsproxy] index = "https://rsproxy.cn/crates.io-index" [net] git-fetch-with-cli = true配置好之后,cargo build拉依赖就会走镜像。要注意,镜像站偶尔会有同步延迟,某些新发布的crate可能找不到版本。遇到这种情况,先注释掉配置再试,用来排除是不是镜像同步问题。
3.4 装完必须检查的几项
装完我会第一时间执行rustup show,它会列出当前安装的工具链和活动工具链。如果默认不是stable-x86_64-pc-windows-msvc,就手动执行:
rustup default stable-x86_64-pc-windows-msvc然后跑rustc -vV,看输出里host:那一行。如果是x86_64-pc-windows-msvc,就说明你现在走在MSVC路线上。如果看到x86_64-pc-windows-gnu,说明你已经切到了GNU路线,此时需要额外确认MinGW是否就位。
rustc --print sysroot可以查看工具链实际安装目录。有些奇怪的环境下,工具链装到了非用户目录,会导致权限相关的编译错误,这种时候直接删掉%USERPROFILE%\.rustup重新安装,往往比排查权限快得多。
4. 从cargo new到cargo build:编译一个真实项目的完整链路
4.1 创建项目并写进第一个可编译的代码
打开终端,进入你准备放代码的目录,然后执行:
cargo new hello_rust --bin cd hello_rust这条命令会生成三个东西:Cargo.toml项目清单、src\main.rs源码文件、.git目录。main.rs里默认有一行println!("Hello, world!");。
我习惯先把Cargo.toml打开看一眼,确认[dependencies]区是空的。后续每装一个第三方库,都会往这里加一行,比如:
[dependencies] serde = { version = "1", features = ["derive"] }4.2 cargo build 到底做了什么
直接执行:
cargo build首次编译会慢一点,因为cargo需要建立构建缓存、加载工具链。看到Compiling hello_rust之后出现Finished dev [unoptimized + debuginfo],就说明编译成功。此时target\debug\hello_rust.exe就是实实在在的Windows可执行文件。
再执行:
cargo run它会先判断是否需要重新编译,然后启动程序,控制台最终输出Hello, world!。如果在这个节点再报link.exe not found,回到第二部分检查Build Tools;如果报缺某个.dll,通常是系统里没有对应的VC运行库,把vc_redist.x64.exe装一下就好。
4.3 中间产物到底是怎么回事
第一次打开target目录,你会看到一长串文件夹,容易懵。简单解释:
target\debug:最终可执行文件target\debug\deps:所有第三方crate的编译中间结果,文件名带哈希是为了防止版本冲突target\debug\build:执行过build script的crate的临时输出target\debug\.fingerprint:记录源码哈希、依赖版本和编译参数,cargo靠它判断哪些文件需要重新编译
明白了这层逻辑,就能理解为什么第二次cargo build会快很多,因为cargo只重编你改动过的部分。如果哪天工具链升级,它检测到环境变化,可能会全部重编,这是正常行为。
4.4 debug和release怎么选
日常开发用cargo build是debug模式,编译快、运行慢、输出体积大,适合调试。需要给别人用或看真实性能时:
cargo build --releaserelease模式会开优化,输出在target\release下。编译时间会明显拉长,但体积和性能都好很多。我的习惯是,如果项目依赖很重,先跑一遍debug把依赖编译缓存建好,再切release,避免从零优化等太久。
4.5 IDE配置和rust-analyzer
命令行能编译之后,建议马上装rust-analyzer。在VS Code的扩展市场搜索并安装,它会自动定位rustup工具链。打开src\main.rs时,它会提供代码补全、类型标注和跳转定义。
如果rust-analyzer无法连接工具链,最常见原因是组件没装。执行:
rustup component add rust-analyzer然后在VS Code设置里把rust-analyzer.server.path指到对应的rust-analyzer.exe路径,基本能解决。
5. 编译过程中最容易被忽视的环境变量和系统设置
5.1 PATH里的多个link.exe到底听谁的
这是Windows环境里一个经典的隐性坑。你可能装过Qt、Anaconda、LLVM、MinGW,这些工具都会往PATH里塞自己的编译器和链接器。当rustc在某条MSVC工具链下编译时,它会调用link.exe,但如果PATH里第一个link.exe是MinGW版本的,最后的链接结果就说不准了,常见的表现是链接报错或者生成的exe启动即崩溃。
排查方式还是那个命令:
where link.exe如果输出多个路径,把非MSVC版本对应的目录从用户PATH或系统PATH里暂时移除。我自己遇到过一次,系统PATH残留了一个很老的MinGW路径,导致Rust项目一连串链接错误,删掉那条路径后立刻恢复。
5.2 中文用户名和特殊字符路径
Rust工具链本身对空格、中文路径的容错已经比几年前好了很多,但第三方crate在编译期会把绝对路径写进生成的代码里,路径一旦包含中文或特殊字符,个别构建脚本还是会出问题。最典型的场景是Windows用户名为中文,路径变成C:\Users\张三,某些原生C库在编译时会因为路径编码报错。
最省事的规避方式,是给cargo指定一个纯英文的中间目录:
CARGO_TARGET_DIR=D:\rust_target这个变量只改变编译产物目录,不会改变项目源码路径。如果项目本身也放在中文路径下,最好把它挪到英文目录,一劳永逸。
5.3 杀毒软件实时扫描让编译变慢
Windows Defender会对新生成的exe和dll做实时扫描,而cargo每次编译都会在target目录下生成大量中间文件,造成CPU额外开销。实测把target目录和.cargo目录加入Defender排除项,release编译时间能缩短20%到40%。
操作路径:Windows安全中心 -> 病毒和威胁防护 -> 管理设置 -> 排除项 -> 添加排除项 -> 文件夹。把D:\rust_target和%USERPROFILE%\.cargo都加进去。第三方杀毒软件同理,实时扫描对编译缓存目录的影响都很大。
5.4 RUST_BACKTRACE和其他调试开关
写Rust程序总会遇到panic。默认情况下只输出一行错误信息,很难定位问题。设置环境变量:
RUST_BACKTRACE=1再次运行程序,就能看到完整调用栈。这是debug阶段最实用的开关。如果你在写服务端程序,还可以设置RUST_LOG=debug,配合env_logger库把日志级别打开。这两个变量我直接写进系统环境变量,省得每次调试都临时敲一遍。
5.5 磁盘空间和cargo clean
Rust编译产物很占空间。一个依赖多点的项目,target目录轻松超过10GB。我习惯定期执行:
cargo clean这条命令会清掉整个target目录,下次编译全部重来。如果只想清release产物,手动删target\release就行。磁盘比较紧张但不大的项目,也可以设置CARGO_INCREMENTAL=0关闭增量编译,省掉部分缓存文件,代价是每次编译都从头开始。
6. MSVC还是GNU:不要迷信网上二选一的说法
6.1 两条路的实质区别
网上很多教程说"Windows上装Rust选MSVC",但没说清楚为什么。两条路线真正的差异在一点:你最终链接的是哪套C运行时。
MSVC路线链接微软的ucrt.dll和vcruntime,和Windows系统、Visual Studio生态天然兼容。如果程序要调用Windows API、做系统级工具,或者嵌入C#项目,MSVC是必选项。GNU路线链接MinGW-w64提供的GNU运行时,和Linux下GCC编译出来的符号兼容性更好,适合从Linux迁过来的项目,或者在MSYS2环境里做跨平台开发。
选错的典型后果是,同一个C库,在MSVC工具链下能用,切到GNU工具链就找不到库文件。所以纯Rust项目选哪个都行,一旦涉及C/C++ FFI,就跟着C库的编译方式走。
6.2 真想切GNU工具链该怎么做
切换命令很简单:
rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu但前提是系统里有MinGW-w64。推荐用winget install MSYS2装MSYS2,再在MSYS2里安装mingw-w64-x86_64-gcc包。这条路我不是很推荐新手走,因为GNU环境下路径配置、crt库版本兼容的问题比MSVC多不少,rustup官方对MSVC工具链的文档和测试也更加充分。
6.3 别忘了Windows上还有WSL这个选项
如果你确实觉得Windows本地编译环境很麻烦,还有一个完全不一样的解法:在WSL里装Rust。WSL2跑的是完整的Linux环境,你可以在里面直接用Linux工具链,编译Linux原生程序,性能损失可以接受。很多教程项目、开源代码的中等复杂度依赖,在WSL里编译比在Windows本地更顺。
当然,如果目标就是产出Windows原生exe,WSL帮不上忙,还是得回到Windows工具链。但如果你只是学习Rust语法、跑LeetCode练习题或者开发Linux服务端,WSL确实能绕开Windows环境配置的一大堆问题。我的建议是,Windows原生开发和WSL各保留一个环境,需求不同就切着用,不必非死磕一边。
6.4 我现在的固定配置是什么
这几年我在Windows上折腾下来,最终固定为:MSVC工具链 + Build Tools 2022 + rust-analyzer + cargo镜像配置。原因很简单,大部分Rust项目最终都要和Windows生态打交道,MSVC能保证链接系统库时不容易出问题。GNU工具链我只在跨平台编译某些C库时用一下,日常主力还是MSVC。
Cargo的链接器其实也能改成lld-link.exe之类的第三方工具,在项目的.cargo\config.toml里指定:
[target.x86_64-pc-windows-msvc] linker = "lld-link.exe"这需要额外装LLVM,属于进阶玩法,日常不推荐。我只有碰到个别依赖和默认linker冲突时才会动这个配置。
如果让我给一句最终的实操建议,那就是:装Rust最核心的不是rustup,而是把Windows的编译链接环境理顺。Build Tools装好、工具链选对、镜像配好,后面的Rust开发基本感觉不到工具链的存在。我上面写的这些踩坑过程,每一步都是从"它为什么不编译"到"我该改哪条环境变量"的真实复盘,照着走一遍,你大概率能在正常下班前跑出第一个Rust程序。