Hello, Cargo!
Cargo est le système de compilation et de gestion de paquets de Rust. La plupart des Rustacés utilisent cet outil pour gérer les projets Rust, car Cargo s’occupe de nombreuses tâches pour vous, comme compiler votre code, télécharger les bibliothèques dont votre code dépend, et compiler ces bibliothèques. (On appelle dépendance une bibliothèque nécessaire pour votre code.)
Des programmes Rust très simples, comme le petit que nous avons écrit précédemment, n’ont pas de dépendance. Si nous avions compilé le projet “Hello, world!” avec Cargo, cela n’aurait fait appel qu’à la fonctionnalité de Cargo qui s’occupe de la compilation de votre code. Quand vous écrirez des programmes Rust plus complexes, vous ajouterez des dépendances, et si vous créez un projet en utilisant Cargo, l’ajout des dépendances sera plus facile à faire.
Comme la large majorité des projets Rust utilisent Cargo, la suite de ce livre va supposer que vous utilisez aussi Cargo. Cargo s’installe avec Rust si vous avez utilisé l’installateur officiel présenté dans la section “Installation”. Si vous avez installé Rust autrement, vérifiez que Cargo est installé en utilisant la commande suivante dans votre terminal :
$ cargo --version
Si vous voyez un numéro de version, c’est qu’il est installé ! Si vous voyez une erreur comme Commande non trouvée (ou command not found), alors consultez la documentation de votre méthode d’installation pour savoir comment installer séparément Cargo.
Créer un projet avec Cargo
Créons un nouveau projet en utilisant Cargo et analysons les différences avec notre projet initial “Hello, world!”. Retournez dans votre répertoire projects (ou là où vous avez décidé d’enregistrer votre code). Ensuite, sur n’importe quel système d’exploitation, lancez les commandes suivantes :
$ cargo new hello_cargo
$ cd hello_cargo
La première commande crée un nouveau répertoire et projet appelés hello_cargo. Nous avons appelé notre projet hello_cargo, et Cargo crée ses fichiers dans un répertoire avec le même nom.
Rendez-vous dans le répertoire hello_cargo et afficher la liste des fichiers. Vous constaterez que Cargo a généré deux fichiers et un répertoire pour nous : un fichier Cargo.toml et un répertoire src avec un fichier main.rs à l’intérieur.
Il a aussi créé un nouveau dépôt Git ainsi qu’un fichier .gitignore. Les fichiers de Git ne seront pas générés si vous lancez cargo new au sein d’un dépôt Git ; vous pouvez désactiver ce comportement temporairement en utilisant cargo new --vcs=git.
Note : Git est un système de gestion de versions très répandu. Vous pouvez changer cargo new pour utiliser un autre système de gestion de versions ou ne pas en utiliser du tout en écrivant le drapeau --vcs. Lancez cargo new --help pour en savoir plus sur les options disponibles.
Ouvrez Cargo.toml dans votre éditeur de texte favori. Son contenu devrait être similaire au code dans l’encart 1-2.
[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2024"
[dependencies]
cargo newCe fichier est au format TOML (Tom’s Obvious, Minimal Language), qui est le format de configuration de Cargo.
La première ligne, [package], est un en-tête de section qui indique que les instructions suivantes configurent un paquet. Au fur et à mesure que nous ajouterons plus de détails à ce fichier, nous ajouterons des sections supplémentaires.
Les trois lignes suivantes définissent les informations de configuration dont Cargo a besoin pour compiler votre programme : le nom, la version, et l’édition de Rust à utiliser. Nous aborderons la clé edition dans l’annexe E.
La dernière ligne, [dependencies], est le début d’une section qui vous permet de lister les dépendances de votre projet. Dans Rust, les paquets de code sont désignés sous le nom de crates. Nous n’allons pas utiliser de crate pour ce projet, mais nous le ferons pour le premier projet au chapitre 2 ; nous utiliserons alors cette section à ce moment-là.
Maintenant, ouvrez src/main.rs et jetez-y un coup d’œil :
Fichier : src/main.rs
fn main() {
println!("Hello, world!");
}
Cargo a généré un programme “Hello, world!” pour vous, exactement comme celui que nous avons écrit dans l’encart 1-1 ! Pour le moment, les seules différences entre notre projet précédent et le projet que Cargo a généré sont que Cargo a placé le code dans le répertoire src, et que nous avons un fichier de configuration Cargo.toml à la racine du répertoire projet.
Cargo prévoit de stocker vos fichiers sources dans le répertoire src. Le répertoire parent est là uniquement pour les fichiers README, pour les informations à propos de la licence, pour les fichiers de configuration et tout ce qui n’est pas directement relié à votre code. Utiliser Cargo vous aide à structurer vos projets. Il y a un endroit pour tout, et tout est à sa place.
Si vous commencez un projet sans utiliser Cargo, comme nous l’avons fait avec le projet “Hello, world!”, vous pouvez le transformer en projet qui utilise Cargo. Déplacez le code de votre projet dans un répertoire src et créez un fichier Cargo.toml adéquat. Pour créer aisément ce fichier Cargo.toml, vous pouvez lancer cargo init, qui le créera automatiquement.
Compiler et exécuter un projet Cargo
Maintenant, regardons ce qu’il y a de différent quand nous compilons et exécutons le programme “Hello, world!” avec Cargo ! À l’intérieur de votre répertoire hello_cargo, compilez votre projet en utilisant la commande suivante :
$ cargo build
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs
Cette commande crée un fichier exécutable dans target/debug/hello_cargo (ou target\debug\hello_cargo.exe sous Windows) plutôt que de le déposer dans votre répertoire courant. Étant donné que la compilation par défaut est une compilation de débogage, Cargo place le binaire dans un répertoire nommé debug. Vous pouvez lancer l’exécutable avec cette commande :
$ ./target/debug/hello_cargo # ou .\target\debug\hello_cargo.exe sous Windows
Hello, world!
Si tout s’est bien passé, Hello, world! devrait s’afficher dans le terminal. Lancer cargo build pour la première fois devrait aussi mener Cargo à créer un nouveau fichier à la racine du répertoire projet : Cargo.lock. Ce fichier garde une trace des versions exactes des dépendances de votre projet. Ce projet n’a pas de dépendance, donc le fichier est un peu vide. Vous n’aurez jamais besoin de changer ce fichier manuellement ; Cargo va gérer son contenu pour vous.
Nous venons de compiler un projet avec cargo build avant de l’exécuter avec ./target/debug/hello_cargo, mais nous pouvons aussi utiliser cargo run pour compiler le code et ensuite lancer l’exécutable dans une seule et même commande :
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/hello_cargo`
Hello, world!
Il est plus pratique d’utiliser cargo run que d’avoir à se souvenir d’exécuter cargo build et d’ensuite utiliser le chemin complet vers l’exécutable ; c’est pourquoi la plupart des développeurs utilisent cargo run.
Notez que cette fois-ci, nous ne voyons pas de messages indiquant que Cargo a compilé hello_cargo. Cargo a détecté que les fichiers n’avaient pas changé, donc il n’a pas recompilé, il a juste exécuté le binaire. Si vous aviez modifié votre code source, Cargo aurait recompilé le projet avant de le lancer, et vous auriez eu les messages suivants :
$ cargo run
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 0.33 secs
Running `target/debug/hello_cargo`
Hello, world!
Cargo fournit aussi une commande appelée cargo check. Elle vérifie rapidement votre code pour s’assurer qu’il est compilable, mais ne produit pas d’exécutable :
$ cargo check
Checking hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs
Dans quel cas n’aurions-nous pas besoin d’un exécutable ? Parfois, cargo check est bien plus rapide que cargo build, car il saute l’étape de création de l’exécutable. Si vous vérifiez votre travail continuellement pendant que vous écrivez votre code, utiliser cargo check accélèrera le processus de vous informer que votre projet continue à pouvoir se compiler correctement ! C’est pourquoi de nombreux Rustacés utilisent périodiquement cargo check quand ils écrivent leur programme afin de s’assurer qu’il compile. Ensuite, ils lancent cargo build quand ils sont prêts à utiliser l’exécutable.
Récapitulons ce que nous avons appris sur Cargo :
- Nous pouvons créer un projet en utilisant
cargo new. - Nous pouvons compiler un projet en utilisant
cargo build. - Nous pouvons compiler puis exécuter un projet en une seule fois en utilisant
cargo run. - Nous pouvons compiler un projet sans produire de binaire afin de vérifier l’existence d’erreurs en utilisant
cargo check. - Au lieu d’enregistrer le résultat de la compilation dans le même répertoire que votre code, Cargo l’enregistre dans le répertoire target/debug.
Un autre avantage d’utiliser Cargo est que les commandes sont les mêmes peu importe le système d’exploitation que vous utilisez. Donc à partir de maintenant, nous n’allons plus faire d’opérations spécifiques à Linux et macOS par rapport à Windows.
Compiler pour diffuser
Quand votre projet est finalement prêt à être diffusé, vous pouvez utiliser cargo build --release pour le compiler en l’optimisant. Cette commande va créer un exécutable dans target/release au lieu de target/debug. Ces optimisations rendent votre code Rust plus rapide à exécuter, mais l’utiliser rallonge le temps de compilation de votre programme. C’est pourquoi il y a deux différents profils : un pour le développement, quand vous voulez recompiler rapidement et souvent, et un autre pour compiler le programme final qui sera livré à un utilisateur, qui n’aura pas besoin d’être recompilé à plusieurs reprises et qui s’exécutera aussi vite que possible. Si vous évaluez le temps d’exécution de votre code, assurez-vous de lancer cargo build --release et d’utiliser l’exécutable dans target/release pour vos bancs de test.
Tirer parti des conventions de Cargo
Pour des projets simples, Cargo n’apporte pas grand-chose par rapport à rustc, mais il vous montrera son intérêt au fur et à mesure que vos programmes deviendront plus complexes. Avec des programmes qui évoluent avec des fichiers multiples ou demandant une dépendance, il est plus facile de laisser Cargo prendre en charge la coordination de la compilation.
Même si le projet hello_cargo est simple, il utilise maintenant une grande partie de l’outillage que vous rencontrerez dans votre carrière avec Rust. En effet, pour travailler sur n’importe quel projet Rust existant, vous n’avez qu’à saisir les commandes suivantes pour télécharger le code avec Git, vous déplacer dans le répertoire projet et compiler :
$ git clone example.org/projet_quelconque
$ cd projet_quelconque
$ cargo build
Pour plus d’informations à propos de Cargo, vous pouvez consulter sa documentation.
Résumé
Vous êtes déjà bien lancé dans votre périple avec Rust ! Dans ce chapitre, vous avez appris comment :
- Installer la dernière version stable de Rust en utilisant
rustup. - Mettre à jour Rust vers une nouvelle version.
- Ouvrir la documentation installée en local.
- Écrire et exécuter un programme “Hello, world!” en utilisant directement
rustc. - Créer et exécuter un nouveau projet en utilisant les conventions de Cargo.
C’est le moment idéal pour construire un programme plus ambitieux pour s’habituer à lire et écrire du code Rust. Donc, au chapitre 2, nous allons écrire un programme de jeu de devinettes. Si vous préférez commencer par apprendre comment les principes de programmation de base fonctionnent avec Rust, rendez-vous au chapitre 3, puis revenez au chapitre 2.