Rust : main.rs et lib.rs — comment ne pas se perdre dans les modules et accélérer le code

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Confusion des modules Rust : comment main.rs et lib.rs rendent fou (et comment y remédier)

\n\n

Avez-vous déjà écrit en Rust, créé un nouveau projet, ajouté main.rs et lib.rs — et soudainement le compilateur a commencé à générer des erreurs qui semblaient n'avoir aucun sens ? Cela vous dit quelque chose ? Si vous avez cherché sur Google "Rust modules confusion when there is main.rs and lib.rs", vous n'êtes pas seul. Cette question sur Stack Overflow a recueilli des milliers de vues, et pour cause. La confusion avec les modules est l'un des problèmes les plus fréquents chez les débutants (et même chez les développeurs expérimentés venant d'autres langages).

\n\n

Dans cet article, nous n'allons pas simplement expliquer comment fonctionne le système de modules de Rust. Nous allons montrer comment son organisation correcte affecte directement l'optimisation et les performances de votre code. Vous découvrirez pourquoi lib.rs n'est pas simplement "un fichier de plus", mais un outil puissant pour accélérer la compilation et créer une API propre. C'est parti !

\n\n

Le problème : "Pourquoi le compilateur ne voit-il pas mes modules ?"

\n\n

Imaginez : vous créez un projet my_project avec cargo new my_project. Par défaut, Cargo crée src/main.rs. Vous ajoutez un deuxième fichier — src/lib.rs — et y écrivez une fonction. Ensuite, vous essayez de l'appeler depuis main.rs — et vous obtenez une erreur :

\n\n
error[E0432]: unresolved import `my_project::some_function`\n --> src/main.rs:1:5\n  |\n1 | use my_project::some_function;\n  |     ^^^^^^^^^^^^^^^^^^^^^^^^^ no `some_function` in the root
\n\n

Une douleur familière ? Quel est le problème ? C'est simple : Rust considère main.rs et lib.rs comme deux racines de crate différentes. Si Cargo.toml ne spécifie pas le contraire, Cargo crée automatiquement deux crates : un binaire (à partir de main.rs) et une bibliothèque (à partir de lib.rs). Ils ne se "voient" pas directement tant que vous ne spécifiez pas explicitement les dépendances.

\n\n

C'est exactement la confusion des modules Rust dont tout le monde parle. Mais au lieu de vous énerver, transformons cette "particularité" en avantage.

\n\n

La solution : comment organiser correctement les modules

\n\n

Il existe deux approches, et le choix dépend de votre objectif. Mais nous allons tout de suite vous donner un spoiler : la deuxième approche est meilleure pour les performances.

\n\n

Option 1 : Tout dans un seul crate (simple, mais non évolutif)

\n\n

Si votre projet est petit, vous pouvez déclarer les modules à l'intérieur de main.rs avec mod :

\n\n
// src/main.rs\nmod utils; // cherche src/utils.rs ou src/utils/mod.rs\n\nfn main() {\n    utils::do_something();\n}
\n\n

Cela fonctionne, mais si vous ajoutez lib.rs, la confusion commence. lib.rs deviendra un crate séparé, et les modules de main.rs ne seront pas disponibles dans celui-ci. Pour les petits scripts, c'est acceptable ; pour les projets sérieux, non.

\n\n

Option 2 : Bibliothèque + binaire (la bonne voie pour l'optimisation)

\n\n

La manière la plus judicieuse est de faire de lib.rs le référentiel principal de la logique, et de main.rs une fine couche de lancement. Ainsi, vous obtenez :

\n
    \n
  • Modularité : toute la logique métier dans la bibliothèque.
  • \n
  • Testabilité : la bibliothèque peut être testée séparément.
  • \n
  • Performances : le compilateur optimise mieux le code de la bibliothèque s'il est utilisé de manière répétée.
  • \n
\n\n

Comment faire ? Simplement :

\n
// src/lib.rs\npub mod utils;\n\npub fn run() {\n    utils::do_something();\n}\n\n// src/main.rs\nfn main() {\n    my_project::run(); // my_project est le nom du crate dans Cargo.toml\n}
\n\n

Remarquez : main.rs utilise maintenant my_project::run(). Cela fonctionne car Cargo voit lib.rs comme une bibliothèque nommée my_project. Et voilà — la confusion a disparu !

\n\n

Optimisation et performances : pourquoi lib.rs est votre ami

\n\n

Maintenant, le plus inté

Blogs

Book Recommendations