Skip to content

Commit 5ff3652

Browse files
authored
Update with notes on Non-Haskell Dependencies
1 parent 7e4e665 commit 5ff3652

1 file changed

Lines changed: 44 additions & 14 deletions

File tree

README.md

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ This is an example Haskell project using Nix to setup a development environment.
44

55
This uses Nix and Cabal without Stack. This is because when using Nix, you don't need Stack, as Nix provides harmonious snapshots of Haskell packages. However Stack users can still develop on this project, they just have to generate an appropriate `stack.yaml` from the Cabal file.
66

7-
The first step is that we have to acquire `cabal2nix`, which we use to generate a `default.nix` file from the `package.yaml`. Note that the usage of `package.yaml` means we are using the [hpack format](https://github.com/sol/hpack). This format is transformed to a cabal file via the `hpack` command.
7+
The first step is that we have to acquire `cabal2nix`, which we use to generate a `cabal.nix` file from the `package.yaml`. Our custom `default.nix` then imports the `cabal.nix` and adds extra custom build steps like encoding environment variables.
8+
9+
Note that the usage of `package.yaml` means we are using the [hpack format](https://github.com/sol/hpack). This format is transformed to a cabal file via the `hpack` command.
810

911
```sh
1012
nix-shell -p cabal2nix
1113
# using --hpack ensures that we always use package.yaml
12-
cabal2nix --hpack . >./default.nix
14+
cabal2nix --hpack . >./cabal.nix
1315
```
1416

1517
The above command is also executed at the beginning of the `shellHook`.
@@ -88,6 +90,14 @@ Once you have finished developing, you can build the package using:
8890
nix-build
8991
```
9092

93+
Note that if you want to create a quick and dirty `nix-shell` with GHC and a few packages, just use:
94+
95+
```sh
96+
nix-shell -p 'ghc.ghcWithPackages (pkgs: [ pkgs.aeson pkgs.dlist ])'
97+
# or if you want to specify a version
98+
nix-shell -p 'haskell.packages.ghc865.ghcWithPackages (pkgs: [ pkgs.aeson pkgs.dlist ])'
99+
```
100+
91101
## Using the `package.yaml`
92102

93103
Any module that is meant to be consumed as a library needs to be listed in the `exposed-modules`. Any module that is not listed there are considered to be private modules.
@@ -106,6 +116,38 @@ Note that Haskell dependency constraints and versions when using `cabal2nix` is
106116

107117
Remember that Haskell package versions conventionally use `Major.Major.Minor.Patch`. For more information see: https://pvp.haskell.org/
108118

119+
## Non-Haskell Dependencies
120+
121+
For non-Haskell dependencies that are CLI executables, if you want them to be made available to the build and final output, you need to add these dependencies to:
122+
123+
```yaml
124+
system-build-tools:
125+
- hello
126+
```
127+
128+
This will put it into the generated `cabal.nix` as a function parameter.
129+
130+
To ensure that these dependency names do not conflict with Haskell dependencies with the same name, it's important to specify them when using the `callPackage`.
131+
132+
```nix
133+
(haskellPackages.callPackage ./cabal.nix { hello = pkgs.hello; });
134+
```
135+
136+
For non-Haskell dependencies that are compiled libraries that are expected to be linked against, you need to add these dependencies to:
137+
138+
```yaml
139+
extra-libraries:
140+
- mnl
141+
```
142+
143+
These C libraries will be made available to `nix-build` and `nix-shell`. The `cabal configure` will automatically find them and link them during compilation.
144+
145+
However in Nixpkgs, these libraries will have different names. You should then explicitly specify them when using the `callPackage`:
146+
147+
```nix
148+
haskellPackages.callPackage (import ./cabal.nix) { mnl = pkgs.libmnl; };
149+
```
150+
109151
## Using GHCi (or `cabal repl` or `stack ghci`)
110152

111153
The `cabal v2-repl` only works against the build targets specified in the `package.yaml`. You have to specify the target name:
@@ -143,15 +185,3 @@ The `include-dirs` is a list of directories containing C headers to be included.
143185
The `install-includes` will ensure that these headers (relative to the include-dirs) are also exported to any downstream package that depends on this package. So they can make use of those same headers, if they were also writing their own C code.
144186

145187
Finally you just need to write code like `FFI.hs`, and everything just works normally.
146-
147-
---
148-
149-
Because Haskell is a compiled language, most building tools are `nativeBuildInputs`. However for the `shell.nix` this distinction doesn't matter, because it just puts you into an environment that has all the dependencies.
150-
151-
Note that if you want to create a quick and dirty `nix-shell` with GHC and a few packages, just use:
152-
153-
```sh
154-
nix-shell -p 'ghc.ghcWithPackages (pkgs: [ pkgs.aeson pkgs.dlist ])'
155-
# or if you want to specify a version
156-
nix-shell -p 'haskell.packages.ghc843.ghcWithPackages (pkgs: [ pkgs.aeson pkgs.dlist ])'
157-
```

0 commit comments

Comments
 (0)