Help us understand the problem. What is going on with this article?

Raspberry PiでAArch64なGHCを動かす

最近のRaspberry Pi(3以降)のCPUのアーキテクチャは64bitのARM (AArch64)である。開発中のHaskellパッケージをAArch64でもテストできると良いので、Raspberry Piを使ってAArch64のHaskell環境を整えてみた。

環境の概要は次の通り:

  • Raspberry Pi 3 Model B
  • Ubuntu Server 18.04.4 LTS aarch64
  • Stack 2.1.3
  • GHC 8.8.3

記事タイトルにラズパイを銘打っているが特にラズパイ依存な部分はない(IoTめいたこともしない)ので、Linuxが動く他のAArch64環境でも同様にできると思う。

64bit Linuxのインストール

まず、Raspbianは32bit版しか用意されていないので、64bitのバイナリを動かしたければRaspbian以外のディストリビューションを入れる必要がある。

筆者が入れたのは、 Ubuntu Server 18.04.4 LTS (64-bit) である。Raspberry Pi 3向けのバイナリを落としてSDカードに書き込む。詳しい手順はわざわざここに書かなくても良いだろう。

Haskell環境のインストール

最近はGHC公式でLinux (AArch64)向けのバイナリが配布されているようだ。しかし、管理のことを考えるとghcupやstackなどでGHCをインストールしたい。

ghcupは残念ながら、2020年3月時点でAArch64に対応していない。

一方、StackはAArch64に対応しており、公式の手順でインストールできる。しかし stack setup でGHCをインストールした際に行われるsanity check(実際にテストプログラムをコンパイルする)には失敗した。

(失敗するのはGHCを使ったファイルのコンパイルであり、GHC自体のインストールは完了している。また、sanity checkに失敗してもGHCiは動作した。)

ちなみに、2020年3月現在のstack (2.1.3)でGHC 8.8系を使うと

Stack has not been tested with GHC versions above 8.6, and using 8.8.3, this may fail
Stack has not been tested with Cabal versions above 2.4, but version 3.0.1.0 was found, this may fail

というふうなメッセージが出るが、動作している限りにおいては特に気にしなくて良い。

LLVMのセットアップ

ターゲットがx86系の場合はGHC自体がコード生成器(NCG)を持っているため、LLVMを使わなくてもバイナリを出力できる。一方、ARM系に対してはNCGが対応していないため、デフォルトでLLVMバックエンドが使用される。

よって、GHCにAArch64向けのバイナリを吐かせるにはLLVMをインストールする必要がある。

GHCが使用するLLVMのバージョンは、GHCのバージョンによって異なる。GHC 8.6系であればLLVM 6、GHC 8.10ではLLVM 9という具合だ。今回インストールされたGHC 8.8系に対応するのはLLVM 7である。

UbuntuでのLLVM 7のパッケージ名は llvm-7 なので

$ sudo apt install llvm-7

でLLVM 7を入れる。

GHCが使用するのはLLVMの opt コマンドと llc コマンドである。しかし、Ubuntuが提供するこれらのコマンド名はそれぞれ opt-7, llc-7 であり、GHCが期待するコマンド名と食い違っている。食い違いを解消するにはGHCにオプション -pgmlo=opt-7 -pgmlc=llc-7 を指定すれば良いのだが、面倒なのでglobal configに次のように書く。

~/.stack/config.yaml
extra-path:
- /usr/lib/llvm-7/bin

/usr/lib/llvm-7/bin 以下にはサフィックスのつかない opt コマンドや llc コマンドが存在する。それを PATH に含めれば -pgmlo などのオプションを指定する必要がないというわけだ。)

バージョンの異なるGHCが共存する場合は複数のLLVMを使い分ける必要があるので、一律にLLVM 7を使うようにするのは問題がある。しかし、うまい対処方法が思いつかないので、とりあえずはこれでいく。

libnuma-dev

LLVMのセットアップを完了させてファイルをコンパイルすると、今度は libnuma が見つからないというようなエラー(リンクエラー)が出る。libnuma-dev をインストールすれば良い。

$ sudo apt install libnuma-dev

これで、筆者のラズパイではGHCを使ったHaskellプログラムのコンパイルができるようになった。

メモリ消費

一部のパッケージをビルドする際にメモリが足りなくなることがある。具体的には、vectorパッケージをRaspberry Pi 3 Model B(物理メモリ1GB)でビルドしたらOOMが発生した。

このケースでは1GBのswapを用意してやるとうまくいった。物理メモリを2GB以上搭載したRaspberry Pi 4であればswapを用意しなくても大丈夫かもしれない。

雑感

当たり前だが、遅い。コンパイル自体も遅いが、筆者の使っているラズパイはLANが100Mbpsとかなのでインターネットからのダウンロードも遅い。ダウンロードに関してはギガビットに対応しているRaspberry Pi 4ならもうちょっとマシかもしれない。

真面目に開発したかったらラズパイとかじゃなくてもっと高性能なARMマシンを用意するとか、クロスコンパイルを検討するべきだろう。(GHCでのクロスコンパイルは茨の道という感じがするが……。)

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした