创建一个静态的Haskell Linux可执行文件。

26

我很少遇到两个我非常喜欢的事情结合在一起给我带来这么多困扰(除了我的孩子)。我在工作中编写了一个使用类似text、xml-enumerator、attoparsec-text等库的Haskell程序。我已经在我工作的Windows机器上,我的Ubuntu虚拟机上(32位),我的Ubuntu桌面上(再次是32位)以及运行Ubuntu(64位)的EC2实例上使它正常工作。

我们的客户正在运行CentOS 5.3,64位。 我无论如何都不能让这个可执行文件正常运行。我尝试使用以下命令创建静态可执行文件:

ghc --make myprog.hs -optl-static -optl-pthread

但是当我尝试在CentOS服务器上运行该可执行文件时,出现错误信息:

openFile: invalid argument (Invalid argument)

我猜这与这里描述的错误有关。我尝试编译32位和64位Ubuntu,尝试静态和共享构建,但无济于事(虽然偶尔会出现段错误而不是上述错误消息)。我可以尝试下载CentOS 5.3并为其创建虚拟机,但需要一些时间才能下载,而且我不确定哪个版本的GHC适用于它(我尝试在他们的服务器上获取GHC 7,但遇到了libc问题)。

目前,我想到了一些可能的方法,但如果有可能的话,我想避免使用它们:

  • 以其他语言重写(尝试用Java做这件事让我感到不舒服,虽然可以尝试Cal / OpenQuark)。
  • 尝试使用其他编译器,例如jhc。但是,我不太确定如何开始安装jhc中此程序所需的所有依赖项;如果有人有经验,并知道text / attoparsec等在jhc中起作用,则很乐意听取建议。
  • 最后的hack:构建Windows可执行文件,安装wine到他们的服务器上,然后以这种方式运行它。

完全离题的是,在这些情况下,我真的希望我们有一个GHC的JVM后端。我想我也可以尝试LambdaVM。但是,我很想听听社区对此该怎么做的建议。


2
如果你未来要向他们分发,那么制作一个CentOS 5.3虚拟机绝对是个好主意。虽然这可能是所有黑客的黑客,但如果它能在Wine下工作,那可以节省你大量时间和痛苦。 - Dan Burton
3个回答

30

这个简单的例子"对我有效":

$ cat A.hs
main = print "yes"

$ ghc -O2 --make -static -optc-static -optl-static A.hs -fvia-C -optl-pthread

$ ldd A
    not a dynamic executable
$ ./A
"yes"

(而且我过去几年已经使用过这个过程,通过.cabal为客户发布可执行文件)。

我认为最好的选择是报告错误并使其正常工作。IHG也可以资助此类工作,但如果您试图发布产品,我相当确定GHC团队会将其视为高优先级。


明天我会尝试一下,我之前没有考虑过-fvia-C或-optc-static选项。通常情况下,我会为此提交错误报告,但是我对他们的服务器的访问权限非常有限,因此我无法提供完整的调试信息。 - Michael Snoyman
1
由于您已经拥有了所有必要的静态库,因此这非常有效。(在我的系统上,我确实需要额外编译libgmp和libffi) - Manoel Vilela
那么这些选项实际上是做什么的呢? - Iizuki

8

该问题涉及到CentOS中旧版glibc库。您需要使用与CentOS上已安装的相同版本的glibc进行编译。

我也遇到了完全相同的问题。在arch(或ubuntu)上编译的Haskell可执行文件无法在CentOS上运行。但是在我的情况下,我很幸运,因为我们的管理员刚好将CentOS替换为应用服务器上的Arch。


6
我找到了问题所在。看起来Biohaskell页面的链接是准确的:这是一个加载iconv的问题。在调用openFile时会出现这种情况,但在调用openBinaryFile时不会。由于xml-enumerator使用后者,所以它可以正常工作。将其余代码切换为使用openBinaryFile(通过Data.Enumerator.Binary.enumFile)就可以让所有内容正常工作。
这对我的用例来说是个好的解决方法,但这个错误仍然存在。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接