Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project Idea: Better haskell-specific tooling for working with nix #45

Closed
wants to merge 5 commits into from
Closed
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
71 changes: 71 additions & 0 deletions content/ideas/cabal-nix-workflow.md
@@ -0,0 +1,71 @@
---
title: Haskell specific tooling for working with nix projects
---

Nix is becoming more and more widely used as a way to manage package dependencies.
This is despite the approach being quite low level and difficult to use. There
are very few layers of abstraction which isolate less experienced uses from the
internal workings of the nix machine.

There are currently three main modes for working with nix which each have benefits and tradeoffs.

1. Using `stack` with nix (somewhat common)
2. Using `cabal` with the nix option (very uncommon)
3. Using nix directly (the most common)

To take each option in turn.

(1) only uses nix to manage non-haskell dependencies. This is clearly not ideal
as we can't make use of the binary caching or anything else which is great about nix.

(2) is quite simple minded currently and relies on the presence of an
already generated `shell.nix` file. When the option is set several commands are run in this shell
instead of using cabal's normal dependency management.

(3) The most flexible option is to invoke `cabal2nix` yourself and then manipulate the
environment using `nix-shell` but there are several redundancies in this approach
such as having to regenerate the `shell.nix` file every time your cabal file changes.
It is also quite low level and requires in-depth knowledge about how nix works. We
want to abstract away from this.

However, the ideal tool doesn't yet exist. We want a tool with the following philosophy:
Nix, you are responsible for provisioning the correct environment but I will take
care of the all important build.

The user provides a declarative specification of their necessary environment (by a cabal file
or some other means), then when a user runs a command, nix provisions this
environment and then the tool runs the haskell specific commands necessary to
build the package locally.

As an exemplification of this, using workflow (3), by default invoking `cabal2nix --shell`
will generate a nix expression which loads both the build and test dependencies into the
environment. It is not usual for the test dependency tree to quite a bit larger than the
build dependency tree. Ideally, when a user runs "cabal build", cabal should enter
a nix shell with the appropriate build dependencies for building whichever component
it wants to build and no more. Similarly, "cabal test" should load enter an
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"should load enter an" doesn't look quite right.

environment with test dependencies. It is currently possible to achieve this
for benchmarking dependencies by the somewhat archaic `nix-shell --argstr doBenchmark true`.


Some more possible angles to explore are:

* In a `cabal.project` file we can specify additional local dependencies.
In `--nix` mode, these should turn into overrides of the local package set and `nix` should
build them.

* There should be an easy way to "pin" a nixpkgs version so that builds are reproducible.
This could take the form of specifying a hash directly of a nixpkgs commit or more indirectly
such as specifying a `lts` version (with an appropriately generated package set) and so on.

* `cabal build --nix -w ghc-8.0.2` should modify the environment to provision the
8.0.2 package set rather than rely on the user to have already installed the
compiler locally.

There are many more angles to explore. A successful proposal will flesh out in
detail what would be necessary to implement one or perhaps two of these ideas.

https://github.com/Gabriel439/haskell-nix/issues
https://docs.haskellstack.org/en/stable/nix_integration/
https://www.haskell.org/cabal/users-guide/nix-integration.html

**Difficulty**: Intermediate