Einführung
Echte Rust-Programme verwenden häufig spezialisierte Bibliotheken, statt jede Funktion von Grund auf selbst zu implementieren. Eine veröffentlichte Rust-Bibliothek wird als Crate bezeichnet. Eine Crate, die von Ihrem Paket verwendet wird, ist eine Abhängigkeit. Abhängigkeiten sicher auszuwählen und hinzuzufügen, gehört zum normalen Entwicklungsprozess in Rust.
In diesem Lab fügen Sie dem vorbereiteten Begrüßungsprogramm den Befehlszeilenparser clap hinzu. Sie nehmen zwei kleine Änderungen am Quellcode vor, sehen die erzeugte Hilfe und Validierung und lernen die unterschiedlichen Aufgaben von Cargo.toml und Cargo.lock kennen. Die Abhängigkeit wird während der Einrichtung vorab heruntergeladen, damit Ihr erster Build schnell bleibt. Das Hinzufügen zum Lernprojekt übernehmen Sie jedoch selbst.
Die Abhängigkeit mit Cargo hinzufügen
In diesem Schritt fügen Sie dem vorbereiteten Paket clap hinzu und prüfen die Änderung am Manifest, die Cargo für Sie vornimmt.
Das Projekt befindet sich unter /home/labex/project/hello-cli. Wechseln Sie dorthin, bevor Sie Cargo-Befehle ausführen:
cd /home/labex/project/hello-cli
Öffnen Sie das Paketmanifest mit nano:
nano Cargo.toml
Cargo.toml beschreibt das Paket und seine direkten Abhängigkeiten. Die leere Tabelle [dependencies] bedeutet, dass dieses Projekt derzeit nur die Rust-Standardbibliothek verwendet. Drücken Sie Ctrl+X, um nano zu verlassen, ohne die Datei zu ändern.
Der Befehl cargo add aktualisiert die Abhängigkeitstabelle sicher. Fügen Sie clap in Version 4.6.7 hinzu und aktivieren Sie das Feature derive:
cargo add clap@4.6.7 --features derive
Ein Feature aktiviert einen optionalen Teil einer Crate. Hier aktiviert derive die Makros, die Rust-Strukturen und -Enums in Befehlszeilenparser umwandeln. Cargo zeigt aktivierte Features mit + und deaktivierte Features mit - an. Deaktivierte Features sind kein Fehler.
Öffnen Sie das Manifest erneut:
nano Cargo.toml
Die Abhängigkeitstabelle enthält nun eine Zeile in dieser Form:
clap = { version = "4.6.7", features = ["derive"] }
Die Versionsangabe ist eine Kompatibilitätsanforderung. Cargo kann eine neuere kompatible Version aus der 4.x-Reihe auswählen. Die genau ausgewählten Versionen werden separat in Cargo.lock festgehalten. Drücken Sie Ctrl+X, um nano zu schließen.
Einen Befehlszeilenparser ableiten
In diesem Schritt verbinden Sie die Struktur Cli mithilfe eines derive-Makros und von Befehlsmetadaten mit clap.
Öffnen Sie die vorbereitete Quelldatei:
nano src/main.rs
Im Einführungskurs haben Sie bereits #[derive(Debug)] verwendet. Ein derive-Makro bittet eine Crate darum, anhand des Aufbaus eines Typs eine Trait-Implementierung zu erzeugen. Ersetzen Sie den ersten TODO-Kommentar über struct Cli durch diese beiden Zeilen:
#[derive(Parser)]
#[command(version, about = "Create a friendly greeting")]
#[derive(Parser)] erzeugt das Parsing-Verhalten. Das Attribut #[command(...)] liefert Informationen über den gesamten Befehl: version liest die Paketversion aus Cargo.toml, und about stellt eine kurze Beschreibung bereit.
Speichern Sie mit Ctrl+O, drücken Sie Enter und beenden Sie nano mit Ctrl+X. Prüfen Sie das Programm, ohne es auszuführen:
cargo check
Bei der ersten Prüfung werden clap und die unterstützenden Crates kompiliert. Daher können mehrere Zeilen mit Compiling und Checking erscheinen. Eine abschließende Zeile, die mit Finished beginnt, bedeutet, dass die Abhängigkeit und der erzeugte Parser gemeinsam kompiliert werden konnten.
Fordern Sie nun die Hilfe des Programms an. Das Trennzeichen -- trennt Cargo-Optionen von den Argumenten für Ihr Programm:
cargo run --quiet -- --help
Die Ausgabe enthält die Beschreibung, einen erforderlichen Wert <NAME> sowie automatisch erzeugte Hilfe- und Versionsoptionen:
Create a friendly greeting
Usage: hello-cli <NAME>
...
Sie haben die Datenstruktur festgelegt; clap hat daraus eine einheitliche Hilfe und Argumentvalidierung erzeugt.
Ein optionales Wiederholungs-Flag hinzufügen
In diesem Schritt fügen Sie eine typisierte Option hinzu und verwenden den eingelesenen Wert in einer kleinen Schleife.
Führen Sie den Befehl zunächst mit einem positionellen Namen aus:
cargo run --quiet -- Ada
Hello, Ada!
name: String wird zu einem erforderlichen positionellen Wert, weil dafür kein Attribut #[arg(...)] angegeben ist. Öffnen Sie den Quellcode erneut:
nano src/main.rs
Ersetzen Sie den zweiten TODO-Kommentar innerhalb von Cli durch:
/// Number of greetings to print
#[arg(short, long, default_value_t = 1)]
times: u8,
Der Dokumentationskommentar wird zum Hilfetext. short erstellt -t, long erstellt --times, und default_value_t = 1 liefert einen typisierten Standardwert, wenn die Option fehlt. Da das Feld vom Typ u8 ist, weist clap außerdem Werte zurück, die keine gültigen vorzeichenlosen 8-Bit-Ganzzahlen sind.
Ersetzen Sie den letzten TODO-Kommentar und die einzelne println!-Zeile durch:
for _ in 0..cli.times {
println!("Hello, {}!", cli.name);
}
Der Unterstrich bedeutet, dass die Schleifenvariable absichtlich nicht verwendet wird. Speichern und beenden Sie nano und geben Sie anschließend drei Begrüßungen aus:
cargo run --quiet -- Ada --times 3
Hello, Ada!
Hello, Ada!
Hello, Ada!
Probieren Sie auch einen ungültigen Wert aus:
cargo run --quiet -- Ada --times many
Dieser Befehl soll fehlschlagen. clap gibt eine Fehlermeldung aus, die erklärt, dass many kein gültiger u8-Wert ist, und beendet das Programm mit einem Status ungleich null, bevor main einen ungültigen Wert verwendet.
Den gesperrten Abhängigkeitsgraphen prüfen und wiederverwenden
In diesem Schritt untersuchen Sie den aufgelösten Abhängigkeitsgraphen von Cargo und weisen nach, dass die Lock-Datei ihn ohne Netzwerkzugriff reproduzieren kann.
clap ist Ihre direkte Abhängigkeit, verwendet aber selbst weitere unterstützende Crates. Zeigen Sie die erste Ebene des aufgelösten Graphen an:
cargo tree --depth 1
Die genaue Patch-Version kann neuer sein als die kompatible Anforderung in Cargo.toml. Entscheidend ist diese Struktur:
hello-cli v0.1.0 (...)
└── clap v4...
Öffnen Sie die erzeugte Lock-Datei:
nano Cargo.lock
Cargo.lock enthält erzeugte Daten und wird normalerweise nicht von Hand bearbeitet. Die Datei speichert die genauen Versionen und Prüfsummen, die Cargo für den gesamten Graphen ausgewählt hat. Bei einer Anwendung wie dieser CLI sollten Sie die Lock-Datei zusammen mit dem Projekt aufbewahren, damit Teammitglieder und automatisierte Builds dieselbe Auflösung wiederverwenden können. Drücken Sie Ctrl+X, um nano zu schließen.
Verlangen Sie nun sowohl die vorhandene Lock-Datei als auch den lokalen Crate-Cache:
cargo check --locked --offline
--locked verhindert Änderungen an Cargo.lock. --offline unterbindet den Netzwerkzugriff. Eine abschließende Zeile mit Finished beweist, dass dieses Projekt mithilfe des bereits heruntergeladenen Abhängigkeitsgraphen geprüft werden kann, ohne stillschweigend andere Versionen aufzulösen.
Zusammenfassung
Sie haben mit Cargo eine direkte Crate-Abhängigkeit hinzugefügt, ein optionales Feature aktiviert, einen typisierten clap-Parser abgeleitet und die automatische Hilfe und Validierung beobachtet. Außerdem haben Sie die kompatible Anforderung in Cargo.toml vom genauen Abhängigkeitsgraphen in Cargo.lock unterschieden und anschließend nachgewiesen, dass der gesperrte Graph offline funktioniert.


