Publication d'une boîte à outils sur Crates.io

RustRustBeginner
Pratiquer maintenant

This tutorial is from open-source community. Access the source code

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Bienvenue sur Publishing a Crate to Crates.io. Ce laboratoire est une partie du Rust Book. Vous pouvez pratiquer vos compétences Rust dans LabEx.

Dans ce laboratoire, nous allons discuter de la manière de publier une boîte à outils (crate) sur crates.io, le registre de boîtes à outils qui distribue le code source open source, facilitant ainsi la découverte et l'utilisation de votre package par les autres.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/DataTypesGroup(["Data Types"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/DataTypesGroup -.-> rust/integer_types("Integer Types") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-100428{{"Publication d'une boîte à outils sur Crates.io"}} rust/integer_types -.-> lab-100428{{"Publication d'une boîte à outils sur Crates.io"}} rust/function_syntax -.-> lab-100428{{"Publication d'une boîte à outils sur Crates.io"}} rust/expressions_statements -.-> lab-100428{{"Publication d'une boîte à outils sur Crates.io"}} rust/operator_overloading -.-> lab-100428{{"Publication d'une boîte à outils sur Crates.io"}} end

Publier une boîte à outils (crate) sur crates.io

Nous avons utilisé des packages provenant de https://crates.io comme dépendances de notre projet, mais vous pouvez également partager votre code avec d'autres personnes en publiant vos propres packages. Le registre de boîtes à outils (crate) situé à https://crates.io distribue le code source de vos packages, il héberge donc principalement du code open source.

Rust et Cargo ont des fonctionnalités qui facilitent la découverte et l'utilisation de votre package publié par les autres. Nous allons parler de certaines de ces fonctionnalités ensuite et expliquer comment publier un package.

Écrire des commentaires de documentation utiles

Documenter précisément vos packages aidera les autres utilisateurs à savoir comment et quand les utiliser, il est donc worthwhile de prendre le temps d'écrire de la documentation. Au chapitre 3, nous avons discuté de la manière de commenter le code Rust en utilisant deux barres obliques, //. Rust dispose également d'un type particulier de commentaire pour la documentation, connu commode ment sous le nom de commentaire de documentation, qui générera une documentation HTML. Le HTML affiche le contenu des commentaires de documentation pour les éléments de l'API publique destinés aux programmeurs intéressés par la manière d'utiliser votre boîte à outils (crate) plutôt que par la manière dont votre boîte à outils est implémentée.

Les commentaires de documentation utilisent trois barres obliques, ///, au lieu de deux et prennent en charge la notation Markdown pour formater le texte. Placez les commentaires de documentation juste avant l'élément qu'ils documentent. La liste 14-1 montre des commentaires de documentation pour une fonction add_one dans une boîte à outils (crate) nommée my_crate.

Nom du fichier : src/lib.rs

/// Ajoute un à un nombre donné.
///
/// ## Exemples
///
/// ```
/// let arg = 5;
/// let answer = my_crate::add_one(arg);
///
/// assert_eq!(6, answer);
/// ```rust
pub fn add_one(x: i32) -> i32 {
    x + 1
}

Liste 14-1 : Un commentaire de documentation pour une fonction

Ici, nous donnons une description de ce que fait la fonction add_one, commençons une section avec le titre Exemples, puis fournissons du code qui démontre comment utiliser la fonction add_one. Nous pouvons générer la documentation HTML à partir de ce commentaire de documentation en exécutant cargo doc. Cette commande exécute l'outil rustdoc distribué avec Rust et place la documentation HTML générée dans le répertoire target/doc.

Pour plus de commodité, exécuter cargo doc --open construira le HTML pour la documentation de votre boîte à outils (crate) actuelle (ainsi que la documentation pour toutes les dépendances de votre boîte à outils) et ouvrira le résultat dans un navigateur web. Accédez à la fonction add_one et vous verrez comment le texte dans les commentaires de documentation est affiché, comme montré dans la figure 14-1.

Figure 14-1 : Documentation HTML pour la fonction add_one

Sections couramment utilisées

Nous avons utilisé le titre Markdown ## Exemples dans la liste 14-1 pour créer une section dans le HTML avec le titre "Exemples". Voici quelques autres sections que les auteurs de boîtes à outils (crates) utilisent couramment dans leur documentation :

  • Panics : Les scénarios dans lesquels la fonction documentée pourrait générer une panique. Les appelants de la fonction qui ne veulent pas que leur programme plante doivent s'assurer de ne pas appeler la fonction dans ces situations.
  • Erreurs : Si la fonction renvoie un Result, décrire les types d'erreurs qui pourraient survenir et quelles conditions pourraient entraîner la renvoi de ces erreurs peut être utile pour les appelants afin qu'ils puissent écrire du code pour gérer les différents types d'erreurs de différentes manières.
  • Sécurité : Si la fonction est unsafe à appeler (nous discutons de l'insécurité au chapitre 19), il devrait y avoir une section expliquant pourquoi la fonction est insécurisée et couvrant les invariants que la fonction attend des appelants pour les maintenir.

La plupart des commentaires de documentation n'ont pas besoin de toutes ces sections, mais c'est une bonne liste de contrôle pour vous rappeler les aspects de votre code qui intéresseront les utilisateurs.

Commentaires de documentation en tant que tests

Ajouter des blocs de code exemple dans vos commentaires de documentation peut aider à démontrer comment utiliser votre bibliothèque, et ce faisant présente un avantage supplémentaire : exécuter cargo test exécutera les exemples de code de votre documentation en tant que tests! Rien n'est mieux que de la documentation avec des exemples. Mais rien n'est pire que des exemples qui ne fonctionnent pas parce que le code a changé depuis que la documentation a été écrite. Si nous exécutons cargo test avec la documentation de la fonction add_one de la liste 14-1, nous verrons une section dans les résultats des tests qui ressemblera à ceci :

   Doc-tests my_crate

running 1 test
test src/lib.rs - add_one (line 5)... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0
filtered out; finished in 0.27s

Maintenant, si nous modifions soit la fonction soit l'exemple de sorte que l'assert_eq! dans l'exemple génère une panique et que nous exécutons cargo test à nouveau, nous verrons que les tests de documentation détectent que l'exemple et le code sont désynchronisés l'un par rapport à l'autre!

Commenter les éléments inclus

Le commentaire de documentation //! ajoute de la documentation à l'élément qui contient les commentaires plutôt qu'aux éléments suivant les commentaires. Nous utilisons généralement ces commentaires de documentation dans le fichier racine de la boîte à outils (crate) (src/lib.rs par convention) ou à l'intérieur d'un module pour documenter la boîte à outils ou le module dans son ensemble.

Par exemple, pour ajouter de la documentation qui décrit le but de la boîte à outils (crate) my_crate qui contient la fonction add_one, nous ajoutons des commentaires de documentation commençant par //! au début du fichier src/lib.rs, comme montré dans la liste 14-2.

Nom du fichier : src/lib.rs

//! ## Ma boîte à outils (My Crate)
//!
//! `my_crate` est une collection d'utilitaires pour faciliter
//! la réalisation de certains calculs.

/// Ajoute un à un nombre donné.
--snip--

Liste 14-2 : Documentation pour la boîte à outils (crate) my_crate dans son ensemble

Remarquez qu'il n'y a pas de code après la dernière ligne commençant par //!. Parce que nous avons commencé les commentaires par //! au lieu de ///, nous documentons l'élément qui contient ce commentaire plutôt qu'un élément qui suit ce commentaire. Dans ce cas, cet élément est le fichier src/lib.rs, qui est la racine de la boîte à outils. Ces commentaires décrivent l'ensemble de la boîte à outils.

Lorsque nous exécutons cargo doc --open, ces commentaires seront affichés sur la page d'accueil de la documentation de my_crate au-dessus de la liste des éléments publics de la boîte à outils, comme montré dans la figure 14-2.

Figure 14-2 : Documentation rendue pour my_crate, y compris le commentaire décrivant l'ensemble de la boîte à outils

Les commentaires de documentation à l'intérieur des éléments sont utiles pour décrire les boîtes à outils et les modules en particulier. Utilisez-les pour expliquer le but général du conteneur afin d'aider vos utilisateurs à comprendre l'organisation de la boîte à outils.

Exporter une API publique pratique avec pub use

La structure de votre API publique est une considération importante lors de la publication d'une boîte à outils (crate). Les personnes qui utilisent votre boîte à outils sont moins familières avec la structure que vous et peuvent avoir du mal à trouver les éléments qu'elles souhaitent utiliser si votre boîte à outils a une hiérarchie de modules importante.

Au chapitre 7, nous avons vu comment rendre des éléments publics en utilisant le mot-clé pub et comment amener des éléments dans une portée avec le mot-clé use. Cependant, la structure qui a du sens pour vous pendant le développement d'une boîte à outils peut ne pas être très pratique pour vos utilisateurs. Vous pouvez vouloir organiser vos structs dans une hiérarchie comportant plusieurs niveaux, mais alors, les personnes qui souhaitent utiliser un type que vous avez défini profondément dans la hiérarchie peuvent avoir du mal à découvrir l'existence de ce type. Ils peuvent également être gênés de devoir taper use my_crate::un_module::un_autre_module::TypeUtile; plutôt que use my_crate::TypeUtile;.

La bonne nouvelle est que si la structure n'est pas pratique pour les autres à utiliser à partir d'une autre bibliothèque, vous n'avez pas besoin de réorganiser votre organisation interne : au lieu de cela, vous pouvez ré-exporter des éléments pour créer une structure publique différente de votre structure privée en utilisant pub use. La ré-exportation prend un élément public dans un emplacement et le rend public dans un autre emplacement, comme s'il était défini dans l'autre emplacement à la place.

Par exemple, disons que nous avons créé une bibliothèque appelée art pour modéliser des concepts artistiques. Dans cette bibliothèque, il y a deux modules : un module kinds contenant deux énumérations nommées PrimaryColor et SecondaryColor et un module utils contenant une fonction nommée mix, comme montré dans la liste 14-3.

Nom du fichier : src/lib.rs

//! ## Art
//!
//! Une bibliothèque pour modéliser des concepts artistiques.

pub mod kinds {
    /// Les couleurs primaires selon le modèle de couleur RYB.
    pub enum PrimaryColor {
        Red,
        Yellow,
        Blue,
    }

    /// Les couleurs secondaires selon le modèle de couleur RYB.
    pub enum SecondaryColor {
        Orange,
        Green,
        Purple,
    }
}

pub mod utils {
    use crate::kinds::*;

    /// Combine deux couleurs primaires en quantités égales pour créer
    /// une couleur secondaire.
    pub fn mix(
        c1: PrimaryColor,
        c2: PrimaryColor,
    ) -> SecondaryColor {
        --snip--
    }
}

Liste 14-3 : Une bibliothèque art avec des éléments organisés dans les modules kinds et utils

La figure 14-3 montre à quoi ressemblerait la page d'accueil de la documentation de cette boîte à outils générée par cargo doc.

Figure 14-3 : Page d'accueil de la documentation de art qui liste les modules kinds et utils

Notez que les types PrimaryColor et SecondaryColor ne sont pas listés sur la page d'accueil, ni la fonction mix. Nous devons cliquer sur kinds et utils pour les voir.

Une autre boîte à outils qui dépend de cette bibliothèque aurait besoin d'énoncés use qui amènent les éléments de art dans la portée, en spécifiant la structure de module actuellement définie. La liste 14-4 montre un exemple d'une boîte à outils qui utilise les éléments PrimaryColor et mix de la boîte à outils art.

Nom du fichier : src/main.rs

use art::kinds::PrimaryColor;
use art::utils::mix;

fn main() {
    let red = PrimaryColor::Red;
    let yellow = PrimaryColor::Yellow;
    mix(red, yellow);
}

Liste 14-4 : Une boîte à outils utilisant les éléments de la boîte à outils art avec sa structure interne exportée

L'auteur du code de la liste 14-4, qui utilise la boîte à outils art, a dû découvrir que PrimaryColor se trouve dans le module kinds et mix se trouve dans le module utils. La structure de module de la boîte à outils art est plus pertinente pour les développeurs travaillant sur la boîte à outils art que pour ceux qui l'utilisent. La structure interne ne contient aucune information utile pour quelqu'un qui essaie de comprendre comment utiliser la boîte à outils art, mais plutôt cause de la confusion car les développeurs qui l'utilisent doivent trouver où chercher et doivent spécifier les noms de module dans les énoncés use.

Pour supprimer l'organisation interne de l'API publique, nous pouvons modifier le code de la boîte à outils art de la liste 14-3 pour ajouter des énoncés pub use pour ré-exporter les éléments au niveau supérieur, comme montré dans la liste 14-5.

Nom du fichier : src/lib.rs

//! ## Art
//!
//! Une bibliothèque pour modéliser des concepts artistiques.

pub use self::kinds::PrimaryColor;
pub use self::kinds::SecondaryColor;
pub use self::utils::mix;

pub mod kinds {
    --snip--
}

pub mod utils {
    --snip--
}

Liste 14-5 : Ajout d'énoncés pub use pour ré-exporter des éléments

La documentation API que cargo doc génère pour cette boîte à outils listera désormais et lira les ré-exportations sur la page d'accueil, comme montré dans la figure 14-4, rendant les types PrimaryColor et SecondaryColor et la fonction mix plus faciles à trouver.

Figure 14-4 : Page d'accueil de la documentation de art qui liste les ré-exportations

Les utilisateurs de la boîte à outils art peuvent toujours voir et utiliser la structure interne de la liste 14-3 comme démontré dans la liste 14-4, ou ils peuvent utiliser la structure plus pratique de la liste 14-5, comme montré dans la liste 14-6.

Nom du fichier : src/main.rs

use art::mix;
use art::PrimaryColor;

fn main() {
    --snip--
}

Liste 14-6 : Un programme utilisant les éléments ré-exportés de la boîte à outils art

Dans les cas où il y a de nombreux modules imbriqués, la ré-exportation des types au niveau supérieur avec pub use peut faire une différence significative dans l'expérience des personnes qui utilisent la boîte à outils. Un autre usage courant de pub use est de ré-exporter des définitions d'une dépendance dans la boîte à outils actuelle pour que les définitions de cette boîte à outils fassent partie de l'API publique de votre boîte à outils.

Créer une structure d'API publique utile est plus une question d'art que de science, et vous pouvez itérer pour trouver l'API qui fonctionne le mieux pour vos utilisateurs. Le choix de pub use vous donne de la flexibilité quant à la manière dont vous structurez votre boîte à outils internement et découple cette structure interne de ce que vous présentez à vos utilisateurs. Considérez le code de certaines des boîtes à outils que vous avez installées pour voir si leur structure interne diffère de leur API publique.

Configuration d'un compte sur crates.io

Avant de pouvoir publier des boîtes à outils (crates), vous devez créer un compte sur https://crates.io et obtenir un jeton API. Pour ce faire, accédez à la page d'accueil à https://crates.io et connectez-vous via un compte GitHub. (Le compte GitHub est actuellement requis, mais le site pourrait prendre en charge d'autres méthodes de création de compte à l'avenir.) Une fois connecté, accédez à vos paramètres de compte à https://crates.io/me et récupérez votre clé API. Ensuite, exécutez la commande cargo login avec votre clé API, comme ceci :

cargo login abcdefghijklmnopqrstuvwxyz012345

Cette commande informera Cargo de votre jeton API et le stockera localement dans ~/.cargo/credentials. Notez que ce jeton est un secret : ne le partagez avec personne d'autre. Si vous le partagez avec quiconque pour quelque raison que ce soit, vous devriez le révoquer et générer un nouveau jeton sur https://crates.io.

Ajout de métadonnées à une nouvelle boîte à outils (crate)

Disons que vous avez une boîte à outils que vous souhaitez publier. Avant de publier, vous devrez ajouter certaines métadonnées dans la section [package] du fichier Cargo.toml de la boîte à outils.

Votre boîte à outils devra avoir un nom unique. Lorsque vous travaillez sur une boîte à outils localement, vous pouvez nommer la boîte à outils comme vous le souhaitez. Cependant, les noms de boîtes à outils sur https://crates.io sont attribués selon le principe "premier arrivé, premier servi". Une fois un nom de boîte à outils pris, personne d'autre ne peut publier une boîte à outils avec ce nom. Avant d'essayer de publier une boîte à outils, recherchez le nom que vous voulez utiliser. Si le nom a déjà été utilisé, vous devrez trouver un autre nom et éditer le champ name dans le fichier Cargo.toml sous la section [package] pour utiliser le nouveau nom pour la publication, comme ceci :

Nom du fichier : Cargo.toml

[package]
name = "guessing_game"

Même si vous avez choisi un nom unique, lorsque vous exécutez cargo publish pour publier la boîte à outils à ce stade, vous obtiendrez un avertissement puis une erreur :

$ cargo publish
    Updating crates.io index
warning: manifest has no description, license, license-file, documentation,
homepage or repository.
See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata
for more info.
--snip--
error: failed to publish to registry at https://crates.io

Caused by:
  the remote server responded with an error: missing or empty metadata fields:
description, license. Please see https://doc.rust-
lang.org/cargo/reference/manifest.html for how to upload metadata

Cela résulte en une erreur car vous manquez d'informations cruciales : une description et une licence sont requises pour que les gens sachent ce que fait votre boîte à outils et sous quelles conditions ils peuvent l'utiliser. Dans Cargo.toml, ajoutez une description d'une ou deux phrases, car elle apparaîtra avec votre boîte à outils dans les résultats de recherche. Pour le champ license, vous devez donner une valeur d'identifiant de licence. Le Software Package Data Exchange (SPDX) de The Linux Foundation à http://spdx.org/licenses liste les identifiants que vous pouvez utiliser pour cette valeur. Par exemple, pour spécifier que vous avez licencié votre boîte à outils sous la licence MIT, ajoutez l'identifiant MIT :

Nom du fichier : Cargo.toml

[package]
name = "guessing_game"
license = "MIT"

Si vous voulez utiliser une licence qui n'apparaît pas dans le SPDX, vous devrez placer le texte de cette licence dans un fichier, inclure le fichier dans votre projet, puis utiliser license-file pour spécifier le nom de ce fichier au lieu d'utiliser la clé license.

La présentation des licences appropriées pour votre projet est en dehors des limites de ce livre. De nombreuses personnes dans la communauté Rust licencient leurs projets de la même manière que Rust en utilisant une double licence MIT OU Apache-2.0. Cette pratique montre également que vous pouvez également spécifier plusieurs identifiants de licence séparés par OU pour avoir plusieurs licences pour votre projet.

Avec un nom unique, la version, votre description et une licence ajoutées, le fichier Cargo.toml d'un projet prêt à être publié pourrait ressembler à ceci :

Nom du fichier : Cargo.toml

[package]
name = "guessing_game"
version = "0.1.0"
edition = "2021"
description = "Un jeu amusant où vous devinez le nombre que
l'ordinateur a choisi."
license = "MIT OR Apache-2.0"

[dependencies]

La documentation de Cargo à https://doc.rust-lang.org/cargo décrit d'autres métadonnées que vous pouvez spécifier pour vous assurer que les autres peuvent découvrir et utiliser votre boîte à outils plus facilement.

Publication sur crates.io

Maintenant que vous avez créé un compte, enregistré votre jeton API, choisi un nom pour votre boîte à outils (crate) et spécifié les métadonnées requises, vous êtes prêt à publier ! Publier une boîte à outils télécharge une version spécifique sur https://crates.io pour qu'autrui puisse l'utiliser.

Faites attention, car une publication est permanente. La version ne peut jamais être écrasée et le code ne peut pas être supprimé. Un des principaux objectifs de Crates.io est d'agir comme un archive permanente de code afin que les builds de tous les projets qui dépendent de boîtes à outils de https://crates.io continuent de fonctionner. Autoriser la suppression de versions rendrait impossible de réaliser cet objectif. Cependant, il n'y a pas de limite au nombre de versions de boîtes à outils que vous pouvez publier.

Exécutez à nouveau la commande cargo publish. Elle devrait réussir maintenant :

$ cargo publish
    Updating crates.io index
   Packaging guessing_game v0.1.0 (file:///projects/guessing_game)
   Verifying guessing_game v0.1.0 (file:///projects/guessing_game)
   Compiling guessing_game v0.1.0
(file:///projects/guessing_game/target/package/guessing_game-0.1.0)
    Finished dev [unoptimized + debuginfo] target(s) in 0.19s
   Uploading guessing_game v0.1.0 (file:///projects/guessing_game)

Félicitations ! Vous avez désormais partagé votre code avec la communauté Rust et n'importe qui peut facilement ajouter votre boîte à outils comme dépendance de leur projet.

Publication d'une nouvelle version d'une boîte à outils existante

Lorsque vous avez apporté des modifications à votre boîte à outils et que vous êtes prêt à publier une nouvelle version, vous modifiez la valeur version spécifiée dans votre fichier Cargo.toml et republiez. Utilisez les règles de numérotation des versions sémantiques à http://semver.org pour décider quelle est la prochaine version appropriée en fonction des types de modifications que vous avez effectuées. Ensuite, exécutez cargo publish pour télécharger la nouvelle version.

Mettre en version obsolète des versions sur Crates.io avec cargo yank

Bien que vous ne puissiez pas supprimer les versions antérieures d'une boîte à outils (crate), vous pouvez empêcher tout projet futur d'ajouter ces versions comme nouvelle dépendance. Cela est utile lorsqu'une version d'une boîte à outils est cassée pour une raison ou une autre. Dans de telles situations, Cargo prend en charge le retrait d'une version d'une boîte à outils.

Retirer une version empêche les nouveaux projets de dépendre de cette version tout en permettant à tous les projets existants qui en dépendent de continuer. Essentiellement, un retrait signifie que tous les projets avec un fichier Cargo.lock ne se casseront pas et que tous les futurs fichiers Cargo.lock générés n'utiliseront pas la version retirée.

Pour retirer une version d'une boîte à outils, dans le répertoire de la boîte à outils que vous avez publiée précédemment, exécutez cargo yank et spécifiez quelle version vous voulez retirer. Par exemple, si nous avons publié une boîte à outils nommée guessing_game version 1.0.1 et que nous voulons la retirer, dans le répertoire du projet guessing_game nous exécuterions :

$ cargo yank --vers 1.0.1
Updating crates.io index
Yank [email protected]

En ajoutant --undo à la commande, vous pouvez également annuler un retrait et autoriser les projets à recommencer à dépendre d'une version :

$ cargo yank --vers 1.0.1 --undo
Updating crates.io index
Unyank [email protected]

Un retrait ne supprime pas de code. Il ne peut pas, par exemple, supprimer des secrets accidentellement téléchargés. Si cela se produit, vous devez réinitialiser immédiatement ces secrets.

Sommaire

Félicitations ! Vous avez terminé le laboratoire Publication d'une boîte à outils sur Crates.io. Vous pouvez pratiquer d'autres laboratoires dans LabEx pour améliorer vos compétences.