2

I'm trying to build with GHC a static binary for a CGI-based web application written in Haskell, to be deployed on a shared server.

I would like to use musl, as mentioned by this answer.

Unfortunately, this is not an easy task:

$ 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

What am I doing wrong? (Full disclaimer: I'm an Haskell newbie (: )

I'm using Arch Linux, GHC 7.6.3, and Network.CGI.

Community
  • 1
  • 1
gioi
  • 1,463
  • 13
  • 16

1 Answers1

5

It looks like your Haskell runtime was compiled against glibc, but you're trying to compile your Haskell source against musl. In general, you cannot mix two C libraries within the same program.

Your specific problem here is that glibc supports a couple different conflicting sets of semantics for the signal function, to match what different historical versions of UNIX provided. It chooses which version to use based on the feature test macros that your C code defines. And to actually switch between them, it uses the C preprocessor to replace your program's references to signal with references to a version of the function with whichever semantics you've requested (in you're case, your Haskell runtime has a reference to __sysv_signal).

The problem is that musl doesn't do this same slight of hand. It exposes a single version of signal that matches what the POSIX standard defines its semantics to be, and it exposes it under the name signal.

The proper way to fix this is going to be to recompile your Haskell runtime against musl's headers. I don't know if anybody's actually tried doing this yet, so YMMV.

Note that you should avoid having libraries installed in the same system directory but compiled against different C libraries. Doing so is likely to break things, because any software trying to use multiple libraries that are compiled against conflicting C libraries will run into variants of the exact problem you're having right now. You should generally compile and install musl into its own prefix, and then compile other libraries (eg. your Haskell runtime) against musl and install into that same prefix. This way, your musl and glibc libraries stay cleanly separated.

Koorogi
  • 51
  • 1
  • 1
    This has been done; see [here](https://github.com/redneb/ghc-alt-libc). However, it looks like it requires a whole Gentoo chroot to host the compiler, which is a little awkward. – user31708 Dec 13 '15 at 03:25
  • 1
    Actually, you don't need a Gentoo chroot specifically. The provided compiler is not a cross compiler, it is itself a binary compiled against musl. As such, it requires a musl based environment to run. That _could_ be a Gentoo chroot/docker container/lxc container/etc, but it could also be any musl based distro such as Alpine Linux. – redneb Aug 31 '16 at 07:52