Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add 'perSystem' and 'systems' schema attributes #6773

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -702,5 +702,15 @@
// { default = self.devShells.${system}.stdenv; }
);




perSystem = {system}: {
packages.a = nixpkgsFor.${system}.bash;
packages.default = nixpkgsFor.${system}.bash; # Overwrites default package
};

#systems = linuxSystems ++ [ "x86_64-darwin" ];
inherit systems;
};
}
115 changes: 102 additions & 13 deletions src/libexpr/flake/call-flake.nix
Original file line number Diff line number Diff line change
@@ -1,6 +1,94 @@
lockFileStr: rootSrc: rootSubdir:

let
inherit (builtins) listToAttrs concatMap attrNames mapAttrs isAttrs isList foldl';
optionalAttrs = check: value: if check then value else { };

mergeAny = lhs: rhs:
lhs // mapAttrs
(name: value:
if isAttrs value then lhs.${name} or { } // value
else if isList value then lhs.${name} or [ ] ++ value
else value
)
rhs;

eachSystem = systems: f:
let
# Taken from <nixpkgs/lib/attrsets.nix>
isDerivation = x: builtins.isAttrs x && x ? type && x.type == "derivation";

# Used to match Hydra's convention of how to define jobs. Basically transforms
#
# hydraJobs = {
# hello = <derivation>;
# haskellPackages.aeson = <derivation>;
# }
#
# to
#
# hydraJobs = {
# hello.x86_64-linux = <derivation>;
# haskellPackages.aeson.x86_64-linux = <derivation>;
# }
#
# if the given flake does `eachSystem [ "x86_64-linux" ] { ... }`.
pushDownSystem = system: merged:
builtins.mapAttrs
(name: value:
if ! (builtins.isAttrs value) then value
else if isDerivation value then (merged.${name} or { }) // { ${system} = value; }
else pushDownSystem system (merged.${name} or { }) value);

# Merge together the outputs for all systems.
op = attrs: system:
let
ret = f system;
op = attrs: key:
let
appendSystem = key: system: ret:
if key == "hydraJobs"
then (pushDownSystem system (attrs.hydraJobs or { }) ret.hydraJobs)
else { ${system} = ret.${key}; };
in
attrs //
{
${key} = (attrs.${key} or { })
// (appendSystem key system ret);
}
;
in
builtins.foldl' op attrs (builtins.attrNames ret);
in
builtins.foldl' op { } systems
;

merger = flake:
let
filterAttrs = pred: set:
listToAttrs (concatMap (name: let value = set.${name}; in if pred name value then [ ({ inherit name value; }) ] else [ ]) (attrNames set));

systems = flake.systems or [ ];
in
mergeAny flake (
eachSystem systems (system:
let
systemOutputs = flake.perSystem { inherit system; };
otherArguments = flake;

mkOutputs = attrs: output:
attrs //
mergeAny
# prevent override of nested outputs in otherArguments
(optionalAttrs (otherArguments ? ${output}.${system})
{ ${output} = otherArguments.${output}.${system}; })
(optionalAttrs (systemOutputs ? ${output})
{ ${output} = systemOutputs.${output}; });
in
(foldl' mkOutputs { } (attrNames systemOutputs))
)
)
;

lockFile = builtins.fromJSON lockFileStr;

Expand All @@ -12,45 +100,46 @@ let
sourceInfo =
if key == lockFile.root
then rootSrc
else fetchTree (node.info or {} // removeAttrs node.locked ["dir"]);
else fetchTree (node.info or { } // removeAttrs node.locked [ "dir" ]);

subdir = if key == lockFile.root then rootSubdir else node.locked.dir or "";

flake = import (sourceInfo + (if subdir != "" then "/" else "") + subdir + "/flake.nix");

inputs = builtins.mapAttrs
(inputName: inputSpec: allNodes.${resolveInput inputSpec})
(node.inputs or {});
(node.inputs or { });

# Resolve a input spec into a node name. An input spec is
# either a node name, or a 'follows' path from the root
# node.
resolveInput = inputSpec:
if builtins.isList inputSpec
then getInputByPath lockFile.root inputSpec
else inputSpec;
if builtins.isList inputSpec
then getInputByPath lockFile.root inputSpec
else inputSpec;

# Follow an input path (e.g. ["dwarffs" "nixpkgs"]) from the
# root node, returning the final node.
getInputByPath = nodeName: path:
if path == []
if path == [ ]
then nodeName
else
getInputByPath
# Since this could be a 'follows' input, call resolveInput.
(resolveInput lockFile.nodes.${nodeName}.inputs.${builtins.head path})
(builtins.tail path);

outputs = flake.outputs (inputs // { self = result; });
outputs = merger (flake.outputs (inputs // { self = result; }));

result = outputs // sourceInfo // { inherit inputs; inherit outputs; inherit sourceInfo; };
in
if node.flake or true then
assert builtins.isFunction flake.outputs;
result
else
sourceInfo
if node.flake or true then
assert builtins.isFunction flake.outputs;
result
else
sourceInfo
)
lockFile.nodes;

in allNodes.${lockFile.root}
in
allNodes.${lockFile.root}
3 changes: 2 additions & 1 deletion src/nix/flake.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1132,7 +1132,8 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
}
}

else {
// Ignore 'systems' and 'perSystem' attributes
else if (!(attrPathS[0] == "systems" || attrPathS[0] == "perSystem")) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If i do attrPathS[0] != "systems" && attrPathS[0] != "perSystem" it throws compilation error:

src/nix/flake.cc:1136:68: error: no match for ‘operator!=’ (operand types are ‘__gnu_cxx::__alloc_traits<std::allocatornix::SymbolStr, nix::SymbolStr>::value_type’ {aka ‘nix::SymbolStr’} and ‘const char [10]’)

auto [type, description] =
(attrPath.size() == 1 && attrPathS[0] == "overlay")
|| (attrPath.size() == 2 && attrPathS[0] == "overlays") ? std::make_pair("nixpkgs-overlay", "Nixpkgs overlay") :
Expand Down
4 changes: 4 additions & 0 deletions test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
make -j $NIX_BUILD_CORES
make install

./outputs/out/bin/nix flake show --extra-experimental-features nix-command --extra-experimental-features flakes