Rust: Verknüpfung mit LLD

Erstellt am 17. Feb. 2017  ·  94Kommentare  ·  Quelle: rust-lang/rust

LLVM 4.0 wird mit aktiviertem LLD ausgeliefert, obwohl AFAIK es noch nicht auf allen Plattformen produktionsbereit ist. Ich glaube, wir haben in Kürze ein LLVM-Upgrade geplant, um AVR/Emscripten-Probleme zu beheben übliche Linker und auf welchen Plattformen wir sie möglicherweise standardmäßig aktivieren möchten.

Aktueller Stand (2020-04-24) zusammengefasst unter https://github.com/rust-lang/rust/issues/39915#issuecomment -618726211

A-linkage C-feature-request I-compiletime T-compiler

Hilfreichster Kommentar

Dieser Fehler ist ein bisschen durcheinander, daher ist hier meine beste Chance für eine kurze Zusammenfassung der aktuellen Situation für Leute, die dies voranbringen möchten.

Was ist lld

Ein Linker, der Teil des llvm-Projekts ist, was aus zwei Gründen wünschenswert ist:

  • es ist sehr freundlich zu Cross-Kompilierung (daher die Betonung für eingebettete Ziele)
  • es ist sehr schnell (läuft oft in der Hälfte der Zeit wie Gold -- das Verlinken kann bei großen Projekten (Rustc, Servo usw.) mehrere Minuten dauern und das Verlinken kann einen großen Prozentsatz der Kompilierung mit inkrementellen Builds ausmachen, daher ist eine Halbierung dieser Laufzeit ein Große Sache.)

Was Rust heute mit lld macht

  • Rust liefert derzeit auf den meisten Plattformen eine eigene Kopie von lld als Binärdatei aus, die es rust-lld nennt
  • rust-lld wird standardmäßig auf vielen Bare-Metal-Zielen verwendet
  • rust-lld wird standardmäßig für wasm verwendet
  • (?) Sie können explizit anfordern, dass rust-lld verwendet wird, indem Sie "-C linker-flavor" verwenden (unscharf, was genau dies auf Nicht-Bare-Metal-Plattformen bewirkt, siehe unten)

Probleme bei der Verwendung von rust-lld an mehreren Stellen (zB Desktop-Linux/Mac/Windows)

  • Das macOS (Mach-O) Backend für lld ist kaputt und aufgegeben

    • ein Umschreiben von Grund auf hat begonnen, aber es ist noch am Anfang

  • Auf Linux/Unix-Plattformen sollten Sie ld/lld nicht direkt aufrufen. Sie sollen den Linker über Ihren System-C-Compiler (zB gcc) aufrufen, dessen Aufgabe es ist, Systemsymbole wie crt1.o zu entdecken und sie ld zur Verfügung zu stellen. Das bedeutet, dass wir nicht "nur" rust-lld verwenden können; wir müssen es in gcc/clang/was auch immer einspeisen. (wir wollen diese Systemsymbollogik nicht selbst implementieren)

    • Im Allgemeinen können Sie den Linker nicht als Pfad angeben, sondern müssen ihn als "ld" in den Suchpfad des C-Compilers einfügen.

    • Alternativ können Sie dasselbe tun, aber als "ld.lld" injizieren und "-fuse-ld=lld" übergeben.



      • Dies kann wichtig sein, anscheinend führt lld eine binäre Namenserkennung im Clang-Stil durch, ob sie als "ld" oder "ld.lld" ausgeführt wird (muss untersucht werden).


      • Leider ist -fuse-ld=lld nur ein Teil von GCC 9, daher benötigen wir möglicherweise eine Feature-/Versionserkennung, um es zu verwenden (clang hat es schon lange).



  • windows-msvc ist anscheinend in gutem Zustand und scheint eine begrenzte Unterstützung für die Verwendung von rust-lld im Backend zu haben, aber mir ist unklar, was hier getan werden muss.
  • windows-mingw scheint ungefähr an der gleichen Stelle wie linux/unix zu sein, außer dass Sie wahrscheinlich einen alten GCC bekommen, und die Dinge sind ein bisschen skurril, weil Pseudo-windows-linux nicht gerade eine gut getestete Konfiguration ist?

Auch allgemein ist lld neuer, es ist nicht die Standardeinstellung für die meisten Betriebssysteme. Es werden mit ziemlicher Sicherheit zufällige Compat-Bugs auftreten, wenn wir damit beginnen, es an mehr Stellen zu verwenden.

Ich habe zwei Metabugs für gezielte Bemühungen zur standardmäßigen Verwendung von (rust-)lld auf zwei Plattformen eingereicht:

  • #71515 - x64 Ubuntu 20.04 LTS (und allgemeiner alle x64 ELF-Plattformen)
  • #71520 - x64-msvc-Fenster

Alle 94 Kommentare

Siehe auch einen PoC in # 36120.

LLD kann ein sehr guter Kandidat für MinGW-Ziele sein, da wir derzeit sowieso einen Linker mit ihnen bündeln und der Linker von MinGW eine Vielzahl von Problemen hat, die von einem Mangel an ASLR bis hin zu keiner Bigobj-Unterstützung reichen. Wenn wir beim Cross-Kompilieren auch irgendwie die notwendigen mingw-Bibliotheken mitbringen können und nicht nur natives Targeting (auf das das mingw-Paket von rustup derzeit beschränkt ist), dann würde das die rust-Cross-Kompilierung von Linux out of the box ermöglichen, was eine enorme Verbesserung wäre über die bestehende Situation, in der Leute MinGW von ihrer Distribution bekommen und dann auf Probleme stoßen, weil Distributionen fast immer ein inkompatibles MinGW verwenden.

LLD ist aus mehreren Gründen kein guter Kandidat für das native Targeting von MSVC-Zielen, der Hauptgrund ist die fehlende Debuginfo-Unterstützung. Cross-Compiling auf MSVC-Ziele erfordert Bibliotheken, die nicht weiterverteilt werden können, daher können wir dies ohnehin nicht sofort unterstützen.

Das Tracking-Problem beim Upgrade auf LLVM 4.0 lautet https://github.com/rust-lang/rust/issues/37609 .

Für den Rekord ist lld definitiv nicht bereit für Solaris-Ziele. Aber unter Solaris gibt es keinen mir bekannten Grund, stattdessen lld anstelle des nativen ld zu verwenden. Wir haben uns bereits angesehen, was es braucht, damit rust Solaris ld auf Solaris verwendet, anstatt gcc zum Verlinken zu verwenden.

@binarycrusader Ein Grund, lld zu verwenden, ist das Erstellen für Solaris, nicht für Solaris.

PR rust-lang/rust#40018 fügt rustc ein -Z linker-flavor Flag hinzu, um die Verwendung von LLD als Linker zu ermöglichen. Diese PR bettet LLD nicht in Rustc ein, sondern erlaubt das Experimentieren außerhalb des Baumes.

@binarycrusader ^ Das kann bei Ihrem Experiment helfen, Solaris' ld anstelle von gcc direkt zu verwenden.

Wir scheinen jetzt auf LLVM 4.0 zu laufen. @japaric , bedeutet dies, dass das Linker-Flavor-Flag jetzt einfach verwendet werden kann, um LLD mit dem

@bstrie #40018 ist vor ein paar Wochen gelandet. Seitdem kann man -Z linker-flavor=ld -C linker=ld.lld , um eine externe LLD-Binärdatei als Linker zu verwenden. Beachten Sie, dass LLD im Gegensatz zu gcc nicht weiß, wo sich die Systembibliotheken befinden, sodass Sie den Bibliothekssuchpfad mit -C link-args='-L ...' an den Linker übergeben müssen, wenn Sie auf eine Systembibliothek verlinken.

Wobei LLVM 4.0 hilft, ist das Zusammenführen von LLD in rustc. Mit dieser Änderung würden wir in einigen Szenarien wie dem Verknüpfen von MUSL-Binärdateien oder Bare-Metal-Programmen keinen externen Linker benötigen. Ich sage einige Szenarien, weil die meisten Ziele eine Verknüpfung mit Systembibliotheken erfordern, bei denen Sie auf das oben erwähnte Problem mit dem Bibliothekssuchpfad stoßen. Für diese Ziele funktioniert LLD nicht sofort. Es ist nicht klar, wie und wo dieses Problem zu lösen ist und ohne eine Lösung dafür können wir für die wichtigsten (Tier 1) Ziele nicht auf LLD umsteigen, was die Attraktivität der Einbettung von LLD in rustc von vornherein verringert.

@japaric Was sind die Argumente gegen das Einbetten von Suchpfaden (sysroot-relative Bibliothek) sowie von Dingen wie -lc -lpthread crt0.o direkt in rustc? Schließlich muss eine Komponente der Toolchain sie einbetten, da wir keinen Standard für die folgenden Plattformen haben und binutils keine gute goldene Quelle für dieses Wissen ist.

Der einzige Nachteil, den ich mir vorstellen kann, ist die Situation, in der dasselbe Triple auf verschiedenen Systemvarianten unterschiedliche Suchpfade haben würde (was wahrscheinlich ausschließlich für Linux/glibc-Triples gilt und insbesondere auf Plattformen mit Multilib schlecht ist). In diesem Fall glaube ich, dass Clang den Betriebssystemnamen ausspioniert und betriebssystemspezifische Konventionen festcodiert, was schlecht erscheint, aber wahrscheinlich unvermeidlich ist, wenn man eine einzelne Binärdatei verteilen möchte, die auf jedem Linux läuft (und den Systemlinker nicht benötigt).

@retep998 Ich habe mir lld vor ein paar Monaten kurz angesehen. Ich war nicht in der Lage, eine .exe von Linux zu kompilieren (querverknüpfen?). Es schien, als würde lld nur plattformnative Formate unterstützen.

Hoffentlich irre ich mich.

Dies wird als Performance-Bug bezeichnet, da es laut den Benchmarks von LLD GNU ld um den Faktor zehn zu übertreffen scheint und die Link-Performance derzeit eine große Komponente der Compiler-Geschwindigkeit ist.

Äh, vergessen die Benchmarks zu verlinken: https://lld.llvm.org/#performance

(Heute relevant, da LLVM 5.0 gerade veröffentlicht wurde.)

Die Verknüpfung mit LLD ist viel schneller als bfd oder gold, aber ich bezweifle, dass die Verwendung die Gesamtleistung erheblich verbessert. Dennoch denke ich, dass dieses Thema wichtig ist und Priorität haben sollte.

@tpimh Ich bin mir eigentlich nicht ganz sicher, ob das I-slow-Tag Laufzeit-Leistungsfehler oder Kompilierzeit-Leistungsfehler darstellen soll, ich hatte es als letzteres beabsichtigt. Und wenn ich mir die Time-Passes-Ausgabeverknüpfung ansehe, befindet sich IME normalerweise in den drei längsten Phasen, deutlich länger als die meisten, so dass selbst eine Halbierung der Verknüpfungszeit wahrscheinlich ein großer Gewinn wäre (insbesondere für große Dinge wie Servo und Rustc).

@bstrie I-slow ist für schlechte Laufzeitleistung, I-compiletime ist für Compiler-Perf, als ich das letzte Mal überprüft habe

Gute Nachrichten für alle, die sich für das obskure Thema Crosslinking von Linux zu Windows interessieren. Ich sagte vorhin, dass es mit lld nicht möglich ist, aber das gilt nur für den ld-Geschmack von lld. Dies ist für die link.exe-Variante von lld (lld-link) möglich.

Speziell für Rust können wir dies heute mit ein paar Codeänderungen tun.

  1. Wir müssen eine sehr kleine Teilmenge der CRT von mingw-w64 in .o-Objektdateien kompilieren. Nämlich einige Thread-Local-Storage-Init. Wir brauchen auch chkstk.

  2. lld mag die üblichen Importbibliotheken von MinGW nicht. Stattdessen müssen wir die .def-Dateien selbst in .lib-Dateien erstellen, indem wir lld-link oder llvm-dlltool verwenden

  3. Ändern Sie lld, um IMPORT_NAME_NOPREFIX so zu behandeln wie
    IMPORT_NAME_UNDECORATE, denn auch bei Schritt 2 sind die .libs nicht perfekt

  4. Ändern Sie Rusts seh.rs, um TYPE_INFO_VTABLE durch ptr::null() zu ersetzen. Erforderlich, da das Symbol ??_7type_info@@6B@ in MinGW nicht definiert ist. Dann bauen und installieren Sie Rust.

  5. Verwenden Sie .cargo/config, um ein benutzerdefiniertes Wrapper-Skript als Linker anzugeben.

  6. Unser Wrapper-Linker-Skript sollte lld-link hauptsächlich mit den übergebenen Parametern aufrufen. Allerdings müssen wir ein paar Anpassungen vornehmen:

    a) Korrigieren Sie die Groß-/Kleinschreibung des Dateinamens, z. B. ändern Sie AdvAPI32.Lib in advapi32.lib

    b) Ändern Sie die .def-Datei, die Rust erzeugt, um Symbole mit einem zusätzlichen Unterstrich voranzustellen

    c) Überschreiben Sie den Einstiegspunkt (/entry). Erforderlich wahrscheinlich aufgrund eines Namensfehlers.

    d) Hängen Sie die mingw-crt-Objektdateien an, die Sie in Schritt 1 kompiliert haben

  7. Erstellen Sie Ihr Rust-Projekt mit xargo --target=i686-pc-windows-msvc

Wenn ich die obigen Schritte ausführe, kann ich Rust-Code querkompilieren. Ich kann sogar in Panik geraten und Panik fangen, wenn ich Rusts SEH-basiertes Abwickeln verwende.

@iainnicol Sie mischen das msvc-Ziel mit MinGW-Bits, weshalb Sie all diese seltsamen Modifikationen vornehmen müssen. Wenn Sie nur die Bibliotheken von einer bestehenden VC++-Installation kopieren, können Sie lld-link normal ohne all diese Modifikationen oder MinGW-Bits verwenden.

Aber ich möchte nicht über eine vorhandene VC ++ Installation verwenden. Es gibt nicht einmal eine Möglichkeit, eine zu bekommen, ohne etwa acht Stunden damit zu verbringen, Junk herunterzuladen und zu installieren, geschweige denn, sie weiterzuverteilen.

Die eigenständigen Build-Tools sind viel leichter, es sei denn, Sie meinen das bereits. In diesem Fall sollten wir vielleicht etwas Arbeit in die Verbesserung oder Neuerstellung von MinGW investieren, damit es tatsächlich mit MSVC kompatibel ist.

Die eigenständigen Build-Tools sind viel leichter

Ich habe nicht bemerkt, dass Microsoft diese verteilt. Könntest du sie verlinken? Gibt es eine vernünftige Möglichkeit, das Installationsarchiv zu extrahieren, ohne es tatsächlich auszuführen, dh ist es ein MSI oder etwas Ähnliches?

Hier sind sie: http://landinghub.visualstudio.com/visual-cpp-build-tools

Sowohl die 2015er als auch die 2017er Version sind Exes, aber Sie können die 2017er Exe davon überzeugen, Ihnen das zu geben, was Sie wollen, indem Sie Folgendes tun: https://docs.microsoft.com/en-us/visualstudio/install/install-vs- inkonsistentes-Qualitäts-Netzwerk

Wenn wir dies für Windows wirklich richtig machen wollen, benötigen wir zunächst https://github.com/rust-lang/rust/issues/30027 , um das Windows SDK oder die Importbibliotheken von MinGW überflüssig zu machen. Dann müssten wir nur noch die CRT-Bits durch unsere eigenen reinen Rust-Versionen ersetzen (Mathematik-/Speicherfunktionen, Einstiegspunkt, ein paar andere Laufzeit-Bits, die Rust benötigt) und wir hätten eine vollständig eigenständige Rust-Toolchain, die das kann Erstellen Sie Windows-Binärdateien! Der Nachteil dabei ist, dass Sie C/C++-Code nicht statisch verknüpfen können, da dies sehr stark von der Verknüpfung in der entsprechenden CRT von MinGW oder VC++ abhängt. Natürlich besteht der ganze Sinn von Rust darin, alles in Rust neu zu schreiben, also ist dies nicht wirklich ein Problem.

Gute Nachrichten für alle, die sich für das obskure Thema Crosslinking von Linux zu Windows interessieren. Ich sagte vorhin, dass es mit lld nicht möglich ist, aber das gilt nur für den ld-Geschmack von lld. Dies ist für die link.exe-Variante von lld (lld-link) möglich.

Sieht so aus, als ob es jetzt auch mit der ld-Variante möglich sein sollte: https://reviews.llvm.org/rL312926

Der MinGW-kompatible Treiber des neuen lld ist ein Wrapper für den lld-Link-Linker. Es übersetzt intern Unix-ähnliche Optionen in Windows-ähnliche Optionen und ruft dann den Einstiegspunkt von lld-link auf. Ich bin mir nicht sicher, ob ihr es verwenden wollt, denn (außer dass der Wrapper-Treiber unvollständig und nicht einsatzbereit ist) scheint es die Dinge nicht einfacher zu machen, es sei denn, ihr habt bereits Makefiles für MinGW.

Ich habe eine (wahrscheinlich dumme) Frage an euch zum Thema Cross-Compilation. Unter Windows haben alle dllimportierten Symbole DLL-Namen, aus denen sie importiert werden. Wenn Sie keine MSVC-Bibliotheksdateien haben, woher wissen Sie dann, aus welchen Dateien dllimportierte Symbole importiert werden?

Ich habe eine (wahrscheinlich dumme) Frage an euch zum Thema Cross-Compilation. Unter Windows haben alle dllimportierten Symbole DLL-Namen, aus denen sie importiert werden. Wenn Sie keine MSVC-Bibliotheksdateien haben, woher wissen Sie dann, aus welchen Dateien dllimportierte Symbole importiert werden?

Wenn Sie keine Importbibliotheken haben, müssen Sie entweder Importbibliotheken erstellen oder https://github.com/rust-lang/rust/issues/30027 implementieren, damit winapi alles tun kann Arbeit, zu spezifizieren, aus welcher DLL jedes Symbol kommt, zusammen mit Verrücktheit wie Ordinalzahlen. Etwas muss die Zuordnung von Symbolen zur Linkzeit zu Symbolen/Ordinalzahlen in DLLs spezifizieren, seien es Importbibliotheken oder Anmerkungen in Ihrem Code.

Nachdem ich https://reviews.llvm.org/rL311734 eingezogen habe, bin ich fast in der Lage, rustc mit lld auf macOS zu booten. Es scheint ein Problem mit Dylib-Metadaten zu geben, das ich noch untersuchen muss.

Ich habe einen Zweig, der https://github.com/rust-lang/rust/pull/36120 wiederbelebt https://github.com/rust-lang/rust/issues/43370 blockiert

@tamird : #43370 wurde geschlossen.

LLD wurde in https://github.com/rust-lang/rust/pull/48125 hinzugefügt und wird jetzt mit Tier-1-Plattformen (Mac, Linux, Windows) ausgeliefert. Sie können es mit -Z linker-flavor für jede Plattform testen, obwohl es unwahrscheinlich ist, dass es standardmäßig für die meisten Plattformen funktioniert. Es funktioniert jedoch standardmäßig auf MSVC. Zum Beispiel:

$ RUSTFLAGS='-Z linker-flavor=lld-link' cargo build

Die Verbindungszeit von Cargo wurde von 2,5s auf 1,5s reduziert, eine schöne Verbesserung!

@alexcrichton , was sind die nächsten Schritte? Im Idealfall würde LLD standardmäßig auf allen Plattformen funktionieren (ich habe keine Ahnung, wie viel Arbeit dies erfordern wird), und dann würde ich gerne Kompilierungs-/Laufzeit-Benchmarks ausführen, um zu sehen, ob es sinnvoll ist, LLD als Standard zu verwenden irgendwelche Plattformen. Insbesondere bei inkrementeller Kompilierung wird die Linking-Performance wichtiger denn je.

Insbesondere bei inkrementeller Kompilierung wird die Linking-Performance wichtiger denn je.

Es ist eine Schande, dass die Verlinkungsleistung immer noch nicht wichtig genug für uns ist, um Dinge wie die inkrementelle Verlinkung auf Plattformen zu ermöglichen, die dies unterstützen. https://github.com/rust-lang/rust/issues/37543

@bstrie Ich nehme an, das sind die nächsten Schritte, damit es auf anderen Plattformen funktioniert :)

Was das bedeutet, bin ich mir nicht sicher, aber es funktioniert bereits auf MSVC, ich denke, es ist weit davon entfernt, auf MinGW/Linux zu funktionieren, und wir sind ziemlich nahe an OSX. Was die architekturübergreifende Unterstützung angeht, bin ich mir auch nicht sicher. Ich erwarte nicht, dass wir es in naher Zukunft für etwas anderes als die Wasm-Plattform "stabilisieren" werden.

@alexcrichton Darf ich fragen, wie Sie "Stabilisieren" angeben würden? Warum wäre es nicht möglich, die Verknüpfung mit lld für die anderen großen Plattformen zu "stabilisieren", die Rost unterstützt? (zB Cross-Kompilieren einer ausführbaren Datei von Linux für macOS).

Im Moment ist das Cross-Kompilieren so mühsam, zum Beispiel erfordert die Arbeit, die zum Cross-Kompilieren einer ausführbaren Datei für macOS (x86_64-apple-darwin) von Linux erforderlich ist, nicht triviale Schritte wie den Erwerb des xcode-SDK und das Erstellen der gesamten Toolchain.

@cynecx eine gute Frage! Eine, über die ich nicht viel nachgedacht habe. Ich denke jedoch, wir wollen LLD nicht de facto stabilisieren, nur weil wir es für eine andere Plattform hinzugefügt haben. Es wird Zeit und Arbeit brauchen, um es richtig zu machen und es gut zu präsentieren.

Zum Beispiel erfordert die Arbeit, die erforderlich ist, um eine ausführbare Datei für macOS (x86_64-apple-darwin) unter Linux zu kompilieren, nicht triviale Schritte wie den Erwerb des xcode-SDK und das Erstellen der gesamten Toolchain.

LLD würde hier nicht wirklich helfen, Sie benötigen immer noch das Xcode-SDK, da es Header enthält, die Sie nicht weiterverteilen können (und je nachdem, was Sie erstellen, benötigen Sie auch andere SDK-Tools).

Das wirklich Schöne daran, dass LLD jetzt bei nightly integriert ist, ist, dass Sie mit RUSTFLAGS='-Z linker-flavor=ld.lld' cargo build --target x86_64-unknown-linux-musl reine Rust-Projekte von Windows nach Linux problemlos kompilieren können. Ideal zum Schreiben kleiner Tools für Linux-Rechner, auf denen Rust nicht einfach installiert werden kann.

Ich erwarte nicht, dass wir es in naher Zukunft für etwas anderes als die Wasm-Plattform "stabilisieren" werden.

Wie @rkarp sagte, sehr nahe daran sind, dass Rust dasselbe tun kann. In Bezug auf die tatsächliche Nutzung wette ich, dass LLD für x86_64-unknown-linux-musl viel breiter verwendet wird als wasm.

Allgemeiner gesagt, wenn es um Cross-Building geht, denke ich nicht, dass ein Ansatz "es muss für alle Hosts und/oder alle Ziele funktionieren" sinnvoll ist. Ich halte es für sinnvoll, dies von Ziel zu Ziel zu stabilisieren, wenn die Ziele zu arbeiten beginnen.

Insbesondere würde ich gerne bei den Bemühungen helfen, LLD für das x86_64-unknown-linux-musl-Ziel so schnell wie möglich zu stabilisieren.

Mein Projekt hat 37 Kisten und der Build verlinkt etwa 70 Binärdateien (viele Tests). Unwissenschaftlich (betrachtet top ) mindestens die Hälfte der Build-Zeit laufen wir nur mit ld. Ich gehe davon aus, dass die Verwendung von lld unsere Builds erheblich beschleunigen würde. Wir sind auf stabilem Rust und ich habe es noch nicht geschafft, lld 6.0 zum Laufen zu bringen.

@briansmith hast du LLD für musl und deinen Anwendungsfall getestet? Theoretisch müssten Sie nur -Z linker-flavor=ld.lld , um es zu testen, und wenn das funktioniert, scheint es plausibel, könnten wir die Standardeinstellungen ändern!

@rocallahan nur zur Bestätigung, ihr verwendet derzeit alle den -Z linker-flavor=ld.lld funktioniert (und schneller ist), dann könnten wir vielleicht versuchen, es zu stabilisieren! Auf welcher Plattform war das?

Unwissenschaftlich (auffällig oben) mindestens die Hälfte der Bauzeit laufen wir nur ld.

Das ist für einen Debug-Build BTW.

Sie verwenden derzeit alle den Goldlinker, oder? (als afaik ist es schneller als der Standard-Binutils-Linker)

Nein, das ist der Fedora-Systemlinker, der Standard-GNU-Linker.

Auf welcher Plattform war das?

Fedora 27, Quad-Core-Skylake-Laptop mit SSD. Ich werde einige Leistungszahlen bekommen.

Ah ok gut zu wissen! Debug-Builds werden wahrscheinlich den größten Nutzen in Bezug auf die Linkzeit aus Split Dwarf (https://github.com/rust-lang/rust/issues/34651) und nicht aus Linker-Verbesserungen ziehen.

Für Timing-Informationen, @rocallahan, wenn Sie einen zufälligen Gedankentest mit ld.gold und ld.lld ?

Sicher. Ich sollte auch daran erinnern, dass Ausgabe Nr. 48762 eine sehr niedrig hängende Frucht ist, um die Linux-Debug-Link-Zeiten zu beschleunigen. (Wir verwenden bereits ein gehacktes Linker-Skript, das .debug_pubnames / .debug_pubtypes aus der ausführbaren Datei entfernt.)

Split DWARF kann gut sein, kann aber auch Probleme für Benutzer verursachen. Ich werde in dieser Ausgabe kommentieren.

@briansmith hast du LLD für musl und deinen Anwendungsfall getestet? Theoretisch müssten Sie zum Testen nur -Z linker-flavor=ld.lld übergeben, und wenn das funktioniert, scheint es plausibel, wir könnten die Standardeinstellungen ändern!

OK, ich werde die Dinge testen. Vielleicht sollte es anfangs einen Mittelweg zwischen "default" und "only on nightly" geben, eine Möglichkeit, LLD zu verwenden, wie wir es mit -Z , aber ohne -Z damit es funktioniert in stabiler Bauweise.

aber ohne -Z zu verwenden, damit es in stabilen Builds funktioniert.

Sie können RUSTC_BOOTSTRAP=1 RUSTFLAGS="-Z linker-flavor=foo" cargo build versuchen

Bitte empfehlen wir das Bootstrap-Flag nicht? Ich mache mir Sorgen, dass die Dinge de-facto stabil werden, wenn sich genügend Projekte darauf verlassen, was den Sinn des gesamten Stabilitätsmechanismus zunichte macht.

Entschuldigung =/

Als Datenpunkt ist das Verknüpfen der rustc_trans Kiste im Rust-Repository selbst von 78s auf 1s Verbindungszeit auf meinem lokalen Computer gesunken.

Meine Leistung resultiert aus einer Whitespace-Änderung zu einer Crate am unteren Ende unserer Crate-Hierarchie. Quad-Core-Skylake-Laptop, 16 GB RAM, Rustc 1.24.0, LLD 7.0.0, GNU ld 2.29-13. Wir verwenden ein benutzerdefiniertes Linker-Skript, das .debug_pubnames und .debug_pubtypes verwirft; LLD verwendet ganz andere Codepfade, wenn ein Linker-Skript vorhanden ist, sodass dies Auswirkungen haben kann.

GNU-ld:

real    2m39.138s
user    8m18.992s
sys 1m37.513s

LLD:

real    2m19.164s
user    6m4.477s
sys 0m56.858s

Gold hat nicht funktioniert, es hat in unserem Linker-Skript gekotzt. Die Ergebnisse sind relativ stabil. LLD hat keinen großen Einfluss auf die End-to-End-Zeit, reduziert jedoch die CPU-Auslastung erheblich. Ich denke, das bedeutet, dass unser Build nicht viel Zeit damit verbringt, auf die Fertigstellung von lds zu warten, aber es verbraucht viel CPU-Zeit, um sie auszuführen.

Siehe #50584 für ein Beispiel aus der Praxis, bei dem der Wechsel von GNU ld zu lld dazu führt, dass eine übliche "geringfügige Änderung und Neuaufbau"-Workload mehr als 2,5x schneller ausgeführt wird.

Äh https://github.com/rust-lang/rust/issues/50584#issuecomment-400918647 ist hier besser geeignet:


Der nächste Schritt zur Stabilisierung von LLD wäre, ein Flag wie -Z linker-flavor=lld zu erhalten, das für alle Ziele (Windows + Mac + Linux) funktioniert. Es würde tun, was immer es tun muss, um auf den verschiedenen Plattformen zu funktionieren.

Sobald dies erledigt ist, können wir es in der Community bewerben und um Feedback bitten. Hier können wir sowohl Timing-Informationen als auch Fehlerberichte erhalten, die wir an LLD senden können. Wenn alles glatt geht (was bei einem ganz neuen Linker zweifelhaft ist, aber hey, man weiß nie!), können wir ihn standardmäßig aktivieren, ansonsten können wir daran arbeiten, die Auswahl von LLD zu stabilisieren und dann eine Option zu Cargo hinzuzufügen. toml, damit Projekte sich zumindest dafür anmelden können.

Wir haben für einige Ziele auf lld umgestellt: https://rust-embedded.github.io/blog/2018-08-2x-psa-cortex-m-breakage/

Ich glaube auch für wasm?

Betrifft dieses Problem sowohl das Verknüpfen mit einer externen lld-Binärdatei als auch das Verknüpfen mit der internen lld-Unterstützung, die in Rustc selbst integriert ist? Oder nur ersteres?

Betrifft dieses Problem sowohl das Verknüpfen mit einer externen lld-Binärdatei als auch das Verknüpfen mit der internen lld-Unterstützung, die in Rustc selbst integriert ist? Oder nur ersteres?

Nur die externe lld-Binärdatei IIUC.

@nnethercote Gibt es ein anderes Problem bei der Verfolgung der Verwendung eines internen Linkers oder sollte ich dafür ein separates Problem einreichen?

Ich habe noch nie von der Idee mit dem internen Linker gehört. Mir ist keine PR dafür bekannt.

https://github.com/rust-lang/rust/pull/57514 bereitete den Boden für die Verwendung von LLD zum Verknüpfen von LLVM vor.

Vielleicht sollte es anfangs einen Mittelweg zwischen "default" und "only on nightly" geben, eine Möglichkeit, LLD zu verwenden, wie wir es mit -Z können, aber ohne -Z, damit es in stabilen Builds funktioniert.

https://github.com/rust-lang/rust/pull/56351 -C linker-flavor hinzugefügt.

Es ist nicht klar, was mit diesem Problem verfolgt werden soll. Es scheint, als wäre es besser, dies zu schließen, um bestimmte Probleme zu haben, z. B. "Link mit LLD für -msvc-Ziele, wenn die Toolchain von Microsoft nicht verfügbar ist".

Für mich geht es bei diesem Problem darum, LLD als Standardlinker für alle Ziele zu aktivieren. Ich würde das gerne haben, weil LLD extrem schnell ist und die Linkzeit oft ein wesentlicher Bestandteil der Kompilierzeit ist und die Kompiliergeschwindigkeit ein Dauerproblem ist.

FWIW Ich habe einen Fehler zur Unterstützung von LLD auf macOS in BMO eingereicht. Anscheinend ist das WONTFIX. Aus den dortigen Kommentaren geht hervor, dass es nicht so einfach ist wie "LLD ist extrem schnell", da die LLDs auf verschiedenen Plattformen unterschiedliche Programme sind und die auf macOS mit ins Stocken geratener Entwicklung kaputt sind.

Ich stimme mit

Ist die Verknüpfung mit LLD irgendwo dokumentiert? Ich habe (unter Linux) rustc -C linker-flavor=ld.lld hello.rs , aber ich habe kein Glück. Ich dachte, dass LLD mit unserer Kopie von LLVM verteilt wurde, liege ich falsch? Ich habe auch versucht, LLD über apt zu installieren, aber rustc ist immer noch mystifiziert. Welche Schritte müssen unternommen werden, um LLD heute mit Rust-Code auszuprobieren?

@bstrie Sie müssen zusätzlich das Argument -C linker=rust-lld .

Soll es mit Fracht funktionieren? Ich erhalte derzeit die folgenden Fehler, wenn ich versuche, ein leeres Projekt auf dem neuesten nächtlichen Build von Rost und Ladung zu erstellen.

$ RUSTFLAGS='-C linker=rust-lld' cargo build
   Compiling rust3 v0.1.0 (/home/carado/tmp/rust3)
error: linking with `rust-lld` failed: exit code: 1
  |
  = note: "rust-lld" "-flavor" "gnu" "-L" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.2ualxzb8lqn4ho3y.rcgu.o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.32vfyq64cfbzv618.rcgu.o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.4rbt3m5y8o8cl09t.rcgu.o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.ben0932xzwyt64v.rcgu.o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.fzsdnygvstiwzxo.rcgu.o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.x0rq6ifodcf11zi.rcgu.o" "-o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.1m259ox4uzrzk583.rcgu.o" "--gc-sections" "-pie" "-zrelro" "-znow" "-L" "/home/carado/tmp/rust3/target/debug/deps" "-L" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "--start-group" "-Bstatic" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-44988553032616b2.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-607feef6be9150b2.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libbacktrace-a8dbf6d92401e34a.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libbacktrace_sys-9a4716f5e8a3e722.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-988a64d96b043c6d.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-cadd6177b8c6d586.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-8f1d8efc92b45369.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-1e76014677816767.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-cc28bce38cb195d9.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-4123e9e89add689a.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-4d259c17788c1fb5.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-9495dbda85bb8f16.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-793d0026c575805f.rlib" "--end-group" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-33c3162edae6574e.rlib" "-Bdynamic" "-ldl" "-lrt" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-lutil"
  = note: rust-lld: error: unable to find library -ldl
          rust-lld: error: unable to find library -lrt
          rust-lld: error: unable to find library -lpthread
          rust-lld: error: unable to find library -lgcc_s
          rust-lld: error: unable to find library -lc
          rust-lld: error: unable to find library -lm
          rust-lld: error: unable to find library -lrt
          rust-lld: error: unable to find library -lpthread
          rust-lld: error: unable to find library -lutil
          rust-lld: error: unable to find library -lutil


error: aborting due to previous error

error: Could not compile `rust3`.

To learn more, run the command again with --verbose.

Ich bekomme die gleichen Fehler wie carado. Managed zu "Schuhanzieher" -L / usr / lib in den Linker Invokation aber das verkürzt nur die Liste der verpassten Libs zu -lgcc , die nicht überall im System vorhanden sind als libgcc (es gibt einen libgcc_s.a ) Ich vermute, dass dies ein Ergebnis von Gnuismus ist, kann aber nicht herausfinden, wie man es beheben kann.

@almindor versuche RUSTFLAGS='-C linker=rust-lld -L /usr/lib -L /usr/lib/gcc/x86_64-pc-linux-gnu/9.1.0' oder etwas Ähnliches. Der Pfad hängt von Ihrer Distribution und Compiler-Version ab.

Ist mein Kommentar oben der richtige Weg, um LLD zu verwenden? Ich kann es nicht zum Laufen bringen, da jedes Programm mit SIGSEGV abstürzt:

Reading symbols from target/debug/hello...
(gdb) show directories
Source directories searched: ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/etc:$cdir:$cwd
(gdb) r
Starting program: target/debug/hello 

Program received signal SIGSEGV, Segmentation fault.
core::ops::function::FnOnce::call_once{{vtable-shim}} () at /rustc/a7f28678bbf4e16893bb6a718e427504167a9494/src/libcore/ops/function.rs:231
(gdb) l
226     #[stable(feature = "fn_once_output", since = "1.12.0")]
227     type Output;
228 
229     /// Performs the call operation.
230     #[unstable(feature = "fn_traits", issue = "29625")]
231     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
232 }
233 
234 mod impls {
235     #[stable(feature = "rust1", since = "1.0.0")] 
(gdb) info reg
rax            0x0                 0
rbx            0x0                 0
rcx            0x0                 0
rdx            0x0                 0
rsi            0x0                 0
rdi            0x0                 0
rbp            0x0                 0x0
rsp            0x7fffffffddb0      0x7fffffffddb0
r8             0x0                 0
r9             0x0                 0
r10            0x0                 0
r11            0x0                 0
r12            0x0                 0
r13            0x0                 0
r14            0x0                 0
r15            0x0                 0
rip            0x7ffff7ffc000      0x7ffff7ffc000 <core::ops::function::FnOnce::call_once{{vtable-shim}}>
eflags         0x10202             [ IF RF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
(gdb) disassemble 
Dump of assembler code for function core::ops::function::FnOnce::call_once{{vtable-shim}}:
=> 0x00007ffff7ffc000 <+0>: mov    (%rdi),%rax
   0x00007ffff7ffc003 <+3>: mov    (%rax),%rdi
   0x00007ffff7ffc006 <+6>: jmpq   *0x11d4(%rip)        # 0x7ffff7ffd1e0
End of assembler dump.

Für alle, die hier landen, lautet die magische Beschwörung RUSTFLAGS="-C link-arg=-fuse-ld=lld" cargo build wenn Sie GCC 9 oder Clang als Compiler verwenden. Alternativ sollte -C linker=clang unabhängig von der GCC-Version funktionieren, daher wird es möglicherweise bevorzugt.

Um dies dauerhaft zu machen, können Sie es in einem bestimmten Projekt zu ~/.cargo/config oder .cargo/config hinzufügen:

[build]
rustflags = ["-C", "linker=clang"]
# rustflags = ["-C", "link-arg=-fuse-ld=lld"]

@lnicola Beachten Sie, dass es nur funktioniert, wenn GCC 9 oder Clang als CC verwendet wird.

@bstrie weißt du wie der aktuelle Stand ist? Was sind die Blocker, um damit voranzukommen?

@mati865 kennst du zufällig einen alternativen Aufruf für Leute mit einem älteren GCC?

@lnicola alle meine Plattformen haben Clang + GCC 9 und ich habe nicht untersucht, wie man es mit inkompatiblen Compilern verwendet.

@jonhoo Ich bin mit der Arbeit in diesem Bereich nicht auf dem Laufenden, ich nehme an, Sie möchten das Compiler-Team fragen.

Ich glaube nicht, dass ich Teams taggen kann, und ich möchte ihnen auch keinen unnötigen Lärm machen. Was ist Ihrer Meinung nach der beste Weg, um jemanden von dort dazu zu bringen, einen kurzen Blick darauf zu werfen?

Triage; @rust-lang/compiler kennt jemand den aktuellen Stand dieses Problems?

Für jeden hier, der es schafft, LLD mit Rust zum Laufen zu bringen, können Sie zusätzlich Details zu Ihrer Plattform und den spezifischen Versionen aller verwendeten Compiler angeben? Ich sehe immer noch, dass Leute in freier Wildbahn Probleme haben, es zum Laufen zu bringen, selbst mit den hier aufgeführten Ratschlägen.

Der oben gepostete Befehl funktioniert unter Linux mit GCC 9.2.0 und LLD 9.0.0. Ich denke, es funktioniert manchmal auch unter Windows, aber ich habe jemanden mit einem GCC 9 für Windows gesehen, der -fuse=lld nicht unterstützte. Unter MacOS ist es laut einigen hier geposteten Links keinen Versuch wert.

Für jeden hier, der es schafft, LLD mit Rust zum Laufen zu bringen, können Sie zusätzlich Details zu Ihrer Plattform und den spezifischen Versionen aller verwendeten Compiler angeben? Ich sehe immer noch, dass Leute in freier Wildbahn Probleme haben, es zum Laufen zu bringen, selbst mit den hier aufgeführten Ratschlägen.

cat /etc/system-release
Fedora-Version 30 (dreißig)

cc --version
cc (GCC) 9.2.1 20190827 (Red Hat 9.2.1-1)

ld.lld --version
LLD 8.0.0 (kompatibel mit GNU-Linkern)

Hoffentlich hilft das

aber ich habe jemanden mit einem GCC 9 für Windows gesehen, der -fuse=lld . nicht unterstützt

@lnicola
Windows GCC 9-Builds unterstützen -fuse-ld=lld (es sei denn, sie sind so gepatcht, dass sie es nicht unterstützen, aber warum sollte es jemand tun?).
Ich nehme an, dass die rust-mingw Komponente installiert wurde und der Linker in .cargo/config nicht überschrieben wurde. Auf diese Weise wählte rustc GCC 6, das es versendet, anstelle des Systems.

Ein weiteres Problem unter Windows ist das hartcodierte Linker-Flag --enable-long-section-names das LLD 9 und älter nicht unterstützen (es ist geplant, es in Zukunft zu unterstützen). Um dies zu umgehen, können Sie:

  • Wrapper erstellen, der diese Flagge entfernt
  • LLD patchen, um dieses Flag als No-Op zu akzeptieren
  • Verwenden Sie lokal gepatchte Rust-Builds, die dieses Flag nicht verwenden

Ein weiteres Problem unter Windows ist das hartcodierte Linker-Flag --enable-long-section-names, das LLD 9 und älter nicht unterstützen (es ist geplant, es in Zukunft zu unterstützen).

Dieser Teil wird behoben von: https://github.com/rust-lang/rust/pull/66257
Windows-Gnu-Benutzer müssen immer noch manuelle Arbeit verrichten, um den C-Compiler zu verwenden, der jedoch -fuse-ld=lld .

@bstrie : Dies funktioniert mit Stable und Nightly auf Windows-MSVC, Details im ersten Beitrag dieser gamedev-wg-Ausgabe: https://github.com/rust-gamedev/wg/issues/50

Ein weiterer Datenpunkt: Wenn Sie RUSTFLAGS="-C link-arg=-fuse-ld=lld" wenn Sie rustc selbst erstellen, sinkt die Linkzeit auf meiner schnellen 14-Kern-Linux-Box von 93 auf 41 Sekunden.

@nnethercote : Unterscheidet sich das von der Einstellung von linker=lld (zum Beispiel) im Abschnitt [target.x86_64-unknown-linux-gnu] von config.toml ?

@ Aaron1011 : Ich vermute, dass die beiden Ansätze den gleichen Effekt haben, aber ich habe dies nicht selbst überprüft.

@mati865
Haben Sie versucht, rustc auf x86_64-pc-windows-gnu mit LLD als Linker aufzubauen?

Ich habe es heute ausprobiert und LLD bleibt entweder mitten im Build hängen und macht keine Arbeit mehr oder beschwert sich über unknown argument: --version-script=... .
Das Aufhängen tritt auch auf, wenn LLD nur zum Verknüpfen von LLVM verwendet wird, mit

[llvm]
use-linker = "lld"

Werkzeugversionen:

$ ld.lld --version
LLD 9.0.1 (https://github.com/msys2/MINGW-packages.git 5e3b8820ed9f04221affee4197e458aca2612e87) (compatible with GNU linkers)

$ gcc --version
gcc.exe (Rev2, Built by MSYS2 project) 9.2.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

@petrochenkov ja, ich könnte es mit ein paar Hacks bauen:

Ich schreibe hier einige zukünftige Möglichkeiten auf. Obwohl einige Implementierungsbemühungen erforderlich sind, denke ich, dass diese dazu beitragen werden, einige langjährige Probleme bei der Entwicklung von Rust zu lösen:

  • Anstatt das extern bereitgestellte lld zu verwenden, erstellen und verwenden Sie es als statische Bibliotheken in rustc. Dies ermöglicht eine engere Integration in Rustc selbst, verbessert die Out-of-Box-Erfahrung und eröffnet zukünftige Möglichkeiten.
  • Anstatt viele Pfadnamen als Linker-Befehl an lld zu übergeben, verwenden Sie ein virtuelles Dateisystem und übergeben Sie diese Daten von Speicher zu Speicher, anstatt Festplatten-IO zu verwenden, wenn genügend Speicherplatz vorhanden ist. Bei größeren Projekten kann dies Hunderte oder sogar Tausende Megabyte an Festplatten-E/A einsparen und somit die Kompilierungszeit verbessern.

Anstatt viele Pfadnamen als Linker-Befehl an lld zu übergeben, verwenden Sie ein virtuelles Dateisystem und übergeben Sie diese Daten von Speicher zu Speicher, anstatt Festplatten-IO zu verwenden, wenn genügend Speicherplatz vorhanden ist. Bei größeren Projekten kann dies Hunderte oder sogar Tausende Megabyte an Festplatten-E/A einsparen und somit die Kompilierungszeit verbessern.

Es geht nicht nur um die IO-Bandbreite. Auf Plattformen wie Windows, insbesondere wenn Windows Defender aktiviert ist, fügt jede Datei, mit der Sie arbeiten möchten, einen ziemlich erheblichen Zeitaufwand hinzu, und das Codegen-Einheitenmodell von Rust bedeutet, dass Kisten in Hunderte von winzigen Objektdateien aufgeteilt werden, die schnell eine Menge Kompilierung verursachen können Zeit.

Dieser Fehler ist ein bisschen durcheinander, daher ist hier meine beste Chance für eine kurze Zusammenfassung der aktuellen Situation für Leute, die dies voranbringen möchten.

Was ist lld

Ein Linker, der Teil des llvm-Projekts ist, was aus zwei Gründen wünschenswert ist:

  • es ist sehr freundlich zu Cross-Kompilierung (daher die Betonung für eingebettete Ziele)
  • es ist sehr schnell (läuft oft in der Hälfte der Zeit wie Gold -- das Verlinken kann bei großen Projekten (Rustc, Servo usw.) mehrere Minuten dauern und das Verlinken kann einen großen Prozentsatz der Kompilierung mit inkrementellen Builds ausmachen, daher ist eine Halbierung dieser Laufzeit ein Große Sache.)

Was Rust heute mit lld macht

  • Rust liefert derzeit auf den meisten Plattformen eine eigene Kopie von lld als Binärdatei aus, die es rust-lld nennt
  • rust-lld wird standardmäßig auf vielen Bare-Metal-Zielen verwendet
  • rust-lld wird standardmäßig für wasm verwendet
  • (?) Sie können explizit anfordern, dass rust-lld verwendet wird, indem Sie "-C linker-flavor" verwenden (unscharf, was genau dies auf Nicht-Bare-Metal-Plattformen bewirkt, siehe unten)

Probleme bei der Verwendung von rust-lld an mehreren Stellen (zB Desktop-Linux/Mac/Windows)

  • Das macOS (Mach-O) Backend für lld ist kaputt und aufgegeben

    • ein Umschreiben von Grund auf hat begonnen, aber es ist noch am Anfang

  • Auf Linux/Unix-Plattformen sollten Sie ld/lld nicht direkt aufrufen. Sie sollen den Linker über Ihren System-C-Compiler (zB gcc) aufrufen, dessen Aufgabe es ist, Systemsymbole wie crt1.o zu entdecken und sie ld zur Verfügung zu stellen. Das bedeutet, dass wir nicht "nur" rust-lld verwenden können; wir müssen es in gcc/clang/was auch immer einspeisen. (wir wollen diese Systemsymbollogik nicht selbst implementieren)

    • Im Allgemeinen können Sie den Linker nicht als Pfad angeben, sondern müssen ihn als "ld" in den Suchpfad des C-Compilers einfügen.

    • Alternativ können Sie dasselbe tun, aber als "ld.lld" injizieren und "-fuse-ld=lld" übergeben.



      • Dies kann wichtig sein, anscheinend führt lld eine binäre Namenserkennung im Clang-Stil durch, ob sie als "ld" oder "ld.lld" ausgeführt wird (muss untersucht werden).


      • Leider ist -fuse-ld=lld nur ein Teil von GCC 9, daher benötigen wir möglicherweise eine Feature-/Versionserkennung, um es zu verwenden (clang hat es schon lange).



  • windows-msvc ist anscheinend in gutem Zustand und scheint eine begrenzte Unterstützung für die Verwendung von rust-lld im Backend zu haben, aber mir ist unklar, was hier getan werden muss.
  • windows-mingw scheint ungefähr an der gleichen Stelle wie linux/unix zu sein, außer dass Sie wahrscheinlich einen alten GCC bekommen, und die Dinge sind ein bisschen skurril, weil Pseudo-windows-linux nicht gerade eine gut getestete Konfiguration ist?

Auch allgemein ist lld neuer, es ist nicht die Standardeinstellung für die meisten Betriebssysteme. Es werden mit ziemlicher Sicherheit zufällige Compat-Bugs auftreten, wenn wir damit beginnen, es an mehr Stellen zu verwenden.

Ich habe zwei Metabugs für gezielte Bemühungen zur standardmäßigen Verwendung von (rust-)lld auf zwei Plattformen eingereicht:

  • #71515 - x64 Ubuntu 20.04 LTS (und allgemeiner alle x64 ELF-Plattformen)
  • #71520 - x64-msvc-Fenster

windows-msvc ist anscheinend in gutem Zustand und scheint eine begrenzte Unterstützung für die Verwendung von rust-lld im Backend zu haben, aber mir ist unklar, was hier getan werden muss.

LLD + windows-msvc befindet sich in einem ziemlich guten Zustand, ich verwende dieses Setup derzeit für die Entwicklung von rustc .

Die gesamte erforderliche Unterstützung für lld-link ist im rustc Backend vorhanden, aber es gibt Fehler wie https://github.com/rust-lang/rust/issues/68647.

  • Dies kann wichtig sein, anscheinend führt lld eine binäre Namenserkennung im Clang-Stil durch, ob sie als "ld" oder "ld.lld" ausgeführt wird (muss untersucht werden).

das tut es, aber ld und ld.lld sind derselbe Modus: https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-02-05/lld/tools/lld/lld. cpp (gleich seit 8.0-2019-01-16)

  • Leider ist -fuse-ld=lld nur ein Teil von GCC 9, daher benötigen wir möglicherweise eine Feature-/Versionserkennung, um es zu verwenden (clang hat es schon lange).

da ld.lld dasselbe wie ld ist und laut https://patches-gcc.linaro.org/patch/11148/ die einzige Änderung mit -fuse-ld=lld darin besteht, ld.lld anstelle von ld auszuführen, wenn Wir verwenden die PATH-Injektion, es sollte in Ordnung sein. Ich denke, es ist nicht gut, dies auf gcc 9+ auszuschließen: Debian Stable hat nur 8.3 und Bullseye wird wahrscheinlich erst 2021 veröffentlicht.

  • windows-mingw scheint ungefähr an der gleichen Stelle wie linux/unix zu sein, außer dass Sie wahrscheinlich einen alten GCC bekommen, und die Dinge sind ein bisschen skurril, weil Pseudo-windows-linux nicht gerade eine gut getestete Konfiguration ist?

mingw-w64 6.0.0, veröffentlicht am 16.09.2018, hat gcc 8.3.0, das nicht -fuse-ld=lld hat, aber noch relativ neu ist. mingw-w64 7.0.0, veröffentlicht am 11.11.2019, hat gcc 9.3.0, das -fuse-ld=lld hat. Debian Buster (stable) hat 6.0.0, Bullseye (Testing) hat 7.0.0. Debian stretch (oldstable) hat nur 5.0.1 mit gcc 6.3.0, aber ich denke, es wäre vernünftig, das neueste Debian Stable für die lld-Unterstützung zu benötigen, wenn es erhebliche Probleme mit gcc 6.3 gibt.

Ich habe zwei Metabugs für gezielte Bemühungen zur standardmäßigen Verwendung von (rust-)lld auf zwei Plattformen eingereicht:

  • #71515 - x64 Ubuntu 20.04 LTS (und allgemeiner alle x64 ELF-Plattformen)
  • #71520 - x64-msvc-Fenster

Über die macOS-Portierung (Mach-O) von lld: Es scheint zu funktionieren oder zumindest in einem deutlich besseren Zustand zu sein, seit https://github.com/rust-lang/rust/issues/39915#issuecomment -618726211 wurde geschrieben!

Mit diesem LLVM-Commit habe ich lld und als projektspezifischen Linker für tokio-rs/tracing festgelegt . Ich habe dann die Ablaufverfolgung für nightly-x86_64-apple-darwin und alle Tests erfolgreich ausgeführt. Besonders freue ich mich über die (Debug-)Buildzeiten:

  • Mit ld cargo build dauerte ein sauberes
  • Mit lld cargo build dauerte ein sauberes

Beachten Sie, dass:

  • diese Leistungszahlen stammen von einem aktuellen MacBook Pro mit 32 GB RAM und einem 8-Core i9, und
  • für lld und mach-O gibt es noch einige offene probleme.

@davidbarsky Cool! Aus Neugier, wie ist diese Leistung im Vergleich zu zld ? ( https://github.com/michaeleisel/zld )

Hast du auch die Thermik berücksichtigt? MBPs gehen sehr schnell in thermisches Throttling über, insbesondere mit dem standardmäßigen Lüftergeschwindigkeitsprofil. Warten Sie einfach, bis sich die Unterseite der Maschine in der Nähe des Scharniers kühl anfühlt, bevor Sie einen Lauf ausführen, um die Konsistenz zu verbessern.

Ich habe gerade so einen Fehler unter Ubuntu 16 i686

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen