Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linking an application to libbz2.so.1 rather than libbz2.so.1.0

Tags:

c++

c

linux

g++

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.

like image 777
Fred Avatar asked Dec 02 '09 20:12

Fred


2 Answers

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).

like image 176
Peeter Joot Avatar answered Sep 28 '22 09:09

Peeter Joot


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.

like image 22
Dirk Eddelbuettel Avatar answered Sep 28 '22 09:09

Dirk Eddelbuettel