pwm / nixkell

A simple Nix-Haskell skeleton
MIT License
97 stars 11 forks source link

Adding outside dependencies to a project #7

Closed elland closed 3 years ago

elland commented 3 years ago

First, thanks for this.

After struggling with reproducible builds across different machines and systems for way too long, I decided to pull the trigger and finally try out nix. As everyone knows, that’s a difficult road to travel and projects such as these help lowering the barrier to entry.

Now as a nix newbie, I have a question I wasn’t able to figure out in the docs. The project has a packages.nix and a packages folder inside, but I’m unsure how to proceed with them.

Let’s say I want to add a dependency to my project that nix can’t build (marked as broken or not even available) but I can download the tarball from hackage. How would one go about adding such a dependency to their project?

On a similar note, if I need to fork a package, what about using a git link?

Both of those are feasible with stack but I’m not sure how to go about it using Nixkell.

Thanks in advance :)

pwm commented 3 years ago

Hey @Elland, first of all apologies for the long radio silence, real world has caught up with me a bit lately...

Great question! It's something I should definitely address in the readme now that I will have a bit more time again.

The easiest way to do that is using cabal2nix. First add it under tools in nixkell.toml.

To get something from hackage:

cabal2nix cabal://mylib-1.2.3.4 > nix/packages/mylib.nix

To get it from github:

cabal2nix git@github.com:myself/mylib.git > nix/packages/mylib.nix

Once the above is done just run direnv reload and nix should get those packages. This works thanks to packagesFromDirectory which we use in packages.nix.

You can tweak things further in the manual section of ourHaskell in package.nix, eg. you can remove version bound checks:

mylib = pkgs.haskell.lib.doJailbreak(hprev.mylib);

With the current way nixkell is set up I think the above is the simplest way to achieve what you want.

Another way would be to do it "on-the-fly", without manually executing cabal2nix and storing the resulting package file under nix/packages. This would mean adding the following in the manual section:

mylib = hprev.callCabal2nix "mylib"
  (builtins.fetchGit {
    url = git@github.com:myself/mylib.git;
    rev = ...;
  })
  { };

You could also use callHackageDirect instead of fetchGit to get it from Hackage.

I think a nicer way of doing the "on-the-fly" version is not to hard-code the url/rev in the nix file, rather use niv:

niv add git git@github.com:myself/mylib

and store the pinned dependency in the usual sources.json file. Then in overlays.nix you can pass in sources as well:

import ./packages.nix { inherit sources; pkgs = prev; };

and then in fetchGit you can just reference it:

    url = sources.mylib.repo;
    rev = sources.mylib.rev;

This way all your pins are kept in one central place (sources.json).

Hope this helps!

elland commented 3 years ago

Thanks @pwm, that was super helpful! If we could add that to the README, that'd be great!