【问题标题】:Moving a compiled Haskell program移动已编译的 Haskell 程序
【发布时间】:2012-07-19 18:51:14
【问题描述】:

我想在一个 Linux 机器上编译一个 Haskell 程序,然后在另一个 Linux 机器上运行它。但是,这似乎根本不起作用。我收到有关缺少库的错误。

大概当我安装 GHC 时,包管理器也会安装它需要的所有库和东西。 [我有些恼火地注意到,至少有一个打包系统无法安装 GCC,而 GHC 显然无法在没有...的情况下运行...] 但是,当然,目标系统没有安装这些依赖项。因此,如果我将编译后的二进制文件复制到目标系统,它就无法运行。

有没有办法解决这个问题?我习惯于使用 Windows,如果您在其中编译某些东西,它只会在所有 Windows 系统上工作。 (至少,直到你真正尝试使用非标准工具,如数据库访问或其他东西......)像这样的一些神秘的胡言乱语。

只是为了让事情变得有趣:我只有对目标机器的 FTP 访问权限,而不是 shell 访问权限。我什至不完全确定它运行的是什么操作系统。所以我可以随心所欲地更改我的 build 机器,但除了将文件复制到它之外,我无法对 target 机器做任何事情。

【问题讨论】:

  • 我会开始但在 google 上查找该错误以及手头的 linux 发行版的名称,可能是其他人使用存储库包时遇到的错误
  • 我不得不笑“如果你编译一些东西,它只适用于所有 Windows 系统。”。你听说过“DLL 地狱”这个词吗?该术语并非来自 Linux。 ;-)
  • @DanielWagner 你意识到“DLL 地狱”在大约 10 年前就不再是一个问题了,对吧?
  • @MathematicalOrchid,DLL 地狱仍然存在。如果程序 A 需要“mylib.dll v3.0”,然后程序 B 需要“mylib.dll v4.0”,程序 A 将停止工作,因为它不支持新覆盖的 DLL。 Windows 有两种解决方案:创建名称略有不同的库的多个副本,并使可执行文件链接到特定版本(因此在我的计算机上通过“d3dx9_43.dll”创建“d3dx9_1.dll”),或创建“虚拟”系统覆盖”在 system32 上,以便程序获取它自己安装的 DLL。这两种解决方案都会导致巨大的内存浪费和磁盘开销。

标签: linux haskell ghc


【解决方案1】:

在这方面,Linux 的行为与 Windows 类似。如果您在 Linux 上编译 Haskell 可执行文件,它将在任何具有正确库的 Linux 发行版上运行。问题是在 Windows 中,Haskell 可执行文件不是用动态版本的 libgmp 编译的。它们是使用静态版本编译的(以便将库编译为可执行文件),这正是因为在分发可执行文件时在 Windows 上处理 dll 非常困难。在 Linux 上安装新库相对容易。

您可以做的是将 libgmp.so.10(可能是指向不同文件的符号链接)从 /usr/lib 复制到与可执行文件相同的目录中。然后,您可以在启动可执行文件之前将 LD_LIBRARY_PATH 环境变量设置为“.”,即当前目录。这将使 Linux 在与其启动的可执行文件相同的目录中查找库,从而找到该库。这可以通过启动器脚本来完成:

#!/bin/sh
export LD_LIBRARY_PATH=.
`dirname "$0"`/myexecutable "$@"

保存此脚本并使用chmod +x myscript 将其标记为可执行文件将使您的可执行文件工作。

您可以使用ldd 命令检查您的可执行文件可能需要的其他库以及目标系统上没有的库。

【讨论】:

  • 这是否意味着 GMP 是导致问题的唯一库?我认为问题在于 Linux 通常不支持在没有复杂包管理器的广泛支持的情况下移动任意二进制文件...
  • 包管理器只管理包。文件被复制。没有魔法。
  • 当然。数百百万个文件。在完全正确的组合。没有魔法 - 只是大量的辛勤工作。 ;-)
  • 你看,ELF(在linux中使用)和PE(在windows中使用)可执行文件格式都支持静态和动态链接。在所有主要的 linux 发行版中,大多数已安装的二进制文件都由发行版维护者动态链接到该发行版还提供的共享库。因此,将/usr/bin/gnome-panel 移动到另一个 linux 系统可能很困难,因为共享库名称被编译到二进制文件中,并且可能无法在外国发行版中解析它们。另一方面,没有什么能阻止您编译二进制文件并静态链接它...
  • ..反对它的所有依赖。您将获得包含运行所需的所有代码的大型二进制文件。您可以向 GHC 提供 -static 选项,它应该编译您的二进制文件,其中包含所有库。
【解决方案2】:

如果你想在机器之间移动可执行文件,你必须静态链接,使单个可执行文件没有外部库依赖。如何做到这一点取决于编译器,并且 ghc 有 -static 标志,即“链接静态版本的 haskell 库”。

顺便说一句,检查一下,您不要尝试在 32 位机器上运行 64 位可执行文件。在大多数情况下,64 位机器上的 32 位可执行文件应该可以工作,但是……嗯,这取决于目标框的配置,所以请检查是否也是这种情况。

【讨论】:

  • “你必须静态链接”不,不是真的。
猜你喜欢
  • 1970-01-01
  • 2013-05-24
  • 1970-01-01
  • 1970-01-01
  • 2012-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多