LoginSignup
8

More than 1 year has passed since last update.

Apple Silicon MacでのHaskell/GHCの現状・2022年3月編

Last updated at Posted at 2021-12-20

この記事は Haskell Advent Calendar 2021 の21日目の記事です。

2020年に発表されたApple Silicon (Arm) Macは、2021年に新チップ “M1 Pro/Max” が、2022年には新チップ “M1 Ultra” が登場し、ますます勢いを増しています。Mac使いの皆さんはもう手にされましたか?

新しいアーキテクチャーにはハードウェアだけではなくソフトウェアの対応も重要です。この記事では、2022年3月時点のApple Silicon MacへのHaskellエコシステムの対応状況をまとめます。

この記事では、なるべくRosetta 2を使わず、Armネイティブに動作する環境を構築することを目指します。

インストールにどれを使うか

UnixでHaskell環境を構築する場合、

  • パッケージマネージャーを使う
  • GHCupを使う
  • Stackを使う

の3つの選択肢があるかと思います。

Mac向けのパッケージマネージャーと言えばHomebrewやMacPortsです。HomebrewはArmネイティブなGHCのインストールに対応しています。一方、MacPortsでGHCをインストールするとIntel版のGHCがインストールされるようです(当該Portfile)。

GHCupはArmネイティブなGHC等のインストールに対応しています。現時点で最もおすすめな方法です。

後述しますが、stackの公式のインストール方法を使うとIntel版のstackがインストールされるので、要注意です。

GHC

Macに限らない最近のGHCの動向については以前記事を書きました:

ここではArmあるいはMac特有のGHCの事情について書いていきます。

GHC 8.10系

GHC 8.10系は8.10.5以降でApple Siliconに対応しています。

最新のGHC 8.10.7は2021年8月27日にリリースされました。この記事の初出の時点(2021年12月)ではこれが一番安定した選択肢でしたが、その後9.0.2や9.2.2がリリースされたので、現時点(2022年3月)でどれが一番安定しているかは筆者からは何とも言えません。

実行ファイルの生成にはLLVMの opt コマンドと llc コマンドが必要になります。これについてはGHCupまたはstackの項目で説明します。

8.10.7の既知の問題:

GHC 9.0系

GHC 9.0系は9.0.2以降でApple Siliconに対応しています。

最新のGHC 9.0.2は2021年12月25日にリリースされました。

実行ファイルの生成にはLLVMの opt コマンドと llc コマンドが必要になります。これについてはGHCupまたはstackの項目で説明します。

9.0.2の既知の問題:

GHC 9.2系

GHC 9.2系は最初からApple Siliconに対応しています。また、AArch64 NCGが実装されているためLLVMがなくても実行ファイルを生成できます(GHCのバックエンドについてはこの記事を参照)。

ただ、9.2.1には深刻なバグがあるため、必ず9.2.2(2022年3月5日リリース)以降を使うようにしてください。

GHCup

公式ページの手順

curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh

に従うとArmネイティブなGHCupがインストールされます。そこでインストールされるツール類もArmネイティブなものになります。

もしもRosetta 2でx86_64なGHCupを導入したい場合は、

curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | arch -x86_64 sh

という風に実行すると良いでしょう(arch -x86_64 に注意)。

GHCupをすでにインストール済みで、自分がどちらを使っているか確認したい場合は、

file ~/.ghcup/bin/ghcup

を実行すると良いでしょう。Armネイティブな場合は Mach-O 64-bit executable arm64 という風に表示されるはずです。もしもIntel版のGHCupがインストール済みで、Arm版のGHCupを入れ直したい場合は ~/.ghcup 以下を全削除するか ghcup nuke コマンドを実行してから、改めてインストールしましょう。

LLVMのセットアップ

GHC 8.10系とGHC 9.0系でArmネイティブな実行ファイルを出力するにはLLVMの opt コマンドと llc コマンドが必要です。HomebrewやMacPortsでLLVM 12を入れましょう。

opt コマンドと llc コマンドにPATHが通っていれば良いのですが、HomebrewやMacPortsのデフォルトではPATHが通っていなかったり、コマンド名にサフィックスがついたりしています。その場合、GHCの実行時に -pgmlo / -pgmlc コマンドでコマンド名を教えてあげるというのが一つの方法ですが、毎回それをするのは面倒なのでセットアップ時に環境変数で指定するのが良いでしょう。

Homebrewの場合は brew install llvm@12 して

# GHC 8.10.7を入れる場合
OPT=/opt/homebrew/opt/llvm@12/bin/opt LLC=/opt/homebrew/opt/llvm@12/bin/llc ghcup install ghc 8.10.7 --force

# GHC 9.0.2を入れる場合
OPT=/opt/homebrew/opt/llvm@12/bin/opt LLC=/opt/homebrew/opt/llvm@12/bin/llc ghcup install ghc 9.0.2 --force

という感じで、MacPortsの場合は sudo port install llvm-12 して

# GHC 8.10.7を入れる場合
OPT=/opt/local/bin/opt-mp-12 LLC=/opt/local/bin/llc-mp-12 ghcup install ghc 8.10.7 --force

# GHC 9.0.2を入れる場合
OPT=/opt/local/bin/opt-mp-12 LLC=/opt/local/bin/llc-mp-12 ghcup install ghc 9.0.2 --force

という感じで ghcup を実行します。--force オプションにより、すでに当該バージョンのGHCがインストール済みであっても新しい設定で再インストールを行うことができます。

再インストールするとデフォルトのGHCの設定がリセットされるので、適宜

ghcup set ghc 8.10.7 # または ghcup set ghc 9.0.2

を実行しましょう。

cabalコマンド (cabal-install)

GHCupで3.4.0.0以降のcabalコマンドを導入できます。

haskell-language-server

GHCupを使うことで1.4.0以降のhaskell-language-serverコマンドを導入できます。

なお、現時点ではVisual Studio CodeのHaskell拡張でHLSを自動インストールさせるとIntel版のHLSが入るようです。

関連Issue:

Stack

Stack 2.7.5の時点ではMac向けの公式バイナリーはIntel版しかありません。公式のインストール方法

curl -sSL https://get.haskellstack.org/ | sh

ではIntel版のstackが入ります。

一方、ArmネイティブなGHCupやHomebrewを使うとArm版のstackをインストールすることができます。

なお、Stack本体のアーキテクチャーと関係なく、 --arch x86_64, --arch aarch64 のオプションで使用するGHCのアーキテクチャーを選択することができます。とはいえ、GHC 8.10.7の既知の問題のところに書いた理由で、Armネイティブなstackを使うのがおすすめです。

GHCupでstackをインストールした場合は、 stack upgrade を使ってはいけません。GHCupを使ってstackのバージョンを管理してください。

LLVMのセットアップ

GHC 8.10系とGHC 9.0系でArmネイティブな実行ファイルを出力するにはLLVMの opt コマンドと llc コマンドが必要です。HomebrewやMacPortsでLLVM 12を入れましょう。

opt コマンドと llc コマンドにPATHが通っていれば良いのですが、HomebrewやMacPortsのデフォルトではPATHが通っていなかったり、コマンド名にサフィックスがついたりしています。その場合、GHCの実行時に -pgmlo / -pgmlc コマンドでコマンド名を教えてあげるというのが一つの方法ですが、毎回それをするのは面倒なのでセットアップ時に環境変数で指定するのが良いでしょう。

Homebrewの場合は brew install llvm@12 して

# GHC 8.10.7を入れる場合
OPT=/opt/homebrew/opt/llvm@12/bin/opt LLC=/opt/homebrew/opt/llvm@12/bin/llc stack setup 8.10.7 --arch aarch64 --reinstall

# GHC 9.0.2を入れる場合
OPT=/opt/homebrew/opt/llvm@12/bin/opt LLC=/opt/homebrew/opt/llvm@12/bin/llc stack setup 9.0.2 --arch aarch64 --reinstall

という感じで、MacPortsの場合は sudo port install llvm-12 して

# GHC 8.10.7を入れる場合
OPT=/opt/local/bin/opt-mp-12 LLC=/opt/local/bin/llc-mp-12 stack setup 8.10.7 --arch aarch64 --reinstall

# GHC 9.0.2を入れる場合
OPT=/opt/local/bin/opt-mp-12 LLC=/opt/local/bin/llc-mp-12 stack setup 9.0.2 --arch aarch64 --reinstall

という感じで stack setup を実行します。--reinstall オプションにより、すでに当該バージョンのGHCがインストール済みであっても新しい設定で再インストールを行うことができます。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8