Jak połączyć dwie biblioteki statyczne „ar” w jedną?

90

Mam 2 statycznych bibliotek Linux, stworzone przez ar cr, libabc.ai libxyz.a.
Chcę połączyć je w jedną bibliotekę statyczną libaz.a.
Jak mogę to zrobić.

Chcę utworzyć scaloną bibliotekę statyczną, aby nie przekazywać obu bibliotek do końcowego łącza aplikacji.

osgx
źródło
7
Zobacz także: libtoollibtool -static -o new.a old1.a old2.a
-based
2
działa idealnie, tylko trochę wątpię, czy te biblioteki mają wspólny plik. o (ale pod względem funkcjonalności są różne) czy nadal będzie działać?
bindofisaac
libtool -static -o new.a old1.a old2.a nie działa na Linuksie (centos 7)
opuszczam

Odpowiedzi:

60

Możesz wyodrębnić obiekt z obu .aplików i utworzyć .aplik przy użyciu wyodrębnionych plików .o:

ar -x libabc.a
ar -x libxyz.a
ar -c libaz.a  *.o
codaddict
źródło
63
Niebezpieczeństwo, Will Robinson! Działa to tylko wtedy, gdy nazwy członków w libabc.a i libxyz.a nie pokrywają się. W przeciwnym razie nadpiszesz jeden i zostanie on utracony.
David Given
6
Ponadto libabc.amoże zawierać obiekty o tej samej nazwie (pochodzące z różnych katalogów) - ponowny montaż nie będzie wtedy działał!
Igor R.
16
ar -cnie działa dla mnie (Ubuntu 14.04). Mam ar: no operation specified. ar -qcZamiast tego zrobiłem i to działało dobrze.
Maksymalnie
ar t lib.a może służyć do przeglądania plików w bibliotece bez faktycznego ich rozpakowywania.
raj_gt1
jak mogę to zrobić w automake?
shuva
120

Można to zrobić natywnie na co najmniej trzy sposoby . Pierwszym i najbardziej przenośnym sposobem jest użycie libtool. Po zbudowaniu innych bibliotek, również za pomocą libtool, możesz je połączyć, po prostu dodając .la libs do zmiennej automake libaz_la_LIBADD lub bezpośrednio z pliku Makefile z czymś takim:

libtool --mode=link cc -static -o libaz.la libabc.la libxyz.la

Pozostałe dwa są dostępne przynajmniej podczas używania GNU ar. Możesz użyć skryptu MRI (nazwanego na przykład libaz.mri), takiego jak:

create libaz.a
addlib libabc.a
addlib libxyz.a
save
end

a następnie wykonaj ar jako:

ar -M <libaz.mri

Lub możesz użyć cienkiego archiwum (opcja -T), które pozwoli na dodanie innych archiwów bez zagnieżdżania ich w środku, chociaż wadą jest to, że jeśli chcesz dystrybuować bibliotekę statyczną, będzie brakować odłączonego obiektu:

ar -rcT libaz.a libabc.a libxyz.a

Wszystkie powyższe metody z wdziękiem obsługują nakładające się nazwy członków z oryginalnych archiwów.

W przeciwnym razie musiałbyś rozpakować do różnych katalogów i ponownie zapakować, aby uniknąć zastępowania nakładających się nazw członków:

mkdir abc; cd abc; ar -x ../libabc.a
mkdir xyz; cd xyz; ar -x ../libxyz.a
ar -qc libaz.a abc xyz
Guillem Jover
źródło
19
Dla tych, którzy chcą normalnego archiwum (nie cienkiego), jedną prostą rzeczą, którą można zrobić, jest utworzenie cienkiego archiwum, a następnie przekonwertowanie go na normalne archiwum. Coś jak: ar cqT libaz.a libabc.a libxyz.a && echo -e 'create libaz.a\naddlib libaz.a\nsave\nend' | ar -M. Tworzy to tymczasowe cienkie libaz.aarchiwum, a następnie konwertuje cienkie archiwum na normalne (aby można je było przenosić / dystrybuować). To również z wdziękiem radzi sobie, gdy nazwy twoich bibliotek zawierają znaki specjalne (spacje, plusy lub przecinki) (tj ar cqT libbundle.a libfoo++.a 'libbar baz.a'.). Ale +1 ode mnie!
Cornstalks
Jaka jest wada pierwszego podanego przykładu skryptu MRI?
jb
Niezła odpowiedź! Dobrze widzieć kilka opcji, które nie wymagają wyodrębniania i ponownego tworzenia. Myślę też, że pomysł @Cornstalks jest dobry. Może należy dodać do odpowiedzi?
Żarówka 1
Hej, kiedy próbuję użyć polecenia libtool, otrzymuję następujące błędy: libtool: link: unable to infer tagged configuration libtool: error: specify a tag with '--tag' Jakieś pomysły, jak to naprawić?
Lars Nielsen
@Guillem @Cornstalks Świetna odpowiedź. Co jeśli --Wl,-whole-archiveopcja jest wymagana w oryginalnym poleceniu łączenia dla wielu bibliotek * .a i muszę połączyć wszystkie biblioteki lib * .a w one.a. Podczas ponownego łączenia --Wl,-whole-archivenie będzie działać z one.a. Co sugerujesz? stackoverflow.com/questions/56323197/…
thinkdeep
10

Jeśli po prostu zrobisz to jako:

ar x a.a
ar x b.a
ar c c.a  *.o 

utracisz niektóre pliki obiektowe, jeśli istnieją członkowie o tej samej nazwie zarówno w aa, jak i ba, więc musisz rozpakować członków różnych archiwów do innego folderu:

ar x a.a && mv *.o a_objs
ar x b.a && mv *.o b_objs
ar c c.a a_objs/*.o b_objs/*.o

Co więcej, możliwe jest, że w jednym archiwum jest wielu członków o tej samej nazwie (powiedzmy w aa), jeśli uruchomisz ar x aa , otrzymasz tylko jednego dla tych członków o tej samej nazwie.

Jedynym sposobem wyodrębnienia wszystkich członków o tej samej nazwie w jednym archiwum jest określenie numeru członka za pomocą opcji „N”:

ar xN 1 a.a  xxx.c.o && mv xxx.c.o xxx.c.1.o
ar xN 2 b.a  xxx.c.o && mv xxx.c.o xxx.c.2.o
...

byłaby to żmudna praca, więc będziesz musiał napisać bardziej wyrafinowany skrypt, aby wykonać tę pracę.

Jednym z opcjonalnych rozwiązań jest połączenie wielu archiwów w jedną wspólną bibliotekę:

g++ -shared -o c.so -Wl,--whole-archive a.a b.a 

w ten sposób konsolidator zajmie się wszystkim za Ciebie!

samuel.zzy220
źródło
1
Samuel, dziękuję. Ale łącząc się w bibliotekę współdzieloną, wszystkie obiekty powinny być skompilowane z -fPIC.
osgx
0

Jeszcze lepiej wykonujesz częściowe łączenie w każdej bibliotece i utworzysz archiwum dwóch wynikowych plików obiektowych. W ten sposób działa jak biblioteki współdzielone

Robisz częściowe linkowanie z

gcc -r --nostdlib

więc zamiast tworzyć archiwum pośrednie lub po jego ponownym rozpakowaniu, uruchom

gcc -r --nostdlib $CFLAGS $OBJECTS_A -o $LIBNAME_A.o
gcc -r --nostdlib $CFLAGS $OBJECTS_B -o $LIBNAME_B.o

następnie

ar -cr $LIBNAME_JOINED.a $LIBNAME_A.o $LIBNAME_B.o
Allan Jensen
źródło
To tak naprawdę nie odpowiada na zadane pytanie - tak jak prosił o biblioteki. Często nie masz nawet podanych źródeł dla bibliotek lub chcesz, aby były one wstępnie zbudowane z innych powodów.
pholat
0
ar -x libx264.a
mkdir sub && cd sub
ar -m ../libx264.a `ar -t ../libx264.a |sort|uniq|grep "\.o"`
ar -x ../libx264.a

teraz masz dwie wersje „macroblock-10.o”

prawo wey
źródło
0
ar crsT libaz.a libabc.a libxyz.a

Tutaj tworzysz archiwum archiwów, a następnie „spłaszczasz” (przerzedzasz) wynik za pomocą flagi T. Nie jestem pewien, jak to będzie działać z plikami o tej samej nazwie, które mogą być w nich zawarte.

Evgeny Yashin
źródło