Aller au contenu

Erreur Rust E0463 : can't find crate (crate introuvable)

E0463 veut dire que le compilateur a cherché une crate entière (une bibliothèque) et qu’il est revenu les mains vides. Le plus souvent, votre code contient une ligne extern crate pour une crate qui n’est pas dans Cargo.toml. Parfois, la crate manquante est std elle-même : cela arrive quand vous compilez pour un autre type de machine sans avoir installé cette cible. Dans les deux cas, la correction est rapide, et vous n’avez pas besoin de comprendre le fonctionnement d’un éditeur de liens pour l’appliquer. Cette page fait partie du guide des erreurs du compilateur.

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

Le compilateur vous dit : « impossible de trouver la crate rand ».

Voici le programme qui la provoque, dans un projet tout neuf créé avec cargo new, sans rien sous [dependencies] :

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

La deuxième forme courante n’a aucun numéro de ligne, parce qu’aucune ligne de votre code ne demande std. Tous les programmes en ont besoin :

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`

La note dit que la cible aarch64-unknown-linux-gnu n’est peut-être pas installée, et l’aide propose de la télécharger avec rustup target add. Vous obtenez ce message avec cargo build --target aarch64-unknown-linux-gnu (Linux ARM 64 bits, comme sur un Raspberry Pi) quand seule la cible de votre propre machine est installée. La solution dépend du nom de la crate et de la ligne note: :

Ce que vous voyez Ce qui s’est généralement mal passé Solution
can't find crate for `rand` sur une ligne extern crate la crate n’est pas dans Cargo.toml Solution 1
la même chose, dans du vieux code avec #[macro_use] du code écrit avant l’édition 2018 Solution 2
can't find crate for `std` + target may not be installed une compilation pour une cible que rustup n’a pas téléchargée Solution 3
crate name using dashes are not valid à côté de E0463 un - dans le nom de la crate dans votre code Solution 4

extern crate rand; dit au compilateur : « relie à ce programme la bibliothèque compilée qui s’appelle rand ». Le compilateur ne télécharge rien et ne cherche pas sur Internet. Il regarde seulement les bibliothèques que Cargo lui donne, et Cargo ne lui donne que les crates listées dans Cargo.toml. Pas de rand dans ce fichier, donc pas de bibliothèque rand dans la liste, donc E0463.

Le cas de std repose sur la même idée, un niveau plus bas. La bibliothèque standard est elle aussi une bibliothèque compilée, et rustup en installe une copie par cible. Votre toolchain habituelle n’a que la copie pour votre propre ordinateur. Demandez une compilation pour ARM, et le compilateur cherche une copie ARM de std qui n’existe pas.

C’est comme une recette qui dit « prenez la farine dans le placard ». Si personne n’a acheté de farine, le cuisinier ne peut pas commencer, aussi bonne que soit la recette.

Rust n’a pas de dossier global et partagé de bibliothèques installées, comme le pip install de Python ou un node_modules commun à tout le système. Chaque projet indique exactement ce qu’il utilise dans Cargo.toml, avec les versions, et Cargo compile ces crates pour ce projet-là. C’est pour cela qu’un même projet se compile de la même façon sur votre ordinateur portable, sur la machine d’un collègue et en intégration continue (CI). Une crate qui n’est pas écrite dans ce fichier n’existe tout simplement pas pour votre code.

extern crate est surtout un vestige de Rust 2015. Depuis l’édition 2018, chaque crate de Cargo.toml est disponible automatiquement : le code moderne écrit simplement use rand::random_range;. Vous croiserez encore extern crate dans de vieux tutoriels et de vieilles réponses Stack Overflow, et c’est de là que viennent la plupart des E0463. Aujourd’hui, sans la dépendance, une ligne use donne plutôt E0432, et un chemin dans votre code donne E0433. Même cause, code différent.

Voir Cargo et les crates pour le fonctionnement des dépendances, et Les outils Rust pour les toolchains et les cibles.

Choisissez-la quand la crate manquante vient de crates.io, comme rand, regex ou serde_json. C’est le cas le plus fréquent. Lancez cette commande dans le dossier qui contient Cargo.toml :

Terminal window
cargo add rand

Cargo ajoute la version la plus récente pour vous :

[dependencies]
rand = "0.10.3"

Cela suffit à corriger E0463. Tant que vous y êtes, supprimez la ligne extern crate rand; : vous n’en avez pas besoin à partir de l’édition 2018 (vérifiez edition = dans Cargo.toml). Cette version affiche une vérification au lieu du résultat du lancer, pour que la sortie soit toujours la même :

fn main() {
let roll = rand::random_range(1..=6);
println!("Le lancer est entre 1 et 6 : {}", (1..=6).contains(&roll));
}

Sortie :

Le lancer est entre 1 et 6 : true
▶ Essayez par vous-même

Le vieux code peut aussi appeler des fonctions qui ont changé d’une version à l’autre. Si cargo add corrige E0463 mais que vous obtenez ensuite E0425 ou E0432 pour quelque chose comme thread_rng, consultez la documentation de la crate pour la version que vous avez. Voir Ajouter une dépendance avec cargo add.

Solution 2 : remplacer les vieilles lignes extern crate par use

Section intitulée « Solution 2 : remplacer les vieilles lignes extern crate par use »

Choisissez-la quand vous avez copié du code d’avant 2018. Il commence souvent par un bloc comme celui-ci, et chaque ligne peut donner 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

N’ajoutez pas serde_derive comme crate séparée. Aujourd’hui, les macros derive sont fournies par serde quand vous activez sa feature derive :

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

Ensuite, supprimez le bloc extern crate et importez ce dont vous avez besoin avec une ligne use normale. #[macro_use] n’est plus nécessaire non plus :

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

Sortie :

{"item":"pomme","qty":3}
▶ Essayez par vous-même

Si une ligne extern crate nomme une crate que votre code n’utilise jamais vraiment, supprimez simplement la ligne. La leçon JSON avec serde montre la configuration moderne en entier.

Solution 3 : installer la cible avec rustup target add

Section intitulée « Solution 3 : installer la cible avec rustup target add »

Choisissez-la quand l’erreur concerne std (ou core) et que la ligne note: dit que la cible n’est peut-être pas installée. Copiez le nom de la cible depuis la ligne help: :

Terminal window
rustup target add aarch64-unknown-linux-gnu
rustup target list --installed # vérifier ce que vous avez maintenant

Puis recompilez avec le même --target. Une cible (target), c’est le type de machine pour lequel vous compilez, écrit sous forme de « triplet » comme aarch64-unknown-linux-gnu ou wasm32-unknown-unknown. rustup télécharge la std précompilée pour cette cible, et E0463 disparaît.

Deux remarques. D’abord, pour beaucoup de cibles, ce n’est pas la dernière étape : compiler un programme complet pour un autre système d’exploitation demande en général aussi un éditeur de liens (linker) pour cette plateforme, et c’est une autre erreur. Ensuite, si le projet a un fichier rust-toolchain.toml, lancez la commande dans le dossier du projet, pour que rustup ajoute la cible à la toolchain que ce projet utilise réellement. Voir Composants et cibles et la leçon WebAssembly pour une cible que vous utiliserez sans doute.

Solution 4 : écrire les tirets comme des underscores dans le code

Section intitulée « Solution 4 : écrire les tirets comme des underscores dans le code »

Choisissez-la quand le nom de la crate contient un tiret, comme serde-json ou tracing-subscriber. Dans Cargo.toml et en ligne de commande, le tiret ne pose pas de problème. Dans du code Rust, un - est un signe moins : le nom s’écrit donc toujours avec _. Du vieux code avec un tiret donne ceci :

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`

Le message dit que les noms de crate avec des tirets ne sont pas valides dans extern crate, et l’aide propose d’utiliser des underscores. rustc lit déjà le nom comme serde_json, donc le E0463 en dessous n’apparaît que si la crate manque aussi dans Cargo.toml. Dans une ligne use, un tiret donne un autre message, expected one of `::`, `;`, or `as`, found `-` . La correction est partout la même : faites un cargo add de la crate si besoin, et écrivez _ dans le code :

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

Sortie :

{"item":"pomme","qty":3}
▶ Essayez par vous-même

La même règle s’applique à votre propre paquet : un projet nommé shop-app s’importe sous le nom shop_app depuis son main.rs et ses tests.

En lançant rustc main.rs directement. rustc seul ne lit pas Cargo.toml. Même après cargo add rand, rustc --edition 2021 src/main.rs dit donc toujours can't find crate for `rand` pour une ligne extern crate rand; (et E0432 pour une ligne use rand::...). Correction : compilez avec cargo run ou cargo build, qui transmettent vos dépendances au compilateur.

Une crate listée sous [dev-dependencies]. Les dev-dependencies (ajoutées avec cargo add --dev) n’existent que pour les tests, les exemples et les benchmarks. En utiliser une depuis le code normal donne E0463 avec extern crate, ou E0433 avec un chemin. Correction : déplacez-la dans [dependencies] avec cargo remove --dev serde_json, puis cargo add serde_json.

Les cartes embarquées sans système d’exploitation. Pour une cible comme thumbv7em-none-eabihf, l’installer ne suffit pas, car elle n’a pas de std du tout. La note change pour le dire :

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

Les notes disent que cette cible ne prend peut-être pas en charge la bibliothèque standard, et que shop en a besoin parce qu’il ne déclare pas #![no_std]. Correction : écrivez le programme en #![no_std], ce qui veut aussi dire pas de println! et votre propre gestionnaire de panic. L’Embedded Rust Book (en anglais) vous guide pas à pas.

  • E0432 : unresolved import (import non résolu), ce que donne une ligne use quand la crate manque dans Cargo.toml.
  • E0433 : failed to resolve (échec de résolution), ce que donne un chemin comme rand::rng() quand la crate manque.
  • E0603 : la crate a été trouvée, mais l’élément que vous voulez utiliser est privé.
  • crate name using dashes are not valid : cette erreur n’a pas de code ; écrivez _ au lieu de - (solution 4).
  • Toutes les erreurs du compilateur : la liste complète des pages d’erreurs.

Petit quiz

1. Du vieux code commence par extern crate regex; et vous obtenez E0463. Quelle est la meilleure correction dans un projet en édition 2021 ?

2. cargo build --target wasm32-unknown-unknown dit qu'il ne trouve pas la crate std et que la cible n'est peut-être pas installée. Que lancez-vous ?

3. Votre Cargo.toml contient tracing-subscriber = "0.3". Comment écrivez-vous le nom de la crate dans le code Rust ?

Score : 0 / 3