40

我必须在当前的 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?
4

2 回答 2

10

看到这个答案。

这甚至是正确的方法吗

不:您不能像链接命令那样使用不匹配的 glibc 版本。您使用crt0.old-linux.so来自的(系统安装的)libc,但libc.so.6来自旧的(从集群复制)libc。那是行不通的。

于 2012-06-03T06:21:00.670 回答
3

-rpath设置 DT_RPATH 标记但不告诉链接器在那里寻找库,你想要-L的。

于 2012-05-30T12:17:30.693 回答