Kapitel 02: Einrichtung der Arbeitsumgebung und erstes Programm
Bevor Sie Ihren ersten Rust-Code schreiben können, müssen Sie die Werkzeuge installieren, die Sie für die Entwicklung benötigen. In diesem Kapitel richten wir Ihre Arbeitsumgebung ein und erstellen Ihr allererstes lauffähiges Rust-Programm mit dem Paketmanager cargo.
In diesem Kapitel bieten wir Ihnen drei verschiedene Perspektiven auf das Thema an. Wählen Sie die Sicht, die am besten zu Ihrem Hintergrund passt:
- Für Anfänger: Konzentriert sich auf die grundlegende Installation, die Einrichtung von VS Code und das Schreiben eines ersten einfachen Zufallszahlen-Programms.
- Für Profis: Richtet sich an erfahrene Entwickler und beleuchtet Cargo-Build-Pipelines, SemVer-Auflösung, Debug/Release-Profile und Workspace-Architekturen.
- Hardware-Sicht: Analysiert die LLVM-Kompilierungsschritte, statische Linker-Prozesse, binäre Stripping-Optimierungen und Hardware-Entropiequellen.
Begleitvideo zu Kapitel 2: Einrichtung & Erstes Programm
Kapitel 02: Einrichtung & Erstes Programm (Sicht für Anfänger)
In diesem Kapitel richten wir Schritt für Schritt deine Arbeitsumgebung ein und schreiben dein erstes lauffähiges Programm. Keine Sorge, wir gehen jeden Schritt gemeinsam durch!
1. Lernziele
Du wirst in diesem Abschnitt:
- Die Rust-Werkzeuge mit dem offiziellen Installationsprogramm
rustupauf deinem Rechner einrichten. - Deinen Code-Editor (VS Code) installieren und mit dem schlauen Helfer
rust-analyzerausstatten. - Ein neues Projekt mit dem Werkzeug
cargoerstellen. - Ein Zufallszahlen-Programm schreiben, das eine Zahl von 1 bis 10 würfelt.
2. Die Installation mit rustup
Um Rust auf deinem Computer zu installieren, nutzen wir das Programm rustup. Du kannst dir rustup wie einen App-Store vorstellen, der speziell für die Programmiersprache Rust da ist. Es installiert für dich:
- Den Compiler (
rustc): Das Programm, das deinen geschriebenen Text in die Sprache des Computers übersetzt. - Das Build-System (
cargo): Dein Bauleiter, der deine Projekte verwaltet und fremden Code herunterlädt.
Installationsschritte:
- Öffne das Terminal (die Kommandozeile) deines Computers.
- Tippe unter Linux oder macOS folgenden Befehl ein und drücke Enter:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - Das Installationsprogramm fragt dich nach Optionen. Drücke einfach die Eingabetaste (Enter), um die empfohlene Standardinstallation (“1”) auszuwählen.
- Sehr wichtig: Damit dein Terminal weiß, wo die neuen Werkzeuge liegen, musst du das Terminal entweder einmal schließen und neu öffnen oder folgenden Befehl eingeben:
source $HOME/.cargo/env
Überprüfe die Installation, indem du nach der Version fragst:
rustc --version
Wenn dort etwas wie rustc 1.75.0 steht, war die Installation erfolgreich!
3. Der schlaue Editor: VS Code und rust-analyzer
Programmieren in einem normalen Texteditor ist mühsam, weil man Tippfehler erst bemerkt, wenn man das Programm startet. Wir richten uns deshalb einen Editor ein, der uns beim Tippen hilft.
- Lade dir Visual Studio Code (VS Code) herunter und installiere es.
- Öffne VS Code. Klicke links in der Seitenleiste auf das Symbol für Erweiterungen (das Symbol sieht aus wie vier Quadrate).
- Suche nach rust-analyzer und klicke auf Installieren.
Tip
Der
rust-analyzerliest deinen Code im Hintergrund sekündlich mit. Er zeichnet rote Wellenlinien unter Fehler (wie vergessene Semikolons oder falsche Variablennamen) und gibt dir direkt Tipps, wie du sie behebst. Er ist dein persönlicher Programmier-Assistent!
4. Ein neues Projekt erstellen
In Rust erstellen wir Projekte nicht manuell, sondern lassen das unseren Bauleiter Cargo machen.
Tippe folgenden Befehl in dein Terminal:
cargo new wuerfelspiel --bin
Das Flag --bin (kurz für binary) sagt Cargo, dass wir ein eigenständiges Programm erstellen wollen, das man direkt ausführen kann.
Cargo legt einen neuen Ordner an. Darin findest du:
Cargo.toml: Die Einkaufs- und Einstellungsliste deines Projekts. Hier tragen wir später Zubehör ein.src/main.rs: Die Textdatei, in die wir unseren Rust-Code schreiben.
5. Code-Evolution: Das Würfelspiel schreiben
Öffne den Ordner wuerfelspiel in VS Code und öffne die Datei src/main.rs. Lösche den Inhalt und schreibe stattdessen folgenden Code hinein:
use rand::Rng; // 1. Wir aktivieren das Zufalls-Werkzeug (Rng)
fn main() {
// 2. Wir würfeln eine Zahl von 1 bis inklusive 10
let gewuerfelte_zahl = rand::thread_rng().gen_range(1..=10);
// 3. Wir geben die Zahl auf dem Bildschirm aus
println!("Du hast eine {} gewürfelt!", gewuerfelte_zahl);
}
Der erste Startversuch
Wechsle in deinem Terminal in den Projektordner (cd wuerfelspiel) und starte das Programm mit:
cargo run
Du wirst sehen, dass der Compiler meckert: “failed to resolve: use of undeclared crate or module ‘rand’”.
Warum? Wir haben zwar gesagt: “Nutze das Werkzeug ‘rand’”, aber in unserer Einkaufsliste (Cargo.toml) steht dieses Werkzeug noch gar nicht drin!
Die Zutat einkaufen
Füge das Paket rand zu deinem Projekt hinzu, indem du folgenden Befehl im Terminal ausführst:
cargo add rand
Dieser Befehl trägt das Paket automatisch in deine Cargo.toml ein. Wenn du das Programm jetzt erneut mit cargo run startest, lädt Cargo das Paket aus dem Internet herunter, baut es ein und führt dein Programm aus. Du wirst ein Ergebnis sehen wie:
Du hast eine 6 gewürfelt!
6. Key Takeaways
- rustup installiert und aktualisiert deine Rust-Werkzeuge.
- Cargo ist dein Bauleiter:
cargo newerstellt Projekte,cargo addfügt Pakete hinzu undcargo runstartet das Programm. Cargo.tomlist die Konfigurationsdatei für dein Projekt.- Der rust-analyzer zeigt dir Programmierfehler sofort im Editor an.
Kapitel 02: Einrichtung & Erstes Programm (Sicht für Profis)
Dieses Kapitel behandelt die Cargo-Build-Infrastruktur, Dependency-Management, semantische Versionierung und die Trennung von Entwicklungs- und Produktionsprofilen.
1. Lernziele
In diesem Abschnitt werden Sie:
- Verstehen, wie Cargo reproduzierbare Builds über Lockfiles erzwingt.
- Die Funktionsweise der semantischen Versionierung (SemVer) bei Cargo analysieren.
- Die Konfiguration von Build-Profilen in der
Cargo.tomlbeherrschen. - Die Strukturierung von Cargo-Workspaces kennenlernen.
2. Item 2: Nutze Cargo zur Gewährleistung reproduzierbarer Builds
In der professionellen Entwicklung ist es kritisch, dass ein Programm auf dem Rechner des Entwicklers, auf dem CI-Server und in der Produktionsumgebung exakt gleich gebaut wird. Cargo stellt dies durch zwei Dateien sicher:
Cargo.toml(Deklarative Konfiguration): Hier spezifiziert der Entwickler die direkten Abhängigkeiten und deren Versionsbereiche (z. B.rand = "0.8.5").Cargo.lock(Konkreter Zustands-Pin): Diese Datei wird von Cargo automatisch generiert. Sie enthält die exakten Versionsnummern und kryptografischen Hashes aller installierten Abhängigkeiten und deren Unterabhängigkeiten.
graph LR
A[Cargo.toml] --> B(Cargo Build)
B --> C[Cargo.lock generieren/lesen]
C --> D[Kryptografischer Abgleich der Crates]
D --> E[Reproduzierbares Binär-Artefakt]
Important
Check-in-Regel: Checken Sie die
Cargo.lockbei eigenständigen Anwendungen (Binaries) immer in Ihre Versionsverwaltung (Git) ein. Bei Bibliotheken (Libraries) wird dieCargo.locktraditionell ignoriert (.gitignore), da die Bibliothek flexibel mit den Versionen des Nutzers kompatibel sein muss.
3. Semantische Versionierung (SemVer) in Cargo
Cargo verwendet die semantische Versionierung (Major.Minor.Patch). Standardmäßig nutzt Cargo das Caret-Symbol (^) als Standard-Operator:
rand = "0.8.5"entspricht^0.8.5und erlaubt Updates auf0.8.6oder0.8.9, blockiert aber0.9.0.- Bei Versionen vor
1.0.0(Pre-1.0) gilt eine Besonderheit:0.8.5erlaubt keine Updates auf0.9.0, da Minor-Versionen vor 1.0 als Major-Updates (mit brechenden API-Änderungen) behandelt werden.
4. Build-Profile (Debug vs. Release)
Cargo unterscheidet grundlegend zwischen Entwicklungs- und Produktions-Builds. Dies wird über Profile in der Cargo.toml gesteuert:
[profile.dev]
opt-level = 0 # Keine Optimierungen, schneller Compile-Vorgang
debug = true # Debug-Symbole im Binär-Artefakt enthalten
[profile.release]
opt-level = 3 # Maximale Optimierungen (Inlining, Loop Unrolling)
lto = true # Link-Time Optimization über Crate-Grenzen hinweg
codegen-units = 1 # Reduziert Parallelisierung beim Kompilieren für bessere Optimierung
cargo builderzeugt ein unoptimiertes Artefakt intarget/debug/.cargo build --releaseerzeugt das hochoptimierte Produktions-Artefakt intarget/release/.
5. Cargo-Workspaces für Multi-Crate-Architekturen
Bei größeren Projekten empfiehlt es sich, das System in mehrere eigenständige Crates aufzuteilen. Ein Cargo-Workspace ermöglicht die gemeinsame Nutzung eines einzigen target/-Ordners und einer globalen Cargo.lock:
# Haupt-Cargo.toml im Root-Verzeichnis
[workspace]
members = [
"crates/cli",
"crates/core",
"crates/parser"
]
6. Key Takeaways (Architektur-Richtlinien)
- Lockfiles: Committen Sie die
Cargo.lockbei Binaries, um deterministische CI/CD-Pipelines zu sichern. - Profile Tuning: Optimieren Sie das
release-Profil durch Aktivierung von LTO (Link-Time Optimization) in performance-kritischen Anwendungen. - Modularität: Strukturieren Sie wachsende Codebasen frühzeitig als Cargo-Workspaces.
Kapitel 02: Einrichtung & Erstes Programm (Hardware- & Systemsicht)
Dieses Kapitel analysiert die physikalischen Abläufe der Rust-Compilation, die Statik der Linker-Infrastruktur, die Funktionsweise von Hardware-Entropiequellen und Optimierungen der Binärgröße.
1. Lernziele
Sie werden in diesem Abschnitt:
- Die Übersetzungsschritte von Rust-Sourcecode über LLVM IR zu nativem Maschinencode nachvollziehen.
- Den Unterschied zwischen statischem und dynamischem Linken analysieren.
- Verstehen, wie der Zufallszahlengenerator auf CPU-Instruktionen (
RDRAND/RDSEED) zugreift. - Techniken zur Minimierung der Binärgröße (Stripping, Panic-Verhalten) anwenden.
2. Die Rust-Kompilierungspipeline (LLVM)
Der Rust-Compiler rustc übersetzt den Code nicht direkt in Maschinencode, sondern nutzt das LLVM-Compiler-Backend:
[Rust Quellcode]
│ (rustc Frontend)
▼
[HIR / MIR (Mid-level Intermediate Representation)]
│ (Transkription zu LLVM)
▼
[LLVM IR (Plattformunabhängiger Zwischencode)]
│ (LLVM Optimierungs-Passes)
▼
[Plattformspezifischer Maschinencode (x86_64, ARM, etc.)]
- MIR (Mid-level IR): Hier führt Rust seine Typsicherheits- und Borrow-Checker-Prüfungen durch. Das MIR ist stark vereinfacht und ideal für Programmanalysen.
- LLVM IR: LLVM führt die hardwarenahen Optimierungen durch (z. B. Vektorisierung, Loop-Transformationen und Inlining).
3. Statisches Linken vs. Dynamisches Linken
Wenn Sie ein Standard-Rust-Programm kompilieren, ist das resultierende Binär-Artefakt vergleichsweise groß (oft mehrere Megabytes für ein einfaches Programm).
Der Grund: Rust linkt standardmäßig statisch.
- Statisch: Alle benötigten Standardbibliotheken (
std) und externen Abhängigkeiten (wie dasrand-Crate) werden direkt in das finale Executable hineinkopiert. Das Programm läuft auf dem Zielrechner ohne externe Abhängigkeiten (keine Fehlermeldungen über fehlende.so- oder.dll-Dateien). - Dynamisch: Bei C/C++ oder Sprachen, die auf Systembibliotheken vertrauen, verweist das Executable nur auf externe Bibliotheken im Betriebssystem. Fehlen diese auf dem Zielsystem, stürzt das Programm ab.
4. Hardware-Entropie unter der Haube
Wenn wir rand::thread_rng() aufrufen, greift Rust auf Betriebssystem-Schnittstellen zurück, die wiederum Hardware-Entropiequellen abfragen:
- Linux: Zugriff auf
/dev/urandomoder den Systemaufrufgetrandom(). - CPU-Instruktionen: Moderne Prozessoren bieten integrierte Zufallsgeneratoren, die auf thermischem Rauschen basieren. LLVM übersetzt die Zugriffe bei aktivierten CPU-Features direkt in native Instruktionen wie
RDRAND(liest eine hardwaregenerierte Zufallszahl) oderRDSEED(erzeugt einen Seed für Software-Generatoren).
5. Binärgrößen-Optimierung auf Systemebene
Für Embedded-Systeme oder WebAssembly-Targets ist die Standard-Binärgröße oft zu hoch. Folgende Stellschrauben in der Cargo.toml reduzieren die Größe drastisch:
[profile.release]
strip = true # Entfernt alle Debug-Symbole und Symboltabellen aus der Binärdatei
opt-level = "z" # Optimiert primär auf Binärgröße, nicht auf Ausführungsgeschwindigkeit
panic = "abort" # Deaktiviert das Stack-Unwinding. Reduziert den Fehlerbehandlungscode.
- Strip: Entspricht dem manuellen Ausführen des System-Befehls
strip target/release/wuerfelspiel. - Panic Abort: Im Fehlerfall stürzt das Programm sofort ab, anstatt den Stack geordnet abzubauen (Unwinding). Das spart viel Boilerplate-Code im Compiler-Ausgabe-Artefakt.
6. Key Takeaways (Systemebene)
- LLVM IR ermöglicht es Rust, hochoptimierten Maschinencode für Dutzende von CPU-Architekturen zu generieren.
- Statisches Linken erhöht die Binärgröße, garantiert aber die absolute Portabilität des Kompilats.
- Hardware-Zufall wird über CPU-spezifische Opcodes (
RDRAND) realisiert, die durch OS-Entropie-Abfragen geschützt sind.