Les paquets et les crates
La première partie du système de modules que nous allons aborder concerne les paquets et les crates. Une crate est un binaire ou une bibliothèque. Pour la compiler, le compilateur Rust part d'un fichier source, la racine de la crate, à partir duquel est alors créé le module racine de votre crate (nous verrons les modules plus en détail dans la section suivante). Un paquet se compose d'une ou plusieurs crates qui fournissent un ensemble de fonctionnalités. Un paquet contient un fichier Cargo.toml qui décrit comment construire ces crates.
Il y a plusieurs règles qui déterminent ce qu'un paquet peut contenir. Il doit contenir au maximum une seule crate de bibliothèque. Il peut contenir autant de crates binaires que vous le souhaitez, mais il doit contenir au moins une crate (que ce soit une bibliothèque ou un binaire).
Découvrons ce qui se passe quand nous créons un paquet. D'abord, nous utilisons
la commande cargo new
:
$ cargo new mon-projet
Created binary (application) `mon-projet` package
$ ls mon-projet
Cargo.toml
src
$ ls mon-projet/src
main.rs
Lorsque nous avons saisi la commande, Cargo a créé un fichier Cargo.toml, qui
définit un paquet. Si on regarde le contenu de Cargo.toml, le fichier
src/main.rs n'est pas mentionné car Cargo obéit à une convention selon
laquelle src/main.rs est la racine de la crate binaire portant le même
nom que le paquet. De la même façon, Cargo sait que si le dossier du paquet
contient src/lib.rs, alors le paquet contient une crate de bibliothèque qui a
le même nom que le paquet, et que src/lib.rs est sa racine. Cargo transmet les
fichiers de la crate racine à rustc
pour compiler la bibliothèque ou le
binaire.
Dans notre cas, nous avons un paquet qui contient uniquement src/main.rs, ce
qui veut dire qu'il contient uniquement une crate binaire qui s'appelle
mon-projet
. Si un paquet contient src/main.rs et src/lib.rs, il a deux
crates : une binaire et une bibliothèque, chacune avec le même nom que le
paquet. Un paquet peut avoir plusieurs crates binaires en ajoutant des fichiers
dans le répertoire src/bin : chaque fichier sera une crate séparée.
Une crate regroupe plusieurs fonctionnalités associées ensemble dans une portée
afin que les fonctionnalités soient faciles à partager entre plusieurs projets.
Par exemple, la crate rand
que nous avons utilisée dans
le chapitre 2 nous permet de générer des nombres
aléatoires. Nous pouvons utiliser cette fonctionnalité dans notre propre projet
en important la crate rand
dans la portée de notre projet. Toutes les
fonctionnalités fournies par la crate rand
sont accessibles via le nom de la
crate, rand
.
Ranger une fonctionnalité d'une crate dans sa propre portée clarifie si une
fonctionnalité précise est définie dans notre crate ou dans la crate rand
et
évite ainsi de potentiels conflits. Par exemple, la crate rand
fournit un
trait qui s'appelle Rng
. Nous pouvons nous aussi définir une structure qui
s'appelle Rng
dans notre propre crate. Comme les fonctionnalités des crates
sont dans la portée de leur propre espace de nom, quand nous ajoutons rand
en
dépendance, il n'y a pas d'ambiguïté pour le compilateur sur le nom Rng
. Dans
notre crate, il se réfère au struct Rng
que nous avons défini. Nous accédons
au trait Rng
de la crate rand
via rand::Rng
.
Poursuivons et parlons maintenant du système de modules !