Skip to content

Commit f279cde

Browse files
authored
Update the project modules and fix missing args param (#1144)
There are now 4 project modules used to check the arguments passed to the various project functions: * `project-common.nix` - Arguments used by all the project functions * `stack-project.nix` - Used by the `stackProject` and `stackProject'` functions * `cabal-project.nix` - Used by the `cabalProject` and `cabalProject'` functions * `project.nix` - Just the `projectFileName` argument that is used by `project` and `project'` functions to determine whether to call `stackProject` or `cabalProject` function. This also includes the `rawProject.args` that was mistakenly left out of #1141 causing #1142 and improvements for the docs for the use of the `shell` argument in `flake.nix` files.
1 parent f53f98a commit f279cde

File tree

7 files changed

+74
-62
lines changed

7 files changed

+74
-62
lines changed

docs/tutorials/getting-started-flakes.md

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,24 +50,26 @@ Add `flake.nix`:
5050
final.haskell-nix.project' {
5151
src = ./.;
5252
compiler-nix-name = "ghc8104";
53+
# This is used by `nix develop .` to open a shell for use with
54+
# `cabal`, `hlint` and `haskell-language-server`
55+
shell.tools = {
56+
cabal = {};
57+
hlint = {};
58+
haskell-language-server = {};
59+
};
60+
# This adds `js-unknown-ghcjs-cabal` to the shell.
61+
shell.crossPlatform = p: [p.ghcjs];
5362
};
5463
})
5564
];
5665
pkgs = import nixpkgs { inherit system overlays; };
57-
flake = pkgs.helloProject.flake {};
66+
flake = pkgs.helloProject.flake {
67+
# This adds support for `nix build .#js-unknown-ghcjs-cabal:hello:exe:hello`
68+
crossPlatforms = p: [p.ghcjs];
69+
};
5870
in flake // {
5971
# Built by `nix build .`
6072
defaultPackage = flake.packages."hello:exe:hello";
61-
62-
# This is used by `nix develop .` to open a shell for use with
63-
# `cabal`, `hlint` and `haskell-language-server`
64-
devShell = pkgs.helloProject.shellFor {
65-
tools = {
66-
cabal = "latest";
67-
hlint = "latest";
68-
haskell-language-server = "latest";
69-
};
70-
};
7173
});
7274
}
7375
```

lib/default.nix

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,9 @@ in {
339339
# The resulting config is then passed to the project function's implementation.
340340
evalProjectModule = projectType: m: f: f
341341
(lib.evalModules {
342-
modules = [m] ++ [
342+
modules = (if builtins.isList m then m else [m]) ++ [
343343
# Include ../modules/cabal-project.nix or ../modules/stack-project.nix
344+
(import ../modules/project-common.nix)
344345
(import projectType)
345346
# Pass the pkgs to the modules
346347
({ config, lib, ... }: {

modules/cabal-project.nix

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,6 @@ in {
1111
_file = "haskell.nix/modules/cabal-project.nix";
1212
options = {
1313
# Used by callCabalProjectToNix
14-
name = mkOption {
15-
type = nullOr str;
16-
default = config.src.name or null;
17-
description = "Optional name for better error messages";
18-
};
19-
src = mkOption {
20-
type = either path package;
21-
};
2214
compiler-nix-name = mkOption {
2315
type = str;
2416
description = "The name of the ghc compiler to use eg. \"ghc884\"";
@@ -137,17 +129,5 @@ in {
137129
type = nullOr (listOf unspecified);
138130
default = [];
139131
};
140-
141-
# Default shell arguments
142-
shell = mkOption {
143-
# TODO make this a submodule
144-
type = unspecified;
145-
default = {};
146-
description = ''
147-
Arguments to use for the default shell `p.shell` (these are passed to p.shellFor).
148-
For instance to include `cabal` and `ghcjs` support use
149-
shell = { tools.cabal = {}; crossPlatforms = p: [ p.ghcjs ]; }
150-
'';
151-
};
152132
};
153133
}

modules/project-common.nix

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{ lib, ... }:
2+
with lib;
3+
with lib.types;
4+
{
5+
_file = "haskell.nix/modules/project-common.nix";
6+
options = {
7+
# Used by callCabalProjectToNix and callStackToNix
8+
name = mkOption {
9+
type = nullOr str;
10+
default = "haskell-project"; # TODO figure out why `config.src.name or null` breaks hix;
11+
description = "Optional name for better error messages";
12+
};
13+
src = mkOption {
14+
type = either path package;
15+
};
16+
# Default shell arguments
17+
shell = mkOption {
18+
# TODO make this a submodule
19+
type = unspecified;
20+
default = {};
21+
description = ''
22+
Arguments to use for the default shell `p.shell` (these are passed to p.shellFor).
23+
For instance to include `cabal` and `ghcjs` support use
24+
shell = { tools.cabal = {}; crossPlatforms = p: [ p.ghcjs ]; }
25+
'';
26+
};
27+
};
28+
}

modules/project.nix

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{ lib, ... }: {
2+
_file = "haskell.nix/modules/project.nix";
3+
options = {
4+
projectFileName = lib.mkOption {
5+
type = lib.types.nullOr lib.types.str;
6+
default = null;
7+
};
8+
};
9+
}

modules/stack-project.nix

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,6 @@ with types;
55
_file = "haskell.nix/modules/stack-project.nix";
66
options = {
77
# Used by callStackToNix
8-
name = mkOption {
9-
type = nullOr str;
10-
default = config.src.name or null;
11-
description = "Optional name for better error messages";
12-
};
13-
src = mkOption {
14-
type = either path package;
15-
};
168
stackYaml = mkOption {
179
type = str;
1810
default = "stack.yaml";
@@ -109,17 +101,5 @@ with types;
109101
default = null;
110102
description = "Deprecated in favour of `compiler-nix-name`";
111103
};
112-
113-
# Default shell arguments
114-
shell = mkOption {
115-
# TODO make this a submodule
116-
type = unspecified;
117-
default = {};
118-
description = ''
119-
Arguments to use for the default shell `p.shell` (these are passed to p.shellFor).
120-
For instance to include `cabal` and `ghcjs` support use
121-
shell = { tools.cabal = {}; crossPlatforms = p: [ p.ghcjs ]; }
122-
'';
123-
};
124104
};
125105
}

overlays/haskell.nix

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ final: prev: {
531531
tools = final.buildPackages.haskell-nix.tools pkg-set.config.compiler.nix-name;
532532
roots = final.haskell-nix.roots pkg-set.config.compiler.nix-name;
533533
projectFunction = haskell-nix: haskell-nix.cabalProject';
534-
inherit projectModule;
534+
inherit projectModule args;
535535
};
536536
in project);
537537

@@ -793,7 +793,7 @@ final: prev: {
793793
tools = final.buildPackages.haskell-nix.tools pkg-set.config.compiler.nix-name;
794794
roots = final.haskell-nix.roots pkg-set.config.compiler.nix-name;
795795
projectFunction = haskell-nix: haskell-nix.stackProject';
796-
inherit projectModule;
796+
inherit projectModule args;
797797
};
798798
in project);
799799

@@ -809,9 +809,17 @@ final: prev: {
809809
# selected file ends in a `.yaml` it is assumed to be for `stackProject`.
810810
# If neither `stack.yaml` nor `cabal.project` exist `cabalProject` is
811811
# used (as it will use a default `cabal.project`).
812-
project' = { src, projectFileName ? null, ... }@args':
812+
project' = projectModule:
813813
let
814-
args = { caller = "project'"; } // final.lib.filterAttrs (n: _: n != "projectFileName") args';
814+
projectModule' = if builtins.isList projectModule then projectModule else [projectModule];
815+
inherit ((final.lib.evalModules {
816+
modules = [
817+
(import ../modules/project-common.nix)
818+
(import ../modules/stack-project.nix)
819+
(import ../modules/cabal-project.nix)
820+
(import ../modules/project.nix)
821+
] ++ projectModule';
822+
}).config) src projectFileName;
815823
dir = __readDir (src.origSrcSubDir or src);
816824
exists = fileName: builtins.elem (dir.${fileName} or "") ["regular" "symlink"];
817825
stackYamlExists = exists "stack.yaml";
@@ -829,15 +837,19 @@ final: prev: {
829837
else "cabal.project"; # the cabal.project file is optional
830838
in
831839
if final.lib.hasSuffix ".yaml" selectedFileName
832-
then stackProject' (args // { stackYaml = selectedFileName; })
833-
else cabalProject' (args // { cabalProjectFileName = selectedFileName; });
840+
then stackProject' ([
841+
(import ../modules/project.nix)
842+
{ caller = "project'"; stackYaml = selectedFileName; }
843+
] ++ projectModule'
844+
)
845+
else cabalProject' ([
846+
(import ../modules/project.nix)
847+
{ caller = "project'"; cabalProjectFileName = selectedFileName; }
848+
] ++ projectModule');
834849

835850
# This is the same as the `cabalPackage` and `stackPackage` wrappers
836851
# for `cabalPackage` and `stackPackage`.
837-
project = args':
838-
let
839-
args = { caller = "project"; } // args';
840-
p = project' args;
852+
project = args: let p = project' args;
841853
in p.hsPkgs // p;
842854

843855
# Like `cabalProject'`, but for building the GHCJS compiler.

0 commit comments

Comments
 (0)