- gccrs ist ein 2014 gestartetes Projekt, das einen Rust-Compiler innerhalb von GCC implementieren will. Es ist noch weit von der Fertigstellung entfernt, macht aber Fortschritte beim Kompilieren der Standardbibliothek und auf dem Weg zur Aufnahme in GCC 14
- Das Projekt nahm statt des sich schnell verändernden aktuellen Rust Rust 1.49 ins Visier. Wegen interner Abhängigkeiten der Standardbibliothek mussten jedoch letztlich auch Funktionen wie
const genericsimplementiert werden - Das Kompilieren von
coreundallocwird noch durch die Namensauflösung von Makros, Dekorator-Makros, in GCC fehlende LLVM-Compiler-Intrinsics und das Fehlen eines Borrow Checkers blockiert - rustc_codegen_gcc ist ein ausgereifterer Ansatz, der Teile von rustc nutzt und GCC als Backend für die Codegenerierung verwendet. Stand Oktober 2023 kann es Rust for Linux ohne zusätzliche Patches kompilieren
- gccrs hat klare Motivationen wie GCC-Sicherheits-Plug-ins, statische Analyse, von LLVM nicht unterstützte Architekturen und Rust for Linux, ist in der Praxis aber noch eingeschränkter als
rustc_codegen_gcc
Ziele und aktueller Stand von gccrs
- gccrs ist ein Projekt zur Implementierung eines Rust-Compilers innerhalb der GNU Compiler Collection (GCC)
- Es wurde 2014 gestartet und hat seit der früheren Berichterstattung von LWN laut Projektberichten Fortschritte gemacht
- 2022 war die Aufnahme in GCC 13 das Ziel, wurde aber nicht erreicht. Laut Monatsbericht vom November 2023 ist nun die Aufnahme in GCC 14 das Ziel
- GCC 14 wurde als Version behandelt, die voraussichtlich Mitte 2024 erscheinen könnte
- Auf der EuroRust 2023 im Oktober 2023 erklärte Arthur Cohen in seinem Vortrag „The road to compiling the standard library with gccrs“ die Arbeit am Kompilieren der Rust-Standardbibliothek und die Gründe, warum dies noch nicht gelingt
- Das Vortragsvideo ist verfügbar
Warum Rust 1.49 als Ziel gewählt wurde
- gccrs zielt auf Rust 1.49, statt ständig der neuesten Rust-Version zu folgen
- Rust 1.49 wurde Ende 2020 veröffentlicht und war die letzte Version vor der in Rust 1.50 allgemein verfügbaren Unterstützung für
const generics - Das Projekt wollte
const genericsvermeiden, doch sie wurden bereits intern in der Standardbibliothek von Rust 1.49 verwendet und konnten daher letztlich nicht ignoriert werden const genericsist inzwischen vollständig implementiert und stellt kein Hindernis mehr dar- gccrs will keine Obermenge von Rust und keine separate „GNU Rust“-Sprache schaffen
- Ziel ist es, die Ausgabe, Bugs und Eigenheiten von
rustczu reproduzieren - Dafür werden sowohl die Rust-Test-Suite als auch die GCC-Test-Suite verwendet
- Ziel ist es, die Ausgabe, Bugs und Eigenheiten von
Blockaden beim Kompilieren der Standardbibliothek
- Die Rust-Standardbibliothek besteht aus mehreren Crates
- gccrs arbeitet an der Unterstützung für das Kompilieren der zwei wichtigsten Crates, core und alloc
coreimplementiert grundlegende Funktionen der Standardbibliothek wie primitive Typen und Makrosallocbehandelt Heap-Speicherallokation und verschiedene Container-Typen
- Derzeit kann gccrs diese Crates wegen folgender fehlender Funktionen nicht kompilieren
- Das Verhalten der Namensauflösung von Makros ist nicht korrekt
- Die Unterstützung für Dekorator-Makros ist nicht vollständig
- Ohne Borrow Checker kann die Codesicherheit nicht korrekt geprüft werden
- LLVM-Compiler-Intrinsics, die es in GCC nicht gibt, müssen implementiert werden
- Das Fehlen des Borrow Checkers verhindert zwar nicht das Kompilieren selbst, sorgt aber dafür, dass die Sicherheitsprüfung von Rust-Code nicht korrekt durchgeführt werden kann
Prozedurale Makros und GCC-Integration
- Im September 2023 stellte Pierre-Emmanuel Patry beim GNU Tools Cauldron den Stand der Aufnahme in GCC 14 und die Arbeit an Makros in den Mittelpunkt seines Vortrags
- Die Vortragsfolien sind verfügbar
- Die Implementierung von prozeduralen Makros (procedural macros) erfordert Änderungen am GCC-Build-System
- Prozedurale Makros geben nicht wie C- oder C++-Makros einfachen Quelltext aus, sondern sind funktionsartige Makros, die Token-Streams ausgeben
- In Rust werden sie über das eingebaute Crate proc_macro implementiert
- Prozedurale Makros sind schwierig zu implementieren, ermöglichen aber mächtige Funktionen
#[attribute]-Dekoratoren#[derive()]-Dekoratoren- Erzeugung domänenspezifischer Sprachen auf Basis von Compile-Time Evaluation
- Zum Zeitpunkt des GNU-Cauldron-Vortrags hatte gccrs mehr als 800 Commits, die noch in GCC upstream gebracht werden mussten
Warum das GCC-Ökosystem für Rust genutzt werden soll
- Eine der Hauptmotivationen für gccrs ist, die Sicherheits-Plug-ins von GCC auch für Rust-Code nutzbar zu machen
- GCC verfügt über verschiedene Plug-ins, die bei Debugging, statischer Analyse und Härtung helfen; sie arbeiten auf GCCs Intermediate Representation
- gccrs will Rust-Entwicklern Workflows ermöglichen, in denen vorhandene GCC-Plug-ins wiederverwendet werden
- Cohen nannte als Beispiel, dass C-Programmierer seit Langem den Fehler machen, File Descriptors nicht zu schließen, weshalb es viele Plug-ins gibt, die solche Probleme erkennen
- Ziel ist es, vorhandene GCC-Plug-ins und statische Analyzer nutzen zu können, um Bugs in Rusts
unsafe-Code zu finden
Bereiche, in denen es bereits teilweise genutzt wird
- Laut Cohen nutzt die Homebrew-Community der Sega Dreamcast gccrs, um neue Spiele für die Dreamcast-Konsole zu erstellen
- Das Interesse der Dreamcast-Community liegt daran, dass das LLVM-Backend von
rustcdie Hitachi-SH-4-Architektur der Konsole nicht unterstützt, GCC dagegen schon - gccrs ist noch unvollständig, kann in solchen Embedded-Anwendungsfällen aber hilfreich sein
- Auch statische Analyse von
unsafe-Rust-Code mit GCC-Plug-ins ist bereits möglich - Bei der Arbeit an gccrs wurden Sprachfunktionen sichtbar, die nicht ausreichend spezifiziert sind, etwa
Derefund die Namensauflösung von Makros; das Projekt konnte so auch zur Erweiterung der Rust-Spezifikation beitragen- Rust hat derzeit keine offizielle Spezifikation, doch gemäß RFC 3355 laufen entsprechende Spezifikationsarbeiten
Zentrale Funktionen, die noch in Entwicklung sind
- In gccrs fehlen weiterhin viele Kernfunktionen eines Rust-Compilers
- Zu den wichtigsten nicht implementierten oder noch in Entwicklung befindlichen Funktionen gehören
async/await- LLVM-Intrinsics, die es in GCC nicht gibt
- das Makro
format_args!(), das von Ausgabemakros wieprintln!()verwendet wird - der Borrow Checker, der Rusts Regeln für Referenzen durchsetzt
- Die wahrscheinlichste Lösung für den Borrow Checker ist das separate Projekt Polonius
- Cohen sagte, dass gccrs Polonius wahrscheinlich in einigen Monaten integrieren werde
- Jakub Dupak hat in den letzten Monaten bei dieser Arbeit Fortschritte erzielt
- Polonius ist derzeit eine Bibliothek, die einen semantisch zum Borrow Checker von
rustcäquivalenten Borrow Checker implementiert- Für die Berechnung der Lebensdauer von Referenzen verwendet sie einen anderen Algorithmus
- Langfristig soll sie Schwächen und Corner Cases des derzeitigen Borrow Checkers von
rustclösen - Wenn Polonius ausgereift ist, könnte auch
rustces künftig übernehmen
Warum format_args!() benötigt wird
- Laut dem gccrs-Monatsbericht vom November 2023 hat die Arbeit am Makro
format_args!()begonnen format_args!()ist ein Hilfsmakro, das die Argumente für String-Formatierungsmakros zusammenstellt- Diese Funktion hängt mit den Traits Display und Debug zusammen
- Sie wird benötigt, um Argumente für Makros wie
format!()undprintln!()vorzubereiten - Ohne
format_args!()können Rust-Programme keine formatierte Ausgabe erzeugen - Daher ist es eine Funktion, die gccrs bereits braucht, bevor es ein „Hello, World“-Programm kompilieren kann
- Als vertiefende Erklärung zu
format_args!()wird auch Mara Bos’ Blogbeitrag behandelt
Unterschied zu rustc_codegen_gcc
rustc_codegen_gccist ein anderes GCC-basiertes Rust-Projekt als gccrs- Es ist reifer als gccrs, hat aber einen begrenzteren Umfang
- Es implementiert den Rust-Compiler nicht vollständig von Grund auf neu
- Es nutzt die Bibliothek libgccjit, um an die LLVM-Backend-API von
rustcanzubinden - Große Teile der Kompilierung übernimmt
rustc; erst in späteren Phasen wird GCC verwendet - Obwohl
libgccjitJIT im Namen trägt, zieltrustc_codegen_gccauf Ahead-of-Time-Kompilierung - Das Hauptziel ist, die Codegenerierung für Rust auf Plattformen zu ermöglichen, die LLVM nicht unterstützt
- Stand Oktober 2023 kann
rustc_codegen_gccRust for Linux ohne zusätzliche Patches kompilieren - Im vergangenen Jahr wurden Unterstützung für SIMD und Link-Time Optimization hinzugefügt
- Beide Funktionen waren zuvor als Ursachen für fehlgeschlagene Tests genannt worden
- Cohen empfahl in seinem EuroRust-Vortrag mehrfach, vorerst
rustc_codegen_gccstatt gccrs zu verwenden rustc_codegen_gccist bereits im upstream Rust-Repository enthalten
Rust for Linux und die Versionslücke
- Rust for Linux ist eine Initiative, die Rust-Unterstützung zum Linux-Kernel hinzufügen will
- Cohen nannte den Linux-Kernel als zentrale Motivation für das gccrs-Projekt
- Denn viele Kernel-Beteiligte bevorzugen es, wenn der Kernel ausschließlich mit der GNU-Toolchain kompiliert werden kann
- Das Rust-for-Linux-Projekt dokumentiert derzeit rustc oder rustc_codegen_gcc als Möglichkeiten, Kernel-Rust-Code zu bauen
- Für den Kernel gibt es auch Dokumentation zu den minimal unterstützten Versionen verschiedener Build-Tools
rustcwird dabei nicht als Mindestversion, sondern als exakt passende Version behandelt- Die derzeit unterstützte
rustc-Version ist 1.73.0, veröffentlicht im Oktober 2023
- Zwischen Rust 1.49, auf das gccrs zielt, und Rust 1.73.0, das Rust for Linux verlangt, liegt eine große Lücke
- Die Unterstützung von Rust for Linux ist ein erklärtes Ziel von gccrs, wegen dieser Versionslücke aber noch in erheblicher Ferne
Gesamtbewertung
- Das gccrs-Repository enthält seit dem 1. Januar 2023 mehr als 3.000 Commits
- Im vergangenen Jahr hat das Projekt erhebliche Fortschritte gemacht
- Da der Umfang eines vollständigen Rust-Compilers von Grund auf jedoch sehr groß ist, ist gccrs für nahezu alle praktischen Zwecke noch nicht einsatzbereit
rustc_codegen_gccwurde in das upstream Rust-Repository gemergt und wird bei Rust for Linux tatsächlich genutzt- Rust ist noch nicht an dem Punkt angekommen, an dem es mehrere unabhängige Compiler-Implementierungen gibt, nähert sich diesem Ziel aber an
1 Kommentare
Meinungen auf Hacker News
Allein anhand der Argumentation des Artikels wirkt die Motivation für gccrs etwas schwach
GCC-Sicherheits-Plugins oder die Präferenz der Linux-Kernel-Seite für die GNU-Toolchain erklären zwar, warum man GCC als Backend verwenden möchte, aber nicht, warum ein dupliziertes Frontend nötig ist
Ich hoffe, Rust wiederholt nicht den Fehler von C++, wo plattformübergreifende Entwicklung durch Schalter verschiedener Compiler, Unterschiede beim Umfang der Sprachunterstützung und plattformspezifische Bugs schwieriger wird
Daher wäre es gut zu erklären, warum gccrs ein besserer Ansatz ist als
rustc_codegen_gcc; Letzteres scheint dasselbe Ziel mit deutlich weniger Aufwand und Risiko erreichen zu könnenWenn man in MSVC auf einen Compiler-Bug stößt, kann man ihn melden und mit GCC weiterarbeiten; bei Rust gibt es diese Option derzeit nicht
Ein Beispiel dafür ist, wie zitiert, die Vorsicht, kein Superset von Rust zu werden
Die Probleme von C/C++ entstanden dadurch, dass Compiler-Hersteller miteinander konkurrierten, „besser“ zu sein; mehrere Frontends haben normalerweise den Vorteil, viele Bugs und fehlerhafte Implementierungen sichtbar zu machen
Rust ist nicht in irgendeinem Sinne heilig, sodass ein Neuschreiben des Frontends verboten wäre, und Rust auf neuen Architekturen zu bootstrappen ist weiterhin schmerzhaft
Für Architekturen, die LLVM nicht unterstützt, gibt es auch keinen funktionierenden Rust-Compiler
codegen_rust_gcchat dieselben Bootstrap-Probleme wie der bestehende Rust-Compiler, und man müsste Architekturunterstützung an mehreren Stellen in Rust einbauen, was die Rust-Maintainer bisher eher gescheut habenWenn es daher in naher Zukunft einen sofort nutzbaren Rust-Compiler gibt, mit dem man auch auf Architekturen wie Alpha wieder in Rust umgeschriebene Bibliotheken ohne große Schmerzen bauen kann, wäre das sehr willkommen
Es gab bereits GCC, G++, libstdc++, das EDG-C++-Frontend
GCC, Clang, MSVC und andere Compiler ergänzen einander, bedienen unterschiedliche Zwecke und Märkte und helfen dabei, die Sprache an der Spezifikation auszurichten und robuster zu machen, statt dass sie nur aus zufälligen Eigenschaften einer einzelnen Implementierung besteht
Das GNU Toolchain Project, das LLVM Project und das Rust-Projekt hatten alle ihre Probleme; daher ist es besser, sich nicht auf einen Single Point of Failure zu verlassen, und Redundanz und Antifragilität sind Freunde
Es wirkt verwirrend, Sprachstandards negativ zu sehen und lieber nicht zu sagen „dieser Code ist C99/C++11“, sondern „dieser Code läuft mit dem rustc-Binary/-Source mit dem SHA256-Hash
e49d560cd008344edf745b8052ef714b07595808898c835f17f962a10012f964“Rust braucht einen Sprachstandard
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
Es gibt viele Organisationen und Branchen, die Rust nicht einführen werden, bevor es einen Standard gibt
C, C++, C# und sogar JavaScript (ECMAScript) haben Sprachstandards; es gibt keinen Grund, warum Rust keinen haben sollte
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...
Der Fortschritt ist zwar enttäuschend langsam, aber das Projekt lebt, und nächstes Jahr könnte es an Fahrt aufnehmen
https://blog.rust-lang.org/inside-rust/2023/11/15/spec-visio...
https://go.dev/ref/spec
Ich sehe nicht, warum man ändern sollte, was gut funktioniert
Es überrascht mich, dass es so viele negative Reaktionen auf GCC-RS gibt
Ich halte eine Sprache für ziemlich armselig, wenn sie nicht mehrere Implementierungen hat
Der Konsens in der Rust-Community geht eher dahin, dass der aktuelle Ansatz — ein Compiler, der per Definition der Standard ist, umfangreiche Dokumentation, eine sicherheitskritische minimale Spezifikation für die Industrie sowie Spezifikationen für einige Modul-Teilbereiche — die meisten Vorteile mehrerer Implementierungen bringt und zugleich deren Nachteile vermeidet
Bei C erlebt man das tatsächlich, und C++ ist wegen seiner absurden und grotesken Komplexität schon fast nicht mehr zu retten
Ohne das sind realistische Alternativimplementierungen schwer vorstellbar
Die GNU-Toolchain ist ein Durcheinander, und ich weiß wirklich nicht, wie man darauf entwickelt
Das ist keine ideologische Aussage; ich verstehe buchstäblich nicht, wie man die Entwicklungsumgebung für GCC selbst aufsetzt
Ich hatte das Pech, es ein paarmal zu bootstrappen, und es war das am schlechtesten funktionierende Stück Software, das ich je gesehen habe
Mir gefällt die Stelle, dass die Sega-Dreamcast-Homebrew-Community mit gccrs neue Spiele erstellt und man mit GCC-Plugins statische Analysen von unsafe Rust-Code durchführen kann
Die Hitachi-SH-4-Architektur der Dreamcast wird vom LLVM-Backend von
rustcnicht unterstützt, von GCC aber schon; daher kann selbst das noch unfertige gccrs bei solchen Embedded-Anwendungen nützlich seinDafür braucht man kein GCC-Frontend, sondern nur das GCC-Backend
Jetzt dürfte man Rust-Unterstützung auch auf Architekturen wie Alpha, SuperH, VAX sehen, die LLVM nicht unterstützt, GCC aber schon
rustckürzlich aufgegeben hat, nachdem der Versuch gescheitert war, von Loongson Geld/Ressourcen zu bekommenhttps://github.com/rust-lang/compiler-team/issues/648
Das größte Problem der LLVM-Denkweise ist, dass Architekturunterstützung als Mittel genutzt wird, um Hardwarefirmen Unterstützung abzuringen, also bezahlte Entwicklerstellen
Bei GNU können die Kriterien für das Mergen von Änderungen lästig hoch sein, aber wenn etwas einmal aufgenommen und unterstützt ist, wird es langfristig gepflegt
Es ist wie der Unterschied zwischen Kaufen und Mieten: Es kostet deutlich mehr Entwicklungszeit, Unterstützung in GCC hineinzubekommen, aber wenn sie einmal drin ist, bleibt sie
Zum Beispiel habe ich kürzlich erfahren, dass GCC bei RISC-V das RV32E-Target unterstützt, LLVM aber nicht
Als ich zuletzt nachgesehen habe, funktionierte eigenständiges C-Compiling in GCC noch
Dass gccrs keine besondere Sprache namens „GNU Rust“ schaffen will, sondern versucht, die Ausgabe von
rustcbis hin zu Bugs und Eigenheiten nachzubilden, halte ich aus Erfahrung für einen großen FehlerRust hat keine Spezifikation, es gibt zwar Referenzdokumente, aber sie sind ausdrücklich nicht normativ
Eine Sprache, die außer durch eine einzelne Referenzimplementierung nicht dokumentiert ist, hat langfristig eine Schwäche
Das Ziel, sicherzustellen, dass bestehender Code auf beiden Implementierungen läuft, ist vernünftig; aber wenn man sogar Bug-Kompatibilität verspricht, versteinert man falsche Entscheidungen und Bugs
Microsoft setzt viel Personal ein, um alte Programme weiter lauffähig zu halten und zugleich Sicherheits- und Zuverlässigkeitsfehler zu beheben; Rust muss sich diese Last nicht schon früh in seiner Lebensdauer aufbürden
Wenn man die Sprache weiterentwickeln will, muss man Qualitätssicherung und Qualitätskontrolle akzeptieren
Qualität lässt sich nicht nachträglich durch Tests hineinprüfen; man muss sie durch Architektur und Design sowie durch Prozesse wie Design- und Code-Reviews so anlegen, dass Dinge korrekt funktionieren und, wenn sie scheitern, in die richtige Richtung scheitern
Starke Standards wie Common Lisp, C++ und FORTRAN haben diese Überzeugung übernommen, und schwächere Sprachen, die faktisch einem Standard nahekommen, wie Python, können zwar populär werden, aber dass Veränderungen schwierig sind, zeigte sich am langen Übergang von Python 2 zu 3 und an der geringen Zahl von Implementierungen
Ich komme spät in diesem Thread dazu, aber das muss nicht unbedingt eine gute Sache sein
Distributionen kommen Sprachen, die alle paar Monate neue Versionen veröffentlichen, nicht hinterher, sodass es ohnehin schon schwierig ist,
rustcoder Go als Distributionspakete zu verwendenHeute gibt es erstaunlicherweise Systeme, auf denen GCC nicht mehr gebraucht und entfernt wurde, während für Updates bestehender Software nur upstream Go und Rust gepflegt werden
Als ich vor ein paar Monaten wegen eines CVE Go aktualisierte, war es ein Albtraum zu sehen, dass Go-basierte Apps an vier verschiedenen Stellen ihre eigene Go-Umgebung abgelegt hatten
Linux kann man, wenn man will, bereits mit Clang kompilieren und damit eine vollständig LLVM-basierte Toolchain verwenden
Dieser doppelte Aufwand, das Ganze um der GNU-„Reinheit“ willen zu entwickeln und zu pflegen, wirkt nicht so, als wäre er es wert
Die ClangBuiltLinux-Community argumentierte, Linux dürfe nicht von einem einzelnen Compiler abhängen; als Rust dazukam, fanden viele derselben Leute plötzlich, ein einzelner Compiler sei doch in Ordnung
Es geht nicht darum, den Kernel exklusiv an GNU zu binden, sondern nur darum, eine reine GNU-Toolchain wählen zu können