为什么 21.10 构建的二进制文件与 21.04 安装不兼容?

Bra*_*ram 12 compatibility versions shared-library glibc

我不明白为什么在 21.10 上构建的二进制文件与 21.04 系统不兼容。

该二进制文件也链接到libc.so.621.04 操作系统版本上。

相同的二进制文件,在 21.10 系统上:

$ ldd turboledzd
    linux-vdso.so.1 (0x00007ffdc2595000)
    libhidapi-hidraw.so.0 => /lib/x86_64-linux-gnu/libhidapi-hidraw.so.0 (0x00007fdd64057000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fdd63e2f000)
    libudev.so.1 => /lib/x86_64-linux-gnu/libudev.so.1 (0x00007fdd63e06000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fdd64085000)
Run Code Online (Sandbox Code Playgroud)

在21.04系统上:

$ ldd turboledzd 
./turboledzd: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by ./turboledzd)
    linux-vdso.so.1 (0x00007fff9c570000)
    libhidapi-hidraw.so.0 => /lib/x86_64-linux-gnu/libhidapi-hidraw.so.0 (0x00007f37ec402000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f37ec216000)
    libudev.so.1 => /lib/x86_64-linux-gnu/libudev.so.1 (0x00007f37ec1ed000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f37ec423000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f37ec1cb000)
Run Code Online (Sandbox Code Playgroud)

我的问题:

如果21.04 与21.10libc.so.6不兼容,那么为什么不调用 21.10 上的 libc libc.so.6libc.so.7

或者,更好的是,为什么它不与称为libglibc.so.2.34- 如果这是依赖项的东西联系起来?

mur*_*uru 25

如果21.04 与21.10libc.so.6不兼容,那么为什么不调用 21.10 上的 libc libc.so.6libc.so.7

libc.so是一个库的核心。几乎一切都取决于它。glibc 的目标之一是提供向后兼容性 - 可以在较旧版本上运行的程序libc.so.6(通常)也可以在较新版本上正常运行。libc.so.7但是,如果您仅因为添加了一些新功能而将soname 更改为,那么所有这些先前构建的程序都将无缘无故地需要重建。glibc 的 API还没有真正重大的突破来保证这一点。

我不明白为什么在 21.10 上构建的二进制文件与 21.04 系统不兼容。

我没有看到任何人保证向前兼容性(这是您所期望的 21.04 能够从 21.10 运行某些东西) - 如果您不采取预防措施来确保它,为什么您会期望这一点?

  • @Bram“我如何使用新的操作系统来构建二进制文件” - docker 在这种情况下有很大帮助。例如,您可以使用“ubuntu:20.04”映像,将源目录映射到其中并在其中构建二进制文件。无需安装单独的 glibc / 交叉编译。 (10认同)
  • @Incomputable我不使用任何新功能。我只是使用新的操作系统进行编译。 (4认同)
  • @Bram是的,只是不要在比最旧的目标更新的系统上编译它,也不要使用比该目标支持更新的GCC,至少对于C++代码来说是这样,因为“libstdc++.so”将有完全相同的问题。 (4认同)
  • @Incomputable 使用 glibc/libstdc++ 并不容易,因为在链接时,您会自动使用这些库支持的最新 ABI,例如 OP 中的“GLIBC_2.34”,这是最终二进制文件需要出现在它加载的库中的在启动时。也许有一些链接器魔术可以做,但我不知道。 (4认同)
  • 自[1997年,Linux libc/glibc 分裂结束](https://man7.org/linux/man-pages/man7/glibc.7.html)以来,似乎如此。 (3认同)

Arc*_*ahi 13

根据packages.ubuntu.com,21.04 使用 glibc 2.33,而 21.10 使用 glibc 2.34,两者并不完全兼容。

但是,您应该能够从源代码构建 Ubuntu 21.04 的二进制文件。

除非源代码被解释,否则您通常需要为不同版本的 Ubuntu 单独构建二进制包。Launchpad可以为您实现自动化。

为什么 21.10 上的 libc 不称为 libc.so.7?

这是只有 glibc 的开发人员才能做出的决定。


sso*_*low 3

谷歌搜索的术语是“glibc 符号版本控制”。

正如本简介所解释的,glibc 包含每个符号的多个版本,这些版本随着时间的推移而发生变化,因此libc.so.6包含从 2.0 到其所说的任何版本的所有 glibc 版本。

当您链接新库或二进制文件时,您将使用.h最新版本符号的文件和导出符号。

至于访问旧的符号,StackOverflow 上有一个问题,名为“ How can I link to a certain glibc version?” ,但是因为所有其他依赖项也可能链接到最新的符号,所以使用 Docker 或 chroot 来定位较旧的系统版本要容易得多,因为如果不这样做,您可能会从头开始构建一个版本。

Python 开发人员实际上维护着manylinux...专门命名的 Docker 容器,用于为带有已编译组件的 Python 包构建轮子(可再发行的二进制包)建立可靠的基线。

我相信 Windows 方法更接近于捆绑多个明确定义的配置文件,并敦促预编译库的所有作者提供针对旧配置文件的构建。(需要注意的是,您必须假设这些内容必须free由相同的编译单元进行malloc处理,因为 PE 没有全局符号,并且不同的库可能依赖于具有自己的static变量和语义差异的不同版本的分配器。 )