Search code examples
c++linuxhyperlinkshared-librariesglibc

Which version of glibc should be used when release my *.so file?


I'm working on a shared library which support SSL connection and transmission. I want to release it as a *.so file. After compiling it in my Ubuntu14.04(64bit Desktop) with g++ 4.8.2, it can not work in the CentOS5.8.

The First Round

I compile the shared library with following command:

g++ -v -shared -Wl,-soname,libmyssl.so.1,-o libmyssl.so.1.0 myssl.o -lz -lssl -lcrypto

I use command objdump -p libmyssl.so.1.0|grep NEEDED to know it depends on following libraries:

NEEDED      libz.so.1
NEEDED      libssl.so.1.0.0
NEEDED      libcrypto.so.1.0.0
NEEDED      libstdc++.so.6
NEEDED      libc.so.6

Then I write a demo to use libmyssl.so.1.0.

g++ -D UNIX64 -o ssldemo ssldemo.cpp ./libmyssl.so.1.0 -lz -lssl -lcrypto 
  1. I compile the demo in Ubuntu14.04(the same version), it works fine.
  2. I compile the demo in CentOS(openssl 0.9.8e), it linked failed because invalid openssl's version

The Second Round

I removed the "-lz lssl -lcrypto", so the command as following

g++ -v -shared -Wl,-soname,libmyssl.so.1,-o libmyssl.so.1.0 myssl.o 

I use command objdump -p libmyssl.so.1.0|grep NEEDED to know it depends on following libraries:

NEEDED      libstdc++.so.6
NEEDED      libc.so.6

I use the libmyssl.so.1.0 in above demo code in the same way:

g++ -D UNIX64 -o ssldemo ssldemo.cpp ./libmyssl.so.1.0 -lz -lssl -lcrypto 
  1. I compile the demo in Ubuntu14.04(the same version), it works fine.
  2. I compile the demo in CentOS(openssl 0.9.8e), it didn't report ssl linked errors, but it report glibc linked errors as follows:

    undefined reference to `memcpy@GLIBC_2.14'

After updating CertOS's glibc, the demo work fine.

The Third Round

I try to remove the depends to "libc.so.6" and "libstdc++.so.6", so I added option "-nodefaultlibs" to the compile command:

g++ -nodefaultlibs -v -shared -Wl,-soname,libmyssl.so.1,-o libmyssl.so.1.0 myssl.o
  • I use command objdump -p libmyssl.so.1.0|grep NEEDED only get empty string.
  • I use command ldd libmyssl.so.1.0 get result "statically linked", no sure why it said "statically linked".

I use the libmyssl.so.1.0 in above demo code in the same way:

g++ -D UNIX64 -o ssldemo ssldemo.cpp ./libmyssl.so.1.0 -lz -lssl -lcrypto 

It always report following error both in Ubuntu14.04 and CentOS5.8:
Ubuntu:

hidden symbol `atexit' in /usr/lib/x86_64-linux-gun/libc_nonshared.a(atexit.oS) is referenced by DSO
/usr/bin/ln: final link failed: Bad value

CentOS:

hidden symbol `atexit' in /usr/lib64/libc_nonshared.a(atexit.oS) is referenced by DSO
/usr/bin/ln: final link failed: Nonrepresentable section on output

Questions:

  1. Which version of GLIBC should be linked when I compile my *.so file so that it can work fine in as many as possible Linux?
  2. Do have a way to avoid the dependency to the GLIBC? I tried it in The Third Round but failed.
  3. Any other suggestions ?

Solution

  • Which version of GLIBC should be linked when I compile my *.so file so that it can work fine in as many as possible Linux?

    You should select the oldest distro that you want to target and build on this one. This would ensure that your library would require the minimum possible Glibc version. So simply select the distro with oldest Glibc and build there.

    Version of your Glibc is usually encoded in libc.so name (e.g. /lib64/libc-2.12.so) but you can also do

    $ strings //lib64/libc-2.12.so | grep GLIBC
    GLIBC_2.2.5
    GLIBC_2.2.6
    ...
    GLIBC_2.12
    GLIBC_PRIVATE
    

    Do have a way to avoid the dependency to the GLIBC? I tried it in The Third Round but failed.

    Writing entirely Glibc-independent library sounds like an overkill (you'll need to re-implement IO, memcpy, etc., with lower quality/performance compared to Glibc). Are you sure you want to go down this path?

    Any other suggestions ?

    For complete applications two common solutions are

    • static linking
    • bundling them together with stdlibs they were linked against (they'll of course need to be run with special LD_LIBRARY_PATH or -Wl,-rpath)

    But in your case (isolated shared library) targeting the lowest supported Glibc seems to be the only option.