如何构build我的Linux c ++应用程序以链接到旧版本的libc?

我已经在Ubuntu 12.04上构build了一个应用程序,并尝试在embedded式系统上运行它。 我在我的开发机器上运行apt-cache show libc6 ,显示(其中包括)

 Package: libc6 Priority: required Section: libs Architecture: i386 Source: eglibc Version: 2.15-0ubuntu10 Replaces: belocs-locales-bin, libc6-i386 Provides: glibc-2.13-1, libc6-i686 

embedded式设备上存在的libc6版本是2.8.90。 在设备的\lib目录中,我有2个库

 libc-2.8.90.so libc.so.6 

当我将应用程序复制到embedded式设备上时,出现以下错误

 /usr/lib/libc.so.6: version `GLIBC_2.15` not found (required by ./ServerSocketApp) 

我知道如果可能的话,当我在开发环境中构build应用程序时,我需要强制它链接到embedded式设备上存在的相同版本的libc6。 我的问题是,我根本不知道如何做到这一点。 我发现的答案现在对我来说毫无意义。 有没有一些选项,我需要传递给g ++得到这个链接到2.8.90版本?

在绝望中,我想是否有可能将我的开发机器上的libc复制到embedded式设备上,而不是已经存在的地方,希望最好? 我只是似乎无法find任何在线文档,用简单的语言解释了你甚至可以如何解决这个问题,所以任何build议都会真正受到欢迎,因为我正在把我的头发拉出来。

这从根本上是不正确的。 虽然您可能能够一起破解旧版libc的链接,但问题在于您的环境设置。

当您为嵌入式系统开发应用程序时。 你在主机上这样做。 通常,主机和嵌入式设备不在相同的架构上。 例如,您的主机通常是在x86上运行的台式机/笔记本电脑,嵌入式系统可能在ARM上。 如果您碰巧与嵌入式设备处于相同的架构,那纯属巧合。 标准的练习环境设置应该仍然如下:

  • 主机应该有一个工具链设置来将构建应用程序交叉到嵌入式架构
  • 主机应该有你的嵌入式设备的完整rootfs副本。 这将包含您的交叉工具将用于编译嵌入式系统的应用程序的所有库

如果你有这样的设置。 发展会很容易。 您将能够设置简单,干净的make文件来构建应用程序,然后将二进制文件scp到嵌入式系统并运行。

好的,这里有一个比较长的解释,但要小心。 我仍然强烈建议你设置一个chroot环境来匹配嵌入式设备上可用的环境,并在构建过程的最后阶段使用它。

您应该了解如何加载和执行动态链接的ELF可执行文件。 有一种称为运行时链接编辑器 (RTLD),也称为动态链接器,负责加载所有必要的动态链接库,修复重定位等。 在具有glibc2 64位Linux系统上,使用glibc2/lib64/ld-linux-x86-64.so.2 32位Linux系统上的动态链接程序的名称是glibc2 。 动态链接器与glibc2库紧密耦合,通常只能处理该库的匹配版本。 而且它的路径被链接器硬编码成可执行文件(通常是ld ,编译器隐式调用来做链接)。 您可以通过简单地执行ldd some_elf_executable轻松检查最后一条语句的ldd some_elf_executable – 运行时链接编辑器显示完整路径:

 $ ldd some_elf_executable linux-vdso.so.1 => (0x00007fffab59e000) libm.so.6 => /lib64/libm.so.6 (0x0000003648400000) libc.so.6 => /lib64/libc.so.6 (0x0000003648800000) /lib64/ld-linux-x86-64.so.2 (0x0000003648000000) <--- the RTLD 

为了生成一个动态链接的可执行文件,该可执行文件使用的glibc2版本与系统上安装的glibc2版本不同,要运行可执行文件,应该将代码与以下一组选项链接到ld

  • -rpath=/path/to/newer/libs – 这个指示动态连接器在尝试解决库依赖关系时首先搜索/path/to/newer/libs/path/to/newer/libs应该与您在嵌入式设备上复制了更新的glibc2版本的路径匹配
  • -rpath-link=/path/to/newer/libs – 此选项指示链接器(而不是动态链接器)在链接时解决共享库之间的依赖关系时使用/path/to/newer/libs – 这不应该是正常的在你的情况下必要的
  • --dynamic-linker=/path/to/newer/libs/ld-linux.so.2 – 这个覆盖了被嵌入到可执行文件中的RTLD的路径

将这些选项提供给ld方法通常是通过GCC的-Wl选项。

 -rpath=/path/to/newer/libs 

变为:

 -Wl,-rpath,/path/to/newer/libs 

(注意=被替换为)

 --dynamic-linker=/path/to/newer/libs/ld-linux.so.2 

变为:

 -Wl,--dynamic-linker,/path/to/newer/libs/ld-linux.so.2 

您应该从开发系统将/lib/ld-linux.so.2复制到嵌入式设备上的/path/to/newer/libs/ 。 您还应该复制libc.so.6 ,数学库libm.so.6以及可执行文件使用的或可能间接加载的所有其他库。 请注意, libc.so.6libm.so.6实际上是名称类似于libc-2.<version>.so的实际库的符号链接。 你应该复制这些库文件,并创建适当的符号链接,让每个人都高兴。

您可能有一些运气与LSB SDK( http://www.linuxfoundation.org/collaborate/workgroups/lsb/download )编译,这限制了可用于可执行文件的符号。