So geben Sie einen alternativen Linker-Befehl an, wenn Sie mit „cc“ verknüpfen

Lesezeit: 10 Minuten

Juans Benutzeravatar
Juan

Wenn Sie verwenden cc(1) Um ein Programm zu verknüpfen, wird ein Standard-Linker-Befehl aufgerufen. Beispielsweise könnte Ihre Version des Compilers so erstellt worden sein, dass sie standardmäßig /usr/bin/ld auf einer Unix-ähnlichen Plattform verwendet.

Gibt es eine Möglichkeit, einen anderen Linker-Befehl anzugeben? cc(1) (oder c++(1)) sollte verwenden (z. B. /usr/local/bin/ld anstatt /usr/bin/ld)? Ich interessiere mich hauptsächlich für GCC und Clang.

Ich suche nicht nach Methoden, bei denen die verschiedenen Kompilierungsschritte separat ausgeführt werden (z. B. Vorverarbeitung, Kompilierung, Assemblierung, Verknüpfung).

Ich hatte zum Beispiel gehofft, dass so etwas funktionieren könnte:

env LD=/usr/local/bin/ld cc foo.c -o foo

Aber das funktioniert nicht für gcc oder clang. Es würde natürlich funktionieren, wenn Sie ein Makefile hätten, das zuerst eine Objektdatei erstellt und dann ${LD} zum Verknüpfen aufruft (z. B. env LD=/usr/local/bin/ld make)

Aktualisieren (mit einer möglichen Motivation): Zum einfachen Testen mit einem anderen Linker als dem Standardlinker. Es wäre zum Beispiel schön, dies tun zu können:

cc --linker=/usr/local/bin/ld foo.c -o foo

Stattdessen müssen Sie die Objektdatei generieren und ausführen cc -v um die Argumente dafür herauszufinden ldführen Sie das manuell aus ld Sie wollen mit diesen Argumenten:

cc -c foo.c
cc -v foo.c -o /dev/null

Schauen Sie sich nun den Linker-Aufruf an und kopieren Sie den Linker und die temporäre Objektdatei manuell und fügen Sie sie manuell ein. Etwas in der Art (Beispiel aus einem Test auf Fedora 23), bei dem Sie ersetzen /usr/libexec/gcc/x86_64-redhat-linux/5.3.1/collect2 mit /usr/local/bin/ld (Obwohl es nicht so ist Exakt das Gleiche wie collect2):

/usr/local/bin/ld -plugin /usr/libexec/gcc/x86_64-redhat-linux/5.3.1/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/x86_64-redhat-linux/5.3.1/lto-wrapper -plugin-opt=-fresolution=/tmp/jhein/ccM2XKIg.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o c /usr/lib/gcc/x86_64-redhat-linux/5.3.1/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/5.3.1/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/5.3.1/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/5.3.1 -L/usr/lib/gcc/x86_64-redhat-linux/5.3.1/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/5.3.1/../../.. c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/5.3.1/crtend.o /usr/lib/gcc/x86_64-redhat-linux/5.3.1/../../../../lib64/crtn.o

Wie Sie sehen, ist das nicht einfach. Beachten Sie, dass es auf der GCC-Infoseite eine Dokumentation darüber gibt, wie Collect2 nach einem Linker-Programm sucht. Diesen Dokumenten zufolge ist die erste Stelle, nach der es sucht, jedoch keine Umgebungsvariable oder etwas, das Sie in der Befehlszeile angeben können (z. B. –linker). Die Dokumente sagen, dass es so aussieht Erste für einen „fest codierten Linker-Dateinamen“. Wenn diese Dokumentation korrekt ist, müssten Sie den Standard-Linker umbenennen, um ihn dazu zu zwingen, diesen Linker nicht zu verwenden (d. h. auszutricksen) sudo mv /usr/bin/ld /usr/bin/ld.tmp-disable).

Update 2: Verwenden -B scheint für meine Bedürfnisse gut genug zu funktionieren. Siehe unten, wo ich eine Antwort gepostet habe. Ich kann meine eigene Antwort nicht akzeptieren, aber ich würde es tun, wenn ich könnte – es scheint das Problem gut zu lösen.

  • cc ist nur ein Alias ​​für gcc, clangoder welcher Standard-C-Compiler Ihr System verwendet.

    – Eli Sadoff

    7. November 2016 um 17:23

  • @BasileStarynkevitch: Ich frage, weil ich einen anderen Linker als den in /usr/bin installierten testen möchte. Hier gibt es kein XY-Problem. Ich teste nur mit einer anderen Version des Linkers.

    – Juan

    7. November 2016 um 18:12 Uhr

  • @Olaf: Ja, ich weiß, was CC ist. Ich habe ausdrücklich erwähnt, dass mir Methoden zur Aufteilung von Compiler-/Linker-Schritten bereits bekannt sind. Bei dieser Frage geht es speziell darum, wie man cc (das alle Build-Stufen mit einem einzigen Aufruf von cc ausführen kann) anweist, einen anderen Linker als den zu verwenden, der standardmäßig beim Erstellen von cc angegeben wird. Vielleicht wussten Sie nicht, dass cc den Linker aufrufen kann (versuchen Sie, ein einfaches C-Programm mit zu erstellen). cc -v helloworld.c).

    – Juan

    7. November 2016 um 18:19 Uhr

  • Sieht nach einem XY-Problem aus. Warum Möchten Sie einen anderen Linker als den Standardlinker verwenden? Für die normale Kompilierung sollte das das sein, was Sie wollen, für die Cross-Kompilierung sollten Sie die entsprechende Toolchain verwenden, die auch den richtigen Linker enthält.

    – zu ehrlich für diese Seite

    7. November 2016 um 20:19 Uhr

  • Kommentare sind nicht Teil der Frage. Sie sollten die Frage bearbeiten, unter „Anleitung stellen“ nachlesen und die FAQ lesen. Aber ja, ich habe übersehen, dass Basil bereits das Gleiche vermutete. Dennoch verstehe ich nicht, was Ihr Problem ist. cc ist für die Standardkompilierung/-erstellung gedacht. Für jedes größere Programm sollten Sie auf jeden Fall ein Build-Tool verwenden, das immer die separate Angabe von Compiler und Linker ermöglicht.

    – zu ehrlich für diese Seite

    7. November 2016 um 20:35 Uhr


Juans Benutzeravatar
Juan

Der -B Mit dieser Option können Sie einen alternativen Suchpfad für ausführbare Dateien, Bibliotheken, Include-Dateien und Datendateien angeben, die der Compiler verwenden wird. Dies funktioniert für einige Versionen von gcc [1] und für Clang (derzeit undokumentiert – in Manpages von mindestens Clang 3.7 und 3.8):

cc -B/usr/local/bin foo.c -o foo

Beachten Sie, dass dies dazu führt, dass cc im von angegebenen Pfad nach anderen Tools (z. B. dem Assembler) sucht -B. Angenommen, Sie haben eine andere Version von Binutils in /usr/local/bin installiert, wenn ja nur Ich möchte diesen Linker verwenden (anstatt /usr/local/bin/as, et. al.), könnten Sie so etwas tun:

mkdir /tmp/usemyld
ln -s /usr/local/bin/ld /tmp/usemyld
cc -B/tmp/usemyld foo.c -o foo

-B verfügt über eigene Regeln, mit denen Sie verschiedene Dateien überschreiben können, die der GCC-Compiler zu verwenden versucht (Programme, Bibliotheken, Include-Dateien, Datendateien). Dies ist mindestens seit GCC 2.95 dokumentiert – lesen Sie die GCC-Man-/Infoseiten. Ich weiß nicht, wie kompatibel das Verhalten von ist -B ist für Klirren. Wie bereits erwähnt, ist es derzeit nicht in der Clang-Manpage dokumentiert. Aber es funktionierte so gut, dass ich wie oben gezeigt einen alternativen Linker auswählen konnte.

gcc Unterstützt auch den Aufruf eines Skripts/Programms wie in angegeben -wrapper. clang nicht (derzeit). Sie können dies auch verwenden und auf ein Wrapper-Skript verweisen, das ändert, welches Programm der Compiler aufruft. Ich weiß nicht, ob collect2 beachtet das -wrapper Option (und für gcc, collect2 ruft den Linker zumindest beim Kompilieren von C/C++-Programmen auf).

[1] Die in der dokumentierte Linker-Suchreihenfolge gcc Infoseite für collect2 sagt, dass zuerst nach „einem fest codierten Linker-Dateinamen gesucht wird, wenn GCC mit der Option ‚–with-ld‘ konfiguriert wurde“). Wenn Ihr gcc also nicht mit „–with-ld“ konfiguriert wurde, wird er schließlich in dem von angegebenen Pfad suchen -B (Wenn es nicht gefunden wird real-ld Erste). Wenn Ihr gcc War konfiguriert mit --with-lddann ist die -B Die Option hilft Ihnen nicht dabei, einen alternativen Linker Ihrer Wahl anzugeben.

  • gebraucht gcc -v -B/usr/bin … und bekam trotzdem einen Anruf /opt/local/bin/ld -syslibroot … – also hat das auch nicht funktioniert.

    – Martin

    4. November 2020 um 10:02 Uhr

  • @Martin – Welche GCC-Version? Gibt es ein gültiges „ld“ in /usr/bin? Erwägen Sie die Verwendung eines Tracing-Tools (ktrace, strace), um zu sehen, ob gcc zuerst /usr/bin versucht. Wurde Ihr gcc mit –with-ld erstellt (siehe Fußnote)?

    – Juan

    7. Januar 2021 um 17:13


askys Benutzeravatar
fragt

Bestimmte Linker sind einfach zu verwenden – einfach gcc -fuse-ld=lld main.c. Dies scheint irgendwo in gcc Version 4 hinzugefügt worden zu sein. -fuse-ld funktioniert auch mit clang 10.0.1.

Unterstützte Linker sind auf aufgeführt https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html

-fuse-ld=bfd

Verwenden Sie den bfd-Linker anstelle des Standardlinkers.

-fuse-ld=Gold

Verwenden Sie den Gold-Linker anstelle des Standard-Linkers.

-fuse-ld=lld

Verwenden Sie den LLVM-LLD-Linker anstelle des Standardlinkers.

Hoffentlich hilft dies Leuten, die von Suchanfragen kommen, da OP ihre Frage schon vor langer Zeit beantwortet hat.

  • Das ist ein guter Fund. Mit gcc können Sie jedoch keinen Pfad zu einem Linker angeben: gcc9 -fuse-ld=/opt/ld.bfd x.c -o /dev/null gcc9: error: unrecognized command line option '-fuse-ld=/opt/ld.bfd' . Tut mir leid, dass das in zwei Zeilen aufgeteilt werden muss. Ich weiß nicht, wie ich das in einem Kommentar machen soll. klirren tut Erlauben Sie eine vollständige Pfadangabe für -fuse-ld, Jedoch. Das ist schön. Beachten Sie, dass -fuse-ld erscheint nicht einmal mit clang --help. Ich habe noch nicht gefunden, wo es für llvm/clang dokumentiert ist. (ab llvm90).

    – Juan

    28. Februar 2020 um 16:33 Uhr


  • Das hat nicht funktioniert: gcc: error: unrecognized command line option '-fuse-ld=/usr/bin/ld' – weitersuchen.

    – Martin

    4. November 2020 um 9:58

  • Wie ich in meiner Antwort erwähnt habe, funktioniert dies nur in einigen Sonderfällen. Wenn Sie bfd verwenden möchten, müssen Sie dies tun -fuse-ld=bfdund kann nicht den gesamten Pfad zum bfd-Linker verwenden.

    – fragt

    5. November 2020 um 5:39

  • @Martin – Wie asky angedeutet hat, ist das Argument für einige der aktuellen Implementierungen von -fuse-ld etwas Besonderes. Wie in meinem früheren Kommentar oben erwähnt, nimmt es für die Implementierung von gcc (z. B. gcc 9) keinen beliebigen Pfad, sondern die Erweiterung nach ld (z. B. -fuse-ld=bfd im Beispiel in meinem obigen Kommentar). ). Wie erwähnt, Ein Pfad funktioniert für Clang, obwohl. Die Antwort könnte angepasst werden, um das etwas klarer zu machen.

    – Juan

    7. Januar 2021 um 17:24


Benutzer-Avatar von Basile Starynkevitch
Basile Starynkewitsch

GCC wird intern verwendet spec-Dateien (um zu entscheiden, wie die gcc Programm verhält sich, insbesondere wie es verlinkt und mit welchem ​​Linker). Das können Sie konfigurieren oder ändern mit -specs= Halten Sie also Ihre eigene Spezifikationsdatei bereit und verwenden Sie diese. Oder nutzen Sie die -T Möglichkeit (von gcc welche ausdrücklich übergibt es an ld), um ein Linker-Skript zu erstellen.

Die Standardspezifikation wird mit erhalten gcc -dumpspecs

Auch von strace(1)-ing einige gcc Befehl, werden Sie feststellen, dass versucht wird, auf z. B. zuzugreifen /usr/lib/gcc/x86_64-linux-gnu/specs; Legen Sie dort also Ihre eigene Spezifikationsdatei ab.

Da es sich bei diesen Spezifikationsdateien um Textdateien handelt, sollten Sie in der Lage sein, Ihre eigenen zu schreiben.

Aber ich bin mir nicht sicher, ob es eine gute Idee ist.

Übrigens, /usr/bin/cc ist auf der Linux-Distribution ein symbolischer Link (auf Debian: /usr/bin/cc -> /etc/alternatives/cc -> /usr/bin/gcc), entweder zu einigen gcc oder zu einigen clang. SO VIEL ICH WEISS, cc (Und c99) ist in POSIX angegeben (aber natürlich wird nichts über seine Beziehung zu gesagt). ld)

  • Der -T Option ist für ld(1)nicht für cc(1). Ich werde es mir ansehen -specs. Sieht so aus, als wäre es gcc-spezifisch. Und ich stimme zu, dass das nicht der Fall ist fühlen wie die richtige Lösung.

    – Juan

    7. November 2016 um 18:07 Uhr

  • Der -T Option ist für gcc

    – Basile Starynkevitch

    7. November 2016 um 21:29

  • -T ist für ld(1). Ähnlich wie bei der Übergabe anderer Optionen an den Linker (z. B --startgroupzum Beispiel), zu bestehen -T' on to the linker using gcc` (oder clang), können Sie verwenden -Wl,-T -Wl,your_link_script_file.ld. Wie sich herausstellt, als Abkürzung (ähnlich wie -L), können Sie -T an übergeben gcc oder clang, aber es ist nirgendwo dokumentiert, wo ich es sehe (Manpages, Infoseiten, –help). Also ja, Sie haben Recht. Entschuldigung, ich habe den Fehler gemacht, in den Dokumenten nachzuschauen. Aber das Linker-Skript wird von ld gelesen, nicht von cc – zu spät, um auf einen anderen Befehl zu verweisen, selbst wenn es eine Möglichkeit gäbe, ihn anzugeben.

    – Juan

    7. November 2016 um 23:56 Uhr

  • NEIN, -T Ist dokumentiert Als ein gcc Option (folgen Sie dem Link). Natürlich wird es weitergegeben ldAber gcc weiß davon

    – Basile Starynkevitch

    8. November 2016 um 5:10


  • Ja, ich sehe es jetzt in der Online-Dokumentation. Es wird immer noch direkt an weitergeleitet /usr/bin/ld (anstatt analysiert von cc) oder welcher Standard-Linker auch immer wann angegeben wurde cc erbaut wurde. Es trägt also nicht zur Lösung des ursprünglichen Problems bei.

    – Juan

    8. November 2016 um 13:25 Uhr

Legen Sie das Verzeichnis ab, das den alternativen Linker enthält ld nach vorne PATH Umgebungsvariable.

Zum Beispiel, wenn eine Alternative ld ist in ~/local/bin. export PATH=~/local/bin:$PATH wird verursachen cc benutzen ~/local/bin/ld.

1453520cookie-checkSo geben Sie einen alternativen Linker-Befehl an, wenn Sie mit „cc“ verknüpfen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy