ARM向けGHCクロスコンパイラ

'15年2月20日
タグ Haskell, ARM, BBB

BeagleBone Black (略称 BBB) というARMマイコンボードにUbuntuを入れて遊んでいたとき、GHCもあるのかな…と思ったら apt-get install であっさりインストールできた。少し使ってみたら問題無く動作はするのだが、コンパイルにかなり時間がかかる。X86-PCでコンパイルできれば快適だろうに…と思ったのが、クロスコンパイラを生成しようとした動機である。

以下の文章は昨年、GHC 7.8.3 がリリースされて間もない頃に書いたもので、こんなものでも誰かの役に立つこともあるかもしれぬ…と思い公開することにした。


GHC Developer Wiki ページの Cross-compiling GHC の説明にしたがって作業を行う。この説明の中に、Stage1, Stage2 という名前が出てくる。今やろうとしていることに即して大雑把に言ってしまえば:

つまり、Stage2コンパイラは、コンパイラの製作過程でARM以外のもの(x86-PC)を使っているだけで、できあがってしまえば普通のコンパイラである。今作ろうとしているものは、Stage1コンパイラである。

まず、GHCのダウンロードページの“Source Distribution”からソースコード一式 ghc-7.8.3-src.tar.xz をダウンロードする。解凍すると ghc-7.8.3 というディレクトリができるのでここに移動し、以下の手順で作業を行う:

  1. mk/build.mk.samplemk/build.mk にコピーし、mk/build.mk を編集する。BuildFlavour として色々準備されているので、その中から quick-cross を選ぶ(27行目)。 これを選ぶと自動的に Stage1Only = YES となる。

  2. ターゲットは arm-linux-gnueabihf であるので、以下のように configure する:

    ./configure --target=arm-linux-gnueabihf --with-gcc=arm-linux-gnueabihf-gcc

    --with-gcc=... の指定はしなくても良いはずなのだが、これを指定しないと make を実行したときに 「/usr/bin/arm-linux-gnueabihf-nm がファイル形式を認識できない…」というエラーが出る。これはどうもバグらしい
    当方の環境では問題無く configure が終了した。

  3. 次に make を行うが、このままでは

    configure: error: in '/working/directory/ghc-7.8.3/libraries/terminfo':

    のようなエラーが出ると思う。これもまたバグらしい。terminfo は GHCi でしか使わないが、Stage1 コンパイラでは GHCi は不要なので、関連箇所を無視すれば良いらしい。具体的には、ghc.mk の PACKAGES_STAGE1 というシンボルにあれこれ追加している箇所(420行目前後)にある以下の2行をコメントにした:

    PACKAGES_STAGE1 += terminfo
    PACKAGES_STAGE1 += haskeline

    これで make を実行すれば無事に終了するはずである。

  4. この時点で直ちにクロスGHCを動かすことができる。./inplace/bin/ghc-stage1 がコンパイラを呼び出すスクリプトである。お決まりの hello.hs をファイルを作成する。中身は次の1行である:

    main = putStrLn "Hello world."

    これを ./inplace/bin/ghc-stage1 hello.hs としてコンパイルすると hello ができる。file で見てみると、

    hello: ELF 32-bit LSB  executable, ARM, EABI5 version 1 (SYSV),
    dynamically linked (uses shared libs), for GNU/Linux 2.6.32,
    BuildID[sha1]=62336c42778ed0a60f79f3950414d9f631ab772a, not stripped

    となっており(実際は1行)、ARMの実行ファイルができている。実際、このファイルをBBBに転送すると、問題無く動作した。

このままでも使えなくは無いが、適当なディレクトリにインストールした方が使い勝手が良いかもしれない。その場合、以下のような感じでインストールする:

./configure --target=arm-linux-gnueabihf --with-gcc=arm-linux-gnueabihf-gcc 
            --prefix=/usr/local/ghc-7.8.3-arm
sudo mkdir /usr/local/ghc-7.8.3-arm
sudo make install

./configure の行は実際には1行である。インストール先のディレクトリをここでは /usr/local/ghc-7.8.3-arm としたが、任意で構わない。

/usr/local/ghc-7.8.3-arm/bin の下にGHCコンパイラなどが置かれている。ghc-stage1 という名前だったものは、arm-unknown-linux-gnueabihf-ghc-7.8.3 という名前に変わっている。arm-unknown-linux-gnueabihf-ghc という名前のリンクが張られているが、それでも名前が長いので短い名前をつけたほうが使いやすそうである。

ともかく、これで x86-PC 上でBBB用のコードを作れるようになった。