释放我的 *.so 文件时应该使用哪个版本的 glibc?

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

我正在开发一个支持 SSL 连接和传输的共享库。我想将其作为 *.so 文件发布。在我的 Ubuntu14.04(64bit Desktop) 中用 g++ 4.8.2 编译后,它不能在 CentOS5.8 中运行。

第一轮

我使用以下命令编译共享库:

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

我使用命令 objdump -p libmyssl.so.1.0|grep NEEDED 知道它依赖于以下库:

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

那我写个demo用libmyssl.so.1.0.

g++ -D UNIX64 -o ssldemo ssldemo.cpp ./libmyssl.so.1.0 -lz -lssl -lcrypto 
  1. 我在Ubuntu14.04(同一个版本)编译demo,没问题
  2. 我在CentOS(openssl 0.9.8e)中编译demo,由于openssl版本不对导致链接失败

第二轮

我删除了“-lz lssl -lcrypto”,所以命令如下

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

我使用命令 objdump -p libmyssl.so.1.0|grep NEEDED 知道它依赖于以下库:

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

我在上面的demo代码中同样使用了libmyssl.so.1.0

g++ -D UNIX64 -o ssldemo ssldemo.cpp ./libmyssl.so.1.0 -lz -lssl -lcrypto 
  1. 我在Ubuntu14.04(同一个版本)编译demo,没问题。
  2. 我在CentOS(openssl 0.9.8e)编译demo,没有报ssl链接错误,但是glibc链接错误如下:

    对`memcpy@GLIBC_2.14'的未定义引用

更新 CertOS 的 glibc 后,演示工作正常。

第三轮

我尝试删除对 "libc.so.6" 和 "libstdc++.so.6" 的依赖,所以我在编译命令中添加了选项“-nodefaultlibs”:

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

我在上面的demo代码中同样使用了libmyssl.so.1.0

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

在Ubuntu14.04和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

问题:

  1. 当我编译我的 *.so 文件时应该链接哪个版本的 GLIBC 以便它可以在尽可能多的地方正常工作 Linux?
  2. 有没有办法避免对 GLIBC 的依赖?我在第三轮中尝试过但失败了。
  3. 还有其他建议吗?

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?

您应该 select 您想要定位并在此基础上构建的最旧的发行版。这将确保您的库需要尽可能低的 Glibc 版本。所以只需 select 最旧的 Glibc 发行版并在那里构建。

您的 Glibc 版本通常以 libc.so 名称编码(例如 /lib64/libc-2.12.so),但您也可以

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

编写完全独立于 Glibc 的库听起来有点矫枉过正(您需要重新实现 IO、memcpy 等,quality/performance 与 Glibc 相比)。您确定要走这条路吗?

Any other suggestions ?

对于完整的应用程序,两种常见的解决方案是

  • 静态链接
  • 将它们与它们所链接的标准库捆绑在一起(它们当然需要 运行 具有特殊的 LD_LIBRARY_PATH 或 -Wl,-rpath)

但在您的情况下(独立的共享库),针对最低支持的 Glibc 似乎是唯一的选择。