2014-04-05 81 views
1

我正在尝试与GHC一起构建一个基于CGI的web应用程序的静态二进制代码,并将其部署在共享服务器上。静态链接musl与ghc

我想用musl,如this answer所述。

不幸的是,这并不是一件容易的事:

$ ghc -static -optl-static -pgmc musl-gcc -pgml musl-gcc -L/usr/local/lib app.hs 
[1 of 1] Compiling Main    (app.hs, app.o) 
Linking app... 
/usr/lib/ghc-7.6.3/libHSrts.a(Itimer.o): In function `exitTicker': 
(.text+0x1af): undefined reference to `__sysv_signal' 
collect2: error: ld returned 1 exit status 

我在做什么错? (全免责声明:我是一个新手哈斯克尔(。)

我使用Arch Linux的,GHC 7.6.3和Network.CGI

回答

5

它看起来像你的Haskell的运行是对glibc的编译,但是你试图编译你的Haskell源代码对抗musl一般来说,你不能在同一个程序中混合使用两个C库

你的具体问题在于glibc支持signal函数的几组不同的语义冲突,以匹配UNIX提供的不同历史版本,它根据C代码定义的特征测试宏选择使用哪个版本,并且在它们之间切换时使用th e C预处理器,用您请求的任何语义(您的情况,您的Haskell运行时对__sysv_signal的引用)引用一个函数版本来替换程序对signal的引用。

问题是musl不会做同样轻微的手动。它公开了单一版本的signal,该版本与POSIX标准定义其语义的内容相匹配,并以名称signal公开。

解决这个问题的正确方法是重新编译你的Haskell运行时对musl的头文件。我不知道是否有人真的尝试过这样做,所以YMMV。

请注意,您应该避免将库安装在相同的系统目录下,但是针对不同的C库进行编译。这样做很可能会破坏事情,因为任何尝试使用针对冲突C库编译的多个库的软件都会遇到您现在遇到的确切问题的变体。您通常应该将musl编译并安装到自己的前缀中,然后针对musl编译其他库(例如,您的Haskell运行时)并将其安装到相同的前缀中。这样,你的musl和glibc库保持干净地分离。

+0

这已完成;见[这里](https://github.com/redneb/ghc-alt-libc)。但是,它看起来需要整个Gentoo chroot来承载编译器,这有点尴尬。 – user31708

+0

其实,你并不需要特别的Gentoo chroot。提供的编译器不是交叉编译器,它本身是一个针对musl编译的二进制文件。因此,它需要一个基于musl的环境来运行。该应用程序可以是Gentoo chroot/docker容器/ lxc容器/等,但也可以是任何基于musl的发行版,如Alpine Linux。 – redneb