views:

480

answers:

1

I've got some .so libraries that I'd like to combine into one shared library so that it doesn't depend on the original .so files anymore.

The .so files have dependencies to each other.

How can I do this? Can I do this?

+4  A: 

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.

Tim Post
What he wants is "libstuff.so: libfoo.so libbar.so", it isn't? I think that the problem is that he doesn't have the object files.
Jaime Soriano
@Jamie Soriano: The best thing to do (in all accounts) is to compile the objects that make the individual shared objects into one big shared object. If you just make one big SO that depends on the rest, you have done nothing to solve the dependency issue that made you do it in the first place.
Tim Post
@Jaime Soriano: That's what I really wanted. But I wasn't even sure this was possible.
Georg
Thanks for your excellent answer! Indeed I've got the source code to the objects and they haven't got circular dependencies. But it's a moderate project http://www.icu-project.org that is quite complicated to build and the advantages of a single `.so` is considerably smaller than the amount of work it is to modify the make-script. I've originally tried to build it into a static library and use that with my own code to build a `.so` file. Unfortunately the static-build of ICU4.2.1 seems to be broken.
Georg
@gs: That is going to be a MAJOR pain to keep up with from version to version. If you're in a position where you simply can not guarantee the presence of each so for binary distribution, shoot for fixing the static objects and using them (ugly, but less than the major surgery you are contemplating). I can imagine how big that might be, I noticed the source .tgz was well over 12M. Neither option seems optimal, unfortunately.
Tim Post
@tinkertim: The source is only that big because of the vast tables, it's not all source code. Still, I'm not going to invest much time and instead I'll just include 4 shared libraries. Ugly, but the only solution I see.
Georg
@gs: Every possible remedy here is ugly .. so picking the one that costs the least as far as time seems sensible. Sometimes, well, stuff is just ugly :)
Tim Post