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

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

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

libc.so.6该二进制文件与 21.04 OS 版本上提供的二进制文件相链接。

相同的二进制文件,在 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)

在 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)

我的问题:

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

或者,更好的是,为什么它没有与某种叫做“-”的东西相联系libglibc.so.2.34——如果那是一种依赖关系的话?

答案1

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

libc.so是它们的核心库。几乎所有东西都依赖于它。glibc 的目标之一是提供向后兼容性 - 可以在较旧版本上运行的程序(通常)也可以在较新版本中正常运行。但是,如果您仅因为添加了一些新功能而将libc.so.6soname 更改为,那么libc.so.7全部这些之前建立的项目将毫无理由地需要重建。还没有真正主要的glibc 的 API 中断,无法保证这一点。

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

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

答案2

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

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

除非解释源代码,否则通常需要为不同版本的 Ubuntu 分别构建二进制包。发射台可以为您自动完成该操作。

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

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

答案3

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

作为本介绍解释说,glibc 包含每个随时间而变化的符号的多个版本,因此libc.so.6包含从 2.0 到它所说的任何版本的所有 glibc 版本。

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

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

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

我认为 Windows 的做法更接近于捆绑多个明确定义的配置文件,并敦促所有预编译库的作者提供针对较旧配置文件的版本。(但需要注意的是,你必须假设这些东西必须free由编写它的同一编译单元编写,因为mallocPE 没有全局符号,并且不同的库可能依赖于具有自己的static变量和语义差异的不同版本的分配器。)

相关内容