Как объединить две статические библиотеки ar в одну?
У меня есть 2 статические библиотеки Linux, созданные ar cr
, libabc.a
а также libxyz.a
,
Я хочу объединить их в одну статическую библиотеку libaz.a
,
Как я могу это сделать.
Я хочу создать объединенную статическую библиотеку, чтобы не дать обеим библиотекам окончательную ссылку приложений.
9 ответов
Вы можете извлечь объект как из .a
файлы и создать свой .a
файл с использованием извлеченного .o
s:
ar -x libabc.a
ar -x libxyz.a
ar -c libaz.a *.o
Есть как минимум три способа сделать это изначально. Первый и самый переносимый способ - использовать libtool. Собрав другие библиотеки также с помощью libtool, вы можете объединить их, просто добавив библиотеки.la в переменную 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
Если вы просто делаете это как:
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
Таким образом, компоновщик будет обрабатывать все для вас!
Вы всегда можете сделать частичное связывание:
gcc -r -o libnew.o -Wl,--whole-archive libabc.a libxyz.a
ar cr libnew.a libnew.o
Еще лучше, если вы выполните частичное связывание для каждой библиотеки, и они сделают архив двух результирующих объектных файлов. Таким образом, он работает как общие библиотеки
Вы делаете частичную связь с
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
Вот скрипт bash, чтобы связать все
.a
libs из указанного каталога в одну библиотеку.
Применение:
./unify-static-libs.sh myFinalLib.a /path/to/input/libs
#!/bin/bash
#
# Creates one static library from several.
#
# Usage: copy all your libs to a single directory and call this script.
#
if [[ $# -ne 2 ]]; then
echo "Usage: unify-static-libs.sh output-name path-to-libs"
exit 2
fi
# Inputs
LIBNAME=$1
LIBSDIR=$2
# Tmp dir
OBJDIR=/tmp/unify-static-libs
mkdir -p ${OBJDIR}
# Extract .o
echo "Extracting objects to ${OBJDIR}..."
for i in ${LIBSDIR}/*.a
do
echo $i
ar --output $OBJDIR -x $i
done
# Link objects into a single lib
echo "Creating $LIBNAME from objects..."
ar -crs $LIBNAME $OBJDIR/*.o
# Clean up
rm -rf ${OBJDIR}
echo "Done."
Этот вопрос специфичен для Linux. Если вы ищете, как это сделать в macOS, ответ будет
libtool
, как объяснено здесь :
libtool -static -o new.a old1.a old2.a
ar crsT libaz.a libabc.a libxyz.a
Здесь вы создаете архив архивов, а затем "сглаживаете" (прореживаете) результат с помощью флага T. Не уверен, как это будет работать с файлами.o с таким же именем, которые могут содержаться внутри.
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"