Как объединить две статические библиотеки «ar» в одну?

92

У меня есть два статических библиотеки Linux, созданные ar cr, libabc.aи libxyz.a.
Я хочу объединить их в одну статическую библиотеку libaz.a.
Как я могу это сделать.

Я хочу создать объединенную статическую библиотеку, а не отдавать обе библиотеки на финальную ссылку приложений.

osgx
источник
8
См. Также: libtoollibtool -static -o new.a old1.a old2.a
-основанное
2
он работает отлично, просто немного сомневаюсь, что у этих библиотек есть общий файл. o (но с точки зрения функциональности они разные), он все равно будет работать?
bindingofisaac 07
libtool -static -o new.a old1.a old2.a не работает на linux (centos 7)
выходит

Ответы:

62

Вы можете извлечь объект из обоих .aфайлов и создать свой .aфайл, используя извлеченные .os:

ar -x libabc.a
ar -x libxyz.a
ar -c libaz.a  *.o
codaddict
источник
66
Опасно, Уилл Робинсон! Это работает, только если имена членов в 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
как я могу сделать это в автомаке?
Шува
126

Есть как минимум три способа сделать это изначально . Первый и самый переносимый способ - использовать libtool. После создания других библиотек также с помощью libtool вы можете объединить их, просто добавив .la libs в переменную automake libaz_la_LIBADD или непосредственно из Makefile с чем-то вроде:

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

Два других по крайней мере доступны при использовании GNU ar. Вы можете использовать сценарий MRI (например, с названием 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 

таким образом компоновщик сделает все за вас!

samuel.zzy220
источник
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
Аллан Дженсен
источник
Это не совсем ответ на заданный вопрос - поскольку он просил библиотеки. Часто у вас даже нет исходников для предоставленных библиотек или вы хотите сохранить их предварительно собранными по другим причинам.
pholat 05
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

теперь у вас есть две версии "макроблока-10.o"

закон вей
источник
0
ar crsT libaz.a libabc.a libxyz.a

Здесь вы создаете архив архивов, а затем «сглаживаете» (прореживаете) результат с помощью флажка T. Не уверен, как это будет работать с файлами .o с таким же именем, которые могут содержаться внутри.

Евгений Яшин
источник