Haskellで書いたプログラムをRaspberry Piで動かす方法

Haskellで書いたプログラムをRaspberry Piで動かす方法に関して少し調べた。

Raspberry Pi上でHaskellプログラムをビルドする方法

LLVM関連パッケージとスワップサイズを増やすことに気をつければ、何とかなりそうな印象。stack/cabal/ghcによるビルドではとにかくメモリを食うのでスワップが必要になるようだ。

ただでさえRaspberry Pi上でのビルドになる上、スワップも必要になるので相当時間がかかりそうではある。

ARM仮想マシン内でHaskellプログラムをビルドする方法

QEMUのARMエミュレーション機能を使えば、x86_64 アーキテクチャマシン上でARM仮想マシンを立てることができる。上記のqemu-rpi-kernelを使えば、ARM仮想マシン上でRaspberry Pi(を模した)カーネルを動かし、Raspbianを動かせるようだ。

ただ、QEMUではメモリサイズが256MBに制限されているらしく、Haskellプログラムのビルドにはどのみちスワップ領域の設定が必要になる。また、QEMUのARMエミュレーションはめちゃくちゃ重いのでどのみちビルド性能はいまいちだと思われる。

ARM向けにHaskellプログラムをクロスコンパイルする方法

状況はかなり難しいようだ。

ARMをターゲットにしたクロスコンパイラとしてGHCをビルドすることはできそう。これによりごくシンプルなHaskellプログラムをビルドすることはできる。

ただ、もう少し複雑なプログラムを扱おうとすると問題が出てくるようだ。特にTemplateHaskellが厄介そう。

TemplateHaskellはコンパイル中にソースコードに埋め込まれたHaskellコード(splice)を実行する仕組みだが、クロスコンパイルではこのspliceがターゲットアーキテクチャの形式で出力されるため、ホストでは実行できない。

なお、ghcjsは本質的にJavaScriptへのクロスコンパイラなわけだが、ghcjsではTemplateHaskell spliceのコンパイル結果をnode.jsに流し込んで評価しているらしい。

上記記事では、spliceのコンパイル結果をネットワーク越しにRaspberry Piに流して評価してもらう構成をとっている。そこまですればTemplateHaskellの問題はクリアできるようだが、、かなりのdirty hackに見える。

TemplateHaskellを使うパッケージを一切使わなければ問題はないはずだが、aesonがTemplateHaskell使ってるんだよなあ。

TemplateHaskellの問題もあるが、クロスコンパイルではFFI(Foreign Function Interface)も問題を起こすことがあるようだ。

上記を鑑みると、Haskell(GHC)のRaspberry Pi(ARM)へのクロスコンパイルはあまり現実的ではないように思う。golangやRustはクロスコンパイルのサポートが充実していると聞くので、羨ましい限りだ。