1# Agda {#agda}
2
3## How to use Agda {#how-to-use-agda}
4
5Agda is available as the [agda](https://search.nixos.org/packages?channel=unstable&show=agda&from=0&size=30&sort=relevance&query=agda)
6package.
7
8The `agda` package installs an Agda-wrapper, which calls `agda` with `--library-file`
9set to a generated library-file within the nix store, this means your library-file in
10`$HOME/.agda/libraries` will be ignored. By default the agda package installs Agda
11with no libraries, i.e. the generated library-file is empty. To use Agda with libraries,
12the `agda.withPackages` function can be used. This function either takes:
13
14* A list of packages,
15* or a function which returns a list of packages when given the `agdaPackages` attribute set,
16* or an attribute set containing a list of packages and a GHC derivation for compilation (see below).
17* or an attribute set containing a function which returns a list of packages when given the `agdaPackages` attribute set and a GHC derivation for compilation (see below).
18
19For example, suppose we wanted a version of Agda which has access to the standard library. This can be obtained with the expressions:
20
21```nix
22agda.withPackages [ agdaPackages.standard-library ]
23```
24
25or
26
27```nix
28agda.withPackages (p: [ p.standard-library ])
29```
30
31or can be called as in the [Compiling Agda](#compiling-agda) section.
32
33If you want to use a different version of a library (for instance a development version)
34override the `src` attribute of the package to point to your local repository
35
36```nix
37agda.withPackages (p: [
38 (p.standard-library.overrideAttrs (oldAttrs: {
39 version = "local version";
40 src = /path/to/local/repo/agda-stdlib;
41 }))
42])
43```
44
45You can also reference a GitHub repository
46
47```nix
48agda.withPackages (p: [
49 (p.standard-library.overrideAttrs (oldAttrs: {
50 version = "1.5";
51 src = fetchFromGitHub {
52 repo = "agda-stdlib";
53 owner = "agda";
54 rev = "v1.5";
55 hash = "sha256-nEyxYGSWIDNJqBfGpRDLiOAnlHJKEKAOMnIaqfVZzJk=";
56 };
57 }))
58])
59```
60
61If you want to use a library not added to Nixpkgs, you can add a
62dependency to a local library by calling `agdaPackages.mkDerivation`.
63
64```nix
65agda.withPackages (p: [
66 (p.mkDerivation {
67 pname = "your-agda-lib";
68 version = "1.0.0";
69 src = /path/to/your-agda-lib;
70 })
71])
72```
73
74Again you can reference GitHub
75
76```nix
77agda.withPackages (p: [
78 (p.mkDerivation {
79 pname = "your-agda-lib";
80 version = "1.0.0";
81 src = fetchFromGitHub {
82 repo = "repo";
83 owner = "owner";
84 version = "...";
85 rev = "...";
86 hash = "...";
87 };
88 })
89])
90```
91
92See [Building Agda Packages](#building-agda-packages) for more information on `mkDerivation`.
93
94Agda will not by default use these libraries. To tell Agda to use a library we have some options:
95
96* Call `agda` with the library flag:
97 ```ShellSession
98 $ agda -l standard-library -i . MyFile.agda
99 ```
100* Write a `my-library.agda-lib` file for the project you are working on which may look like:
101 ```
102 name: my-library
103 include: .
104 depend: standard-library
105 ```
106* Create the file `~/.agda/defaults` and add any libraries you want to use by default.
107
108More information can be found in the [official Agda documentation on library management](https://agda.readthedocs.io/en/v2.6.1/tools/package-system.html).
109
110## Compiling Agda {#compiling-agda}
111
112Agda modules can be compiled using the GHC backend with the `--compile` flag. A version of `ghc` with `ieee754` is made available to the Agda program via the `--with-compiler` flag.
113This can be overridden by a different version of `ghc` as follows:
114
115```nix
116agda.withPackages {
117 pkgs = [
118 # ...
119 ];
120 ghc = haskell.compiler.ghcHEAD;
121}
122```
123
124## Writing Agda packages {#writing-agda-packages}
125
126To write a nix derivation for an Agda library, first check that the library has a `*.agda-lib` file.
127
128A derivation can then be written using `agdaPackages.mkDerivation`. This has similar arguments to `stdenv.mkDerivation` with the following additions:
129
130* `everythingFile` can be used to specify the location of the `Everything.agda` file, defaulting to `./Everything.agda`. If this file does not exist then either it should be patched in or the `buildPhase` should be overridden (see below).
131* `libraryName` should be the name that appears in the `*.agda-lib` file, defaulting to `pname`.
132* `libraryFile` should be the file name of the `*.agda-lib` file, defaulting to `${libraryName}.agda-lib`.
133
134Here is an example `default.nix`
135
136```nix
137{
138 nixpkgs ? <nixpkgs>,
139}:
140with (import nixpkgs { });
141agdaPackages.mkDerivation {
142 version = "1.0";
143 pname = "my-agda-lib";
144 src = ./.;
145 buildInputs = [
146 agdaPackages.standard-library
147 ];
148}
149```
150
151### Building Agda packages {#building-agda-packages}
152
153The default build phase for `agdaPackages.mkDerivation` runs `agda` on the `Everything.agda` file.
154If something else is needed to build the package (e.g. `make`) then the `buildPhase` should be overridden.
155Additionally, a `preBuild` or `configurePhase` can be used if there are steps that need to be done prior to checking the `Everything.agda` file.
156`agda` and the Agda libraries contained in `buildInputs` are made available during the build phase.
157
158### Installing Agda packages {#installing-agda-packages}
159
160The default install phase copies Agda source files, Agda interface files (`*.agdai`) and `*.agda-lib` files to the output directory.
161This can be overridden.
162
163By default, Agda sources are files ending on `.agda`, or literate Agda files ending on `.lagda`, `.lagda.tex`, `.lagda.org`, `.lagda.md`, `.lagda.rst`. The list of recognised Agda source extensions can be extended by setting the `extraExtensions` config variable.
164
165## Maintaining the Agda package set on Nixpkgs {#maintaining-the-agda-package-set-on-nixpkgs}
166
167We are aiming at providing all common Agda libraries as packages on `nixpkgs`,
168and keeping them up to date.
169Contributions and maintenance help is always appreciated,
170but the maintenance effort is typically low since the Agda ecosystem is quite small.
171
172The `nixpkgs` Agda package set tries to take up a role similar to that of [Stackage](https://www.stackage.org/) in the Haskell world.
173It is a curated set of libraries that:
174
1751. Always work together.
1762. Are as up-to-date as possible.
177
178While the Haskell ecosystem is huge, and Stackage is highly automatised,
179the Agda package set is small and can (still) be maintained by hand.
180
181### Adding Agda packages to Nixpkgs {#adding-agda-packages-to-nixpkgs}
182
183To add an Agda package to `nixpkgs`, the derivation should be written to `pkgs/development/libraries/agda/${library-name}/` and an entry should be added to `pkgs/top-level/agda-packages.nix`. Here it is called in a scope with access to all other Agda libraries, so the top line of the `default.nix` can look like:
184
185```nix
186{
187 mkDerivation,
188 standard-library,
189 fetchFromGitHub,
190}:
191{ }
192```
193
194Note that the derivation function is called with `mkDerivation` set to `agdaPackages.mkDerivation`, therefore you
195could use a similar set as in your `default.nix` from [Writing Agda Packages](#writing-agda-packages) with
196`agdaPackages.mkDerivation` replaced with `mkDerivation`.
197
198Here is an example skeleton derivation for iowa-stdlib:
199
200```nix
201mkDerivation {
202 version = "1.5.0";
203 pname = "iowa-stdlib";
204
205 src = <...>;
206
207 libraryFile = "";
208 libraryName = "IAL-1.3";
209
210 buildPhase = ''
211 runHook preBuild
212
213 patchShebangs find-deps.sh
214 make
215
216 runHook postBuild
217 '';
218}
219```
220
221This library has a file called `.agda-lib`, and so we give an empty string to `libraryFile` as nothing precedes `.agda-lib` in the filename. This file contains `name: IAL-1.3`, and so we let `libraryName = "IAL-1.3"`. This library does not use an `Everything.agda` file and instead has a Makefile, so there is no need to set `everythingFile` and we set a custom `buildPhase`.
222
223When writing an Agda package it is essential to make sure that no `.agda-lib` file gets added to the store as a single file (for example by using `writeText`). This causes Agda to think that the nix store is a Agda library and it will attempt to write to it whenever it typechecks something. See [https://github.com/agda/agda/issues/4613](https://github.com/agda/agda/issues/4613).
224
225In the pull request adding this library,
226you can test whether it builds correctly by writing in a comment:
227
228```
229@ofborg build agdaPackages.iowa-stdlib
230```
231
232### Maintaining Agda packages {#agda-maintaining-packages}
233
234As mentioned before, the aim is to have a compatible, and up-to-date package set.
235These two conditions sometimes exclude each other:
236For example, if we update `agdaPackages.standard-library` because there was an upstream release,
237this will typically break many reverse dependencies,
238i.e. downstream Agda libraries that depend on the standard library.
239In `nixpkgs` we are typically among the first to notice this,
240since we have build tests in place to check this.
241
242In a pull request updating e.g. the standard library, you should write the following comment:
243
244```
245@ofborg build agdaPackages.standard-library.passthru.tests
246```
247
248This will build all reverse dependencies of the standard library,
249for example `agdaPackages.agda-categories`, or `agdaPackages.generic`.
250
251In some cases it is useful to build _all_ Agda packages.
252This can be done with the following Github comment:
253
254```
255@ofborg build agda.passthru.tests.allPackages
256```
257
258Sometimes, the builds of the reverse dependencies fail because they have not yet been updated and released.
259You should drop the maintainers a quick issue notifying them of the breakage,
260citing the build error (which you can get from the ofborg logs).
261If you are motivated, you might even send a pull request that fixes it.
262Usually, the maintainers will answer within a week or two with a new release.
263Bumping the version of that reverse dependency should be a further commit on your PR.
264
265In the rare case that a new release is not to be expected within an acceptable time,
266mark the broken package as broken by setting `meta.broken = true;`.
267This will exclude it from the build test.
268It can be added later when it is fixed,
269and does not hinder the advancement of the whole package set in the meantime.