10 points par GN⁺ 2024-12-29 | 3 commentaires | Partager sur WhatsApp

#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

 
annyeong 2024-12-30

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 👀

 
GN⁺ 2024-12-29
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

    • Fish n’a pas été publié comme un programme hybride C++/Rust. C’est parce que la phase finale de tests n’était pas terminée
    • Certains ne comprennent pas la motivation à ajouter des fonctionnalités C++ en Rust, mais cela pourrait constituer une bonne étude de cas
    • Certains estiment qu’il serait bien de pouvoir écrire du nouveau code Rust dans une base de code C++
  • 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

    • La détection par version/nom est la raison pour laquelle Chrome et IE prétendent être Mozilla, et pourquoi Clang prétend être GCC. La détection de fonctionnalités ne provoque pas ce type de problèmes
  • 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

    • Il serait préférable qu’un autre outil soit mis en œuvre plutôt que d’étendre Cargo à ce type de cas d’usage
  • 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 garde if doit être compilé. Compiler sans my_feature peut échouer

  • Fish 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