- gccrs est un projet lancé en 2014 pour implémenter un compilateur Rust au sein de GCC ; il est encore loin d’être terminé, mais progresse vers la compilation de la bibliothèque standard et une inclusion dans GCC 14
- Le projet a choisi de viser Rust 1.49 plutôt que de suivre en permanence les dernières évolutions de Rust, mais a finalement dû implémenter des fonctionnalités comme
const genericsen raison de dépendances internes de la bibliothèque standard - La compilation de
coreetallocreste bloquée par la résolution des noms de macros, les macros décoratrices, des intrinsics de compilateur LLVM absents de GCC, et l’absence de borrow checker - rustc_codegen_gcc est une approche plus mature, qui réutilise une partie de rustc et emploie GCC comme backend de génération de code ; en octobre 2023, il pouvait compiler Rust for Linux sans patch supplémentaire
- gccrs a des motivations claires — plugins de sécurité GCC, analyse statique, architectures non prises en charge par LLVM, Rust for Linux — mais reste encore moins pratique que
rustc_codegen_gcc
Objectifs de gccrs et état actuel
- gccrs est un projet visant à implémenter un compilateur Rust dans le GNU Compiler Collection (GCC)
- Il a commencé en 2014 et, d’après les rapports du projet après une précédente couverture de LWN, il a progressé
- En 2022, l’objectif était une inclusion dans GCC 13, mais cela n’a pas été atteint ; selon le rapport mensuel de novembre 2023, l’objectif est désormais GCC 14
- GCC 14 est présenté comme une version susceptible de sortir au milieu de 2024
- À l’EuroRust 2023, en octobre 2023, Arthur Cohen a présenté “The road to compiling the standard library with gccrs”, expliquant le travail de compilation de la bibliothèque standard Rust et les raisons pour lesquelles elle ne compile pas encore
- La vidéo de la présentation est disponible
Pourquoi viser Rust 1.49
- gccrs choisit de viser Rust 1.49 plutôt que de suivre en continu les versions les plus récentes de Rust
- Rust 1.49 est sorti fin 2020 et constitue la dernière version avant la disponibilité générale de
const genericsdans Rust 1.50 - Le projet voulait éviter
const generics, mais cette fonctionnalité était déjà utilisée en interne dans la bibliothèque standard de Rust 1.49, ce qui l’a rendue impossible à ignorer const genericsa depuis été entièrement implémenté et ne constitue plus un obstacle- gccrs ne cherche pas à créer un sur-ensemble de Rust ni un langage séparé de type « GNU Rust »
- L’objectif est de reproduire jusqu’aux sorties, bugs et comportements particuliers de
rustc - Pour cela, le projet utilise à la fois la suite de tests de Rust et celle de GCC
- L’objectif est de reproduire jusqu’aux sorties, bugs et comportements particuliers de
Ce qui bloque la compilation de la bibliothèque standard
- La bibliothèque standard Rust est composée de plusieurs crates
- gccrs travaille à la prise en charge de la compilation des deux crates les plus importantes, core et alloc
coreimplémente les fonctionnalités de base de la bibliothèque standard, comme les types primitifs et les macrosallocgère l’allocation mémoire sur le tas et plusieurs types de conteneurs
- À l’heure actuelle, gccrs ne peut pas compiler ces crates en raison des manques suivants
- la résolution des noms de macros ne fonctionne pas correctement
- le support des macros décoratrices n’est pas complet
- l’absence de borrow checker empêche une vérification correcte de la sûreté du code
- certains intrinsics de compilateur LLVM absents de GCC doivent être implémentés
- L’absence de borrow checker n’empêche pas la compilation en elle-même, mais ne permet pas d’effectuer correctement les vérifications de sûreté du code Rust
Macros procédurales et intégration à GCC
- En septembre 2023, lors du GNU Tools Cauldron, Pierre-Emmanuel Patry a présenté l’avancement vers une inclusion dans GCC 14, en se concentrant sur le travail autour des macros
- Les slides de la présentation sont disponibles
- La manière d’implémenter les macros procédurales (procedural macro) nécessite des modifications du système de build de GCC
- Les macros procédurales sont des macros fonctionnelles qui produisent des flux de jetons, et non un simple texte source comme les macros C ou C++
- En Rust, elles sont implémentées via la crate intégrée proc_macro
- Elles sont difficiles à implémenter, mais permettent des fonctionnalités puissantes
- les décorateurs
#[attribute] - les décorateurs
#[derive()] - la création de langages spécifiques à un domaine basée sur l’évaluation au moment de la compilation
- les décorateurs
- Au moment de cette présentation au GNU Cauldron, gccrs comptait plus de 800 commits devant encore être intégrés upstream dans GCC
Pourquoi exploiter l’écosystème GCC pour Rust
- L’une des principales motivations de gccrs est de pouvoir appliquer aux programmes Rust les plugins de sécurité de GCC
- GCC dispose de nombreux plugins pour le débogage, l’analyse statique et le hardening, qui opèrent sur la représentation intermédiaire de GCC
- gccrs veut permettre aux développeurs Rust de réutiliser les workflows existants basés sur les plugins GCC
- Cohen a donné comme exemple le fait que les programmeurs C oublient depuis longtemps de fermer des descripteurs de fichiers, ce qui a conduit à de nombreux plugins capables de détecter ce type d’erreur
- L’objectif est de pouvoir exploiter ces plugins GCC existants et des analyseurs statiques pour détecter des bugs dans du code Rust
unsafe
Des usages existent déjà dans certains domaines
- Selon Cohen, la communauté homebrew de la Sega Dreamcast utilise gccrs pour créer de nouveaux jeux pour la console Dreamcast
- Cet intérêt vient du fait que le backend LLVM de
rustcne prend pas en charge l’architecture Hitachi SH-4 de la console, alors que GCC la prend en charge - gccrs reste inachevé, mais il est utile dans ce type de cas d’usage embarqué
- L’analyse statique de code Rust
unsafeau moyen de plugins GCC est déjà possible - Le travail sur gccrs a aussi mis en lumière des fonctionnalités du langage dont la spécification n’était pas suffisamment définie, comme
Derefet la résolution des noms de macros, et le projet a pu contribuer à l’effort de spécification de Rust- Rust ne dispose pas encore de spécification officielle, mais le travail avance conformément à la RFC 3355
Fonctionnalités clés encore en développement
- gccrs ne dispose toujours pas d’un grand nombre de fonctionnalités essentielles d’un compilateur Rust
- Parmi les principales fonctionnalités absentes ou encore en développement figurent
async/await- des intrinsics LLVM absents de GCC
- la macro
format_args!()utilisée par des macros d’affichage commeprintln!() - le borrow checker, qui fait respecter les règles de référence de Rust
- La solution la plus prometteuse pour le borrow checker est le projet distinct Polonius
- Cohen a déclaré qu’il était probable que gccrs intègre Polonius dans quelques mois
- Jakub Dupak a fait progresser ce travail ces derniers mois
- Polonius est actuellement une bibliothèque qui implémente un borrow checker sémantiquement équivalent à celui de
rustc- elle utilise un algorithme différent pour calculer la durée de vie des références
- à long terme, elle vise à corriger certaines limites et corner cases du borrow checker actuel de
rustc - une fois suffisamment mûr, Polonius pourrait aussi être adopté par
rustcà l’avenir
Pourquoi format_args!() est nécessaire
- Selon le rapport mensuel de gccrs de novembre 2023, le travail sur la macro
format_args!()a commencé format_args!()est une macro auxiliaire qui construit les arguments à transmettre aux macros de formatage de chaînes- Cette fonctionnalité est liée aux traits Display et Debug
- Elle est nécessaire pour préparer les arguments passés à des macros comme
format!()etprintln!() - Sans
format_args!(), un programme Rust ne peut pas produire de sortie formatée - Elle est donc nécessaire avant même que gccrs puisse compiler un programme « Hello, World »
- Une publication de blog de Mara Bos consacrée à
format_args!()est également mentionnée
Différences avec rustc_codegen_gcc
rustc_codegen_gccest un autre projet Rust basé sur GCC, distinct de gccrs- Il est plus mature que gccrs, mais son périmètre est plus limité
- Il ne cherche pas à réimplémenter entièrement un compilateur Rust à partir de zéro
- Il utilise la bibliothèque libgccjit pour se connecter à l’API du backend LLVM de
rustc - Une grande partie de la compilation est effectuée par
rustc, puis GCC est utilisé dans les phases ultérieures - Malgré le mot JIT dans le nom
libgccjit,rustc_codegen_gccvise la compilation ahead-of-time - Son objectif principal est de permettre la génération de code Rust sur des plateformes non prises en charge par LLVM
- En octobre 2023,
rustc_codegen_gccpouvait compiler Rust for Linux sans patch supplémentaire - Au cours de l’année écoulée, il a ajouté le support du SIMD et de l’optimisation à l’édition de liens
- ces deux fonctionnalités étaient auparavant identifiées comme causes d’échec des tests
- Lors de sa présentation à EuroRust, Cohen a recommandé à plusieurs reprises d’utiliser
rustc_codegen_gccpour l’instant à la place de gccrs rustc_codegen_gccest déjà intégré upstream dans le dépôt du langage Rust
Rust for Linux et l’écart de version
- Rust for Linux est une initiative visant à ajouter la prise en charge de Rust dans le noyau Linux
- Cohen a cité le noyau Linux comme motivation centrale du projet gccrs
- de nombreux acteurs du noyau préfèrent que celui-ci puisse être compilé uniquement avec la chaîne d’outils GNU
- Actuellement, le projet Rust for Linux documente rustc ou rustc_codegen_gcc comme moyens de compiler le code Rust du noyau
- Le noyau documente aussi des versions minimales prises en charge pour plusieurs outils de build
rustcy est traité non pas comme une version minimale, mais comme une version devant correspondre exactement- la version actuellement prise en charge de
rustcest 1.73.0, publiée en octobre 2023
- Il existe donc un écart important entre Rust 1.49, visé par gccrs, et Rust 1.73.0, requis par Rust for Linux
- La prise en charge de Rust for Linux est bien un objectif explicite de gccrs, mais cet écart de version montre qu’il reste encore un long chemin à parcourir
Évaluation d’ensemble
- Le dépôt gccrs compte plus de 3 000 commits depuis le 1er janvier 2023
- Le projet a connu des progrès significatifs au cours de l’année écoulée
- Mais compte tenu de l’ampleur du travail nécessaire pour implémenter un compilateur Rust complet à partir de zéro, il n’est pas encore utilisable pour presque tous les usages pratiques
rustc_codegen_gcca été fusionné dans le dépôt upstream de Rust et est déjà utilisé concrètement dans Rust for Linux- On n’en est pas encore au stade où le langage Rust dispose de plusieurs implémentations de compilateur indépendantes réellement exploitables, mais on s’en rapproche
1 commentaires
Avis sur Hacker News
À s’en tenir aux affirmations de l’article, la motivation de gccrs paraît un peu faible
Les plugins de sécurité GCC ou la préférence de la communauté du noyau Linux pour la chaîne d’outils GNU expliquent pourquoi on voudrait utiliser GCC comme backend, mais pas pourquoi il faudrait un frontend redondant
J’aimerais que Rust évite de répéter l’erreur de C++, où le développement multiplateforme devient difficile à cause des différences d’options entre compilateurs, des niveaux de prise en charge du langage et des bugs propres à chaque plateforme
Il serait donc utile d’expliquer pourquoi gccrs est une meilleure approche que
rustc_codegen_gcc, alors que ce dernier semble pouvoir atteindre le même objectif avec beaucoup moins d’efforts et de risquesQuand on tombe sur un bug de compilateur avec MSVC, on peut le signaler puis passer à GCC pour continuer à travailler ; avec Rust, cette option n’existe pas aujourd’hui
Comme cité, le fait de veiller à ne pas devenir un sur-ensemble de Rust en est un exemple
Les problèmes de C/C++ sont nés du fait que les fournisseurs de compilateurs se faisaient concurrence en affirmant être « meilleurs » les uns que les autres, et plusieurs frontends ont généralement l’avantage de révéler beaucoup de bugs et de mauvaises implémentations
Rust n’a rien de sacré qui interdirait une réécriture du frontend, et amorcer Rust sur de nouvelles architectures reste pénible
Sur les architectures non prises en charge par LLVM, il n’existe pas non plus de compilateur Rust fonctionnel
codegen_rust_gcca les mêmes problèmes de bootstrap que le compilateur Rust existant, et il faut ajouter la prise en charge des architectures à plusieurs parties de Rust, ce que les mainteneurs de Rust ont été réticents à faireDonc si, dans un avenir proche, on obtient un compilateur Rust utilisable permettant de reconstruire sans trop de douleur, même sur des architectures comme Alpha, des bibliothèques réécrites en Rust, ce sera très bienvenu
Il existait déjà GCC, G++, libstdc++, ainsi que le frontend C++ d’EDG
GCC, Clang, MSVC et d’autres compilateurs se complètent, répondent à des objectifs et des marchés différents, et contribuent à rendre le langage robuste par rapport à une spécification plutôt qu’aux propriétés accidentelles d’une implémentation unique
Le GNU Toolchain Project, le projet LLVM et le projet Rust ont tous connu des difficultés ; mieux vaut donc ne pas dépendre d’un point de défaillance unique, et la redondance et l’antifragilité sont nos alliées
Il est déroutant de voir quelqu’un considérer les standards de langage d’un mauvais œil et préférer dire « ce code fonctionne avec le binaire/la source rustc dont le hash SHA256 est
e49d560cd008344edf745b8052ef714b07595808898c835f17f962a10012f964» plutôt que « ce code est en C99/C++11 »Rust a besoin d’un standard de langage
https://blog.m-ou.se/rust-standard/
https://rust-lang.github.io/rfcs/3355-rust-spec.html
https://github.com/rust-lang/rfcs/pull/3355
Beaucoup d’organisations et d’industries n’adopteront pas Rust tant qu’un standard n’existera pas
C, C++, C#, et même JavaScript (ECMAScript) ont un standard de langage ; il n’y a pas de raison que Rust n’en ait pas
C : https://www.iso.org/standard/74528.html
C++ : https://isocpp.org/std/the-standard
C# : https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...
JavaScript / ECMAScript : https://ecma-international.org/publications-and-standards/st...
Les progrès sont d’une lenteur décevante, mais le projet est vivant, et il pourrait accélérer l’an prochain
https://blog.rust-lang.org/inside-rust/2023/11/15/spec-visio...
https://go.dev/ref/spec
Je ne vois pas pourquoi il faudrait changer une méthode qui fonctionne bien
Je suis surpris qu’il y ait autant de réactions négatives à GCC-RS
À mon avis, un langage qui n’a pas plusieurs implémentations est un langage assez pauvre
Le consensus de la communauté Rust va plutôt dans le sens que l’approche actuelle — un compilateur qui fait office de standard par définition, beaucoup de documentation, une spécification minimale pour les secteurs critiques en matière de sûreté, et des spécifications pour certains sous-domaines de modules — apporte la plupart des avantages de plusieurs implémentations tout en évitant leurs inconvénients
C en souffre réellement, et C++ est déjà presque irrécupérable à cause de sa complexité absurde et monstrueuse
Sans cela, il sera difficile de voir émerger des implémentations alternatives réalistes
La toolchain GNU est un foutoir, et je ne vois vraiment pas comment on développe dessus
Ce n’est pas une question idéologique : littéralement, je ne comprends pas comment mettre en place l’environnement de développement de GCC lui-même
J’ai eu la malchance de le bootstrapper quelques fois, et c’est la chose qui s’est comportée le plus mal parmi tous les logiciels que j’ai vus
J’aime bien le passage où la communauté homebrew Sega Dreamcast pourrait créer de nouveaux jeux avec gccrs, et où l’on pourrait faire de l’analyse statique de code Rust unsafe avec des plugins GCC
L’architecture Hitachi SH-4 de la Dreamcast n’est pas prise en charge par le backend LLVM de
rustc, mais GCC la prend en charge ; même dans son état inachevé, gccrs peut donc être utile pour ce genre d’usage embarquéPour cela, il n’y a pas besoin d’un frontend GCC, seulement du backend GCC
On pourrait maintenant voir du support Rust aussi sur des architectures comme Alpha, SuperH, VAX, que LLVM ne prend pas en charge mais que GCC prend en charge
rustca récemment abandonné le support après avoir échoué à obtenir des financements/ressources de Loongsonhttps://github.com/rust-lang/compiler-team/issues/648
Le plus gros problème de la mentalité LLVM est d’utiliser le support des architectures comme un moyen d’obtenir du soutien des fabricants de matériel, c’est-à-dire des postes de développeurs rémunérés
GNU peut avoir des critères d’intégration péniblement élevés, mais une fois qu’un support est accepté, il est maintenu sur le long terme
C’est un peu la différence entre acheter et louer : ajouter un support dans GCC demande beaucoup plus de temps de développement, mais une fois qu’il y est, il reste
Par exemple, j’ai récemment découvert que, sur RISC-V, GCC prend en charge la cible RV32E, contrairement à LLVM
La dernière fois que j’ai vérifié, la compilation C autonome fonctionnait encore dans GCC
D’après mon expérience, le fait que gccrs essaie de reproduire la sortie de
rustc, y compris ses bugs et ses particularités, plutôt que de créer un langage spécial appelé « GNU Rust », est une grave erreurRust n’a pas de spécification ; il existe de la documentation de référence, mais elle n’est explicitement pas normative
Un langage qui n’est pas documenté autrement que par une implémentation de référence unique a une faiblesse à long terme
L’objectif de garantir que le code existant fonctionne avec les deux implémentations est raisonnable, mais promettre une compatibilité avec les bugs fossilise de mauvaises décisions et des bugs
Microsoft consacre beaucoup de personnel à corriger des bugs de sécurité et de fiabilité tout en continuant à faire fonctionner d’anciens programmes ; Rust n’a pas besoin de porter ce fardeau si tôt dans sa vie
Si l’on veut faire évoluer le langage, il faut accepter l’assurance qualité et le contrôle qualité
La qualité ne peut pas être injectée après coup par des tests ; il faut la construire par l’architecture et la conception, et par des processus comme les revues de conception et de code, de façon à ce que le système fonctionne correctement et, s’il échoue, échoue dans la bonne direction
Des standards forts comme Common Lisp, C++ ou FORTRAN ont adopté cette conviction ; des langages plus faibles, proches d’un standard de fait, comme Python, peuvent aussi devenir populaires, mais leur difficulté à évoluer se voit dans la longue transition de Python 2 à 3 et dans le faible nombre d’implémentations
J’arrive tard dans la deuxième moitié de ce fil, mais ce n’est pas forcément une bonne chose
Les distributions n’arrivent déjà pas à suivre les langages qui sortent une nouvelle version tous les quelques mois, ce qui rend difficile l’utilisation de
rustcou de Go via les paquets de distributionAujourd’hui, étonnamment, il existe des systèmes où GCC n’est plus nécessaire et a été supprimé, et où l’on ne maintient que les versions upstream de Go et Rust pour mettre à jour les logiciels existants
Quand j’ai mis à jour Go il y a quelques mois à cause d’une CVE, c’était cauchemardesque de voir que des applications basées sur Go avaient stocké quatre environnements Go différents chacune de leur côté
Linux peut déjà être compilé avec Clang si on le souhaite, et utiliser ainsi une toolchain entièrement basée sur LLVM
Cet effort dupliqué pour développer et maintenir cela au nom de la « pureté » GNU ne semble pas en valoir la peine
La communauté ClangBuiltLinux soutenait que Linux ne devait pas dépendre d’un compilateur unique ; avec l’arrivée de Rust, beaucoup de ces mêmes personnes ont soudain commencé à considérer qu’un compilateur unique pouvait très bien convenir
Il ne s’agit pas d’enfermer le noyau dans du GNU uniquement, mais simplement de permettre de choisir une toolchain GNU pure