带容器

带容器

假设您有一个针对 32 位 Intel x86 动态编译的二进制文件,您希望在 64 位 x86-64 Guix 系统上运行它。该二进制文件已在不同的系统上编译。您将如何运行它?

在 Ubuntu 上,可以在此处找到执行相同操作的说明:如何在 Ubuntu 64 位上运行 32 位应用程序?

答案1

在 Guix 系统上运行二进制文件的一个问题是它们不知道库的实际位置。他们想要使用全局安装的库,但 guix 仅将它们安装在商店中。有两种解决方案:创建一个二进制文件可以找到库的环境,或者修补二进制文件以查找库。

对于这两种解决方案,您需要知道需要哪些库。试试这个(ldd来自glibc包装):

$ ldd my-binary
linux-vdso.so.1 (0x00007ffe80da9000)
    libdl.so.2 => not found
    libc.so.6 => /gnu/store/fa6wj5bxkj5ll1d7292a70knmyl7a0cr-glibc-2.31/lib/libc.so.6 (0x00007f7651b77000)
    /gnu/store/fa6wj5bxkj5ll1d7292a70knmyl7a0cr-glibc-2.31/lib/ld-linux-x86-64.so.2 (0x00007f7651d3b000)

现在,您知道需要哪些库文件。记下它们并找到glibc运行该包所需的包。

带容器

第一个解决方案要求您创建一个容器,在其中在全局位置公开库和二进制文件。请注意我们如何-s i686-linux为该架构而不是默认架构构建环境。

PROFILE=$(guix environment -C -N --ad-hoc glibc ... -s i686-linux -- bash -c 'echo $GUIX_ENVIRONMENT')
guix environment -C -N --ad-hoc glibc ... -s i686-linux --expose=$PROFILE/lib=/lib --expose=$PROFILE/lib=/lib64

第一行创建PROFILE变量,其中包含我们为环境创建的配置文件的路径。它运行 echo 命令并立即存在。使用单引号是必不可少的,因为不希望 bash 来自外部扩展变量的环境。第二个命令实际上让您进入环境。如果程序需要图形显示,您将需要共享/公开更多内容。

与补丁

第二种解决方案是修补二进制文件,这样您就可以在正常环境中运行它,这意味着访问图形界面、音频或其他硬件时会遇到更少的麻烦。这使用 patchelf,有两种方法:手动方式(快速且肮脏)或打包方式。

又快又脏

快速而肮脏的方法是像这样构建您之前注意到的每个依赖项(对于 glibc):

$ guix build glibc -s i686-linux
/gnu/store/9728x9zhj8d3zlyzsjpz342jpccrgkgd-glibc-2.31

这将为您提供商店路径,并确保该库存在于您的商店中。

现在,使用 patchelf (来自patchelf包):

patchelf --set-interpreter /gnu/store/...-glibc-.../lib/ld-linux.so.2
patchelf --set-rpath /gnu/store/...-glibc-.../lib:/gnu/store/.../lib:/gnu/store/.../lib:...

这将解释器设置为 ld-linux.so.2(对于 32 位),以及 rpath(动态库的搜索路径)。它应该是所需库所在目录的以冒号分隔的列表。

这种方法相对较快,但是很脏,因为它没有注册任何 gc root,并且每次更新 guix 或运行垃圾收集器时都需要重做一次。

使用包

最后一种可能性是为您的二进制文件创建一个包定义,它将注册依赖项信息,您也可以使用此方法在您的配置文件中安装二进制文件。你可以在nonguix中使用binary-build-systemhttps://gitlab.com/nonguix/nonguix

此方法的一个缺点是它将二进制文件复制到存储中,并且二进制文件可能很大。但使用包定义更加面向未来,因为您始终可以再次构建它并更新包。二进制构建系统本质上以一种更具声明性的方式为您执行上面的 patchelf 命令。你可以这样定义一个包:

(package
  (name "my-binary")
  (version "version")
  (source (local-file "/home/..."))
  (build-system binary-build-system)
  (arguments
   `(#:patchelf-plan
     `(("my-binary" ("libc" "gcc:lib" ...)))
     #:install-plan
     `(("my-binary" "bin/"))))
  (inputs
   `(("gcc:lib" ,gcc "lib")))); note how the first string must match the one in
                              ; patchelf-plan. libc is already implicitely defined

然后,您可以使用以下内容构建此包:

guix build -s i686-linux -f my-package.scm

相关内容