Statische Verknüpfung der gemeinsam genutzten Bibliotheksfunktion in gcc


137

Wie kann ich eine gemeinsam genutzte Bibliotheksfunktion statisch in gcc verknüpfen?


13
Was meinst du mit statisch verknüpft? Möchten Sie, dass Ihre ausführbare Datei verteilt wird, ohne dass die .so erforderlich ist?
Emiliano

Antworten:


108

Beziehen auf:

http://www.linuxquestions.org/questions/linux-newbie-8/forcing-static-linking-of-shared-libraries-696714/

http://linux.derkeiler.com/Newsgroups/comp.os.linux.development.apps/2004-05/0436.html

Sie benötigen die statische Version der Bibliothek, um sie zu verknüpfen.

Eine gemeinsam genutzte Bibliothek ist eine ausführbare Datei in einem speziellen Format mit angegebenen Einstiegspunkten (und einigen Problemen bei der Adressierung). Es verfügt nicht über alle Informationen, die für eine statische Verknüpfung erforderlich sind.

Sie können eine gemeinsam genutzte Bibliothek nicht statisch verknüpfen (oder eine statische Bibliothek dynamisch verknüpfen).

Das Flag -staticzwingt den Linker, statische Bibliotheken (.a) anstelle von gemeinsam genutzten (.so) zu verwenden. Da statische Bibliotheken jedoch nicht immer standardmäßig installiert sind, müssen Sie die statische Bibliothek möglicherweise selbst installieren.

Ein anderer möglicher Ansatz ist die Verwendung von Statifier oder Hermelin . Beide Tools verwenden als Eingabe eine dynamisch verknüpfte ausführbare Datei und erstellen als Ausgabe eine in sich geschlossene ausführbare Datei, in die alle gemeinsam genutzten Bibliotheken eingebettet sind.


11
Welche Informationen hat die statische Bibliothek, damit sie statisch verknüpft werden kann, die die dynamische Bibliothek nicht hat?
Kbolino

75

Wenn Sie beispielsweise libapplejuice statisch verknüpfen möchten , aber nicht liborangejuice , können Sie Folgendes verknüpfen:

gcc object1.o object2.o -Wl,-Bstatic -lapplejuice -Wl,-Bdynamic -lorangejuice -o binary

Es gibt eine Einschränkung - wenn liborangejuiceverwendet libapplejuice, libapplejuicewird auch dynamisch verknüpft.

Sie müssen liborangejuicestatisch mit verknüpfen libapplejuice, um libapplejuicestatisch zu werden.

Und vergessen -Wl,-BdynamicSie nicht , alles zu behalten, sonst verknüpfen Sie am Ende alles Statische, einschließlich libc(was nicht gut ist).


2
Gibt es nicht eine Möglichkeit, gcc direkt mitzuteilen, was statisch verknüpft werden soll, und ihn nicht zu umgehen und mit dem Linker zu sprechen?
Elazar Leibovich

1
@ElazarLeibovich Sie können auf diese Weise keine Kombination aus statisch und dynamisch erhalten.
Haozhun

@ EugeneBujak: Die Einschränkung gilt nicht für mein System. Beispiel: gcc -o main main.cc -Wl,-rpath=. -Wl,-Bdynamic -lB -Wl,-Bstatic -lA -Wl,-Bdynamic -L. libB verwendet libA , ist verknüpft und lddzeigt keinen Verweis auf libA an . Die ausführbare Datei funktioniert einwandfrei. Getestet mit g ++ 4.7.3.
Radix

Eine indirekte (verschachtelte) statische Abhängigkeit einer direkten, dynamischen Abhängigkeit wird selbst nicht dynamisch verknüpft.
Vinny

Beachten Sie Folgendes: binA hängt von libB.so ab, was von libC.a abhängt. Wie andere bereits angegeben haben, sind .so selbst ausführbare Dateien. Wenn also ein freigegebenes Objekt verknüpft wird, werden alle statischen Bibliotheksabhängigen vom Linker ähnlich verarbeitet, als ob Eine ausführbare Datei wurde verknüpft: Die einzigen Symbole, die aus der statischen .a-Bibliothek abgerufen werden, sind diejenigen, auf die die .so verweist (und die nicht aufgelöst werden). Dies bedeutet, dass wenn binA auf ein Symbol in libC.a verweist, auf das in libB.so nirgendwo verwiesen wird, dieses Symbol auch dann nicht definiert ist, wenn binA auf libB.so verweist (es sei denn, -Wl, - wird beim Verknüpfen das gesamte Archiv verwendet libB.so).
Vinny

18

Wenn Sie die .a-Datei Ihrer gemeinsam genutzten Bibliothek (.so) haben, können Sie sie einfach in ihren vollständigen Pfad einfügen, als wäre es eine Objektdatei, wie folgt:

Dies erzeugt main.o durch einfaches Kompilieren:

gcc -c main.c

Dadurch wird diese Objektdatei mit der entsprechenden statischen Bibliothek verknüpft und die ausführbare Datei (mit dem Namen "main") erstellt:

gcc main.o mylibrary.a -o main

Oder in einem einzigen Befehl:

gcc main.c mylibrary.a -o main

Es könnte auch ein absoluter oder relativer Pfad sein:

gcc main.c /usr/local/mylibs/mylibrary.a -o main

12

Ja, ich weiß, dass dies eine 8 Jahre alte Frage ist, aber mir wurde gesagt, dass es möglich ist, eine statische Verknüpfung mit einer Bibliothek mit gemeinsam genutzten Objekten herzustellen, und dies war buchstäblich der Top-Hit, als ich nach weiteren Informationen darüber suchte.

Verwenden Sie den folgenden Befehl, um zu demonstrieren, dass das statische Verknüpfen einer Bibliothek mit gemeinsam genutzten Objekten mit ld( gcc's Linker) nicht möglich ist - im Gegensatz zu nur einer Gruppe von Personen, die darauf bestehen, dass dies nicht möglich ist gcc:

gcc -o executablename objectname.o -Wl,-Bstatic -l:libnamespec.so

(Natürlich müssen Sie objectname.oaus kompilieren sourcename.c, und Sie sollten wahrscheinlich auch Ihre eigene Bibliothek für gemeinsam genutzte Objekte erstellen . Wenn Sie dies tun, verwenden Sie -Wl,--library-path,.diese Option , damit ld Ihre Bibliothek im lokalen Verzeichnis finden kann.)

Der tatsächliche Fehler, den Sie erhalten, ist:

/usr/bin/ld: attempted static link of dynamic object `libnamespec.so'
collect2: error: ld returned 1 exit status

Hoffentlich hilft das.


10

Ein bisschen spät, aber ... Ich habe einen Link gefunden, den ich vor ein paar Jahren gespeichert habe, und ich dachte, er könnte für euch nützlich sein:

CDE: Erstellen Sie automatisch tragbare Linux-Anwendungen

http://www.pgbovine.net/cde.html

  • Laden Sie einfach das Programm herunter
  • Führen Sie die Binärdatei aus, indem Sie als Argument den Namen der Binärdatei übergeben, die portabel gemacht werden soll, z. B. nmap

    ./cde_2011-08-15_64bit nmap

Das Programm liest alle mit nmap und seinen Abhängigkeiten verknüpften Bibliotheken und speichert sie alle in einem Ordner namens cde-package / (in demselben Verzeichnis wie Sie).

  • Schließlich können Sie den Ordner komprimieren und die tragbare Binärdatei in einem beliebigen System bereitstellen.

Denken Sie daran, um das tragbare Programm zu starten, müssen Sie die Binärdatei in cde-package / nmap.cde ausführen

Freundliche Grüße


2
Obwohl es nicht genau die Antwort auf die Frage gibt, ist es eine bemerkenswerte Lösung für das Problem.
Rasong

0

In gcc wird dies nicht unterstützt. Tatsächlich wird dies in keinem mir bekannten Compiler / Linker unterstützt.


4
Können Sie erklären, wie statische Verknüpfungen von keinem vorhandenen Compiler unterstützt werden?
JWW

5
@noloader, statische Verknüpfung der dynamischen Bibliothek?
Nothrow
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.