Bỏ qua để đến nội dung

Lỗi Rust E0463: can't find crate (không tìm thấy crate)

E0463 nghĩa là trình biên dịch đi tìm cả một crate (một thư viện) và trở về tay không. Thường thì code của bạn có một dòng extern crate cho một crate chưa có trong Cargo.toml. Đôi khi crate bị thiếu lại chính là std, chuyện này xảy ra khi bạn build cho một loại máy khác mà chưa cài target đó. Cả hai đều có cách sửa nhanh, và bạn không cần hiểu về linker mới áp dụng được. Trang này thuộc hướng dẫn về lỗi trình biên dịch.

error[E0463]: can't find crate for `rand`
--> src/main.rs:1:1
|
1 | extern crate rand;
| ^^^^^^^^^^^^^^^^^^ can't find crate

Trình biên dịch báo rằng nó không tìm thấy crate rand được yêu cầu ở dòng extern crate.

Đây là chương trình gây ra lỗi, trong một project vừa tạo bằng cargo new và chưa có gì dưới [dependencies]:

extern crate rand;
fn main() {
let roll = rand::random_range(1..=6);
println!("You rolled {roll}");
}

Dạng thường gặp thứ hai hoàn toàn không có số dòng, vì không dòng code nào của bạn yêu cầu std. Chương trình nào cũng cần nó:

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`

Ở đây Rust nói target aarch64-unknown-linux-gnu có thể chưa được cài, và gợi ý tải nó bằng rustup target add. Bạn gặp lỗi đó khi chạy cargo build --target aarch64-unknown-linux-gnu (Linux ARM 64-bit, như Raspberry Pi) trong khi chỉ cài target cho chính máy của bạn. Cách sửa nào phù hợp tùy vào tên crate và dòng note::

Bạn thấy gì Thường sai ở đâu Cách sửa
can't find crate for `rand` ở một dòng extern crate crate chưa có trong Cargo.toml Cách sửa 1
như trên, trong code cũ có #[macro_use] code viết trước edition 2018 Cách sửa 2
can't find crate for `std` + target may not be installed build cho một target mà rustup chưa tải về Cách sửa 3
crate name using dashes are not valid cạnh E0463 tên crate trong code có dấu - Cách sửa 4

extern crate rand; bảo trình biên dịch “hãy liên kết thư viện đã biên dịch tên rand vào chương trình này”. Trình biên dịch không tải gì về và không tìm trên internet. Nó chỉ xem các thư viện mà Cargo đưa cho nó, và Cargo chỉ đưa những crate được liệt kê trong Cargo.toml. Không có rand ở đó nghĩa là không có thư viện rand trong danh sách, vậy là E0463.

Trường hợp std cũng cùng ý tưởng, chỉ ở tầng thấp hơn. Thư viện chuẩn cũng là một thư viện đã biên dịch, và rustup cài một bản cho mỗi target. Toolchain bình thường của bạn chỉ có bản dành cho chính máy tính của bạn. Hãy yêu cầu build cho ARM và trình biên dịch sẽ đi tìm một bản std cho ARM không hề có ở đó.

Giống như một công thức nấu ăn ghi “dùng bột mì trong tủ”. Nếu chẳng ai mua bột mì, người nấu không thể bắt đầu, công thức có hay tới đâu cũng vậy.

Rust không có một thư mục thư viện dùng chung toàn hệ thống như pip install của Python hay một node_modules cho cả máy. Mỗi project ghi rõ nó dùng gì trong Cargo.toml, kèm phiên bản, và Cargo build các crate đó cho riêng project đó. Đó là lý do cùng một project build ra y như nhau trên laptop của bạn, trên máy đồng nghiệp và trên CI. Một crate không được ghi ra thì đơn giản là không tồn tại với code của bạn.

extern crate phần lớn là thứ còn sót lại từ Rust 2015. Từ edition 2018, mọi crate trong Cargo.toml đều tự động dùng được, nên code hiện đại chỉ cần viết use rand::random_range;. Bạn vẫn gặp extern crate trong các bài hướng dẫn cũ và các câu trả lời trên Stack Overflow, và đó là nơi phần lớn lỗi E0463 xuất phát. Ngày nay, nếu thiếu dependency, một dòng use sẽ cho ra E0432 còn một đường dẫn trong code sẽ cho ra E0433. Cùng nguyên nhân, khác mã lỗi.

Xem Cargo và crate để biết dependency hoạt động thế nào, và Công cụ Rust về toolchain và target.

Chọn cách này khi crate bị thiếu đến từ crates.io, như rand, regex hay serde_json. Đây là trường hợp phổ biến nhất. Chạy lệnh này trong thư mục chứa Cargo.toml:

Terminal window
cargo add rand

Cargo thêm phiên bản mới nhất cho bạn:

[dependencies]
rand = "0.10.3"

Chỉ vậy thôi là sửa được E0463. Nhân tiện, hãy xóa dòng extern crate rand;; bạn không cần nó từ edition 2018 trở đi (xem edition = trong Cargo.toml). Phiên bản này in ra một phép kiểm tra thay vì con số tung được, để kết quả lúc nào cũng giống nhau:

fn main() {
let roll = rand::random_range(1..=6);
println!("Số tung được nằm trong khoảng 1 đến 6: {}", (1..=6).contains(&roll));
}

Kết quả:

Số tung được nằm trong khoảng 1 đến 6: true
▶ Tự chạy thử

Code cũ cũng có thể gọi các hàm đã thay đổi giữa các phiên bản. Nếu cargo add sửa được E0463 nhưng sau đó bạn lại gặp E0425 hoặc E0432 cho thứ gì đó như thread_rng, hãy xem tài liệu của crate cho đúng phiên bản bạn đang dùng. Xem Thêm dependency bằng cargo add.

Cách sửa 2: Thay các dòng extern crate cũ bằng use

Phần tiêu đề “Cách sửa 2: Thay các dòng extern crate cũ bằng use”

Chọn cách này khi bạn chép code viết trước 2018. Code đó thường bắt đầu bằng một khối như thế này, và dòng nào cũng có thể gây 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

Rust không tìm thấy cả serde_derive lẫn serde_json. Đừng thêm serde_derive thành một crate riêng. Ngày nay các macro derive đi kèm với serde khi bạn bật feature derive của nó:

Terminal window
cargo add serde --features derive
cargo add serde_json

Rồi xóa khối extern crate và import những gì bạn dùng bằng một dòng use bình thường. #[macro_use] cũng không cần nữa:

use serde::Serialize;
#[derive(Serialize)]
struct Order {
item: String,
qty: u32,
}
fn main() {
let order = Order { item: String::from("táo"), qty: 3 };
println!("{}", serde_json::to_string(&order).unwrap());
}

Kết quả:

{"item":"táo","qty":3}
▶ Tự chạy thử

Nếu một dòng extern crate nêu tên một crate mà code của bạn chẳng hề dùng tới, cứ xóa dòng đó đi. Bài JSON với serde trình bày đầy đủ cách thiết lập hiện đại.

Cách sửa 3: Cài target bằng rustup target add

Phần tiêu đề “Cách sửa 3: Cài target bằng rustup target add”

Chọn cách này khi lỗi nói về std (hoặc core) và dòng note: nói target có thể chưa được cài. Chép tên target từ dòng help::

Terminal window
rustup target add aarch64-unknown-linux-gnu
rustup target list --installed # xem bạn đang có những gì

Rồi build lại với cùng --target. Target là loại máy mà bạn biên dịch cho, được viết dưới dạng một “bộ ba” (triple) như aarch64-unknown-linux-gnu hay wasm32-unknown-unknown. rustup tải về bản std đã biên dịch sẵn cho target đó, và E0463 biến mất.

Hai lưu ý. Thứ nhất, với nhiều target, đó chưa phải bước cuối: build một chương trình hoàn chỉnh cho hệ điều hành khác thường còn cần một linker cho nền tảng đó, và đó là một lỗi khác. Thứ hai, nếu project có file rust-toolchain.toml, hãy chạy lệnh trong thư mục project, để rustup thêm target vào đúng toolchain mà project đó dùng. Xem Component và target và bài WebAssembly cho một target có lẽ bạn sẽ dùng tới.

Cách sửa 4: Viết dấu gạch ngang thành gạch dưới trong code

Phần tiêu đề “Cách sửa 4: Viết dấu gạch ngang thành gạch dưới trong code”

Chọn cách này khi tên crate có dấu gạch ngang, như serde-json hay tracing-subscriber. Trong Cargo.toml và trên dòng lệnh, dấu gạch ngang không sao. Trong code Rust, - là dấu trừ, nên tên luôn được viết bằng _. Code cũ có dấu gạch ngang sẽ cho ra:

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`

Rust giải thích rằng tên có dấu gạch ngang không hợp lệ trong code, và gợi ý dùng dấu gạch dưới. rustc đã đọc tên đó thành serde_json, nên lỗi E0463 bên dưới chỉ xuất hiện khi crate cũng chưa có trong Cargo.toml. Trong một dòng use, dấu gạch ngang cho ra một thông báo khác, expected one of `::`, `;`, or `as`, found `-` . Cách sửa ở đâu cũng vậy: cargo add crate nếu cần, và viết _ trong code:

use serde_json::json;
fn main() {
let order = json!({ "item": "táo", "qty": 3 });
println!("{order}");
}

Kết quả:

{"item":"táo","qty":3}
▶ Tự chạy thử

Quy tắc này cũng áp dụng cho package của chính bạn: một project tên shop-app được import thành shop_app từ main.rs và các test của nó.

Chạy rustc main.rs trực tiếp. Riêng rustc không đọc Cargo.toml, nên ngay cả sau khi cargo add rand, rustc --edition 2021 src/main.rs vẫn báo can't find crate for `rand` cho dòng extern crate rand; (và E0432 cho dòng use rand::...). Cách sửa: build bằng cargo run hoặc cargo build, chúng sẽ truyền các dependency cho trình biên dịch.

Một crate nằm dưới [dev-dependencies]. Dev-dependency (thêm bằng cargo add --dev) chỉ tồn tại cho test, ví dụ và benchmark. Dùng một crate như vậy trong code thường sẽ gây E0463 với extern crate, hoặc E0433 với một đường dẫn. Cách sửa: chuyển nó sang [dependencies] bằng cargo remove --dev serde_json rồi cargo add serde_json.

Bo mạch nhúng không có hệ điều hành. Với một target như thumbv7em-none-eabihf, cài nó thôi là chưa đủ, vì nó hoàn toàn không có std. Dòng note đổi lại để nói điều đó:

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]`

Rust báo rằng target này có thể không hỗ trợ thư viện chuẩn, và crate shop cần std vì nó không khai báo #![no_std]. Cách sửa: viết chương trình dưới dạng #![no_std], nghĩa là cũng không có println! và bạn phải tự viết panic handler. Embedded Rust Book (tiếng Anh) hướng dẫn bạn từng bước.

  • E0432: unresolved import, lỗi mà một dòng use gây ra khi crate chưa có trong Cargo.toml.
  • E0433: failed to resolve, lỗi mà một đường dẫn như rand::rng() gây ra khi thiếu crate.
  • E0603: đã tìm thấy crate, nhưng mục bạn cần trong đó là riêng tư.
  • crate name using dashes are not valid: lỗi này không có mã; hãy viết _ thay cho - (Cách sửa 4).
  • Tất cả lỗi trình biên dịch: danh sách đầy đủ các trang lỗi.

Kiểm tra nhanh

1. Code cũ bắt đầu bằng extern crate regex; và bạn gặp E0463. Cách sửa tốt nhất trong một project edition 2021 là gì?

2. cargo build --target wasm32-unknown-unknown báo không tìm thấy crate std và target có thể chưa được cài. Bạn chạy lệnh gì?

3. Cargo.toml của bạn có tracing-subscriber = "0.3". Trong code Rust, bạn viết tên crate này thế nào?

Điểm: 0 / 3