macOSでGHCをソースコードからビルドする（2024年2月現在）

こんにちは｜こんばんは。カエルのアイコンで活動しております @kyamaz :frog: です。

## はじめに
HaskellのGHC（Glasgow Haskell Compiler）をソースコードからビルドするには時代により変化していきます。また、OS環境により微妙に異なる場合もありますので、本家 https://www.haskell.org/ghc/ から最新の情報を探したり、ソースコードのなかの情報（README.md等）を読んでビルドすることになります。
少し前には『[Haskell 教養としての関数型プログラミング](https://qiita.com/YoshikuniJujo/items/0708f108bf53a216a61a)』の著者である@YoshikuniJujoさんのエントリがあり、GHCのバージョン8.5をソースコードからビルドした例が紹介されています。

https://qiita.com/YoshikuniJujo/items/980775598e65fda36d33

本稿では、2024年2月現在で最新であるGHCのバージョン9.9をmacOSでソースコードからビルドする例を紹介します。GHCをソースコードからビルドする際には、ブートストラップ用のGHCが使えるようにしてある必要があります。まず『[Haskellの環境構築2023](https://zenn.dev/mod_poppo/articles/haskell-setup-2023)』を参考に、GHCupでGHC実行環境を整えておきましょう。
なお、本稿を検証した環境は以下の通りです。本稿の内容が上手く動作しない場合は、ご自身の環境との差異を比べてみてください。

**本稿の環境**
- macOS: Sonoma 14.2.1 (chip: Apple M1)
- Homebrew 4.2.8
- LLVM: Homebrew LLVM version 17.0.6
- Xcode: Apple clang version 15.0.0 (clang-1500.1.0.2.5)
（PATH環境変数により、Homebrew LLVMを先にしてあります）
- Python: 3.12.1 （anyenvにて設定）
- GHCup: 0.1.20.0
- Stack: 2.13.1
- Cabal: 3.10.2.1
- GHC: 9.8.1 （GHCupにてインストール）

## GHCのソースコードを入手する
本家は https://gitlab.haskell.org/ghc/ghc/ ですが、ここではPublic mirrorであるGithubからソースコードを入手します。適当なワーキングフォルダ（例：~/work）に移動して`git clone`を実行します。

```shell-session:
$ cd ~/work
$ git clone --recursive https://github.com/ghc/ghc.git
$ cd ghc
```

## 必要なパッケージを準備する
GHCをビルドするためのライブラリ群（libffiやgmp）と、Haskell環境のAlex（lex相当）とHappy（yacc相当）を事前にインストールします。

```shell-session:
$ brew install libffi gmp
$ stack install alex happy
```
※ドキュメントを作成するときには、上記に加えてSphinxをインストールしておきます。
<details><summary>Sphinxのインストール</summary>

```shell-session:
$ pip install Sphinx
```
</details>

## ghcをビルドする
### bootとconfigureコマンドの実行
プロジェクトフォルダで、`boot` と `configure` コマンドをそれぞれ実行します。

```shell-session:
$ cd ~/work/ghc
$ ./boot
$ ./configure --prefix=/opt/local --with-system-libffi --with-ffi-libraries=/opt/homebrew/lib --with-ffi-includes=/opt/homebrew/include --with-intree-gmp
```

### ビルドの実行
プロジェクトフォルダで、`hadrian/build`コマンドを実行してビルドします。

```shell-session:
$ ./hadrian/build -j$(nproc)
```
`Build completed in ?h??m`と表示されればビルドは成功です。（表示されたメッセージのinの後にはビルドにかかった時間が表示されます。）

【参考】前述の@YoshikuniJujoさんのエントリでは、`make`コマンドでビルドする方法が紹介されていますが、GHCバージョン9.6からビルドツールがHaskellベースの`hadrian`のみに変更されました。[^1]

ビルドしたファイルは、プロジェクトフォルダ直下の`_build`の下に出力されます。GHCのビルド手順は次のようなステージで進みます。

```mermaid
flowchart LR
A[stageBoot] --> B[stage0] --> C[stage1]
```
`_build`フォルダの下にそれぞれのステージのフォルダが作成されて、その中にビルドされたファイルが出力されます。

### インストールの実行
プロジェクトフォルダで、次のように`hadrian/build`コマンドの引数に`install`を指定して実行します。`--prefix`オプションで指定したフォルダ（ここでは /opt/local ）に実行ファイルや実行に必要なライブラリファイルがインストールされます。

```shell-session:
$ ./hadrian/build install --prefix=/opt/local --docs=none
```

#### ドキュメントのビルドとインストール
上の例では`--docs`オプションに`none`を指定してドキュメントはビルド＆インストールしない場合を挙げています。この`--docs`オプションには、`none`,`no-haddocks`,`no-sphinx-html`,`no-sphinx-pdfs`,`no-sphinx-man`が指定できます。`--docs`オプションを指定しないデフォルトでは、ドキュメントがビルド＆インストールされます。ただし、Sphinxをインストールした私の環境では、PDF対応ができませんでした。そのため`--docs=no-sphinx-pdfs`を指定する必要がありました。

## ビルドしたghcを試す

```shell-session:
$ /opt/local/bin/ghc --version
The Glorious Glasgow Haskell Compilation System, version 9.9.YYYYMMDD
```
ビルドした日付のついたバージョンが表示されます。

```shell-session:
$ /opt/local/bin/ghci
GHCi, version 9.9.YYYYMMDD: https://www.haskell.org/ghc/  :? for help
ghci> 1+2
3
ghci> :q
Leaving GHCi.
```
異常なく動きました。
ghcのビルド＆インストール手順は以上となります。この手順どおりに実行すれば、GHCのソースコードを改変して、色々と試すことができます。

## おわりに
Haskell界隈で活躍されている上級者の方々は、Qiitaではなく[Zenn](https://zenn.dev/)で情報発信されていることが多いようです。最新情報を入手するにはZennの記事も探してみることをお薦めします。
（●）（●） Happy Hacking!
/""　＿＿""＼

[^1]: 『[GHC 9.6の新機能](https://zenn.dev/mod_poppo/articles/whats-new-in-ghc-9-6)』に記載されている「ビルドシステムがHadrianのみになる」の項を参考にしました。