views:

172

answers:

5

Hi. I have a c++ code that runs perfect on my linux machine (Ubuntu Karmic). When I try to run it on another version, I have all sort of shared libraries missing.

Is there any way to merge all shared libraries into single executable?

Edit: I think I've asked the wrong question. I should have ask for a way to static-link my executable when it is already built. I found the answer in ermine & statifier

+4  A: 

What you are describing is the use of static libraries instead of shared libraries.

Trent
The libraries need to be compiled as static first!
windfinder
system libraries often are provided in static versions. however, there is a problem here, since one function of dynamically linked libraries is to ensure compatibility against different kernel versions or different hardware. In this case statically linking may cause your program to fail where dynamic linking would select the appropriate compatible version. Also note that very few libraries are allowed to be linked statically UNLESS you have prepared for your program to be GPL licensed, which is fine unless you intend to keep your profits and code secrets to yourself.
Alex Brown
@windfinder, that's true, but if you want to be able to have no dependencies on shared libraries that is the only way. There are other solutions to try and handle the dependencies in a smart manner, but sagie asked how to merge everything into a single executable.
Trent
He did, but I think he needs to consider other solutions to the problem, since static linking is unsatisfactory in a number of ways. see my post for possible solutions.
Alex Brown
@Alex, I agree, he may not have known what question to ask, that is why I up-voted your answer as well.
Trent
+1  A: 

I am not too sure, but you may want to create your executable by statically linking all the libraries.

Amit
+6  A: 

There are 3 possible reasons you have shared libraries missing:

  • you are using shared libraries which do not exist by default on the other distribution, or you have installed them on your host, but not the other one, e.g. libDBI.so
  • you have over-specified the version at link time, e.g. libz.so.1.2.3 and the other machine has an API compatible (major version 1) but different minor version 2.3, which would probably work with your program if only it would link
  • the major version of the library has changed, which means it is incompatible libc.so.2 vs libc.so.1.

The fixes are:

  • don't link libraries which you don't need that may not be on different distros, OR, install the additional libraries on the other machines, either manually or make them dependencies of your installer package (e.g. use RPM)
  • don't specify the versions so tightly on the command line - link libz.so.1 instead of libz.so.1.2.3.
  • compile multiple versions against different libc versions.
Alex Brown
+1  A: 

One alternative is to dynamically load shared libraries using dlopen() and if it fails to load, exit gracefully with the message that the dependent library is required for the executable to work.
The user then may install the appropriate library.

Neeraj
+1  A: 

There have been several technical solutions to the original problem noted here, e.g.

compile multiple versions against different libc versions.

or

install the additional libraries on the other machines

but if you're in the position of an ISV, there is really just one sane solution:

Get a clean install of an older system, (e.g. Ubuntu 6.x if you're targeting desktops, perhaps as far back as Red Hat 9 if you're targeting servers) and build your software on that. Generally libraries (and definitely libc) are backwards compatible, so you you won't have problems running on newer systems.

Of course if you have non-standard or recent-version lib dependencies this doesn't completely solve the problem. In that case, as other's have suggested, if you want to be robust it's better to dlopen() and report the problems (or run with reduced functionality).

Nathan Kidd