【问题标题】:Statically linking musl with ghc将 musl 与 ghc 静态链接
【发布时间】:2014-04-05 12:04:44
【问题描述】:

我正在尝试使用 GHC 为用 Haskell 编写的基于 CGI 的 Web 应用程序构建一个静态二进制文件,以部署在共享服务器上。

我想使用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

我做错了什么? (完全免责声明:我是 Haskell 新手 (:)

我正在使用 Arch Linux、GHC 7.6.3 和 Network.CGI。

【问题讨论】:

    标签: haskell ghc


    【解决方案1】:

    看起来您的 Haskell 运行时是针对 glibc 编译的,但您正在尝试针对 musl 编译您的 Haskell 源代码。通常,您不能在同一个程序中混合使用两个 C 库。

    您的具体问题是 glibc 支持 signal 函数的几个不同的冲突语义集,以匹配 UNIX 提供的不同历史版本。它根据您的 C 代码定义的功能测试宏选择要使用的版本。为了在它们之间进行实际切换,它使用 C 预处理器将程序对 signal 的引用替换为对具有您请求的任何语义的函数版本的引用(在您的情况下,您的 Haskell 运行时引用__sysv_signal)。

    问题是 musl 不会做同样的事情。它公开了与 POSIX 标准定义的语义相匹配的 signal 的单个版本,并以名称 signal 公开它。

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

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

    【讨论】:

    • 这已经完成了;见here。但是,看起来它需要一个完整的 Gentoo chroot 来托管编译器,这有点尴尬。
    • 实际上,您并不需要专门的 Gentoo chroot。提供的编译器不是交叉编译器,它本身是针对 musl 编译的二进制文件。因此,它需要一个基于 musl 的环境来运行。 可能是Gentoo chroot/docker container/lxc container/etc,但也可以是任何基于musl的发行版,例如Alpine Linux。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多