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

时间:2012-07-09 14:57:49

标签: c++ linux linker g++ embedded-linux

我在Ubuntu 12.04上构建了一个应用程序,并尝试在嵌入式系统上运行它。我在我的开发机器上运行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

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

libc-2.8.90.so
libc.so.6

当我将我的应用程序复制到嵌入式设备上时,我收到以下错误

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

我知道如果可能的话,当我在开发机器上构建应用程序时,我需要强制它链接到嵌入式设备上存在的相同版本的libc6。我遇到的问题是我根本不知道该怎么做。我发现的任何答案对我来说都毫无意义。是否有一些选项需要传递给g ++才能将其链接到版本2.8.90 ??

绝望中我想是可以将我的开发机器上的libc复制到嵌入式设备上代替已经存在的东西并希望最好的???我似乎无法在网上找到任何文件,用简单的术语解释你怎么做到这一点所以任何建议都会非常受欢迎,因为我在这里撕裂我的头发。

3 个答案:

答案 0 :(得分:9)

好的,这是一个稍长的解释,但要小心。我仍然强烈建议您设置一个chrooted环境以匹配嵌入式设备上可用的环境,并在构建过程的最后阶段使用它。

您应该了解如何加载和执行动态链接的ELF可执行文件。有一种称为运行时链接编辑器(RTLD)的东西,也称为动态链接器,它负责加载所有必需的动态链接库,修复重定位等。动态链接器的名称在32位Linux系统上为/lib/ld-linux.so.2,在64位Linux系统上具有glibc2/lib64/ld-linux-x86-64.so.2 glibc2。动态链接器非常紧密耦合到glibc2库,通常只能处理该库的匹配版本。此外,它的路径是链接器硬编码到可执行文件中(通常是ld,由编译器隐式调用以进行链接)。只需执行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版本与系统上安装的版本不同,要运行可执行文件,您应该将代码与以下一组选项链接到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的真实库的符号链接。您应该复制这些库文件并创建适当的符号链接,以使每个人都满意。

答案 1 :(得分:1)

您可能会对LSB SDK(http://www.linuxfoundation.org/collaborate/workgroups/lsb/download)进行编译,这会限制可执行文件可用的符号。

答案 2 :(得分:1)

这基本上是不正确的。虽然您可能能够在旧libc中链接一种链接方式,但问题在于您的环境设置。

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

  • 主机应具有工具链设置,以便将应用程序交叉构建到嵌入式体系结构
  • 主机应具有嵌入式设备中存在的完整rootfs的副本。这将包含您的交叉工具将用于编译嵌入式系统的应用程序的所有库

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