Verified Commit 57698b37 authored by doshitan's avatar doshitan
Browse files

More nix page content

parent 1032a015
......@@ -290,7 +290,6 @@ This automatically calls `cabal2nix`, makes it easy to specify overrides and suc
If you want to fix a compiler version, say the default is too new for you:
```nix
{ pkgs ? import <nixpkgs> {}
, ghcVersion ? "ghc842"
}:
......@@ -304,11 +303,77 @@ There's a little more on this in [the
manual](https://nixos.org/nixpkgs/manual/#how-to-specify-source-overrides-for-your-haskell-package),
particularly for when you need to override a dependencies packaged version.
A more complete (and complicated) example:
```nix
{ pkgs ? import <nixpkgs> {}
, ghcVersion ? "ghc842"
}:
pkgs.haskell.packages."${ghcVersion}".developPackage {
root = ./.;
# `source-overrides` are overrides on which source code to fetch for a
# package, here we can specify *what* to build for a dependency
source-overrides = {
# if you need to use a different version from Hackage than what is in
# the current package set, can just specify the version and it will be
# fetched automatically (gets turned into a call to the `callHackage`
# function)
HUnit = "1.5.0.0";
# if you need a Haskell package that is not on Hackage, say either an
# unpublished version or a fork, just fetch the repo
servant-swagger = pkgs.fetchFromGitHub {
owner = "haskell-servant";
repo = "servant-swagger";
rev = "9c0ceb9f5cd00a47e922ba5de4be5ad591d99a0a";
sha256 = "1qkpj40sgy0nidd9av4rvd8754lh6zhakdqa05jgkzizf37wfz10";
};
# if you have a local checkout of a package, you can specify the path to it,
# this might commonly be a submoduled package, but you can specify paths
# outside the current project, though this of course only works for you personal
# local setup, but sometimes that's all you need
my-local-package = ../my-local-package;
};
# `overrides` are overrides to the package derivations themselves, so it's
# here we can can specify changes to *how* dependencies are built, generally
# using helper functions from the nix haskell library, see all the options:
# https://github.com/NixOS/nixpkgs/blob/f3282c8d1e0ce6ba5d9f6aeddcfad51d879c7a4a/pkgs/development/haskell-modules/lib.nix
#
# "overriding" a set of things is a common pattern in nix, for clarity here
# I've used a more verbose style, but:
#
# `newHaskellPkgs` is conventionally called `self` and is the overridden set
# after it's been resolved, which you sometimes need
#
# `oldHaskellPkgs` is conventionally called `super`, it's basically the set of
# things you are overriding
overrides = newHaskellPkgs: oldHaskellPkgs: {
# sometimes you need to use a package that has a broken test suite for
# whatever reason, here in overrides you can use the helper `dontCheck` to
# skip the test suite when building the package
hasktags = pkgs.haskell.lib.dontCheck oldHaskellPkgs.hasktags;
# sometimes packages have overly restrictive version bounds, the
# `doJailbreak` helper can tell the build to ignore them so it can be built
# against the versions you have in your package set
async = pkgs.haskell.lib.doJailbreak oldHaskellPkgs.async;
# sometimes you need to patch a package to build or work right with you
# package set
some-package = pkgs.haskell.lib.appendPatch oldHaskellPkgs.some-package ./fix-some-package.patch;
};
}
```
## Improved setup
While `haskellPackages.developPackage` is pretty easy, for any non-trivial
project, you are probably going to want a little more control over the shell
environment.
project, you are probably going to want a little more control, particularly over
the shell environment.
In your `default.nix`, extend the Haskell package set to include the project packages:
......@@ -322,10 +387,6 @@ let
bar = ./bar;
# for a simple project with only one package at the top-level, this might be
# baz = ./.;
# fetch free version 5.0.2 from Hackage instead of what is in `pkgs`,
# `packageSourceOverrides` wraps this in a `callHackage` call
free = "5.0.2";
});
in {
inherit pkgs haskellPackages;
......@@ -389,6 +450,118 @@ and
[haskell.lib.packageSourceOverrides](https://github.com/NixOS/nixpkgs/blob/713a45ecf79a4b4c632819f1c898d3e66c77bdd2/pkgs/development/haskell-modules/lib.nix#L43)
for more on what is actually going on.
A more complete (and complicated) example equivalent to the `developPackage` one:
```{.nix caption="default.nix"}
{ pkgs ? import <nixpkgs> {} }:
let
haskellPackages = pkgs.haskellPackages.extend (pkgs.lib.composeExtensions
# these are "source overrides", that is, overrides on which source code to
# fetch for a package, here we can specify *what* to build
(pkgs.haskell.lib.packageSourceOverrides ({
# your Haskell packages for the project
foo = ./foo;
bar = ./bar;
# if you need to use a different version from Hackage than what is in
# the current package set, can just specify the version and it will be
# fetched automatically (gets turned into a call to the `callHackage`
# function)
HUnit = "1.5.0.0";
# if you need a Haskell package that is not on Hackage, say either an
# unpublished version or a fork, just fetch the repo
servant-swagger = pkgs.fetchFromGitHub {
owner = "haskell-servant";
repo = "servant-swagger";
rev = "9c0ceb9f5cd00a47e922ba5de4be5ad591d99a0a";
sha256 = "1qkpj40sgy0nidd9av4rvd8754lh6zhakdqa05jgkzizf37wfz10";
};
# if you have a local checkout of a package, you can specify the path to it,
# this might commonly be a submoduled package, but you can specify paths
# outside the current project, though this of course only works for you personal
# local setup, but sometimes that's all you need
my-local-package = ../my-local-package;
}))
# these are overrides to the package derivations themselves, so it's here we
# can specify changes to *how* things are built, generally using helper
# functions from the nix haskell library, see all the options:
# https://github.com/NixOS/nixpkgs/blob/f3282c8d1e0ce6ba5d9f6aeddcfad51d879c7a4a/pkgs/development/haskell-modules/lib.nix
#
# "overriding" a set of things is a common pattern in nix, for clarity here
# I've used a more verbose style, but:
#
# `newHaskellPkgs` is conventionally called `self` and is the overridden set
# after it's been resolved, which you sometimes need
#
# `oldHaskellPkgs` is conventionally called `super`, it's basically the set of
# things you are overriding
(newHaskellPkgs: oldHaskellPkgs: {
# you can tweak the build flags for you packages here if needed
foo = pkgs.haskell.lib.buildStrictly oldHaskellPkgs.foo
bar = pkgs.haskell.lib.buildStrictly oldHaskellPkgs.bar
# sometimes you need to use a package that has a broken test suite for
# whatever reason, here in overrides you can use the helper `dontCheck` to
# skip the test suite when building the package
hasktags = pkgs.haskell.lib.dontCheck oldHaskellPkgs.hasktags;
# sometimes packages have overly restrictive version bounds, the
# `doJailbreak` helper can tell the build to ignore them so it can be built
# against the versions you have in your package set
async = pkgs.haskell.lib.doJailbreak oldHaskellPkgs.async;
# sometimes you need to patch a package to build or work right with you
# package set
some-package = pkgs.haskell.lib.appendPatch oldHaskellPkgs.some-package ./fix-some-package.patch;
})
);
in {
inherit pkgs haskellPackages;
# same as if we'd written:
# pkgs = pkgs;
# haskellPackages = haskellPackages;
# make the project package a top level attributes for easier building, e.g.,
# nix-build -A foo
#
# instead of
#
# nix-build -A haskellPackages.foo
foo = haskellPackages.foo;
bar = haskellPackages.bar;
# say foo is an executable, statically linking it to it's Haskell libs can
# reduce the closure size and simplify some things, e.g., non-nix deploys,
# though fully static Haskell executables take some more work, see:
# https://github.com/NixOS/nixpkgs/issues/43795
foo-static = pkgs.haskell.lib.justStaticExecutables haskellPackages.foo;
}
```
## haskell.nix
[haskell.nix](https://input-output-hk.github.io/haskell.nix/) is an alternate
Haskell infrastructure for nixpkgs. It's own [motivation
section](https://input-output-hk.github.io/haskell.nix/#motivation) details why
it exists, but generally, the goal is to have nix doing more of the work
natively (instead of relying on things like `cabal2nix`), which increases
flexibility, control, and simplicity.
I've not used it personally, but it's neat and seems a worthwhile endeavor to
experiment with what else is possible.
## Other nix-haskell stuff
- <https://notes.srid.ca/haskell-nix>
- <https://github.com/cdepillabout/post-about-nix-and-haskell>
# Learning Nix
......@@ -480,6 +653,45 @@ would do something in Ubuntu and the equivalent command on NixOS.
It also has a bunch of short little snippets about how to do various things,
cross-compile a package, and other similar tasks.
# Get source hash
So anytime something is fetched in a nix expression, we want the hash of the
result (the `sha256` attribute) for reproduciblity and security; to know it
hasn't been changed from what we expect (either from a malicious attack or
simple error) and to make checking if we even need to go fetch anything in the
first place (i.e., we've already fetched this version so the source so can just
use the local copy).
There are some `nix-prefetch-*` tools to help with getting that hash, the most
commonly used one is probably `nix-prefetch-url`.
Just give it a URL (usually to a tarball), it will fetch it, add it to the nix
store and print the hash for your expression.
For the hash to use in a `fetchTarball` call, you can just the tool directly.
For the hash to use in a `fetchFromGitHub` call, you will want to add the
`--unpack` flag, as this will check against the hash of the *content* of the
archive, not the hash of the tarball itself.
For example:
```nix
nix-prefetch-url --unpack https://github.com/NixOS/nix/archive/1f795f9f44607cc5bec70d1300150bfefcef2aae.tar.gz
```
There are other tools, `nix-prefetch-git` and `nix-prefetch-github`, equivalent
to above would be:
```nix
nix run -f '<nixpkgs>' nix-prefetch-github -c nix-prefetch-github --rev 1f795f9f44607cc5bec70d1300150bfefcef2aae NixOS nix
```
You can also just take another hash^[Or use `lib.fakeSha256` or generate a
random hash to use, e.g., `uuidgen | sha256sum`.], change one character, then
try to build the thing, nix will error telling you the hash it expected, which
you can then use and build again. This is hacky, and best to be avoided.
See the [relevant sections in the
manual](https://nixos.org/nixpkgs/manual/#how-to-specify-source-overrides-for-your-haskell-package).
# LaTeX
......@@ -493,3 +705,4 @@ Arbitrary, one-off environments:
- <https://hercules-ci.com/>
- <https://nixery.dev/>
- <https://r13y.com/>
- <https://nixos.org/nixpkgs/manual/#chap-conventions>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment