Rust-Programm liest Metadaten aus Cargo.toml

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Wie ein Rust-Programm seine Metadaten aus Cargo.toml ausliest

\n\n

Hast du jemals ein CLI-Tool in Rust geschrieben und wolltest, dass es beim Aufruf mit --version nicht einfach "0.1.0", sondern genau die Version aus deiner Cargo.toml anzeigt? Oder musstest du den Crate-Namen und die Beschreibung loggen – aber das Hineinkopieren aus dem Code war umständlich und fehleranfällig?

\n\n

Diese Frage ist eine der beliebtesten auf Stack Overflow (tausende Aufrufe!). Und das zu Recht: Es scheint einfach, die eigene Konfiguration zu lesen, aber in Rust gibt es einige Fallstricke – und vor allem mehrere elegante Lösungswege.

\n\n

In diesem Artikel zeigen wir dir drei grundlegende Ansätze, um Cargo-Paket-Metadaten direkt aus dem Code zu lesen: vom einfachen env!()-Makro bis zum flexiblen build.rs-Skript. Du erfährst, wie du Version, Crate-Namen und Beschreibung korrekt ausliest und typische Fehler vermeidest.

\n\n

Warum ist das nötig? Drei typische Szenarien

\n\n

Bevor wir in den Code eintauchen, schauen wir uns an, warum es sinnvoll ist, auf die Paket-Metadaten zuzugreifen. Hier sind drei reale Anwendungsfälle:

\n\n
    \n
  • CLI-Tools: Der Befehl myapp --version sollte die Version aus der Cargo.toml anzeigen, nicht einen fest codierten Wert.
  • \n
  • Logging & Telemetrie: Beim Start der Anwendung ist es hilfreich, Crate-Name und Version zu loggen – das vereinfacht die Fehlersuche.
  • \n
  • Automatische Dokumentation: Du kannst die Crate-Beschreibung in Hilfe-Nachrichten oder dynamisch generierte README-Dateien einfügen.
  • \n
\n\n

Nachdem wir das "Warum" geklärt haben, kommen wir zum "Wie".

\n\n

Methode #1: Das env!()-Makro – einfach und beliebt

\n\n

Der direkteste Weg ist das eingebaute Makro env!(). Es liest Umgebungsvariablen aus, die Cargo während der Kompilierung automatisch setzt. Hier sind die nützlichsten:

\n\n
    \n
  • CARGO_PKG_NAME – der Paketname (z. B. "my_cool_app")
  • \n
  • CARGO_PKG_VERSION – die Version (z. B. "0.2.1")
  • \n
  • CARGO_PKG_DESCRIPTION – die Beschreibung aus dem Feld description in der Cargo.toml
  • \n
  • CARGO_PKG_AUTHORS – eine durch Doppelpunkte getrennte Liste der Autoren
  • \n
  • CARGO_PKG_LICENSE – die Lizenz
  • \n
  • CARGO_PKG_REPOSITORY – die Repository-URL
  • \n
\n\n

Beispiel zur Verwendung:

\n\n
fn main() {\n    let name = env!("CARGO_PKG_NAME");\n    let version = env!("CARGO_PKG_VERSION");\n\n    println!("{} v{}", name, version);\n    // Ausgabe: my_cool_app v0.2.1\n}\n
\n\n

Wichtig: env!() ist ein Compile-Zeit-Makro. Wenn die Umgebungsvariable nicht gesetzt ist, wird das Programm nicht kompiliert! Das ist ein Vorteil (Typsicherheit) und ein Nachteil (kein Fallback ohne zusätzlichen Aufwand).

\n\n

Wenn du die Version nur für Debugging-Zwecke benötigst, kannst du option_env!() verwenden, das einen Option<&str> zurückgibt:

\n\n
let version = option_env!("CARGO_PKG_VERSION").unwrap_or("unknown");\nprintln!("Version: {}", version);\n
\n\n

Diese Methode ist ideal für 90% der Fälle. Sie benötigt keine zusätzlichen Abhängigkeiten und funktioniert "out of the box".

\n\n

Methode #2: include_str!() + manuelles Parsen – für maximale Kontrolle

\n\n

Manchmal reicht es nicht, nur ein einzelnes Feld auszulesen – du möchtest strukturierte Daten aus der Cargo.toml extrahieren, z. B. alle Abhängigkeiten oder Schlüsselwörter. In diesem Fall kannst du die Datei als String einlesen und parsen.

\n\n
fn main() {\n    let cargo_toml = include_str!("../Cargo.toml");\n    // Hier könnte ein TOML-Parser verwendet werden, aber als Beispiel – einfache Suche\n    if let Some(line) = cargo_toml.lines().find(|l| l.starts_with("version =")) {\n        let version = line.trim_start_matches("version = \\"").trim_end_matches('"');\n        println!("Version aus Datei: {}", version);                

Blogs

Buchempfehlungen