diff --git a/doc/languages-frameworks/agda.section.md b/doc/languages-frameworks/agda.section.md
new file mode 100644
index 00000000000..7a5dc767b7c
--- /dev/null
+++ b/doc/languages-frameworks/agda.section.md
@@ -0,0 +1,96 @@
+---
+title: Agda
+author: Alex Rice (alexarice)
+date: 2020-01-06
+---
+# Agda
+
+## How to use Agda
+
+Agda can be installed from `agda`:
+```
+$ nix-env -iA agda
+```
+
+To use agda with libraries, the `agda.withPackages` function can be used. This function either takes:
++ A list of packages,
++ or a function which returns a list of packages when given the `agdaPackages` attribute set,
++ or an attribute set containing a list of packages and a GHC derivation for compilation (see below).
+
+For example, suppose we wanted a version of agda which has access to the standard library. This can be obtained with the expressions:
+
+```
+agda.withPackages [ agdaPackages.standard-library ]
+```
+
+or
+
+```
+agda.withPackages (p: [ p.standard-library ])
+```
+
+or can be called as in the [Compiling Agda](#compiling-agda) section.
+
+If you want to use a library in your home directory (for instance if it is a development version) then typecheck it manually (using `agda.withPackages` if necessary) and then override the `src` attribute of the package to point to your local repository.
+
+Agda will not by default use these libraries. To tell agda to use the library we have some options:
+- Call `agda` with the library flag:
+```
+$ agda -l standard-library -i . MyFile.agda
+```
+- Write a `my-library.agda-lib` file for the project you are working on which may look like:
+```
+name: my-library
+include: .
+depends: standard-library
+```
+- Create the file `~/.agda/defaults` and add any libraries you want to use by default.
+
+More information can be found in the [official Agda documentation on library management](https://agda.readthedocs.io/en/v2.6.1/tools/package-system.html).
+
+## Compiling Agda
+Agda modules can be compiled with the `--compile` flag. A version of `ghc` with `ieee` is made available to the Agda program via the `--with-compiler` flag.
+This can be overridden by a different version of `ghc` as follows:
+
+```
+agda.withPackages {
+ pkgs = [ ... ];
+ ghc = haskell.compiler.ghcHEAD;
+}
+```
+
+## Writing Agda packages
+To write a nix derivation for an agda library, first check that the library has a `*.agda-lib` file.
+
+A derivation can then be written using `agdaPackages.mkDerivation`. This has similar arguments to `stdenv.mkDerivation` with the following additions:
++ `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).
++ `libraryName` should be the name that appears in the `*.agda-lib` file, defaulting to `pname`.
++ `libraryFile` should be the file name of the `*.agda-lib` file, defaulting to `${libraryName}.agda-lib`.
+
+The build phase for `agdaPackages.mkDerivation` simply runs `agda` on the `Everything.agda` file. If something else is needed to build the package (e.g. `make`) then the `buildPhase` should be overridden (or a `preBuild` or `configurePhase` can be used if there are steps that need to be done prior to checking the `Everything.agda` file). `agda` and the Agda libraries contained in `buildInputs` are made available during the build phase. The install phase simply copies all `.agda`, `.agdai` and `.agda-lib` files to the output directory. Again, this can be overridden.
+
+To 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:
+```
+{ mkDerivation, standard-library, fetchFromGitHub }:
+```
+and `mkDerivation` should be called instead of `agdaPackages.mkDerivation`. Here is an example skeleton derivation for iowa-stdlib:
+
+```
+mkDerivation {
+ version = "1.5.0";
+ pname = "iowa-stdlib";
+
+ src = ...
+
+ libraryFile = "";
+ libraryName = "IAL-1.3";
+
+ buildPhase = ''
+ patchShebangs find-deps.sh
+ make
+ '';
+}
+```
+This 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`.
+
+When 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).
diff --git a/doc/languages-frameworks/index.xml b/doc/languages-frameworks/index.xml
index 9364c764bbf..97202751f7d 100644
--- a/doc/languages-frameworks/index.xml
+++ b/doc/languages-frameworks/index.xml
@@ -5,6 +5,7 @@
The standard build environment makes it easy to build typical Autotools-based packages with very little code. Any other kind of package can be accomodated by overriding the appropriate phases of stdenv. However, there are specialised functions in Nixpkgs to easily build packages for other programming languages, such as Perl or Haskell. These are described in this chapter.
+
diff --git a/pkgs/build-support/agda/default.nix b/pkgs/build-support/agda/default.nix
index 0d054eaa546..205aff55573 100644
--- a/pkgs/build-support/agda/default.nix
+++ b/pkgs/build-support/agda/default.nix
@@ -1,90 +1,71 @@
-# Builder for Agda packages. Mostly inspired by the cabal builder.
+# Builder for Agda packages.
-{ stdenv, Agda, glibcLocales
-, writeShellScriptBin
-, extension ? (self: super: {})
-}:
+{ stdenv, lib, self, Agda, runCommandNoCC, makeWrapper, writeText, mkShell, ghcWithPackages }:
-with stdenv.lib.strings;
+with lib.strings;
let
- defaults = self : {
- # There is no Hackage for Agda so we require src.
- inherit (self) src name;
-
- isAgdaPackage = true;
-
- buildInputs = [ Agda ] ++ self.buildDepends;
- buildDepends = [];
-
- buildDependsAgda = stdenv.lib.filter
- (dep: dep ? isAgdaPackage && dep.isAgdaPackage)
- self.buildDepends;
- buildDependsAgdaShareAgda = map (x: x + "/share/agda") self.buildDependsAgda;
-
- # Not much choice here ;)
- LANG = "en_US.UTF-8";
- LOCALE_ARCHIVE = stdenv.lib.optionalString
- stdenv.isLinux
- "${glibcLocales}/lib/locale/locale-archive";
-
- everythingFile = "Everything.agda";
-
- propagatedBuildInputs = self.buildDependsAgda;
- propagatedUserEnvPkgs = self.buildDependsAgda;
-
- # Immediate source directories under which modules can be found.
- sourceDirectories = [ ];
-
- # This is used if we have a top-level element that only serves
- # as the container for the source and we only care about its
- # contents. The directories put here will have their
- # *contents* copied over as opposed to sourceDirectories which
- # would make a direct copy of the whole thing.
- topSourceDirectories = [ "src" ];
-
- # FIXME: `dirOf self.everythingFile` is what we really want, not hardcoded "./"
- includeDirs = self.buildDependsAgdaShareAgda
- ++ self.sourceDirectories ++ self.topSourceDirectories
- ++ [ "." ];
- buildFlags = stdenv.lib.concatMap (x: ["-i" x]) self.includeDirs;
-
- agdaWithArgs = "${Agda}/bin/agda ${toString self.buildFlags}";
-
- buildPhase = ''
- runHook preBuild
- ${self.agdaWithArgs} ${self.everythingFile}
- runHook postBuild
+ withPackages' = {
+ pkgs,
+ ghc ? ghcWithPackages (p: with p; [ ieee ])
+ }: let
+ pkgs' = if builtins.isList pkgs then pkgs else pkgs self;
+ library-file = writeText "libraries" ''
+ ${(concatMapStringsSep "\n" (p: "${p}/${p.libraryFile}") pkgs')}
'';
+ pname = "agdaWithPackages";
+ version = Agda.version;
+ in runCommandNoCC "${pname}-${version}" {
+ inherit pname version;
+ nativeBuildInputs = [ makeWrapper ];
+ passthru.unwrapped = Agda;
+ } ''
+ mkdir -p $out/bin
+ makeWrapper ${Agda}/bin/agda $out/bin/agda \
+ --add-flags "--with-compiler=${ghc}/bin/ghc" \
+ --add-flags "--library-file=${library-file}" \
+ --add-flags "--local-interfaces"
+ makeWrapper ${Agda}/bin/agda-mode $out/bin/agda-mode
+ ''; # Local interfaces has been added for now: See https://github.com/agda/agda/issues/4526
- installPhase = let
- srcFiles = self.sourceDirectories
- ++ map (x: x + "/*") self.topSourceDirectories;
- in ''
- runHook preInstall
- mkdir -p $out/share/agda
- cp -pR ${concatStringsSep " " srcFiles} $out/share/agda
- runHook postInstall
- '';
+ withPackages = arg: if builtins.isAttrs arg then withPackages' arg else withPackages' { pkgs = arg; };
- passthru = {
- env = stdenv.mkDerivation {
- name = "interactive-${self.name}";
- inherit (self) LANG LOCALE_ARCHIVE;
- AGDA_PACKAGE_PATH = concatMapStrings (x: x + ":") self.buildDependsAgdaShareAgda;
- buildInputs = let
- # Makes a wrapper available to the user. Very useful in
- # nix-shell where all dependencies are -i'd.
- agdaWrapper = writeShellScriptBin "agda" ''
- exec ${self.agdaWithArgs} "$@"
- '';
- in [agdaWrapper] ++ self.buildDepends;
+
+ defaults =
+ { pname
+ , buildInputs ? []
+ , everythingFile ? "./Everything.agda"
+ , libraryName ? pname
+ , libraryFile ? "${libraryName}.agda-lib"
+ , buildPhase ? null
+ , installPhase ? null
+ , ...
+ }: let
+ agdaWithArgs = withPackages (builtins.filter (p: p ? isAgdaDerivation) buildInputs);
+ in
+ {
+ inherit libraryName libraryFile;
+
+ isAgdaDerivation = true;
+
+ buildInputs = buildInputs ++ [ agdaWithArgs ];
+
+ buildPhase = if buildPhase != null then buildPhase else ''
+ runHook preBuild
+ agda -i ${dirOf everythingFile} ${everythingFile}
+ runHook postBuild
+ '';
+
+ installPhase = if installPhase != null then installPhase else ''
+ runHook preInstall
+ mkdir -p $out
+ find \( -name '*.agda' -or -name '*.agdai' -or -name '*.agda-lib' \) -exec cp -p --parents -t "$out" {} +
+ runHook postInstall
+ '';
};
- };
- };
in
-{ mkDerivation = args: let
- super = defaults self // args self;
- self = super // extension self super;
- in stdenv.mkDerivation self;
+{
+ mkDerivation = args: stdenv.mkDerivation (args // defaults args);
+
+ inherit withPackages withPackages';
}
diff --git a/pkgs/development/libraries/agda/agda-prelude/default.nix b/pkgs/development/libraries/agda/agda-prelude/default.nix
index 86f21ad9b19..1709ce314d9 100644
--- a/pkgs/development/libraries/agda/agda-prelude/default.nix
+++ b/pkgs/development/libraries/agda/agda-prelude/default.nix
@@ -1,16 +1,16 @@
-{ stdenv, agda, fetchgit }:
+{ stdenv, mkDerivation, fetchFromGitHub }:
-agda.mkDerivation (self: rec {
+mkDerivation rec {
version = "eacc961c2c312b7443109a7872f99d55557df317";
- name = "agda-prelude-${version}";
+ pname = "agda-prelude";
- src = fetchgit {
- url = "https://github.com/UlfNorell/agda-prelude.git";
+ src = fetchFromGitHub {
+ owner = "UlfNorell";
+ repo = "agda-prelude";
rev = version;
sha256 = "0iql67hb1q0fn8dwkcx07brkdkxqfqrsbwjy71ndir0k7qzw7qv2";
};
- topSourceDirectories = [ "src" ];
everythingFile = "src/Prelude.agda";
meta = with stdenv.lib; {
@@ -18,6 +18,6 @@ agda.mkDerivation (self: rec {
description = "Programming library for Agda";
license = stdenv.lib.licenses.mit;
platforms = stdenv.lib.platforms.unix;
- maintainers = with maintainers; [ mudri ];
+ maintainers = with maintainers; [ mudri alexarice ];
};
-})
+}
diff --git a/pkgs/development/libraries/agda/agda-iowa-stdlib/default.nix b/pkgs/development/libraries/agda/iowa-stdlib/default.nix
similarity index 71%
rename from pkgs/development/libraries/agda/agda-iowa-stdlib/default.nix
rename to pkgs/development/libraries/agda/iowa-stdlib/default.nix
index 23013bfbc32..9cda6ceec13 100644
--- a/pkgs/development/libraries/agda/agda-iowa-stdlib/default.nix
+++ b/pkgs/development/libraries/agda/iowa-stdlib/default.nix
@@ -1,8 +1,8 @@
-{ stdenv, agda, fetchFromGitHub }:
+{ stdenv, mkDerivation, fetchFromGitHub }:
-agda.mkDerivation (self: rec {
+mkDerivation (rec {
version = "1.5.0";
- name = "agda-iowa-stdlib-${version}";
+ pname = "iowa-stdlib";
src = fetchFromGitHub {
owner = "cedille";
@@ -11,7 +11,9 @@ agda.mkDerivation (self: rec {
sha256 = "0dlis6v6nzbscf713cmwlx8h9n2gxghci8y21qak3hp18gkxdp0g";
};
- sourceDirectories = [ "./." ];
+ libraryFile = "";
+ libraryName = "IAL-1.3";
+
buildPhase = ''
patchShebangs find-deps.sh
make
@@ -22,6 +24,6 @@ agda.mkDerivation (self: rec {
description = "Agda standard library developed at Iowa";
license = stdenv.lib.licenses.free;
platforms = stdenv.lib.platforms.unix;
- maintainers = with stdenv.lib.maintainers; [ ];
+ maintainers = with stdenv.lib.maintainers; [ alexarice ];
};
})
diff --git a/pkgs/development/libraries/agda/agda-stdlib/default.nix b/pkgs/development/libraries/agda/standard-library/default.nix
similarity index 74%
rename from pkgs/development/libraries/agda/agda-stdlib/default.nix
rename to pkgs/development/libraries/agda/standard-library/default.nix
index 6647677f71c..6d85d560a9b 100644
--- a/pkgs/development/libraries/agda/agda-stdlib/default.nix
+++ b/pkgs/development/libraries/agda/standard-library/default.nix
@@ -1,8 +1,8 @@
-{ stdenv, agda, fetchFromGitHub, ghcWithPackages }:
+{ stdenv, mkDerivation, fetchFromGitHub, ghcWithPackages }:
-agda.mkDerivation (self: rec {
+mkDerivation rec {
+ pname = "standard-library";
version = "1.1";
- name = "agda-stdlib-${version}";
src = fetchFromGitHub {
repo = "agda-stdlib";
@@ -16,13 +16,11 @@ agda.mkDerivation (self: rec {
runhaskell GenerateEverything.hs
'';
- topSourceDirectories = [ "src" ];
-
meta = with stdenv.lib; {
homepage = "https://wiki.portal.chalmers.se/agda/pmwiki.php?n=Libraries.StandardLibrary";
description = "A standard library for use with the Agda compiler";
license = stdenv.lib.licenses.mit;
platforms = stdenv.lib.platforms.unix;
- maintainers = with maintainers; [ jwiegley mudri ];
+ maintainers = with maintainers; [ jwiegley mudri alexarice ];
};
-})
+}
diff --git a/pkgs/top-level/agda-packages.nix b/pkgs/top-level/agda-packages.nix
new file mode 100644
index 00000000000..5bd57b5dec8
--- /dev/null
+++ b/pkgs/top-level/agda-packages.nix
@@ -0,0 +1,24 @@
+{ pkgs, lib, callPackage, newScope, Agda }:
+
+let
+ mkAgdaPackages = Agda: lib.makeScope newScope (mkAgdaPackages' Agda);
+ mkAgdaPackages' = Agda: self: let
+ callPackage = self.callPackage;
+ inherit (callPackage ../build-support/agda {
+ inherit Agda self;
+ inherit (pkgs.haskellPackages) ghcWithPackages;
+ }) withPackages mkDerivation;
+ in {
+ inherit mkDerivation;
+
+ agda = withPackages [] // { inherit withPackages; };
+
+ standard-library = callPackage ../development/libraries/agda/standard-library {
+ inherit (pkgs.haskellPackages) ghcWithPackages;
+ };
+
+ iowa-stdlib = callPackage ../development/libraries/agda/iowa-stdlib { };
+
+ agda-prelude = callPackage ../development/libraries/agda/agda-prelude { };
+ };
+in mkAgdaPackages Agda
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index ea1a0791762..8c1414803ee 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -15128,19 +15128,10 @@ in
### DEVELOPMENT / LIBRARIES / AGDA
- agda = callPackage ../build-support/agda {
- glibcLocales = if pkgs.stdenv.isLinux then pkgs.glibcLocales else null;
- extension = self : super : { };
+ agdaPackages = callPackage ./agda-packages.nix {
inherit (haskellPackages) Agda;
};
-
- agdaIowaStdlib = callPackage ../development/libraries/agda/agda-iowa-stdlib { };
-
- agdaPrelude = callPackage ../development/libraries/agda/agda-prelude { };
-
- AgdaStdlib = callPackage ../development/libraries/agda/agda-stdlib {
- inherit (haskellPackages) ghcWithPackages;
- };
+ agda = agdaPackages.agda;
### DEVELOPMENT / LIBRARIES / JAVA
diff --git a/pkgs/top-level/release.nix b/pkgs/top-level/release.nix
index e0723523f4e..60a4a679f16 100644
--- a/pkgs/top-level/release.nix
+++ b/pkgs/top-level/release.nix
@@ -181,6 +181,7 @@ let
haskell.compiler = packagePlatforms pkgs.haskell.compiler;
haskellPackages = packagePlatforms pkgs.haskellPackages;
idrisPackages = packagePlatforms pkgs.idrisPackages;
+ agdaPackages = packagePlatforms pkgs.agdaPackages;
tests = packagePlatforms pkgs.tests;