I’m sort of attached to the GHCup workflow, especially if I go to NixOS, simply because Haskell is niche, Nix / NixOS is niche, and crossing two niche technologies together gets me easily into the space where I have no community support at all (incidentally, IHP doesn’t run trivially on NixOS, despite being married to Nix).
From what I’ve heard, maerwald isn’t planning on supporting NixOS with GHCup at the moment, especially given NixOS’s hostility to outside toolchains (pip doesn’t seem to work either), but does anyone have experience in forcing NixOS to support GHCup? I’m now running an entertaining triboot system of NixOS - Arch - Win10 (with Debian WSL2 underneath to boot), so it’s not such a big deal, but it’d be fun to have access to the GHCup-based workflow on NixOS.
If you took all the nixpills (including flakes), I would argue it’s actually much easier to setup Haskell tooling consistently and reproducibly using Nixpkgs. NixOS is not necessary relevant in this context. I use NixOS mostly on laptops, and I have an old server using Fedora+nixpkgs.
I still recommend people using ghcup unless I sense they might be interested in the pills too.
But I do see that it might be difficult to quickly get started because there is a lack of single way of doing it, and hence hard to get started if one’s Nix Fu is not there yet.
Is anyone aware of a good writeup on this subject already? I might be able to provide one otherwise.
Yeah, perhaps I’m just too attached to maerwald’s work, because Nix is relatively rare and NixOps is actually a specific skill that can lead to lucrative positions.
It’s probably why I’m attached to Windows Haskell, even though Haskell on Windows is mediocre at best, since Windows is ubiquitous and being able to get Windows Haskell to work and be productive helps in pushing for acceptance of Haskell.
In my case, I love NixOS (it’s literally the most newbie friendly Linux provided you aren’t afraid of screwing around with .nix config files), I love Haskell, I love GHCup. I’m typing this on an Arch distro just to keep my GHCup, but I’ll probably figure out how to jerry-rig GHCup to sort of work.
I’ve also been thinking about this. The workflow I would want is just the exact same as GHCup on other platforms: always downloading binaries (unless explicitly running ghcup compile ...) and having GHC (and HLS, cabal, stack) versions decoupled from nixpkgs.
I have thought having a pinned nixpkgs branch maintained by someone, where its caching can be ensured, so that no one would need to recompile them for recent versions of two latest major release GHCs. But perhaps the cost can be an issue for caching things for the community.
We have built something somewhat related with our devx shell. It used haskell.nix to get the compilers, cabal, hls (and some other tools); and is cached on cache.zw3rk.com.
which provide a shell with ghc, cabal, hls, hlint, …
There is also a guide on how to use it with direnv, and make it work with VSCode, emacs, and vim.
There is also a note on getting DevContainer/CodeSpaces to work.
We’ve also got a corresponding speed-optimised GitHub Action, which we use in ci to test the various combinations we have to build the hello package.
As this builds on the logic in haskell.nix, we can do (limited) cross compilation (e.g. to windows), and static targets. However I will note that there may still be residual bugs.
I was able to install GHC 9.8.1 with HLS support using only binaries in less than 2 minutes or so. I haven’t been able to do that yet using any other approach.
(The devx documentation says you can alternatively add yourself to the list of trusted users and enable some setting which trusts flakes, but that involves a bit too much trust for my taste.)
It seems to download a whole new OS including packages like git, gcc, and even systemd. That seems a bit overkill.
It also installs an isolated cabal and I needed to do cabal update first.
I don’t know how to add additional system dependencies. For example what if I want to use sbv and need Z3 installed? Or perhaps more interesting, what if there really is a C dependency like gi-gtk?
The cabal version seems to be 3.10.1.0 currently, while I had hoped to get 3.10.2.0 (or maybe it doesn’t include cabal and that is just the version I already had installed?).
What I really want is to install a few common versions of GHC and corresponding HLS globally such that I can use with-compiler: ... in cabal.project files to have cabal automatically pick up the right compiler version without me having to bother with direnv for most packages.
I believe you could somehow build an entirely different installation logic behind the same cli interface.
It will lose some properties like simplicity of where files are placed, maybe also different space requirements. But you’ll be able to get a different configuration experience.
I’d prefer the word “incompatibility” to “hostility” — toolchains are used in Nixpkgs wherever they don’t destroy the value Nix brings.
That said, Nix and NixOs are definitely hard to figure out and aren’t compatible with every workflow.
What I’ve recently learned is embrace flakes — if you’re gonna have a bad time, you might as well have the best bad time available. I’ve gotten as far as creating a template with all the best practices I know for packaging Cabal packages on Nix. Now I run
whenever I want to instantly get going. Using a different compiler is as easy as changing which branch of NixOS I pull from, assuming I’m within a reasonable range for production use. Once the flake.nix is initialized, it’s a one line change.
If the compiler I want isn’t on a NixOS release, then this doesn’t work. Working on the bleeding edge is one of the use cases I don’t use NixOS for, nor indeed any distro. But I do still use nix-shell for the dev environment when skating on the bleeding edge.
For me it is much more about HLS and whether or not it is cached. Building it from source cost me more than half an hour if I remember it right, so I’d really like to avoid that. And that is much more common, for example the HLS for GHC 9.6.3 is not in the (nixpkgs/hydra) cache let alone the one for GHC 9.8.1.
@jaror we are trying to address this. I hope to have some good answers to the points you raised. The biggest issue with haskell.nix (and thus devx) we run into is that adding new compilers and support all the targets we do, is often a lot of work. Just adding 9.4.8 has been quite some work :-/
I think for most items we can probably try to make them easier. For globally installed GHCs though I don’t see this working easily. That’s something that GHCup is much better at.
Adding additional system dependencies I think should work by entering another sub shell. After all it’s all cabal + ghc really so as soon as they are available in the environment it should work. We haven’t found a good way to augment flake shells yet.
I think the main question of this topic is “How can we get a GHCup(-like) workflow on NixOS?”
For me that includes:
Quick access to new releases, e.g. 9.8 now.
Use normal cabal workflow including the ability to use C dependencies
One of the suggestions was to use the devx shell, but I’m encountered some ways in which it doesn’t quite behave as well as GHCup would on other platforms.
I guess @Liamzy never answered this question and I did kind of take over the discussion from there.
@Liamzy if you want to keep this thread strictly on the topic of making GHCup work on NixOS then I can split out my part of the discussion to another thread.