假设您有一个针对 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-system
:https://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