Як об’єднати дві статичні бібліотеки “ar” в одну?


92

У мене є 2 статичні бібліотеки Linux, створені ar cr, libabc.aі libxyz.a.
Я хочу об'єднати їх в одну статичну бібліотеку libaz.a.
Як я можу це зробити.

Я хочу створити об'єднану статичну бібліотеку, а не віддавати обидві бібліотеки остаточному посиланню програм.


8
Див. Також: libtoolрішення на основі :libtool -static -o new.a old1.a old2.a
osgx

2
це працює ідеально, лише невеликий сумнів, якщо ці бібліотеки мають спільний файл.o (але функціонально вони різні), чи все одно це буде працювати?
bindingofisaac

libtool -static -o new.a old1.a old2.a не працює на Linux (centos 7)
зміни

Відповіді:


60

Ви можете витягти об’єкт з обох .aфайлів і створити свій .aфайл, використовуючи витягнуті .os:

ar -x libabc.a
ar -x libxyz.a
ar -c libaz.a  *.o

65
Небезпека, Уілл Робінзон! Це працює, лише якщо імена членів у libabc.a та libxyz.a не збігаються. Інакше ви перезапишете один, і він буде загублений.
Девід Дано

7
Більше того, libabc.aможуть містити об'єкти з однаковим ім'ям (походять із різних каталогів) - повторне збирання тоді не буде працювати!
Ігор Р.

17
ar -cне працював у мене (Ubuntu 14.04). Я зрозумів ar: no operation specified. Я ar -qcнатомість це зробив, і це спрацювало добре.
Макс.

ar t lib.a може використовуватися для перегляду файлів у бібліотеці без фактичного вилучення файлів.
raj_gt1

як я можу це зробити в automake?
shuva

122

Існує щонайменше три способи зробити це споконвічно . Перший і найбільш портативний спосіб - це використання libtool. Після побудови інших бібліотек також за допомогою libtool, ви можете комбінувати їх, просто додаючи .la libs до автоматичної змінної libaz_la_LIBADD або безпосередньо з Makefile з чимось на зразок:

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

Два інших принаймні доступні при використанні GNU ar. Ви можете використовувати скрипт МРТ (названий, наприклад, libaz.mri), наприклад:

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

а потім виконайте ar як:

ar -M <libaz.mri

Або ви можете використовувати тонкий архів (опція -T), який дозволить додавати інші архіви, не вкладаючи їх всередину, хоча недоліком є ​​те, що якщо ви хочете поширити статичну бібліотеку, від’єднаний об’єкт буде відсутній:

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

Усі вищезазначені методи витончено обробляють накладені імена членів з оригінальних архівів.

В іншому випадку вам доведеться розпаковувати в різні каталоги і знову упаковувати, щоб уникнути заміни перекриваються імен членів:

mkdir abc; cd abc; ar -x ../libabc.a
mkdir xyz; cd xyz; ar -x ../libxyz.a
ar -qc libaz.a abc xyz

19
Для тих, хто хоче нормальний архів (не тонкий), можна зробити одну просту справу - створити тонкий архів, а потім перетворити його в звичайний архів. Що - щось на кшталт: ar cqT libaz.a libabc.a libxyz.a && echo -e 'create libaz.a\naddlib libaz.a\nsave\nend' | ar -M. Це створює тимчасовий тонкий файл libaz.a, а потім перетворює тонкий архів у звичайний (щоб ви могли його переміщати / розповсюджувати). Це також витончено обробляє, коли назви бібліотек мають спеціальні символи (пробіли, плюси чи коми) (тобто ar cqT libbundle.a libfoo++.a 'libbar baz.a'). Але +1 від мене!
Cornstalks

У чому мінус першого наведеного прикладу сценарію МРТ?
jb

Приємна відповідь! Добре бачити деякі варіанти, які не вимагають витягування та повторного отримання. Також я думаю, що ідея @Cornstalks хороша. Може, слід додати до відповіді?
Lightbulb1,

Гей, коли я намагаюся використовувати команду, щоб libtoolотримати ці помилки: libtool: link: unable to infer tagged configuration libtool: error: specify a tag with '--tag' Будь-які ідеї, як це виправити?
Ларс Нільсен,

@Guillem @Cornstalks Чудова відповідь. Що робити, якщо --Wl,-whole-archiveопція потрібна в оригінальній команді зв’язування для декількох lib * .a, і мені потрібно об’єднати всі lib * .a в one.a. При повторному підключенні --Wl,-whole-archiveне працюватиме one.a. Яка ваша пропозиція? stackoverflow.com/questions/56323197 / ...
thinkdeep

10

Якщо ви просто зробите це як:

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

ви втратите деякі об’єктні файли, якщо в aa і ba є члени з однаковим іменем, тож вам потрібно витягти члени різних архівів в іншу папку:

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

крім того, можливо, що в одному архіві є декілька членів з однаковим іменем (скажімо в aa), якщо ви запустите ar x aa , ви отримаєте лише одного для тих членів з одним іменем.

Єдиний спосіб вилучити всіх членів з одним іменем в одному архіві - вказати номер члена за допомогою опції '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
...

це було б нудною роботою, тож вам доведеться написати складніший сценарій, щоб виконати цю роботу.

Одним із необов’язкових рішень є те, що ви можете об’єднати кілька архівів в одну спільну бібліотеку:

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

таким чином лінкер буде обробляти всі речі за вас!


1
Самуелю, дякую. Але, об'єднуючись у спільну бібліотеку, усі об'єкти слід компілювати -fPIC.
osgx

0

Ще краще ви виконуєте часткове зв'язування з кожною бібліотекою, і вони роблять архів двох отриманих об'єктних файлів. Таким чином він працює так, як працювали б спільні бібліотеки

Ви робите часткове зв'язування з

gcc -r --nostdlib

тож, замість того, щоб робити проміжний архів, або після його повторного вилучення, запустіть

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

тоді

ar -cr $LIBNAME_JOINED.a $LIBNAME_A.o $LIBNAME_B.o

Це насправді не відповідає на запитання - як він просив про бібліотеки. Багато разів у вас навіть немає джерел для бібліотек, які ви надаєте, або ви хочете зберегти їх заздалегідь з інших причин.
Фолат

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

тепер у вас є дві версії "macroblock-10.o"


0
ar crsT libaz.a libabc.a libxyz.a

Тут ви створюєте архів архівів, а потім `` вирівнюєте '' (стоншуєте) результат за допомогою прапора Т. Не впевнений, як це працюватиме з однойменними .o-файлами, які можуть міститися всередині.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.