我必须在当前的 ubuntu (12.04) 上编译一个程序。然后,该程序应在使用 CentOS 和旧内核 (2.6.18) 的集群上运行。不幸的是,我无法直接在集群上编译。如果我只是编译和复制程序而不做任何更改,我会收到错误消息“内核太旧”。
按照我的理解,其原因与其说是内核版本,不如说是用于编译的libc版本。因此,我尝试编译我的程序,动态链接集群中的 libc 并静态链接其他所有内容。
研究
SO上已经有很多关于这个的问题,但没有一个答案真的对我有用。所以这是我对该主题的研究:
- 这个问题解释了 Kernel too old 消息的原因
- 这个问题类似但更专业,没有答案
- 此处提出的静态链接不起作用,因为集群上的 libc 太旧了。一个答案还提到使用旧的 libc 进行构建,但没有解释如何做到这一点。
- 一种方法是在运行旧操作系统的 VM 中编译。这有效但很复杂。我还读到你不应该静态链接 libc
- 显然可以使用该选项编译不同的 libc 版本,
-rpath
但这对我不起作用(见下文)
当前状态
我将以下文件从集群复制到目录中/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?