How to Combine Several C/C++ Libraries into One

How can I combine several C/C++ libraries into one?

On Unix like systems, the ld and ar utilities can do this. Check out http://en.wikipedia.org/wiki/Ar_(Unix) or lookup the man pages on any Linux box or through Google, e.g., 'Unix man ar'.

Please note that you might be better off linking to a shared (dynamic) library. This would add a dependency to your executable, but it will dramatically reduce its size, especially if you're writing a graphic application.

Merge multiple .so shared libraries

Merging multiple shared libraries into one is indeed practically impossible on all UNIXen, except AIX: the linker considers the .so a "final" product.

But merging archives into .so should not be a problem:

gcc -shared -o c.so -Wl,--whole-archive a.a b.a -Wl,--no-whole-archive

How to merge two ar static libraries into one?

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

How to combine shared libraries?

This assumes you have the source code to all shared objects:

Provided there are no name space conflicts (which there should not be if the two co-exist as it is), it would not be too terribly hard to build them into one shared object.

If the shared libraries themselves depend on code from another library, order is going to matter. The real work is just getting the dependencies worked out in the makefile. I've never seen circular dependencies in SO's successfully link, so I doubt that you have them to begin with. I.e. foo() depends on bar() which depends on foo().

I've done this several times, though the libraries themselves were trivial. I took parts from ustr (string handler), a configuration file handler, some other custom parsers and other utility functions and created a custom mash up.

The real pain is bringing in upstream improvements to each once you have combined them, however I'm not sure if that's an issue for you.

So if you have:

libfoo.so: $(LIB_FOO_OBJECTS) $(LIB_BAR_OBJECTS) $(LIBFOOBAR_OBJECTS)

Where:

LIB_FOO_OBJECTS = \
$(libfoo)/foo.o \
$(libfoo)/strings.o

LIB_BAR_OBJECTS = \
$(libbar)/bar.o
....

... and the order is correct .. the rest is pretty easy. Note I didn't show header deps, everyone does that a little differently. They are important when making mash-ups though, as you'd probably want to avoid recompiling the whole library every time one header changes.

NB: If all three projects are using autotools .. your task just got exponentially easier (or harder) depending.

If you DON'T have the source code

If there is a static version of each library, you may be able to extract the objects and use them. I.e.:

$ cp /usr/lib/foo.a ./foo.a
$ ar x foo.a
$ gcc -fPIC -shared *.o -o foo.so

Of course its quite a bit more involved than illustrated.

I have never tried that and don't know how to handle SOs that have main() when it comes to linking in that case.

Combining static libraries

1/ Extract ALL of the object files from each library (using ar) and try to compile your code without the libraries or any of the object files. You'll probably get an absolute bucket-load of undefined symbols. If you get no undefined symbols, go to step 5.

2/ Grab the first one and find out which object file satisfies that symbol (using nm).

3/ Write down that object file then compile your code, including the new object file. You'll get a new list of undefined symbols or, if there's none, go to step 5.

4/ Go to step 2.

5/ Combine all the object files in your list (if any) into a single library (again with ar).

Bang! There you have it. Try to link your code without any of the objects but with the new library.

This whole thing could be relatively easily automated with a shell script.



Related Topics



Leave a reply



Submit