How to merge two "ar" static libraries into one?

LinuxStatic LibrariesUnix Ar

Linux Problem Overview


I have 2 static Linux libraries, created by ar cr, libabc.a and libxyz.a.
I want to merge them into one static library libaz.a.
How can I do this.

I want to create a merged static library, not to give both libraries to final link of applications.

Linux Solutions


Solution 1 - Linux

There are at least three ways to do this natively. The first and most portable way is to use libtool. After having built the other libraries also with libtool, you can combine them just by adding the .la libs to an automake libaz_la_LIBADD variable, or directly from a Makefile with something like:

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

The other two are at least available when using GNU ar. You can use an MRI script (named for example libaz.mri), such as:

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

and then execute ar as:

ar -M <libaz.mri

Or you can use a thin archive (option -T), which will allow adding other archives without getting them nested inside, although the downside is that if you want to distribute the static library, the detached object will be missing:

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

All the above methods gracefully handle overlapping member names from the original archives.

Otherwise, you'd have to unpack into different directories and repack again, to avoid replacing overlapping member names:

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

Solution 2 - Linux

You can extract the object from both the .a files and create your .a file using the extracted .os:

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

Solution 3 - Linux

If you simply do it as :

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

you will lost some object files if there are members with same name in both a.a and b.a so, you need to extract members of different archives into different folder:

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

further more, it is posible that there are multiple members of same name in one archive (say in a.a), if you run ar x a.a, you will get only one for those members of same name.

The only way to extract all members of same name in one archive is to specify the member number by option '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
...

this would be a tedious work, so you will have to write a more sophisticate script to do that job.

One optional solutions is that you can combine multiple archives into one shared library:

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

this way the linker will handle all things for you!

Solution 4 - Linux

Even better you perform partial linking on each library and them make an archive of the two resulting object files. That way it operates like shared libraries would

You do partial linking with

gcc -r --nostdlib

so either instead of making the intermediate archive or after reextracting it, run

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

then

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

Solution 5 - Linux

You can always do partial linking:

gcc -r -o libnew.o -Wl,--whole-archive libabc.a libxyz.a
ar cr libnew.a libnew.o

Solution 6 - Linux

ar -x libx264.a
mkdir sub && cd sub
ar -m ../libx264.a `ar -t ../libx264.a |sort|uniq|grep "\.o"`
ar -x ../libx264.a

now you have two version of "macroblock-10.o"

Solution 7 - Linux

ar crsT libaz.a libabc.a libxyz.a

Here, you create archive of archives and then 'flatten' (thinning) result with T flag. Not sure how it'll work with same name .o files that might be contained within.

Solution 8 - Linux

This question is specific to Linux. If you're looking for how to do this on macOS, the answer is libtool, as explained here:

libtool -static -o new.a old1.a old2.a

Solution 9 - Linux

Here is a bash script to link all .a libs from a specified directory into a single library.

Usage: ./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."

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionosgxView Question on Stackoverflow
Solution 1 - LinuxGuillem JoverView Answer on Stackoverflow
Solution 2 - LinuxcodaddictView Answer on Stackoverflow
Solution 3 - Linuxsamuel.zzy220View Answer on Stackoverflow
Solution 4 - LinuxAllan JensenView Answer on Stackoverflow
Solution 5 - LinuxAllan JensenView Answer on Stackoverflow
Solution 6 - Linuxlaw weyView Answer on Stackoverflow
Solution 7 - LinuxEvgeny YashinView Answer on Stackoverflow
Solution 8 - LinuxtbodtView Answer on Stackoverflow
Solution 9 - LinuxDanijelView Answer on Stackoverflow