Statyczne łącze funkcji biblioteki współdzielonej w gcc

138

Jak mogę statycznie połączyć funkcję biblioteki współdzielonej w gcc?

suresh
źródło
13
Co masz na myśli mówiąc statycznie połączone? Czy chcesz, aby Twój plik wykonywalny był dystrybuowany bez wymagania pliku .so?
Emiliano,

Odpowiedzi:

108

Odnosić się do:

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

Aby ją połączyć, potrzebujesz statycznej wersji biblioteki.

Biblioteka współdzielona jest w rzeczywistości plikiem wykonywalnym w specjalnym formacie z określonymi punktami wejścia (i zawiera kilka lepkich problemów z adresowaniem). Nie zawiera wszystkich informacji potrzebnych do statycznego łączenia.

Nie można łączyć statycznie udostępnionej biblioteki (ani dynamicznie łączyć biblioteki statycznej).

Flaga -staticzmusi konsolidator do użycia bibliotek statycznych (.a) zamiast udostępnionych (.so). Jednak biblioteki statyczne nie zawsze są instalowane domyślnie, więc może być konieczne samodzielne zainstalowanie biblioteki statycznej.

Innym możliwym podejściem jest użycie statifier lub Ermine . Oba narzędzia przyjmują jako dane wejściowe dynamicznie połączony plik wykonywalny, a jako dane wyjściowe tworzą samodzielny plik wykonywalny z osadzonymi wszystkimi bibliotekami współdzielonymi.

Sam Liao
źródło
11
Jakie informacje ma biblioteka statyczna, aby można ją było łączyć statycznie, a których nie ma biblioteka dynamiczna?
kbolino
75

Jeśli chcesz połączyć, powiedzmy, libapplejuice statycznie, ale nie, powiedzmy, liborangejuice , możesz połączyć w ten sposób:

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

Jest zastrzeżenie - jeśli liborangejuiceużywa libapplejuice, libapplejuicezostanie również dynamicznie połączony.

Będziesz musiał łączyć się liborangejuicestatycznie wraz z, libapplejuiceaby uzyskać libapplejuicestatyczny.

I nie zapomnij zachować -Wl,-Bdynamic, w przeciwnym razie skończysz łącząc wszystko statyczne, w tym libc(co nie jest dobre do zrobienia).

Eugene Bujak
źródło
2
Czy nie ma sposobu, aby bezpośrednio powiedzieć gcc, co ma łączyć statycznie, a nie omijać go i rozmawiać z linkerem?
Elazar Leibovich
1
@ElazarLeibovich nie można w ten sposób uzyskać połączenia statycznego i dynamicznego.
Haozhun
@EugeneBujak: the zastrzeżenie nie ma zastosowania w moim systemie. Przykład: gcc -o main main.cc -Wl,-rpath=. -Wl,-Bdynamic -lB -Wl,-Bstatic -lA -Wl,-Bdynamic -L. libB używa libA , jest połączona i lddnie pokazuje odniesienia do libA . Plik wykonywalny działa dobrze. Testowany za pomocą g ++ 4.7.3.
radix
Pośrednia (zagnieżdżona), statyczna zależność bezpośredniej, dynamicznej zależności nie jest sama w sobie dynamicznie łączona.
Vinny
Weź pod uwagę następujące kwestie: binA zależy od libB.so, które zależy od libC. A Jak już powiedzieli inni, pliki .so są same w sobie plikami wykonywalnymi, więc kiedy obiekt współdzielony jest linkowany, wszystkie zależności biblioteki statycznej są przetwarzane przez konsolidator tak samo, jak gdyby plik wykonywalny był łączony: jedynymi symbolami pobieranymi z biblioteki statycznej .a są te, do których odwołuje się plik .so. Oznacza to, że jeśli binA odwołuje się do symbolu w libC.a, do którego nie odwołuje się nigdzie w libB.so, to nawet jeśli binA dowiązuje do libB.so, ten symbol będzie niezdefiniowany (chyba że -Wl, - całe archiwum jest używane podczas łączenia libB.so).
Vinny
18

Jeśli masz plik .a swojej biblioteki współdzielonej (.so), możesz po prostu dołączyć go z pełną ścieżką, tak jakby był plikiem obiektowym, na przykład:

To generuje main.o po prostu kompilując:

gcc -c main.c

To łączy ten plik obiektu z odpowiednią biblioteką statyczną i tworzy plik wykonywalny (o nazwie „main”):

gcc main.o mylibrary.a -o main

Lub jednym poleceniem:

gcc main.c mylibrary.a -o main

Może to być również ścieżka bezwzględna lub względna:

gcc main.c /usr/local/mylibs/mylibrary.a -o main
NeoEGM
źródło
12

Tak, wiem, że to pytanie od 8 lat, ale powiedziano mi, że można statycznie łączyć się z biblioteką obiektów współdzielonych i to był dosłownie największy hit, gdy szukałem więcej informacji na jego temat.

Aby wykazać, że rzeczywiście statycznie łączenie biblioteki dzielonego obiektu nie jest możliwe ld( gcc„s łącznik) - w przeciwieństwie do tylko kilka osób, twierdząc, że nie jest to możliwe - użyć następującego gccpolecenia:

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

(Oczywiście będziesz musiał skompilować objectname.oz sourcename.c, i prawdopodobnie powinieneś również stworzyć własną bibliotekę obiektów współdzielonych. Jeśli to zrobisz, użyj -Wl,--library-path,., aby ld mógł znaleźć twoją bibliotekę w lokalnym katalogu.)

Rzeczywisty otrzymany błąd to:

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

Mam nadzieję, że to pomoże.

Ian Moote
źródło
10

Trochę późno, ale ... znalazłem link, który zapisałem kilka lat temu i pomyślałem, że może się wam przydać:

CDE: Automatyczne tworzenie przenośnych aplikacji dla systemu Linux

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

  • Wystarczy pobrać program
  • Wykonaj plik binarny, przekazując jako argument nazwę pliku binarnego, który chcesz uczynić przenośnym, na przykład: nmap

    ./cde_2011-08-15_64bit nmap

Program odczyta wszystkie biblioteki dowiązane do nmap i jego elementów zależnych i zapisze je wszystkie w folderze o nazwie cde-package / (w tym samym katalogu, w którym jesteś).

  • Na koniec możesz skompresować folder i wdrożyć przenośny plik binarny w dowolnym systemie.

Pamiętaj, że aby uruchomić przenośny program, musisz uruchomić plik binarny znajdujący się w cde-package / nmap.cde

Z poważaniem

Francis
źródło
2
Chociaż nie do końca udziela odpowiedzi na pytanie - jest to godne uwagi rozwiązanie problemu.
razong
Wydaje się, że łącze jest teraz martwe.
sinan
0

W gcc nie jest to obsługiwane. W rzeczywistości nie jest to obsługiwane w żadnym istniejącym kompilatorze / konsolidatorze, o którym wiem.

nothrow
źródło
4
Czy możesz wyjaśnić, dlaczego żaden istniejący kompilator nie obsługuje łączenia statycznego?
jww
5
@noloader, statyczne łączenie biblioteki dynamicznej?
nothrow