nix-community / flakelight

Framework for simplifying flake setup [maintainer=@accelbread]
MIT License
177 stars 3 forks source link

Autoload bundlers does not seem to work #7

Closed noverby closed 8 months ago

noverby commented 8 months ago

With flake:

# flake.nix
{
  inputs.flakelight.url = "github:accelbread/flakelight";
  outputs = {flakelight, ...}:
    flakelight ./. {
      package = {stdenv}:
        stdenv.mkDerivation {
          pname = "pkg1";
          version = "0.0.1";
          src = ./.;
          installPhase = "make DESTDIR=$out install";
        };
    };
}

And bundler foo:

# nix/bundlers/foo.nix
{hello, ...}: x: hello

Results in the error:

> nix bundle --bundler .#foo .#
 anonymous function at /nix/store/aanfrr366bbkf7jskfkgpplz5aqnybyy-source/nix/bundlers/foo.nix:1:1 called without required argument 'hello
accelbread commented 8 months ago

Yeah, that is trying to use {hello, ...}: x: hello as the bundler which is failing since its not the intended x: hello. To make that work I'll have to test a bit. Right now a bundlers/foo.nix containing x: x would work.

For bundlers.nix the following works right now:

{ hello, ... }:
{
  default = x: hello;
}

We can do the above since bundlers should be an attrset, so if we are given a function, we just apply the args and expect an attrset.

For bundlers/foo.nix, we expect a bundler with a function. It is not trivial to tell x: x apart from pkgs: x: x. Both are functions. It would need to be applied, which in the latter case returns a function, and in the former a derivation. Though we also need to apply appropriate parameters.

We can tell { hello, ... }: x: hello apart from x: x since we can inspect a function's named arguments. There is also precedence for requiring named arguments as with pkgs.callPackage.

The first issue is that this makes { hello, ... }: x: hello work but not pkgs: x: pkgs.hello. I also find callPackage not defaulting to passing the whole set surprising at first discovery. Though this could be acceptable as the intent is clear in the named arguments case, though leaves the pkgs case as an unintuitive error.

Second is that { src, ... }: src is a valid bundler, though this is a really edge case so would be fine to ignore (if needed, perSystem with bundlers can be used).

Third is that wrapping the function removes named arguments. let f = { hello, ... }: x: hello; in x: f x; returns a function with same behavior but where the arguments can't be inspected. This is likely not an issue for direct use, but causes issues when dealing directly with the module system for example.

Ideally there is a way to tell apart x: x from pkgs: x: x; if so that can be used to determine whether to apply module args. There may be a way to do so abusing lazy eval or with tryEval; I'll have to play around with it a bit.

Evaluating a bundler during flake evaluation might also not be a good idea since the bundler could use IFD.

accelbread commented 8 months ago

Somewhat interesting:

nix-repl> builtins.attrNames (builtins.intersectAttrs pkgs.hello pkgs)
[ "src" "stdenv" "system" "tests" ]

Apparently there is a package named src.

We cannot rely on builtins.functionArgs after all, since pkgs: { hello, ... }: (x: hello) pkgs is the same as the inner function but with args hidden.

Applying function to determine if pkgs: x: x or x: x should work if the arg used is pkgs // pkgs.hello since that is both a valid derivation, so should result in a derivation for the bundler, and is a set with all pkgs names so should result in a function if it is a function that takes pkgs.

Downsides are that the bundler must support bundling pkgs.hello, and evaluating the flake output would result in IFD if the bundler uses IFD. The former is fine, and the second might be solvable by wrapping the bundler, capturing pkgs, and determining whether to apply pkgs at bundler eval time instead of at flake output eval time (need to check if that interferes with any nix flake check warnings).

accelbread commented 8 months ago

Fixed with ff24d5d4330db69a4dc4e6fdb97ca3ce9f8881a2.

With the wrapper, also do not need to rely on pkgs.hello as can use the passed derivation.

noverby commented 8 months ago

@accelbread Is pkgs suppose to be exposed?

error: anonymous function at /nix/store/n0cyhxv3v8878mqcv4cz46zh69cqq4ad-source/nix/bundlers/bundler.nix:1:1 called without required argument 'pkgs'
accelbread commented 8 months ago

Do you have an example flake?

I am not able to reproduce that error.

I have tested the following contents of bundler.nix: x: x, pkgs: x: pkgs.hello, { hello, ... }: x: hello, { pkgs, ... }: x: pkgs.hello, and all work.

noverby commented 8 months ago

@accelbread Oh sorry, the flakelight input didn't properly update, it actually works. Thanks!