使用 Guix 针对旧的 glibc 进行构建

Build against an old glibc with Guix

假设你有一个 c 程序,但几乎任何程序都可以,并将它放在一个文件中:

#include <stdio.h>
#include <gnu/libc-version.h>

int main (void) {
    puts (gnu_get_libc_version ());
    return 0;
}

并说出于某种原因,您想针对特定版本的 glibc 构建它。我最初的尝试是创建一个 Guix 环境,其中包含 glibc 的旧版本以及 gcc(对于像 ls 这样的程序,coreutils)。

$ guix environment --pure --ad-hoc glibc@2.29 gcc-toolchain coreutils
$ rm a.out && gcc printer.c && ldd a.out && a.out
    linux-vdso.so.1 (0x00007ffd2cd0c000)
    libgcc_s.so.1 => /gnu/store/jlrfl1ss3b4xjggvajwffa9zppfcxksf-gcc-5.5.0-lib/lib/libgcc_s.so.1 (0x00007fcefd7b6000)
    libc.so.6 => /gnu/store/fa6wj5bxkj5ll1d7292a70knmyl7a0cr-glibc-2.31/lib/libc.so.6 (0x00007fcefd5f9000)
    /gnu/store/fa6wj5bxkj5ll1d7292a70knmyl7a0cr-glibc-2.31/lib/ld-linux-x86-64.so.2 (0x00007fcefd7d1000)
2.31

不幸的是,这似乎不起作用。生成的程序链接到比我预期的更新的 glibc 版本,2.31 而不是 2.29。但这可能是由于 gcc 本身被链接到 glibc 2.31 并且最终污染了环境,可以这么说。

$ ldd $(which gcc)
    linux-vdso.so.1 (0x00007fff7cfc5000)
    libm.so.6 => /gnu/store/fa6wj5bxkj5ll1d7292a70knmyl7a0cr-glibc-2.31/lib/libm.so.6 (0x00007ff842b93000)
    libc.so.6 => /gnu/store/fa6wj5bxkj5ll1d7292a70knmyl7a0cr-glibc-2.31/lib/libc.so.6 (0x00007ff8429d6000)
    /gnu/store/fa6wj5bxkj5ll1d7292a70knmyl7a0cr-glibc-2.31/lib/ld-linux-x86-64.so.2 (0x00007ff842cd6000)

我从这里去哪里?我试过使用 Guix 中打包的旧版本 gcc,但它们似乎都是针对 glibc 2.31 构建的。我也尝试将 -L /gnu/store/hlsas48h6x7364kcfs8yy6xfksdsffr4-glibc-2.29/lib 添加到我的 gcc-invocation 但无济于事。

我能够弄清楚,或者更确切地说:#guix@freenode 上的 cbaines 将我指向函数 make-gcc-toolchain,它允许我设置我想要的环境。通过将以下代码放入名为 development-environment.scm:

的文件中
(use-modules (gnu packages base)
             (gnu packages commencement)
             (gnu packages gcc)
             (gnu packages version-control))

(define-public gcc-glibc-2.29-toolchain
  (make-gcc-toolchain gcc glibc-2.29))

(list gcc-glibc-2.29-toolchain git coreutils)

然后 运行宁 guix environment --pure --ad-hoc --load=development-environment.scm 我能够使用我想要的 glibc 版本构建我的程序:

$ rm a.out && gcc printer.c && ldd a.out && ./a.out
    linux-vdso.so.1 (0x00007fff7e17c000)
    libgcc_s.so.1 => /gnu/store/71rcc4qxfgyzr0qphkh9adjsqsb999zk-gcc-glibc-2.29-7.5.0-lib/lib/libgcc_s.so.1 (0x00007f2c8adc9000)
    libc.so.6 => /gnu/store/hlsas48h6x7364kcfs8yy6xfksdsffr4-glibc-2.29/lib/libc.so.6 (0x00007f2c8ac0f000)
    /gnu/store/hlsas48h6x7364kcfs8yy6xfksdsffr4-glibc-2.29/lib/ld-linux-x86-64.so.2 (0x00007f2c8ade4000)
2.29

后人的热点提示:将以下内容放入名为 .envrc 的文件中,安装包 direnv 并将其插入到您的 shell rc 中,并在其中填充以下内容:

use guix --ad-hoc --load=development-environment.scm

这样,每次您使用 shell 进入该文件夹时,都会为您加载开发环境。 glibc/gcc 的正确版本将是 运行 即使没有 --pure 标志。