#9512 - Rewrite It in Rust
- Le shell Fish a été réécrit en Rust. Il ne contient plus aucun code C++ et est composé à près de 100 % de Rust pur
- Il y a environ deux ans, une PR (#9512) a été ouverte pour faire passer Fish du C++ à Rust
- Fish avait déjà connu une transition de C vers C++ par le passé, mais le passage à Rust était un projet bien plus ambitieux
Problèmes avec le C++
- Différences d’outils et de compilateurs : l’outillage C++ est médiocre, et l’adoption des standards C++ récents complique la vie des packageurs et des contributeurs.
- Sécurité des threads : l’exécution des commandes internes de Fish est actuellement sérialisée, et l’ajout d’un prompt asynchrone ou d’une autocomplétion non bloquante nécessite du parallélisme.
- Complexité du langage : les fichiers d’en-tête, les templates et la gestion des chaînes en C++ sont complexes et peu sûrs.
- Communauté : le C++ n’attire pas beaucoup de contributeurs.
- Problèmes de dépendances : l’instabilité de certaines bibliothèques C (
curses) et des problèmes de build ont causé des contraintes supplémentaires.
Pourquoi avoir choisi Rust
- Plaisir et intérêt : Fish est un projet hobby, qui a besoin d’un langage amusant et stimulant. Rust est aussi plus attractif pour les contributeurs.
- Excellents outils :
rustup permet d’installer facilement le compilateur, et les messages d’erreur sont clairs.
- Ergonomie : Rust fournit un système
use explicite ainsi que des mécanismes sûrs comme Option et Result.
- Bonne conception du langage : le système de pointeurs et d’options de Rust est bien plus sûr que celui du C++.
- Support du parallélisme :
Send et Sync en Rust permettent un parallélisme sûr.
- Gestion des dépendances : il est facile d’ajouter le support de formats externes comme YAML ou JSON.
Support des plateformes
- La plupart des grandes plateformes (macOS, Linux, BSD, etc.) sont prises en charge, mais le support natif de Windows n’est pas un objectif.
- Fish est un shell centré sur UNIX, davantage tourné vers les API UNIX et les langages de script que vers l’environnement Windows.
Processus de portage
- Fish a migré progressivement du C++ vers Rust selon une approche de « poisson de Thésée ». Les composants ont été déplacés un par un vers Rust, avec une coexistence du C++ et de Rust pendant la transition.
- Le bateau de Thésée (Ship of Theseus) : « Si l’on remplace toutes les planches en bois d’un navire par des neuves, est-ce toujours le même navire ? »
- Utilisation de la FFI :
autocxx a été utilisé pour générer les liaisons entre C++ et Rust, en portant les composants un par un.
- Portage à grande échelle : certaines parties spécifiques (par exemple le traitement des E/S) ont été migrées d’un seul bloc afin de réduire la complexité du code FFI.
- Amélioration des outils :
autocxx a été personnalisé pendant le portage pour résoudre les problèmes d’interopérabilité entre Rust et C++.
Chronologie
- Janvier 2023 : ouverture de la PR initiale
- Janvier 2024 : suppression complète du code C++
- Décembre 2024 : sortie de la bêta de Fish 4.0
Frictions avec Rust
- Problèmes de portabilité : l’approche Rust avec
#[cfg(...)] est peu efficace pour gérer les différences système à bas niveau.
- Localisation : les chaînes de format Rust sont vérifiées à la compilation, mais ne sont pas traduisibles.
- Temps de build : l’utilisation de LTO et du build de release par défaut peut allonger les temps de compilation.
- Quelques erreurs ont été commises pendant le portage, mais la plupart ont été faciles à corriger.
Principaux résultats
- Suppression de
curses : la base de données terminfo a été remplacée par une crate Rust, ce qui a résolu les problèmes d’état global et de build.
- Fichier exécutable unique : il est possible de produire un binaire Fish incluant toutes les dépendances.
- Le paquet Fish peut ainsi être auto-installable, ce qui facilite son usage pour les utilisateurs.
- Amélioration des performances : optimisation de l’usage mémoire et ajout de nouvelles fonctionnalités facilité.
Limites
- CMake n’a pas pu être complètement supprimé
- Fin du support de Cygwin : il n’existe pas de cible Rust correspondante
- Sous Windows, l’exécution reste possible uniquement via WSL
Présent et avenir
- Fish 4.0 a été porté avec succès et ses performances se sont améliorées.
- Fish reste un shell UNIX, mais la transition vers Rust permet désormais d’ajouter de nouvelles fonctionnalités.
- La base de code est maintenant entièrement passée à Rust, ce qui facilite davantage la maintenance et l’ajout de fonctionnalités qu’auparavant. Les avantages de Rust peuvent désormais être exploités pour développer de nouvelles fonctions.
- Cette transition a été menée à bien avec succès et a eu un impact positif à la fois pour les contributeurs et pour les utilisateurs
3 commentaires
J’envie l’ergonomie de fish, mais à cause de problèmes de compatibilité, de performances, etc., j’utilise zsh en le configurant pour qu’il ressemble le plus possible à fish. Je suis curieux de voir ce que donnera cette nouvelle version de fish 👀
Un shell interactif convivial - Fish
Commentaires sur Hacker News
Félicitations à l’équipe de Fish, et les détails du projet sont intéressants. On se demande s’il s’agit du plus grand projet à être passé entièrement de C++ à Rust. Cela pourrait offrir des enseignements utiles à d’autres projets
Le principal reproche fait à Rust concerne la prise en charge de la détection de version. La détection de fonctionnalités est meilleure pour les distributions, les navigateurs web et les compilateurs
L’un des objectifs du portage était de supprimer CMake, mais cela a échoué. Cargo est excellent pour la compilation, mais simpliste pour l’installation. Fish comporte beaucoup de scripts et de documentation, ce qui ne correspond pas au cas d’usage de Cargo
Lors d’un passage de bash à zsh il y a quelques années, l’expérience avait été satisfaisante, mais après avoir essayé fish sur un nouvel ordinateur, zsh a semblé lourd et daté. Il est recommandé d’essayer fish pendant quelques semaines
C’est dommage que Cygwin ne soit pas pris en charge. On espère que Rust prendra en charge Cygwin comme cible de compilation
Les efforts de l’équipe Fish impressionnent, et on a hâte de voir comment le projet va évoluer
On se demande à quel point il sera facile pour les mainteneurs de paquets de distribuer Rust-fish en suivant les directives Debian
Félicitations à l’équipe Fish, avec l’avis que le meilleur shell est devenu encore meilleur. Il est proposé de mettre à jour le slogan du projet en « Finally, a shell for the 00s! »
Après être passé de zsh à Fish, la configuration est devenue plus simple, et comme Fish fonctionne comme attendu, il n’y a aucune intention de changer à nouveau
La macro
cfg!est compilée en true/false, donc le code à l’intérieur d’un gardeifdoit être compilé. Compiler sansmy_featurepeut échouerFish utilise des threads pour l’autocomplétion et la coloration syntaxique, et il existe un projet de long terme visant à ajouter la concurrence au langage