Movatterモバイル変換


[0]ホーム

URL:


RSS

One does not simply use GHCup on macOS M1

Info

SummaryUsing Haskell through Nix or Docker might be easier paths on macOS, but this article should help if those options aren't available.
Shared2023-03-20
Revised2023-03-22 @ 11:51 UTC

Intro

TheGHCup tool is the official installer for coreHaskell tools:cabal,stack,haskell-language-server, andghc.

I usually use Haskell throughNix (I’m likingdevenv.sh, too), and I’ve also used it through Docker, but I was frustrated with build times and wanted to try the official Haskell way.

Unfortunately, I had a rough time trying to use GHCup on a macOS M1 (Ventura 13.2.1), so I documented trying to build a small Haskell project of mine,slugger, with it.

A note about Homebrew

I useHomebrew for installing all sorts of CLI tools and apps for macOS (here’s my personalBrewfile).

While I will use it for something else later in this guide, I could not getghcup to work properly when installed via Homebrew, and trying to upgrade GHCup through its interface conflicted with the Homebrew install. Instead, I will use the installer found onthe GHCup page.

The library I tried to build

The example library I tried building was my URI slug library,slugger.

Installing GHCup

I like to keep my$HOME directory clean by having tools adhere to theXDG spec. I read that if I wanted GHCup to useXDG, I needed to export this variable in the shell where the installer was going to run:

exportGHCUP_USE_XDG_DIRS="true"

Here are my XDG environment variables.

Since I always want this to be true,I include that in my.zshenv dotfile just in case.

Next, I installed GHCup:

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

This is an interactive installer, so there was a bit of output and questions.

GHCup installer messages

Tip: if you run this installer, make sure you read the messages.

Including the GHCup environment

The script asked if it could append something to the end of my.zshrc file. I prefer to own my environment setup, so I let it do its thing, inspected the file to make sure it looked good, then I changed the sourcing code into a style I prefer:

ghcup_script_path="${XDG_DATA_HOME}/ghcup/env"[[ -f"${ghcup_script_path}"]]&&source"${ghcup_script_path}"

This adds some Haskell bin-related directories to$PATH if they aren’t already there.

Running the GHCup terminal user interface

Once this was all done, I opened a new shell window and ran

ghcup tui

TUI is an acronym for “terminal user interface”.

GHCup terminal user interface

I used the interface to install the recommended tool versions, and this was really easy! Well done, GHCup crew.

Then I went to go see if I could buildslugger.

Building slugger: failure #1 (LLVM)

When I went to theslugger project directory, I rancabal v2-build, and some LLVM errors printed to the screen.

LLVM not found when trying to build the slugger project

Notably:

Warning: Couldn’t figure out LLVM version! Make sure you have installed LLVM between [9 and 13]

Remember how I said to make sure you read the installer messages? Yeah. I didn’t.

On Darwin M1 you might also need a working llvm installed (e.g. via brew) and have the toolchain exposed in the PATH.

Update: User bgamari on lobste.rs had a valuable insight intowhy installing LLVM is recommended by GHCup.

Building slugger: failures #2-4 (also LLVM)

As suggested by the warnings above, I addedbrew llvm@9 to myBrewfile, installed it, and tried tocabal v2-build theslugger project.

That didn’t work (same sort of issue).

I triedllvm@10,llvm@11, andllvm@12.

None of those worked, either! Wouldllvm@13 work? Maybe, maybe, maybe…

Building slugger: failure #5 (GHC and LLVM)

Update: This section may not be necessary. I went back, disabled this option, and I’m able still able to build the library. I don’t recall this being my experience the first time around, though.

It seems none of these will work ifghc doesn’t know to use LLVM.

I keep acabal config file in my dotfiles and it had a section,program-default-options, that contained aghc-options key for passing flags to ghc.

Here’s how I told GHC about LLVM:

program-default-options  ghc-options: -fllvm

There’s more information about that on theHaskell GHC Backends doc.

Did that make a difference? Yep!

Building slugger: failure #6 (missing foreign libraries)

Aha! A different error.

Missing foreign libraries terminal error

cabal-3.6.2.0 Missing dependencies on foreign libraries:
Missing (or bad) C libraries: icuuc, icui18n, icudata

This one stemmed from trying to build a dependency,text-icu, and it seemed I was missing some libraries it expected to find on the OS.

I saw some references on GitHub issues to theicu4c tool, but I was luckily able to findthis archived “Missing dependency on a foreign library” guide that simply told me what to do:

  1. brew install icu4c

  2. If you’re using stack, add this to~/.stack/config.yaml:

    extra-include-dirs:- /usr/local/opt/icu4c/includeextra-lib-dirs:- /usr/local/opt/icu4c/lib

Unfortunately, none of this worked out of the box for me for two reasons:

  1. I’m not usingstack
  2. Homebrew uses/opt/homebrew/ for Apple Silicon—not/usr/local/

But those config options lookedexactly the same as the recommendation from the build warning above, and that gave me some things to try:

If the libraries are already installed but in a non-standard location then you can use the flags--extra-include-dirs= and--extra-lib-dirs= to specify where they are.

Fixing the missing foreign libraries issue

It turns out that mycabal.conf file hadextra-include-dirs andextra-lib-dirs in it, so I didn’t need to pass paths every time I tried to build with cabal.

I don’t regularly edit cabal config files, so I took thestackYAML config above and tried it:

extra-include-dirs:- /opt/homebrew/opt/icu4c/includeextra-lib-dirs:- /opt/homebrew/opt/icu4c/lib

Nope, that didn’t work. I tried indenting the- to see if the config file liked that.

Nope.

While this config file might, at a glance, resemble YAML, it isn’t—it seems to resemble (or even be) a.cabal file (email me if you know, please!). Here was a correct way to write them:

extra-include-dirs:  /opt/homebrew/opt/icu4c/includeextra-lib-dirs:  /opt/homebrew/opt/icu4c/lib

Sweet success

With high hopes, I rancabal v2-build again, and it worked!

Successful build result and test of the slugger library

I was successfully able to build my little library and test it out withcabal.

Personal retrospective on the experience

There are a number of places here where, if I’d have paid closer attention to (admittedly helpful) walls of text, I’d have been led to solutions faster. That is unquestionably my fault!

That said, the errors don’t cover everything you have to do (like the-fllvm GHC flag), and this overall experience on macOS was rough for me.

I am grateful for all the effort put into GHCup, and I know it takes time and money to make things simple.

For now, even though Nix’s story isn’t one of simplicity, either, I’m going to mostly stick with building Haskell projects that way. However, I’ll keep my options open and periodically try things the GHCup way, as well.


Thanks for reading!
— Robert


[8]ページ先頭

©2009-2025 Movatter.jp