tags:

views:

371

answers:

2

Here's the current situation I'm in:

I want to distribute a binary app on Linux that would run on several distros (not all of them, just the main ones matter at the moment, let's focus on Ubuntu and Fedora for the sake of this discussion). The app in question links to libbz2 for some of its work. A simple "Hello World" will illustrate the situation :

/* main.cpp */
#include <iostream>

int main(int argc, char* argv[])
{
  std::cout << "Hello World!\n";
  return 0;
}

The app is built as such :

g++ -lbz2 -o test.bin main.cpp

My build system is on Ubuntu. When I perform a check with ldd on the resulting binary, it lists libbz2.so.1.0 as a runtime dependency. When I take this app to a Fedora machine, the app doesn't run and ldd reveals that it can't find libbz2.so.1.0. Fedora only has libbz2.so.1 and libbz2.so.1.0.4, but not libbz2.so.1.0.

Red Hat's Bugzilla database reveals that this behavior is not a bug, but a feature. I don't really need libbz2.so.1.0, and I would be satisfied with simply linking to libbz2.so.1, but I have yet to figure out how.

I have seen a similar question asked here previously, but the accepted answer (You can pass the actual .so file instead of -l on the linker command line) doesn't seem to work. I tried building with the following command :

g++ /lib/libbz2.so.1 -o test.bin main.cpp

However, ldd still mentions that the app depends on libbz2.so.1.0, even though I passed the full name to g++.

Now, the question is, is there a way on Ubuntu to build the app to have it depend only on libbz2.so.1 rather than on libbz2.so.1.0?

Thanks.

+3  A: 

Why don't you just link statically instead?

I have done that in the past for builds on Ubuntu and deployment on RHEL which works just fine using static builds.

Dirk Eddelbuettel
*facepalm* ... because that was too obvious. For some reason I took for granted that bzip2 would be licensed LGPL, which forbids static linking, but it would seem it is BSD, which allows it... Static linking it is then. Thanks.
Fred
No sweat. But why do you think LGPL has anything to say on how you link? You can use static or dynamic links with LGPL and GPL code -- your restrictions are on how you distribute your app etc pp and whether you have to provide source code. That is wholly independent of your build process.
Dirk Eddelbuettel
Ok, I should have been more precise. LGPL forbids static linking into a proprietary app.As for people looking for the full answer, here's how to do it if you want to link statically with *some* libs and dynamically with *some* other libs :g++ -Wl,-Bstatic -lbz2 -Wl,-Bdynamic -lotherlib -o test.bin main.cpp
Fred
+1  A: 

Here's a bit of background to explain what got linked. On ELF platforms the -L and -l flags you pass only locate the binary at link time. If the linker linker determines that a library is required it generates a reference to the SONAME in that binary, regardless of what it was called. For example:

$ objdump -p /lib64/libbz2.so.1 | grep SONAME
  SONAME      libbz2.so.1

So regardless of what libbz2 is named, that is what will show up as a dependency. Again by example, doing something totally whacked:

$ ln -s /lib64/libbz2.so.1 libblah.so
$ g++ t.C -L. -l blah

You have the apparency of having linked to libblah but because its the SONAME in that binary that matters, your dependency is still this libbz2.so.1

$ ldd a.out | grep bz2
        libbz2.so.1 => /lib64/libbz2.so.1 (0x00002b3d1a000000)

Other than the -static trickery (which can break things in interesting ways), there is not easy way out of the mess (ideally the library would do nice symbol versioning like glibc and never or rarely change its SONAME).

Peeter Joot