No access to flake inputs within a perSystem module
Similar to https://github.com/hercules-ci/flake-parts/issues/81.
Trying to add inputs to the perSystem args, triggers this error:
error: `inputs` (without `'`) is not a `perSystem` module argument, but a
module argument of the top level config.
The following is an example usage of `inputs`. Note that its binding
is in the `top` parameter list, which is declared by the top level module
rather than the `perSystem` module.
top@{ config, lib, inputs, ... }: {
perSystem = { config, inputs', ... }: {
# in scope here:
# - inputs
# - inputs'
# - config (of perSystem)
# - top.config (note the `top@` pattern)
};
}
The statements about the scope only hold true as long as all code is defined inside a single flake.nix file.
The lexical scope breaks as soon as the code is split into modules.
For example given the following flake.nix:
{
inputs = {
flake-parts.url = "github:hercules-ci/flake-parts";
poetry2nix.url = "poetry2nix";
};
outputs = inputs@{ flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
systems = [
"x86_64-linux"
];
perSystem = { config, pkgs, ... }: {
imports = [./my-package.nix];
};
};
}
and my-package.nix:
# flake-parts module for the tesh package
{config, pkgs, inputs, self, ...}: let
poetry2nix = import inputs.poetry2nix {inherit pkgs;};
in {
packages.tesh = poetry2nix.mkPythonPplication {
projectDir = self;
};
}
This breaks because inputs is not allowed as a function argument. This means it is not possible to access some inputs lib or similar things inside a perSystem module.
The idea behind this restriction is to make sure that all flake-parts modules are in one, compatible form. This convention avoids weird errors that would arise when importing a perSystem-level module into the top level or vice versa.
- https://github.com/NixOS/nixpkgs/pull/197547 would help, but only in cases where the module has its "class" set; usually not by the author, but possibly by flake-parts itself, via
flake.flakeModulesor similar.
The statements about the scope only hold true as long as all code is defined inside a single
flake.nixfile. The lexical scope breaks as soon as the code is split into modules.
This should work if you define the module as a top-level module. The top-level module provides the lexical scope with these variables, as suggested in the error message.
This decision could be reverted when we have
- [ ] error messages for bad imports: https://github.com/NixOS/nixpkgs/pull/197547
- [ ]
deferredModuleoptions that tag modules with their class
I think the top-level module should always be a flake module, then it can define nested nixosModules/flakeModules. For example:
- https://github.com/Preemo-Inc/nix-ml-ops/blob/main/nixos-modules/nix-ld.nix
- https://github.com/Preemo-Inc/nix-ml-ops/blob/main/flake-modules/options-document.nix
When defining a nested flakeModules, the top level inputs are from the flake that defines the module, and the nested inputs are from the flake that use the module.
I just had the same issue, I wanted to access my util flake from a perSystem module. A workaround is adding this to the imports where the module gets imported:
({...}: {
_module.args.origInputs = inputs;
})
I could then just use origInputs.<flake>