Skip to content

Commit 0de60e8

Browse files
authored
reinstallable lib:ghc and option inheritance (#88)
- reinstallable lib:ghc - adds global options and option inheritance.
1 parent 8ee6fcf commit 0de60e8

File tree

4 files changed

+159
-159
lines changed

4 files changed

+159
-159
lines changed

default.nix

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ let
1313
# up much later on hackage; but are not installable
1414
# anyway. Therefore we just strip them out of the
1515
# pkg-def's packages.
16-
boot-pkgs = [ "rts" "ghc" "ghci" "ghc-boot" "ghc-boot-th"
16+
#
17+
# Note: these will need to be provided by alternative
18+
# means outside of hackage.
19+
boot-pkgs = [ "rts" "ghc" "ghc-boot-th" "ghc-boot" "ghci"
1720
"ghc-heap" # since ghc 8.6.
1821
];
1922
strip-pkg-def = pkgs: pkg-def: hackage: with pkgs.lib;

modules/component-driver.nix

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,27 @@ in
2323
type = lib.types.listOf lib.types.str;
2424
};
2525

26+
# Dependencies
27+
#
28+
# .--------. .------------------.
29+
# | pretty | < ------- | template-haskell |
30+
# '--------' '------------------'
31+
# v |
32+
# .---------. .-------. |
33+
# | deepseq | - > | array | |
34+
# '---------' '-------' v
35+
# v v .-------------.
36+
# .----------. .----------. .------. .- | ghc-boot-th |
37+
# | ghc-heap | | ghc-prim | | base |< -' '-------------'
38+
# '----------' '----------' '------' .----------------.
39+
# | v | | | integer-simple |
40+
# | .-----. | '-- > |-------or-------|
41+
# '---- > | rts | < -----' | integer-gmp |
42+
# '-----' '----------------'
43+
2644
config.nonReinstallablePkgs =
27-
[ "rts" "ghc" "ghc-prim" "integer-gmp" "integer-simple" "base"
28-
"array" "deepseq" "pretty" "ghc-boot-th" "template-haskell" "ghc-heap" ];
45+
[ "rts" "ghc-heap" "ghc-prim" "integer-gmp" "integer-simple" "base"
46+
"deepseq" "array" "ghc-boot-th" "pretty" "template-haskell" ];
2947

3048
options.hsPkgs = lib.mkOption {
3149
type = lib.types.unspecified;

modules/package.nix

Lines changed: 6 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -13,39 +13,22 @@
1313
# tests = { "..." = { depends = ... }; ... };
1414
# };
1515

16+
{ parentConfig, mod_args, listOfFilteringNulls, componentOptions, packageOptions }:
1617
{ lib, config, pkgs, haskellLib, ... }:
1718

1819
with lib;
1920
with types;
2021

21-
let
22-
# This is just like listOf, except that it filters out all null elements.
23-
listOfFilteringNulls = elemType: listOf elemType // {
24-
# Mostly copied from nixpkgs/lib/types.nix
25-
merge = loc: defs:
26-
map (x: x.value) (filter (x: x ? value && x.value != null) (concatLists (imap1 (n: def:
27-
if isList def.value then
28-
imap1 (m: def':
29-
(mergeDefinitions
30-
(loc ++ ["[definition ${toString n}-entry ${toString m}]"])
31-
elemType
32-
[{ inherit (def) file; value = def'; }]
33-
).optionalValue
34-
) def.value
35-
else
36-
throw "The option value `${showOption loc}` in `${def.file}` is not a list.") defs)));
37-
};
38-
in {
22+
{
3923
# This is how the Nix expressions generated by *-to-nix receive
4024
# their flags argument.
41-
config._module.args.flags = config.flags;
25+
config._module.args = mod_args // { flags = config.flags; };
4226

43-
options = {
27+
options = (packageOptions parentConfig) // {
4428
# TODO: Add descriptions to everything.
4529
flags = mkOption {
4630
type = attrsOf bool;
4731
};
48-
4932
package = {
5033
specVersion = mkOption {
5134
type = str;
@@ -98,7 +81,8 @@ in {
9881

9982
components = let
10083
componentType = submodule {
101-
options = {
84+
# add the shared componentOptions
85+
options = (componentOptions config) // {
10286
depends = mkOption {
10387
type = listOfFilteringNulls unspecified;
10488
default = [];
@@ -119,43 +103,6 @@ in {
119103
type = listOfFilteringNulls unspecified;
120104
default = [];
121105
};
122-
configureFlags = mkOption {
123-
type = listOfFilteringNulls str;
124-
default = config.configureFlags;
125-
};
126-
setupBuildFlags = mkOption {
127-
type = listOfFilteringNulls str;
128-
default = config.setupBuildFlags;
129-
};
130-
setupTestFlags = mkOption {
131-
type = listOfFilteringNulls str;
132-
default = config.setupTestFlags;
133-
};
134-
setupInstallFlags = mkOption {
135-
type = listOfFilteringNulls str;
136-
default = config.setupInstallFlags;
137-
};
138-
setupHaddockFlags = mkOption {
139-
type = listOfFilteringNulls str;
140-
default = config.setupHaddockFlags;
141-
};
142-
doExactConfig = mkOption {
143-
type = bool;
144-
default = config.doExactConfig;
145-
};
146-
doCheck = mkOption {
147-
type = bool;
148-
default = config.doCheck;
149-
};
150-
doCrossCheck = mkOption {
151-
type = bool;
152-
default = config.doCrossCheck;
153-
};
154-
doHaddock = mkOption {
155-
description = "Enable building of the Haddock documentation from the annotated Haskell source code.";
156-
type = bool;
157-
default = config.doHaddock;
158-
};
159106
};
160107
};
161108
in {
@@ -224,96 +171,6 @@ in {
224171
type = listOf (either unspecified path);
225172
default = [];
226173
};
227-
configureFlags = mkOption {
228-
type = listOfFilteringNulls str;
229-
default = [];
230-
};
231-
setupBuildFlags = mkOption {
232-
type = listOfFilteringNulls str;
233-
default = [];
234-
};
235-
setupTestFlags = mkOption {
236-
type = listOfFilteringNulls str;
237-
default = [];
238-
};
239-
setupInstallFlags = mkOption {
240-
type = listOfFilteringNulls str;
241-
default = [];
242-
};
243-
setupHaddockFlags = mkOption {
244-
type = listOfFilteringNulls str;
245-
default = [];
246-
};
247-
preUnpack = mkOption {
248-
type = nullOr lines;
249-
default = null;
250-
};
251-
postUnpack = mkOption {
252-
type = nullOr string;
253-
default = null;
254-
};
255-
preConfigure = mkOption {
256-
type = nullOr string;
257-
default = null;
258-
};
259-
postConfigure = mkOption {
260-
type = nullOr string;
261-
default = null;
262-
};
263-
preBuild = mkOption {
264-
type = nullOr string;
265-
default = null;
266-
};
267-
postBuild = mkOption {
268-
type = nullOr string;
269-
default = null;
270-
};
271-
preCheck = mkOption {
272-
type = nullOr string;
273-
default = null;
274-
};
275-
postCheck = mkOption {
276-
type = nullOr string;
277-
default = null;
278-
};
279-
preInstall = mkOption {
280-
type = nullOr string;
281-
default = null;
282-
};
283-
postInstall = mkOption {
284-
type = nullOr string;
285-
default = null;
286-
};
287-
preHaddock = mkOption {
288-
type = nullOr string;
289-
default = null;
290-
};
291-
postHaddock = mkOption {
292-
type = nullOr string;
293-
default = null;
294-
};
295-
shellHook = mkOption {
296-
type = nullOr string;
297-
default = null;
298-
};
299-
doExactConfig = mkOption {
300-
type = bool;
301-
default = false;
302-
};
303-
doCheck = mkOption {
304-
type = bool;
305-
default = false;
306-
};
307-
doCrossCheck = mkOption {
308-
description = "Run doCheck also in cross compilation settings. This can be tricky as the test logic must know how to run the tests on the target.";
309-
type = bool;
310-
default = false;
311-
};
312-
doHaddock = mkOption {
313-
description = "Enable building of the Haddock documentation from the annotated Haskell source code.";
314-
type = bool;
315-
default = true;
316-
};
317174
};
318175

319176
# This has one quirk. Manually setting options on the all component

modules/plan.nix

Lines changed: 129 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,139 @@
1515
with lib;
1616
with types;
1717

18-
{
19-
options = {
18+
19+
let
20+
# This is just like listOf, except that it filters out all null elements.
21+
listOfFilteringNulls = elemType: listOf elemType // {
22+
# Mostly copied from nixpkgs/lib/types.nix
23+
merge = loc: defs:
24+
map (x: x.value) (filter (x: x ? value && x.value != null) (concatLists (imap1 (n: def:
25+
if isList def.value then
26+
imap1 (m: def':
27+
(mergeDefinitions
28+
(loc ++ ["[definition ${toString n}-entry ${toString m}]"])
29+
elemType
30+
[{ inherit (def) file; value = def'; }]
31+
).optionalValue
32+
) def.value
33+
else
34+
throw "The option value `${showOption loc}` in `${def.file}` is not a list.") defs)));
35+
};
36+
37+
componentOptions = def: {
38+
configureFlags = mkOption {
39+
type = listOfFilteringNulls str;
40+
default = (def.configureFlags or []);
41+
};
42+
setupBuildFlags = mkOption {
43+
type = listOfFilteringNulls str;
44+
default = (def.setupBuildFlags or []);
45+
};
46+
setupTestFlags = mkOption {
47+
type = listOfFilteringNulls str;
48+
default = (def.setupTestFlags or []);
49+
};
50+
setupInstallFlags = mkOption {
51+
type = listOfFilteringNulls str;
52+
default = (def.setupInstallFlags or []);
53+
};
54+
setupHaddockFlags = mkOption {
55+
type = listOfFilteringNulls str;
56+
default = (def.setupHaddockFlags or []);
57+
};
58+
doExactConfig = mkOption {
59+
type = bool;
60+
default = (def.doExactConfig or false);
61+
};
62+
doCheck = mkOption {
63+
type = bool;
64+
default = (def.doCheck or false);
65+
};
66+
doCrossCheck = mkOption {
67+
description = "Run doCheck also in cross compilation settings. This can be tricky as the test logic must know how to run the tests on the target.";
68+
type = bool;
69+
default = (def.doCrossCheck or false);
70+
};
71+
doHaddock = mkOption {
72+
description = "Enable building of the Haddock documentation from the annotated Haskell source code.";
73+
type = bool;
74+
default = (def.doHaddock or true);
75+
};
76+
};
77+
packageOptions = def: componentOptions def // {
78+
preUnpack = mkOption {
79+
type = nullOr lines;
80+
default = (def.preUnpack or null);
81+
};
82+
postUnpack = mkOption {
83+
type = nullOr string;
84+
default = (def.postUnpack or null);
85+
};
86+
preConfigure = mkOption {
87+
type = nullOr string;
88+
default = (def.preConfigure or null);
89+
};
90+
postConfigure = mkOption {
91+
type = nullOr string;
92+
default = (def.postConfigure or null);
93+
};
94+
preBuild = mkOption {
95+
type = nullOr string;
96+
default = (def.preBuild or null);
97+
};
98+
postBuild = mkOption {
99+
type = nullOr string;
100+
default = (def.postBuild or null);
101+
};
102+
preCheck = mkOption {
103+
type = nullOr string;
104+
default = (def.preCheck or null);
105+
};
106+
postCheck = mkOption {
107+
type = nullOr string;
108+
default = (def.postCheck or null);
109+
};
110+
preInstall = mkOption {
111+
type = nullOr string;
112+
default = (def.preInstall or null);
113+
};
114+
postInstall = mkOption {
115+
type = nullOr string;
116+
default = (def.postInstall or null);
117+
};
118+
preHaddock = mkOption {
119+
type = nullOr string;
120+
default = (def.preHaddock or null);
121+
};
122+
postHaddock = mkOption {
123+
type = nullOr string;
124+
default = (def.postHaddock or null);
125+
};
126+
shellHook = mkOption {
127+
type = nullOr string;
128+
default = (def.shellHook or null);
129+
};
130+
};
131+
132+
133+
in {
134+
# Global options. These are passed down to the package level, and from there to the
135+
# component level, unless specifically overridden. Depending on the flag flags are
136+
# combined or replaced. We seed the package Options with an empty set forcing the
137+
# default values.
138+
options = (packageOptions {}) // {
20139
packages = mkOption {
21-
type = attrsOf (submodule {
22-
imports = [./package.nix];
23-
_module.args = {
140+
type =
141+
let mod_args = {
24142
inherit pkgs pkgconfPkgs haskellLib;
25143
inherit (config) hsPkgs;
26144
inherit (config.cabal) system compiler;
27-
};
28-
});
145+
}; in
146+
attrsOf (submodule (import ./package.nix {
147+
inherit mod_args listOfFilteringNulls;
148+
inherit componentOptions packageOptions;
149+
parentConfig = config;
150+
}));
29151
};
30152

31153
compiler = {

0 commit comments

Comments
 (0)