Introduction
Bienvenue dans Cargo Workspaces. Ce laboratoire est une partie du Rust Book. Vous pouvez pratiquer vos compétences Rust dans LabEx.
Dans ce laboratoire, nous allons explorer la fonction des espaces de travail de Cargo, qui aide à gérer plusieurs packages liés développés en tandem en divisant un package en plusieurs crânes de bibliothèque.
Cargo Workspaces
Au chapitre 12, nous avons construit un package qui incluait un crâne binaire et un crâne de bibliothèque. Au fur et à mesure que votre projet évolue, vous pouvez constater que le crâne de bibliothèque continue à grossir et que vous voulez diviser votre package en plusieurs crânes de bibliothèque. Cargo propose une fonction appelée workspaces qui peut aider à gérer plusieurs packages liés développés en tandem.
Création d'un espace de travail
Un espace de travail est un ensemble de packages qui partagent le même fichier Cargo.lock et le même répertoire de sortie. Créons un projet utilisant un espace de travail - nous utiliserons du code trivial pour nous concentrer sur la structure de l'espace de travail. Il existe plusieurs façons de structurer un espace de travail, nous montrerons juste une façon commune. Nous aurons un espace de travail contenant un binaire et deux bibliothèques. Le binaire, qui fournira la fonctionnalité principale, dépendra des deux bibliothèques. Une bibliothèque fournira une fonction add_one et l'autre bibliothèque une fonction add_two. Ces trois crânes feront partie du même espace de travail. Commençons par créer un nouveau répertoire pour l'espace de travail :
mkdir add
cd add
Ensuite, dans le répertoire add, nous créons le fichier Cargo.toml qui configurera tout l'espace de travail. Ce fichier n'aura pas de section [package]. Au lieu de cela, il commencera par une section [workspace] qui nous permettra d'ajouter des membres à l'espace de travail en spécifiant le chemin vers le package avec notre crâne binaire ; dans ce cas, ce chemin est adder :
Nom du fichier : Cargo.toml
[workspace]
members = [
"adder",
]
Ensuite, nous créerons le crâne binaire adder en exécutant cargo new dans le répertoire add :
$ cargo new adder
Created binary (application) `adder` package
À ce stade, nous pouvons construire l'espace de travail en exécutant cargo build. Les fichiers dans votre répertoire add devraient ressembler à ceci :
├── Cargo.lock
├── Cargo.toml
├── adder
│ ├── Cargo.toml
│ └── src
│ └── main.rs
└── target
L'espace de travail a un répertoire target au niveau supérieur dans lequel les artefacts compilés seront placés ; le package adder n'a pas son propre répertoire target. Même si nous exécutons cargo build à l'intérieur du répertoire adder, les artefacts compilés finiront toujours dans add/target plutôt que dans add/adder/target. Cargo structure le répertoire target dans un espace de travail de cette manière car les crânes dans un espace de travail sont supposés dépendre les uns des autres. Si chaque crâne avait son propre répertoire target, chaque crâne devrait recompiler chacun des autres crânes dans l'espace de travail pour placer les artefacts dans son propre répertoire target. En partageant un seul répertoire target, les crânes peuvent éviter de recompiler inutilement.
Création du second package dans l'espace de travail
Ensuite, créons un autre package membre dans l'espace de travail et appelons-le add_one. Modifions le Cargo.toml de niveau supérieur pour spécifier le chemin add_one dans la liste members :
Nom du fichier : Cargo.toml
[workspace]
members = [
"adder",
"add_one",
]
Ensuite, générez un nouveau crâne de bibliothèque nommé add_one :
$ cargo new add_one --lib
Created library $(add_one) package
Votre répertoire add devrait maintenant avoir ces répertoires et fichiers :
├── Cargo.lock
├── Cargo.toml
├── add_one
│ ├── Cargo.toml
│ └── src
│ └── lib.rs
├── adder
│ ├── Cargo.toml
│ └── src
│ └── main.rs
└── target
Dans le fichier add_one/src/lib.rs, ajoutons une fonction add_one :
Nom du fichier : add_one/src/lib.rs
pub fn add_one(x: i32) -> i32 {
x + 1
}
Maintenant, nous pouvons avoir le package adder avec notre binaire dépendant du package add_one qui contient notre bibliothèque. Tout d'abord, nous devrons ajouter une dépendance de chemin sur add_one à adder/Cargo.toml :
Nom du fichier : adder/Cargo.toml
[dependencies]
add_one = { path = "../add_one" }
Cargo n'assume pas que les crânes dans un espace de travail dépendront les uns des autres, donc nous devons être explicites sur les relations de dépendance.
Ensuite, utilisons la fonction add_one (du crâne add_one) dans le crâne adder. Ouvrez le fichier adder/src/main.rs et ajoutez une ligne use en haut pour porter le nouveau crâne de bibliothèque add_one dans la portée. Ensuite, modifiez la fonction main pour appeler la fonction add_one, comme dans la Liste 14-7.
Nom du fichier : adder/src/main.rs
use add_one;
fn main() {
let num = 10;
println!(
"Hello, world! {num} plus one is {}!",
add_one::add_one(num)
);
}
Liste 14-7 : Utilisation du crâne de bibliothèque add_one à partir du crâne adder
Construisons l'espace de travail en exécutant cargo build dans le répertoire add de niveau supérieur!
$ cargo build
Compiling add_one v0.1.0 (file:///projects/add/add_one)
Compiling adder v0.1.0 (file:///projects/add/adder)
Finished dev [unoptimized + debuginfo] target(s) in 0.68s
Pour exécuter le crâne binaire à partir du répertoire add, nous pouvons spécifier quel package dans l'espace de travail nous voulons exécuter en utilisant l'argument -p et le nom du package avec cargo run :
$ cargo run -p adder
Finished dev [unoptimized + debuginfo] target(s) in 0.0s
Running `target/debug/adder`
Hello, world! 10 plus one is 11!
Cela exécute le code dans adder/src/main.rs, qui dépend du crâne add_one.
Dépendre d'un package externe dans un espace de travail
Remarquez que l'espace de travail n'a qu'un seul fichier Cargo.lock au niveau supérieur, plutôt que d'avoir un Cargo.lock dans le répertoire de chaque crâne. Cela garantit que tous les crânes utilisent la même version de toutes les dépendances. Si nous ajoutons le package rand aux fichiers adder/Cargo.toml et add_one/Cargo.toml, Cargo résoudra les deux vers une version de rand et enregistrera cela dans le seul Cargo.lock. Faire en sorte que tous les crânes dans l'espace de travail utilisent les mêmes dépendances signifie que les crânes seront toujours compatibles les uns avec les autres. Ajoutons le crâne rand à la section [dependencies] dans le fichier add_one/Cargo.toml afin que nous puissions utiliser le crâne rand dans le crâne add_one :
Nom du fichier : add_one/Cargo.toml
[dependencies]
rand = "0.8.5"
Nous pouvons maintenant ajouter use rand; au fichier add_one/src/lib.rs, et construire l'espace de travail complet en exécutant cargo build dans le répertoire add fera entrer et compiler le crâne rand. Nous obtiendrons un avertissement car nous ne faisons pas référence au rand que nous avons mis dans la portée :
$ cargo build
Updating crates.io index
Downloaded rand v0.8.5
--snip--
Compiling rand v0.8.5
Compiling add_one v0.1.0 (file:///projects/add/add_one)
Compiling adder v0.1.0 (file:///projects/add/adder)
Finished dev [unoptimized + debuginfo] target(s) in 10.18s
Le Cargo.lock de niveau supérieur contient maintenant des informations sur la dépendance de add_one sur rand. Cependant, même si rand est utilisé quelque part dans l'espace de travail, nous ne pouvons pas l'utiliser dans d'autres crânes de l'espace de travail à moins d'ajouter rand à leurs fichiers Cargo.toml également. Par exemple, si nous ajoutons use rand; au fichier adder/src/main.rs pour le package adder, nous obtiendrons une erreur :
$ cargo build
--snip--
Compiling adder v0.1.0 (file:///projects/add/adder)
error[E0432]: unresolved import `rand`
--> adder/src/main.rs:2:5
|
2 | use rand;
| ^^^^ no external crate `rand`
Pour corriger cela, éditez le fichier Cargo.toml pour le package adder et indiquez que rand est également une dépendance pour lui. Construire le package adder ajoutera rand à la liste des dépendances pour adder dans Cargo.lock, mais aucune copie supplémentaire de rand ne sera téléchargée. Cargo a veillé à ce que chaque crâne dans chaque package de l'espace de travail utilisant le package rand utilise la même version, nous économisant de l'espace et garantissant que les crânes dans l'espace de travail seront compatibles les uns avec les autres.
Ajout d'un test à un espace de travail
Pour une autre amélioration, ajoutons un test de la fonction add_one::add_one dans le crâne add_one :
Nom du fichier : add_one/src/lib.rs
pub fn add_one(x: i32) -> i32 {
x + 1
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
assert_eq!(3, add_one(2));
}
}
Maintenant, exécutez cargo test dans le répertoire add de niveau supérieur. Exécuter cargo test dans un espace de travail structuré comme celui-ci exécutera les tests pour tous les crânes de l'espace de travail :
[object Object]
La première section de la sortie montre que le test it_works dans le crâne add_one a réussi. La section suivante montre qu'aucun test n'a été trouvé dans le crâne adder, et la dernière section montre qu'aucun test de documentation n'a été trouvé dans le crâne add_one.
Nous pouvons également exécuter les tests pour un crâne particulier dans un espace de travail à partir du répertoire de niveau supérieur en utilisant le drapeau -p et en spécifiant le nom du crâne que nous voulons tester :
[object Object]
Cette sortie montre que cargo test n'a exécuté que les tests pour le crâne add_one et n'a pas exécuté les tests du crâne adder.
Si vous publiez les crânes de l'espace de travail sur https://crates.io, chaque crâne de l'espace de travail devra être publié séparément. Comme cargo test, nous pouvons publier un crâne particulier de notre espace de travail en utilisant le drapeau -p et en spécifiant le nom du crâne que nous voulons publier.
Pour plus de pratique, ajoutez un crâne add_two à cet espace de travail de manière similaire au crâne add_one!
Au fur et à mesure que votre projet grandit, envisagez d'utiliser un espace de travail : il fournit des composants individuels plus faciles à comprendre et plus petits qu'un gros bloc de code. De plus, garder les crânes dans un espace de travail peut faciliter la coordination entre les crânes si elles sont souvent modifiées en même temps.
Sommaire
Félicitations ! Vous avez terminé le laboratoire sur les espaces de travail Cargo. Vous pouvez pratiquer d'autres laboratoires sur LabEx pour améliorer vos compétences.