hercules-ci/flake-parts

Cannot access `inputs.self.outPath` in top level `imports`

Opened this issue · 4 comments

Atry commented

Given

# flake.nix
{
  inputs.flake-parts.url = "github:hercules-ci/flake-parts";
  outputs = inputs@{ self, flake-parts, ... }:
    flake-parts.lib.mkFlake { inherit inputs; } ({inputs, ...}: {
      imports = [
        "${inputs.self.outPath}/my-module.nix"
      ];
    });
}
# my-module.nix
{
  flake.lib.myFunction = x: x;
}

When running

nix flake show

Got

error: infinite recursion encountered

Root cause

NixOS/nix#8300

Workaround

# flake.nix
{
  inputs.flake-parts.url = "github:hercules-ci/flake-parts";
  outputs = inputs@{ self, flake-parts, ... }:
    {
      inherit (
        flake-parts.lib.mkFlake { inherit inputs; } ({inputs, ...}: {
          imports = [
            "${inputs.self.outPath}/my-module.nix"
          ];
        })
      ) lib;
    };
}

Workaround 2

Instead of self.outPath, you could use the equivalent ./. (edit: unless you're writing a reusable flakeModule):

# flake.nix
{
  inputs.flake-parts.url = "github:hercules-ci/flake-parts";
  outputs = inputs@{ flake-parts, ... }:
    flake-parts.lib.mkFlake { inherit inputs; } ({inputs, ...}: {
      imports = [
        ./my-module.nix
      ];
    });
}
Atry commented

It's not equivalent when your flake is used in another flake

So I guess you're writing a framework with a fixed location for a flake module then?

With the Nix we have, you can only imports from a self where you've already decided the set of outputs attrNames.
In other words, there's no workaround for NixOS/nix#8300.
There might be a solution in the form of NixOS/nix#4154, but otherwise, the best we can do is workarounds.

Workaround 3, perSystem only

Maybe this helps you or someone. perSystem generally does not affect the attrNames of the flake option.

# flake.nix
{
  inputs.flake-parts.url = "github:hercules-ci/flake-parts";
  outputs = inputs@{ self, flake-parts, ... }:
    flake-parts.lib.mkFlake { inherit inputs; } ({inputs, ...}: {
      perSystem = {
        imports = [
          "${inputs.self.outPath}/my-module.nix"
        ];
      };
    });
}

Workaround 4, specialArgs

specialArgs was designed for imports.
You might require specialArgs.root = ./. to be passed by users. I don't think it's the right tradeoff between inconveniences, but you could require this for your framework.

Users would call

mkFlake { inherit inputs; specialArgs.root = ./.; } <module>

You would write a module such as

{ root, ... }:
{
  imports = [ (root + "/my-module.nix") ];
}
bb010g commented

See also my investigation of this in #137. I should probably extract that commit set out into its own PR.