Rust 错误 E0463:can't find crate(找不到 crate)
E0463 的意思是:编译器去找一整个 crate(一个库),结果空手而归。通常是你的代码里有一行 extern crate,而那个 crate 并不在 Cargo.toml 里。有时候找不到的 crate 就是 std 本身,这发生在你为另一种机器编译、却还没安装那个目标平台的时候。这两种情况都有很快的修法,而且你不需要懂链接器也能修好。这一页属于 Rust 编译错误详解系列。
error[E0463]: can't find crate for `rand` --> src/main.rs:1:1 |1 | extern crate rand; | ^^^^^^^^^^^^^^^^^^ can't find crate意思是“找不到 rand 这个 crate”。在一个刚用 cargo new 创建、[dependencies] 下面什么都没有的项目里,下面的程序就会产生这个错误:
extern crate rand;
fn main() { let roll = rand::random_range(1..=6); println!("你掷出了 {roll}");}第二种常见形式根本没有行号,因为你的代码里没有哪一行要求 std。每个程序都需要它:
error[E0463]: can't find crate for `std` | = note: the `aarch64-unknown-linux-gnu` target may not be installed = help: consider downloading the target with `rustup target add aarch64-unknown-linux-gnu`note 说这个目标平台可能没有安装,help 建议你用 rustup target add 下载它。当你的电脑上只装了本机的目标平台,却运行 cargo build --target aarch64-unknown-linux-gnu(64 位 ARM Linux,比如树莓派)时,就会看到它。需要哪种修法,取决于 crate 的名字和 note: 的内容:
| 你看到的 | 通常哪里出了问题 | 修法 |
|---|---|---|
extern crate 那一行报 can't find crate for `rand` |
这个 crate 不在 Cargo.toml 里 |
修复 1 |
同样的错误,出现在带 #[macro_use] 的老代码里 |
代码写于 2018 版次之前 | 修复 2 |
can't find crate for `std` + target may not be installed |
为 rustup 还没下载的目标平台编译 | 修复 3 |
E0463 旁边出现 crate name using dashes are not valid |
代码里的 crate 名字带了 - |
修复 4 |
这个错误是什么意思
Section titled “这个错误是什么意思”extern crate rand; 告诉编译器:“把名叫 rand 的已编译库链接进这个程序”。编译器不会下载任何东西,也不会上网搜索。它只看 Cargo 交给它的那些库,而 Cargo 只交出 Cargo.toml 里列出的 crate。那里没有 rand,清单上就没有 rand 这个库,于是就是 E0463。
std 的情况是同一个道理,只是往下深了一层。标准库也是一个已编译的库,rustup 会为每个目标平台各装一份。你平常的工具链里只有给本机用的那一份。你要求编译 ARM 版本,编译器就去找 ARM 版的 std,而它并不存在。
这就像一份菜谱写着“用橱柜里的面粉”。如果没人买过面粉,菜谱写得再好,厨师也没法开工。
Rust 为什么要这样做
Section titled “Rust 为什么要这样做”Rust 没有全局共享的“已安装库”文件夹,不像 Python 的 pip install 或系统级的 node_modules。每个项目都在 Cargo.toml 里写清楚自己用了什么、用哪个版本,Cargo 再专门为这个项目构建这些 crate。所以同一个项目在你的笔记本、同事的电脑和 CI 上都能以同样的方式构建。没写下来的 crate,对你的代码来说就是不存在的。
extern crate 基本上是 Rust 2015 留下来的东西。从 2018 版次开始,Cargo.toml 里的每个 crate 都会自动可用,所以现代代码直接写 use rand::random_range; 就行。你仍然会在老教程和 Stack Overflow 的回答里看到 extern crate,大多数 E0463 也正是从那里来的。如今在缺少依赖的情况下,use 那一行会报 E0432,代码里的路径会报 E0433。原因一样,代码不同。
依赖是怎么工作的,见 Cargo 和 crate;工具链和目标平台,见 Rust 工具。
修复 1:用 cargo add 添加这个 crate
Section titled “修复 1:用 cargo add 添加这个 crate”当缺少的 crate 来自 crates.io(比如 rand、regex 或 serde_json)时,选这个方法。这是最常见的情况。在包含 Cargo.toml 的文件夹里运行:
cargo add randCargo 会替你加上最新的版本:
[dependencies]rand = "0.10.3"光是这样就能修好 E0463。顺手把 extern crate rand; 这一行删掉吧;在 2018 及以后的版次里不需要它(看看 Cargo.toml 里的 edition = )。下面这个版本打印的是一个检查结果,而不是点数,所以输出永远一样:
fn main() { let roll = rand::random_range(1..=6); println!("点数在 1 到 6 之间:{}", (1..=6).contains(&roll));}输出:
点数在 1 到 6 之间:true老代码可能还会调用在不同版本之间变过的函数。如果 cargo add 修好了 E0463,接着却因为 thread_rng 之类的东西报 E0425 或 E0432,就去查一下你所用版本的 crate 文档。参见用 cargo add 添加依赖。
修复 2:把旧的 extern crate 换成 use
Section titled “修复 2:把旧的 extern crate 换成 use”当你复制的是 2018 年之前的代码时,选这个方法。这种代码常常以这样一段开头,而每一行都可能报 E0463:
#[macro_use]extern crate serde_derive;extern crate serde_json;
#[derive(Serialize)]struct Order { item: String, qty: u32,}error[E0463]: can't find crate for `serde_derive` --> src/main.rs:2:1 |2 | extern crate serde_derive; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate
error[E0463]: can't find crate for `serde_json` --> src/main.rs:3:1 |3 | extern crate serde_json; | ^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate不要把 serde_derive 当作单独的 crate 添加。如今,只要打开 serde 的 derive 特性,派生宏就会随 serde 一起提供:
cargo add serde --features derivecargo add serde_json然后删掉那段 extern crate,用普通的 use 导入你要用的东西。#[macro_use] 也不需要了:
use serde::Serialize;
#[derive(Serialize)]struct Order { item: String, qty: u32,}
fn main() { let order = Order { item: String::from("apple"), qty: 3 }; println!("{}", serde_json::to_string(&order).unwrap());}输出:
{"item":"apple","qty":3}如果某行 extern crate 引入的 crate 你的代码其实根本没用到,直接删掉这一行就好。用 serde 处理 JSON 这一课完整展示了现代的写法。
修复 3:用 rustup target add 安装目标平台
Section titled “修复 3:用 rustup target add 安装目标平台”当错误说的是 std(或 core),并且 note: 说目标平台可能没有安装时,选这个方法。从 help: 那一行复制目标平台的名字:
rustup target add aarch64-unknown-linux-gnurustup target list --installed # 查看现在装了哪些目标平台然后用同样的 --target 再构建一次。目标平台(target)就是你要为之编译的机器类型,写成一个“三元组”(triple),比如 aarch64-unknown-linux-gnu 或 wasm32-unknown-unknown。rustup 会为它下载预编译好的 std,E0463 就消失了。
有两点要注意。第一,对很多目标平台来说,这还不是最后一步:要为另一个操作系统构建完整的程序,通常还需要那个平台的链接器,那是另一个错误。第二,如果项目里有 rust-toolchain.toml,要在项目文件夹里运行这条命令,这样 rustup 才会把目标平台加到这个项目实际使用的工具链上。参见组件和目标平台,以及你很可能会用到的一个目标平台:WebAssembly 这一课。
修复 4:在代码里把短横线写成下划线
Section titled “修复 4:在代码里把短横线写成下划线”当 crate 的名字带短横线(比如 serde-json 或 tracing-subscriber)时,选这个方法。在 Cargo.toml 和命令行里,短横线没问题。但在 Rust 代码里,- 是减号,所以名字永远要写成 _。带短横线的老代码会报这样的错:
error: crate name using dashes are not valid in `extern crate` statements --> src/main.rs:1:14 |1 | extern crate serde-json; | ^^^^^^^^^^ dash-separated idents are not valid |help: if the original crate name uses dashes you need to use underscores in the code |1 - extern crate serde-json;1 + extern crate serde_json; |
error[E0463]: can't find crate for `serde_json`第一个错误是说:extern crate 语句里的 crate 名字不能带短横线;help 告诉你,如果原来的 crate 名字带短横线,在代码里要改用下划线。rustc 已经把名字读成了 serde_json,所以下面那个 E0463 只有在这个 crate 同时也没写进 Cargo.toml 时才会出现。在 use 那一行里,短横线会给出另一条信息:expected one of `::`, `;`, or `as`, found `-` 。修法在哪里都一样:需要的话先 cargo add 这个 crate,然后在代码里写 _:
use serde_json::json;
fn main() { let order = json!({ "item": "apple", "qty": 3 }); println!("{order}");}输出:
{"item":"apple","qty":3}同样的规则也适用于你自己的包:一个名叫 shop-app 的项目,在它的 main.rs 和测试里要以 shop_app 的名字导入。
直接运行 rustc main.rs。 单独的 rustc 不会读 Cargo.toml,所以就算已经 cargo add rand 了,rustc --edition 2021 src/main.rs 对 extern crate rand; 这一行还是会报 can't find crate for `rand` (对 use rand::... 这一行则报 E0432)。修法:用 cargo run 或 cargo build 构建,它们会把依赖传给编译器。
写在 [dev-dependencies] 下面的 crate。 开发依赖(用 cargo add --dev 添加)只给测试、示例和基准测试用。在普通代码里用它,配合 extern crate 会报 E0463,配合路径会报 E0433。修法:先运行 cargo remove --dev serde_json,再运行 cargo add serde_json,把它移到 [dependencies]。
没有操作系统的嵌入式开发板。 像 thumbv7em-none-eabihf 这样的目标平台,光安装是不够的,因为它根本没有 std。这时 note 会变成:
error[E0463]: can't find crate for `std` | = note: the `thumbv7em-none-eabihf` target may not support the standard library = note: `std` is required by `shop` because it does not declare `#![no_std]`意思是这个目标平台可能不支持标准库,而 shop 没有声明 #![no_std],所以需要 std。修法:把程序写成 #![no_std],这也意味着没有 println!,还得自己写 panic 处理函数。The Embedded Rust Book(英文)会一步步带你完成。
- E0432:
unresolved import(无法解析的导入),当 crate 不在Cargo.toml里时,use那一行报的错。 - E0433:
failed to resolve(无法解析),当 crate 缺失时,rand::rng()这样的路径报的错。 - E0603:crate 找到了,但你要的那个项是私有的。
crate name using dashes are not valid:这个错误没有错误代码;把-改成_就好(修复 4)。- 所有编译错误:全部错误页面的列表。
小测验
1. 老代码以 extern crate regex; 开头,你得到了 E0463。在一个 2021 版次的项目里,最好的修法是什么?
2. cargo build --target wasm32-unknown-unknown 说找不到 std 这个 crate,还说目标平台可能没有安装。你该运行什么?
3. 你的 Cargo.toml 里有 tracing-subscriber = "0.3"。在 Rust 代码里,这个 crate 的名字怎么写?
得分: 0 / 3
- E0463 — Rust 错误代码索引(英文):关于找不到 crate 的官方说明。
- 使用 crate 来增加更多功能 — Rust 程序设计语言:一步步往
Cargo.toml里添加你的第一个依赖。 - Specifying Dependencies — The Cargo Book(英文):版本、特性,以及
[dependencies]和[dev-dependencies]的区别。 - Path and module changes in Rust 2018 — Edition Guide(英文):为什么不再需要
extern crate。 - Cross-compilation — The rustup book(英文):用
rustup target add安装目标平台。