2009-03-20 13 views
13

Załóżmy, że mam trzy C biblioteki statyczne powiedzieć libColor.a która zależy * libRGB. * A co z kolei zależy od libPixel.a. Biblioteka libColor.a mówi się, zależy od biblioteki libRGB.a ponieważ istnieją odniesienia w libColor.a niektórych symboli określonych w libRGB.a. Jak połączyć wszystkie powyższe biblioteki z nowym, niezależnym?Łączenie bibliotek statycznych

Niezależny oznacza, że ​​nowa biblioteka powinna mieć zdefiniowane wszystkie symbole. Tak więc podczas łączenia wystarczy podać -lNewColor. Wielkość nowej biblioteki powinny być minimalne czyli nie powinny zawierać żadnych symboli libRGB.a który nie jest używany przez libColor.a itp Próbowałem szczęścia przy użyciu różnych opcji w ar polecenia (stosowane w tworzyć i aktualizować statyczne biblioteki/archiwa).

+0

można alternatywnie spojrzeć na http: // stackoverflow. com/questions/8170450/combine-static-library/8170851 # 8170851 i użyj libt ool – Bruce

+0

Należy zauważyć, że krok minimalizacji naprawdę nie jest konieczny. W przypadku bibliotek statycznych linker pobierze tylko pliki obiektów, których potrzebuje, w przeciwieństwie do bibliotek współdzielonych, które zawierają wszystko. Istnieją powody i korzyści dla każdego podejścia; oni są po prostu inni. I naprawdę nie musisz się martwić podczas pracy z bibliotekami statycznymi. –

Odpowiedz

11

1/Wyodrębnij WSZYSTKIE pliki obiektów z każdej biblioteki (używając ar) i spróbuj skompilować swój kod bez bibliotek lub plików obiektów. Prawdopodobnie otrzymasz bezwzględny ładunek z nieokreślonymi symbolami. Jeśli nie otrzymasz niezdefiniowanych symboli, przejdź do kroku 5.

2/Chwyć pierwszą i dowiedz się, który plik obiektowy spełnia ten symbol (używając nm).

3/Zapisz ten plik obiektowy, a następnie skompiluj swój kod, w tym nowy plik obiektowy. Dostaniesz nową listę symboli niezdefiniowanych lub, jeśli istnieje żaden, przejdź do kroku 5.

4/przejdź do kroku 2.

5/Połącz wszystkie pliki obiektów na liście (jeśli istnieją) do jednej biblioteki (ponownie z ar).

Bang! Tam to masz. Spróbuj połączyć swój kod bez żadnych obiektów, ale z nową biblioteką z z.

Całość można stosunkowo łatwo zautomatyzować za pomocą skryptu powłoki.

+2

Niepotrzebnie skomplikowane, można po prostu wyodrębnić wszystkie pliki .o do dużego .a, jak wtedy, gdy jest w końcu połączony z plikiem wykonywalnym, linker zrezygnuje i tak nieużywane – MarkR

+2

@ MarkerR, @AIB chciał rozmiar * biblioteki * być minimalnym, a nie rozmiarem pliku wykonywalnego. – paxdiablo

+0

Akceptuję to, choć bardzo bym chciał, żeby oneliner to zrobił. Jak przekazanie niektórych opcji ld do połączenia tylko z potrzebnymi symbolami itp. – AIB

5

Biblioteka statyczna to niewiele więcej niż archiwum niektórych plików obiektowych (.o). Możesz tylko wyodrębnić wszystkie obiekty z dwóch bibliotek (używając "ar x"), a następnie użyć "ar", aby połączyć je ze sobą w nowej bibliotece.

15

Trochę używane cechą archiwizatora GNU jest skrypt archiwum, jest prosty, ale potężny interfejs, a to może zrobić dokładnie to, co chcesz, na przykład jeśli poniższy skrypt nazywa script.ar:

CREATE libNewColor.a 
ADDLIB libColor.a 
ADDLIB libRGB.a 
ADDLIB libPixel.a 
SAVE 
END 

Następnie można wywołać ar następująco:

ar -M < script.ar 

i dostaniemy libNewColor.a, który zawiera wszystkie pliki z .o libColor.a libRGB.a i libPixel.a.

Dodatkowo można również dodać zwykłe.o pliki, jak również z polecenia ADDMOD:

CREATE libNewColor.a 
ADDLIB libColor.a 
ADDLIB libRGB.a 
ADDLIB libPixel.a 
ADDMOD someRandomCompiledFile.o 
SAVE 
END 

Ponadto jest to bardzo proste do wygenerowania tych skryptów w Makefile, więc zazwyczaj stworzyć nieco ogólną regułę makefile do tworzenia archiwów, które faktycznie generuje skrypt i wywołuje ar na scenariusz. Coś takiego:

$(OUTARC): $(OBJECTS) 
    $(SILENT)echo "CREATE [email protected]" > $(ODIR)/$(ARSCRIPT) 
    $(SILENT)for a in $(ARCHIVES); do (echo "ADDLIB $$a" >> $(ODIR)/$(ARSCRIPT)); done 
    $(SILENT)echo "ADDMOD $(OBJECTS)" >> $(ODIR)/$(ARSCRIPT) 
    $(SILENT)echo "SAVE" >> $(ODIR)/$(ARSCRIPT) 
    $(SILENT)echo "END" >> $(ODIR)/$(ARSCRIPT) 
    $(SILENT)$(AR) -M < $(ODIR)/$(ARSCRIPT) 

Choć teraz, gdy patrzę na to myślę, że to nie działa, jeśli $ (obiekty) jest pusta (czyli jeśli po prostu chcesz się połączyć archiwa bez dodawania dodatkowych plików obiektowych), ale będę pozostawić go jako ćwiczenie dla czytelnika, aby rozwiązać ten problem, w razie potrzeby ...: D

Oto docs dla tej funkcji:

https://sourceware.org/binutils/docs/binutils/ar-scripts.html#ar-scripts

+0

To jest świetne! Tyle że wszystkie ścieżki/biblioteki, które mają + w nazwie, łamią skrypt. Na przykład openssl ma libncurses ++. A – Gregory

+0

Schludny! Jest to o wiele łatwiejsze niż samodzielne rozpakowywanie i przepakowywanie plików obiektów. – Thomas

+0

Należy pamiętać, że z jakiegoś powodu -D nie działa w połączeniu z -M. Jeśli chcesz uzyskać wyniki deterministyczne, nadal potrzebujesz trasy wyodrębnij, a następnie archiwizuj. –

Powiązane problemy