#9512 - Rewrite It in Rust
- Die Fish-Shell wurde in Rust neu geschrieben. Es gibt keinerlei C++-Code mehr, und sie besteht nun fast zu 100 % aus reinem Rust.
- Vor etwa zwei Jahren wurde der PR (#9512) eröffnet, um Fish von C++ auf Rust umzustellen.
- Fish hat in der Vergangenheit bereits einen Wechsel von C zu C++ erlebt, doch der Umstieg auf Rust war ein deutlich größeres Projekt.
Probleme mit C++
- Werkzeuge und Compiler-Unterschiede: Die Werkzeuge für C++ sind nicht gut, und die Übernahme moderner C++-Standards macht es für Paketbetreuer und Mitwirkende kompliziert.
- Thread-Sicherheit: Die Ausführung interner Fish-Befehle erfolgt derzeit seriell. Um asynchrone Prompts oder nicht blockierende Vervollständigung hinzuzufügen, ist Parallelisierung nötig.
- Komplexität der Sprache: Header-Dateien, Templates und String-Verarbeitung in C++ sind komplex und unsicher.
- Community: C++ zieht nicht viele Mitwirkende an.
- Abhängigkeitsprobleme: Es gab Aufwand durch die Instabilität und Build-Probleme bestimmter C-Bibliotheken (
curses).
Warum Rust gewählt wurde
- Spaß und Interesse: Fish ist ein Hobbyprojekt und braucht eine Sprache, die Spaß macht und interessant ist. Rust ist für Mitwirkende attraktiver.
- Hervorragende Werkzeuge: Mit
rustup lässt sich der Compiler einfach installieren, und Fehlermeldungen sind klar verständlich.
- Ergonomie: Ein explizites
use-System sowie sichere Funktionen wie Option und Result.
- Gutes Sprachdesign: Rusts Pointer- und Option-System ist deutlich sicherer als das von C++.
- Unterstützung für Parallelität: Rusts
Send und Sync ermöglichen sichere Parallelverarbeitung.
- Abhängigkeitsverwaltung: Unterstützung für externe Formate wie YAML und JSON lässt sich leicht hinzufügen.
Plattformunterstützung
- Die meisten wichtigen Plattformen (macOS, Linux, BSD usw.) werden unterstützt; native Windows-Unterstützung ist kein Ziel.
- Fish ist eine UNIX-zentrierte Shell und konzentriert sich eher auf UNIX-APIs und Skriptsprachen als auf Windows-Umgebungen.
Der Portierungsprozess
- Fish wurde nach dem Muster des „Fischs des Theseus“ schrittweise von C++ auf Rust umgestellt. Komponenten wurden einzeln nach Rust migriert, sodass C++ und Rust nebeneinander bestehen konnten.
- Schiff des Theseus (Ship of Theseus): „Wenn alle Holzplanken eines Schiffs durch neue ersetzt werden, ist es dann noch dasselbe Schiff?“
- FFI-Einsatz: Mit
autocxx wurden Bindings zwischen C++ und Rust erzeugt, und jeweils nur eine Komponente auf einmal portiert.
- Groß angelegte Portierungen: Bestimmte Teile (z. B. I/O-Verarbeitung) wurden als Ganzes migriert, um komplexen FFI-Code zu reduzieren.
- Verbesserung der Werkzeuge: Im Verlauf der Portierung wurde
autocxx angepasst, um Interoperabilitätsprobleme zwischen Rust und C++ zu lösen.
Zeitachse
- Januar 2023: Eröffnung des ersten PR
- Januar 2024: C++-Code vollständig entfernt
- Dezember 2024: Veröffentlichung der Beta-Version von Fish 4.0
Reibungen mit Rust
- Portabilitätsprobleme: Rusts
#[cfg(...)]-Ansatz ist ineffizient, wenn Systemunterschiede auf niedriger Ebene behandelt werden müssen.
- Lokalisierung: Rust-Format-Strings werden zur Compile-Zeit geprüft, sind aber nicht übersetzbar.
- Build-Zeiten: Durch LTO und standardmäßige Release-Builds können die Build-Zeiten lang werden.
- Während der Portierung wurden einige Fehler gemacht, die sich jedoch größtenteils leicht beheben ließen.
Wichtige Ergebnisse
curses entfernt: Die terminfo-Datenbank wurde durch ein Rust-Crate ersetzt, wodurch globaler Zustand und Build-Probleme beseitigt wurden.
- Eine einzelne ausführbare Datei: Es kann ein Fish-Binary erzeugt werden, das alle Abhängigkeiten enthält.
- Dadurch lässt sich das Fish-Paket selbst installieren, was die Nutzung für Anwender erleichtert.
- Bessere Performance: Optimierter Speicherverbrauch und leichteres Hinzufügen neuer Funktionen.
Einschränkungen
- CMake konnte nicht vollständig entfernt werden.
- Unterstützung für Cygwin eingestellt: Es gibt kein Rust-Target dafür.
- Unter Windows läuft Fish weiterhin nur über WSL.
Gegenwart und Zukunft
- Fish 4.0 wurde erfolgreich portiert und bietet bessere Performance.
- Fish bleibt eine UNIX-Shell, kann durch den Wechsel zu Rust aber leichter um neue Funktionen erweitert werden.
- Die Codebasis ist nun vollständig auf Rust umgestellt und dadurch einfacher zu warten und zu erweitern als zuvor. Die Vorteile von Rust können nun für neue Funktionen genutzt werden.
- Diese Umstellung wurde erfolgreich abgeschlossen und wirkt sich positiv auf Mitwirkende und Nutzer aus.
3 Kommentare
Ich beneide fish zwar um seine Benutzerfreundlichkeit, nutze aber wegen Problemen bei Kompatibilität, Performance usw. zsh, das ich so eingestellt habe, dass es fish möglichst ähnlich ist. Ich bin gespannt, wie das überarbeitete fish sein wird 👀
Freundliche interaktive Shell – Fish
Hacker-News-Kommentare
Glückwunsch an das Fish-Team; die Details des Projekts sind spannend. Ich frage mich, ob dies das größte Projekt ist, das vollständig von C++ auf Rust umgestellt wurde. Das könnte nützliche Lehren für andere Projekte bieten
Ein Hauptkritikpunkt an Rust ist die Unterstützung für Versionserkennung. Funktionserkennung ist besser für Distributionen, Webbrowser und Compiler geeignet
Eines der Ziele des Ports war es, CMake zu entfernen, aber das ist nicht gelungen. Cargo ist großartig für Builds, aber schlicht bei der Installation. Fish hat viele Skripte und Dokumentationen und passt damit nicht zu den Anwendungsfällen von Cargo
Als ich vor ein paar Jahren von bash zu zsh gewechselt bin, war ich zufrieden, aber als ich auf einem neuen Rechner fish ausprobierte, fühlte sich zsh umständlich und veraltet an. Ich würde empfehlen, fish ein paar Wochen lang zu nutzen
Schade, dass Cygwin nicht unterstützt wird. Hoffentlich unterstützt Rust Cygwin künftig als Build-Ziel
Beeindruckend, wie viel Arbeit das Fish-Team investiert hat, und ich bin gespannt, wie sich das Projekt weiterentwickelt
Ich frage mich, wie leicht es für Distribution-Paketierer ist, Rust-fish gemäß den Debian-Richtlinien zu paketieren
Glückwunsch an das Fish-Team; die beste Shell ist noch besser geworden. Vielleicht sollte der Slogan des Projekts auf "Finally, a shell for the 00s!" aktualisiert werden
Nach dem Wechsel von zsh zu Fish ist meine Konfiguration viel einfacher geworden, und Fish funktioniert genau wie erwartet, daher habe ich nicht vor, noch einmal zu wechseln
Das Makro
cfg!wird zu true/false kompiliert, daher muss der Code innerhalb einesif-Guards kompilierbar sein. Ohnemy_featurekann die Kompilierung fehlschlagenFish verwendet Threads für Autovervollständigung und Syntaxhervorhebung, und es gibt ein langfristiges Projekt, um der Sprache Nebenläufigkeit hinzuzufügen