GHCup is a simple installer. This feature request is basically asking package manager like functionality, such as tracking of ABI compatibility.
As an example, Gentoo got a similar feature fairly ārecentlyā in 2012: Sub-slots and Slot-Operators - Gentoo wiki
It caused a lot of problems and complexity for end users.
The second problem is that such binaries are also tied to a single GHC version. So how do you install the debugger for multiple GHC versions? For HLS I solved that by just installing all HLS binaries regardless of what GHC versions are installed.
I donāt think micro-managing installed binaries per GHC version is a good user experience.
But that opens up the following problem: if we install HLS for all supported GHC versions, then we have a ādynamicā matrix of ABIs.
ghcupDownloads:
GHC:
9.6.7:
viArch:
A_64:
Linux_CentOS:
( >= 7 && < 8 ): &ghc-967-64-centos7
dlHash: c1a0c27cbb18152a9ee3474c44f6d00399bc6b1633cea2e0169a34b8f57f5f39
dlSubdir: ghc-9.6.7-x86_64-unknown-linux
dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/9.6.7/ghc-9.6.7-x86_64-centos7-linux.tar.xz
unknown_versioning: *ghc-967-64-centos7
Linux_Fedora:
'>= 33': &ghc-967-64-fedora33
dlHash: f845a79f15fcbfe8e659c43f4cd0b1f1bc15e2309665726c573de850278296f1
dlSubdir: ghc-9.6.7-x86_64-unknown-linux
dlUri: https://downloads.haskell.org/~ghc/9.6.7/ghc-9.6.7-x86_64-fedora33-linux.tar.xz
unknown_versioning: *ghc-967-64-centos7
Linux_UnknownLinux:
unknown_versioning:
dlHash: e1078062054732eb12ec0267d74a72362a5fc66d45cf0aeebbf4caf425e264e5
dlSubdir: ghc-9.6.7-x86_64-unknown-linux
dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/9.6.7/ghc-9.6.7-x86_64-rocky8-linux.tar.xz
9.14.1:
viArch:
A_64:
Linux_UnknownLinux:
unknown_versioning: &ghc9141-x86_64-linux-rocky8
dlHash: f796b25efc1c02f15ab716d69c655b38faab8b398a8d408ba5ff97f41ff2831a
dlSubdir: ghc-9.14.1-x86_64-unknown-linux
dlUri: https://downloads.haskell.org/~ghc/9.14.1/ghc-9.14.1-x86_64-rocky8-linux.tar.xz
Linux_Fedora:
'(>= 33 && < 38)': &ghc9141-x86_64-linux-fedora33
dlHash: b92cd3a35d8b5b83d36ddaf99d7a21907b1e18b32d73bc9457bd2a1029e5c66c
dlSubdir: ghc-9.14.1-x86_64-unknown-linux
dlUri: https://downloads.haskell.org/~ghc/9.14.1/ghc-9.14.1-x86_64-fedora33-linux.tar.xz
'>= 38':
dlHash: cd73823eb6747b16393d802bfb7feacfb0e789a4a6f10b7b5a62c6cdbe806e9e
dlSubdir: ghc-9.14.1-x86_64-unknown-linux
dlUri: https://downloads.haskell.org/ghc/9.14.1/ghc-9.14.1-x86_64-fedora38-linux.tar.xz
unknown_versioning: *ghc9141-x86_64-linux-rocky8
What does this mean? It means that Fedora versions lower than 33 will get a Centos bindist for GHC 9.6.7, but a rocky8 bindist for GHC 9.14.1. It also means that 9.14.1 has more fedora bindists than 9.6.7. So we do not have a simple distroversion ā bindist relationship that we could exploit.
Now, say I want to ship HLS, how do I build binaries and ship HLS so that it works on:
- fedora <33 (or: unknown versions)
- fedora >= 33 && < 38
- fedora >= 42
And that across all GHC versions?
Indeed⦠we need the most exhaustive matrix of distro+distroversion across all supported GHC versions, so we end up with:
ghcupDownloads:
HLS:
2.12.0.0:
viArch:
A_64:
Linux_Fedora:
'(>= 33 && < 38)': &hls-21200-64-fedora33
dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/haskell-language-server/2.12.0.0/haskell-language-server-2.12.0.0-x86_64-linux-fedora33.tar.xz
dlSubdir: haskell-language-server-2.12.0.0
dlHash: 236a0786accddd440c277e0812b0a7ad1cab0ff92347a108aff015b6f4a84edc
'(>= 38 && < 42)':
dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/haskell-language-server/2.12.0.0/haskell-language-server-2.12.0.0-x86_64-linux-fedora38.tar.xz
dlSubdir: haskell-language-server-2.12.0.0
dlHash: 6fd8d1b5b3876b50e337ee4a426f401a56254ca1544b4634aa753583888fdeaf
'>= 42':
dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/haskell-language-server/2.12.0.0/haskell-language-server-2.12.0.0-x86_64-linux-fedora42.tar.xz
dlSubdir: haskell-language-server-2.12.0.0
dlHash: 6e57c3617665774a4b82bb2c7d07583af09421c1ebd4f8590471a1723247d9a5
unknown_versioning: *hls-21200-64-fedora33
This is huge CI complexity and there are cases where it breaks down. If we donāt get the HLS CI matrix correctly, the end user may get a runtime failure saying their HLS+GHC combination is not ABI compatible (this has happened). Uh. After all, GHCup in this case has no knowledge of ABI. Weāre just trying to coerce GHCup into doing the right thing.
Now the other option is to make GHCup ABI aware. This is simple if HLS 2.12.0.0 only supports a single GHC version. But it doesnāt. So we have in fact a set of ABIs and they can be in all sorts of different combinations.
The only way this can work is that we record the ABIs per GHC version⦠but that also means we need separate HLS bindists per GHC version, so that GHCup can discover āoh, you need ABI abc84 for 9.6.7 and ABI dfe93 for 9.14.1ā. Then GHCup has to download multiple bindists and install each of them. This is a hard deviation from how GHCup is designed and works today. I am not super keen on exploring this approach.
To me, the right solution is a different one and we are exploring this solution in stable-haskell. That is: instead of this madness of 20 GHC bindists, we only have two different linux bindists (just like rust):
Then we link gmp statically (or use integer-simple), use the new libffi-clib package for libffi and hope that we find a solution for ncurses (which is a bit more delicate to statically link).
This makes the GHC matrix so simple, that itās feasible to build binaries for HLS/HDB without teaching GHCup about the ABI problem.
Edit: Of course⦠Iām not even sure what the plan is for HDB and if a single HDB version is meant to support multiple GHC versions. If that is not the case, then thereās even less of a reason to ship it separately from GHC.