hercules-ci / flake-parts

❄️ Simplify Nix Flakes with the module system
https://flake.parts
MIT License
721 stars 41 forks source link

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

Open Atry opened 1 year ago

Atry commented 1 year ago

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

https://github.com/NixOS/nix/issues/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;
    };
}
roberth commented 1 year ago

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 1 year ago

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

roberth commented 1 year ago

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 https://github.com/NixOS/nix/issues/8300. There might be a solution in the form of https://github.com/NixOS/nix/pull/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 1 year ago

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