基本的にghc -O -static -threaded -optl-static Main.hs
でビルドすればいいらしい。
しかしArch Linuxだとlibgmpなどのスタティック版が存在しなくて自分でビルドする必要があったのでその記録。
まず普通に上記コマンドでビルドするとこのようなエラーが出た:
[~:1]# ghc -O -static -threaded -optl-static Main.hs
Linking Main ...
/usr/bin/ld: -lgmp が見つかりません
/usr/lib/ghc-8.0.1/rts/libHSrts_thr.a(Linker.thr_o): 関数 `internal_dlopen' 内:
(.text+0x3a5): 警告: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/bin/ld: -lffi が見つかりません
collect2: エラー: ld はステータス 1 で終了しました
`gcc' failed in phase `Linker'. (Exit code: 1)
libgmpとlibffiのスタティック版が存在しないようなので、ソースを落としてきてビルド
https://gmplib.org/download/gmp/gmp-6.1.1.tar.xz
ftp://sourceware.org/pub/libffi/libffi-3.2.1.tar.gz
どちらも./configure && make && make install
で問題なくビルド通って/usr/local/lib
にインストールされる。
今度は成功:
[~:1]# ghc -O -static -threaded -optl-static Main.hs
Linking Main ...
/usr/lib/ghc-8.0.1/rts/libHSrts_thr.a(Linker.thr_o): 関数 `internal_dlopen' 内:
(.text+0x3a5): 警告: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
dlopen
を使っているから実行時にも同じバージョンのライブラリが必要だよと出ている。
/usr/lib/ghc-8.0.1/rts/libHSrts_thr.a
とやらの中で明示的にdlopen
を呼んでいるということなのだろうか?そうだとしたらghcではgolangと同じような完全ポータブルなシングルバイナリを作るのは無理ということなんでしょうかね?
試しにArch(glibc 2.24-2)からAmazon Linux(glibc 2.17)へ持っていったらちゃんと動いた。でも、そもそもスタティックリンクしなくてもAmazonでなら動いた。
参考
https://ro-che.info/articles/2015-10-26-static-linking-ghc
http://www.edofic.com/posts/2014-05-03-ghc-arch-static.html