modular-flake/nix/default.nix

101 lines
2.5 KiB
Nix

{ modularFlake, nixpkgs }:
let
# similar to `deepSeq`, but doesn't get a panic attack upon seeing a derivation
safeSeq =
with builtins;
val: res:
seq (
if isAttrs val && (val.type or null) == "derivation" then
val.outPath
else if isAttrs val then
all (v: safeSeq v true) ((attrValues val) ++ (attrNames val))
else if isList val then
all (v: safeSeq v true) val
else
val
) res;
lib = nixpkgs.lib;
mkNop = pkgs: pkgs.runCommand "no-op" { } "${pkgs.coreutils}/bin/touch $out";
noSystem = throw "system is not provided here";
noPkgs = throw "pkgs is not provided here";
output = import ./output modularFlake;
mkSys = system: {
inherit lib;
hasSystem = system != null;
system = if system == null then noSystem else system;
pkgs = if system == null then noPkgs else (import nixpkgs { inherit system; });
};
mkDef =
{
flakeInputs,
outputs,
system,
}:
let
raw =
(lib.evalModules {
modules = outputs ++ [ output.definition ];
}).config;
defs = map (
kind:
(lib.recursiveUpdate {
options = { };
outputs = _: { };
specialArgs = _: { };
} (kind (mkSys system)))
) raw.outputKinds;
specialArgs = with lib; foldl' recursiveUpdate { } (map (def: def.specialArgs raw) defs);
in
{
inherit raw defs specialArgs;
};
mkOutputs =
{
flakeInputs,
outputs,
system,
modules,
}:
let
sysAttr = mkSys system;
inherit (mkDef { inherit flakeInputs outputs system; }) defs specialArgs;
raw = lib.evalModules {
modules = (map (def: { options = def.options; }) defs) ++ modules;
specialArgs = specialArgs // sysAttr // { inherit flakeInputs; };
};
in
with lib;
foldl' recursiveUpdate { } (map (def: def.outputs (raw // sysAttr)) defs);
mkFlake =
{
flakeInputs ? { },
outputs ? builtins.attrValues output.defaultOutputs,
systems ? [ ],
modules ? [ ],
}:
let
systemOutputs = map (
system:
mkOutputs {
inherit
flakeInputs
outputs
system
modules
;
}
) (lib.unique systems);
noSystemOutputs = mkOutputs {
inherit flakeInputs outputs modules;
system = null;
};
in
with lib;
foldl' recursiveUpdate noSystemOutputs systemOutputs;
in
{
inherit mkFlake safeSeq mkNop;
defaultOutputs = output.defaultOutputs;
}