Tip: if you run this installer, make sure you read the messages.
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.
Once this was all done, I opened a new shell window and ran
ghcup tui
TUI is an acronym for “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 build slugger
.
When I went to the slugger
project directory, I ran cabal v2-build
, and some LLVM errors printed to the screen.
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 into why installing LLVM is recommended by GHCup.
As suggested by the warnings above, I added brew [email protected]
to my Brewfile
, installed it, and tried to cabal v2-build
the slugger
project.
That didn’t work (same sort of issue).
I tried [email protected]
, [email protected]
, and [email protected]
.
None of those worked, either! Would [email protected]
work? Maybe, maybe, maybe…
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 if ghc
doesn’t know to use LLVM.
I keep a cabal config file in my dotfiles and it had a section, program-default-options
, that contained a ghc-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 the Haskell GHC Backends doc.
Did that make a difference? Yep!
Aha! A different 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 the icu4c
tool, but I was luckily able to find this archived “Missing dependency on a foreign library” guide that simply told me what to do:
brew install icu4c
If you’re using stack, add this to ~/.stack/config.yaml
:
extra-include-dirs:
- /usr/local/opt/icu4c/include
extra-lib-dirs:
- /usr/local/opt/icu4c/lib
Unfortunately, none of this worked out of the box for me for two reasons:
stack
/opt/homebrew/
for Apple Silicon—not /usr/local/
But those config options looked exactly 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.
It turns out that my cabal.conf
file had extra-include-dirs
and extra-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 the stack
YAML config above and tried it:
extra-include-dirs:
- /opt/homebrew/opt/icu4c/include
extra-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/include
extra-lib-dirs:
/opt/homebrew/opt/icu4c/lib
With high hopes, I ran cabal v2-build
again, and it worked!
I was successfully able to build my little library and test it out with cabal
.
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