我需要在当前的Ubuntu(12.04)上编译一个程序。该程序应该在使用较旧内核(2.6.18)的CentOS集群上运行。不幸的是,我不能直接在集群上进行编译。如果我只是编译并复制程序而没有做任何更改,我会收到“内核版本太老”的错误消息。
据我所知,造成这个问题的原因不是内核版本,而是用于编译的libc版本。因此,我尝试动态链接集群中的libc并静态地链接其他所有内容来编译我的程序。
研究:
已经有很多关于此问题的问题在SO上,但没有一个答案真正适用于我。因此,以下是我对该主题的研究:
我对这个错误有些困惑,因为它使用了正确的路径(即来自集群的libc),但仍然抱怨缺少glibc版本。在集群上运行ldd时返回
现在我有两个主要问题:
据我所知,造成这个问题的原因不是内核版本,而是用于编译的libc版本。因此,我尝试动态链接集群中的libc并静态地链接其他所有内容来编译我的程序。
研究:
已经有很多关于此问题的问题在SO上,但没有一个答案真正适用于我。因此,以下是我对该主题的研究:
- 这个问题解释了Kernel版本过旧的原因
- 这个问题类似但更加专业,没有答案
- 像这里建议的静态链接并不起作用,因为集群上的libc版本太老了。一个答案也提到了使用旧的libc构建,但没有解释如何做到。
- 一种方法是在运行旧操作系统的虚拟机中编译。这个方法很复杂。我还读到你不应该静态链接libc
- 显然可以使用选项
-rpath
为不同的libc版本进行编译,但对我来说并没有起作用(见下文)
当前状态
我将以下文件从集群复制到目录 /path/to/copied/libs
中。
- libc-2.5.so
- libgcc_s.so.1
- libstdc++.so.6
我正在使用选项-nodefaultlibs -Xlinker -rpath=/path/to/copied/libs -Wl,-Bstatic,-lrt,-lboost_system,-lboost_filesystem -Wl,-Bdynamic,-lc,-lstdc++,-lgcc_s
进行编译。
编译后的二进制文件的ldd输出为:
mybin: /path/to/copied/libs/libc.so.6: version `GLIBC_2.14' not found (required by mybin)
mybin: /path/to/copied/libs/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by mybin)
linux-vdso.so.1 => (0x00007ffff36bb000)
libc.so.6 => /path/to/copied/libs/libc.so.6 (0x00007fbe3789a000)
libstdc++.so.6 => /path/to/copied/libs/libstdc++.so.6 (0x00007fbe37599000)
libgcc_s.so.1 => /path/to/copied/libs/libgcc_s.so.1 (0x00007fbe3738b000)
/lib64/ld-linux-x86-64.so.2 (0x00007fbe37bf3000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fbe37071000)
我对这个错误有些困惑,因为它使用了正确的路径(即来自集群的libc),但仍然抱怨缺少glibc版本。在集群上运行ldd时返回
not a dynamic executable
,运行二进制文件会导致上述相同的两个错误。看起来还包括其他库(linux-vdso.so.1、ld-linux-x86-64.so.2和libm.so.6)。我是否也应该使用旧版本的这些库?现在我有两个主要问题:
- 这是否是正确的方法?
- 如果是:如何正确地链接旧的libc?