NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
18.12k stars 14.15k forks source link

Basic flake.nix results in `error: attribute 'currentSystem' missing` on `nix build` #303736

Open samuela opened 7 months ago

samuela commented 7 months ago

Issue description

I have the following flake.nix:

{
  inputs = { utils.url = "github:numtide/flake-utils"; };

  outputs = { self, nixpkgs, utils }:
    utils.lib.eachDefaultSystem (system:
      let pkgs = import nixpkgs { };
      in { packages = { inherit (pkgs) hello; }; });
}

And I'm seeing the following error when attempting to build:

root@b62e2017d34d:/workspaces/bitbop# nix build .#hello
warning: Git tree '/workspaces/bitbop' is dirty
error:
       … while evaluating a branch condition
         at /nix/store/371rdljjbpd9njxnrzns793apg1x1x2k-source/pkgs/stdenv/booter.nix:64:9:
           63|       go = pred: n:
           64|         if n == len
             |         ^
           65|         then rnul pred

       … while calling the 'length' builtin
         at /nix/store/371rdljjbpd9njxnrzns793apg1x1x2k-source/pkgs/stdenv/booter.nix:62:13:
           61|     let
           62|       len = builtins.length list;
             |             ^
           63|       go = pred: n:

       (stack trace truncated; use '--show-trace' to show the full trace)

       error: attribute 'currentSystem' missing
       at /nix/store/371rdljjbpd9njxnrzns793apg1x1x2k-source/pkgs/top-level/impure.nix:17:43:
           16|   # (build, in GNU Autotools parlance) platform.
           17|   localSystem ? { system = args.system or builtins.currentSystem; }
             |                                           ^
           18|
root@b62e2017d34d:/workspaces/bitbop#

Steps to reproduce

I've posted my complete setup, including flake.lock in this gist.

Technical details

root@b62e2017d34d:/workspaces/bitbop# nix-shell -p nix-info --run "nix-info -m"
 - system: `"aarch64-linux"`
 - host os: `Linux 6.6.22-linuxkit, Ubuntu, 24.04 (Noble Numbat), nobuild`
 - multi-user?: `yes`
 - sandbox: `no`
 - version: `nix-env (Nix) 2.20.5`
 - nixpkgs: `/nix/store/bjv2qk3gg1iv69rbama3q9aprcp6d9wp-source`
lunaneff commented 7 months ago

you need to do let pkgs = import nixpkgs { inherit system; }; instead

samuela commented 7 months ago

Thanks @lunaneff -- that indeed was the issue. I'm confused however: Specifying system isn't required in other invocations, eg in nix-shell. Why is it failing here? Shouldn't it ought to default to the host system?

This seems like a real footgun.

lolbinarycat commented 7 months ago

@samuela nix-shell defaults to impure evaluation, whereas nix shell defaults to pure evaluation (unless it is called with --file).

Shouldn't it ought to default to the host system? that's what it's trying to do, using builtins.currentSystem, but that information is not available in pure evaluation mode.

also, you should really be doing pkgs = nixpkgs.legacyPackages.${system}; to actually import the packages from the flake. currently you are implicitly asking nix to evaluate the default.nix file found in the same directory as the flake.nix file.

lolbinarycat commented 7 months ago

perhaps we could change impure.nix to do something like builtins.currentSystem or throw "it seems you are trying to load nixpkgs in pure evaluation mode, please specify system"

we could even check for the presence of builtins.getFlake to decide if we should give flake-related hints, like recommending using legacyPackages.${system}.

samuela commented 7 months ago

Ah yeah that makes sense! I think that would be a big improvement in terms of clarity

samuela commented 7 months ago

also, you should really be doing pkgs = nixpkgs.legacyPackages.${system}; to actually import the packages from the flake.

why should i be using legacyPackages? that sounds like... legacy code?

Also, when using nixpkgs.legacyPackages.${system} how would one specify config options? Eg what's the equivalent of

        pkgs = import nixpkgs {
          inherit system;
          config.allowUnfree = true;
        };
RossComputerGuy commented 7 months ago

why should i be using legacyPackages? that sounds like... legacy code?

Because legacyPackages is for the legacy package method, the multi-level attribute way Nixpkgs does it. The regular packages is for your Flake's own packages.

eclairevoyant commented 7 months ago

that sounds like... legacy code?

It's not, it's how nixpkgs exposes its packages in the first place.

Qyriad commented 7 months ago

also, you should really be doing pkgs = nixpkgs.legacyPackages.${system}; to actually import the packages from the flake. currently you are implicitly asking nix to evaluate the default.nix file found in the same directory as the flake.nix file.

legacyPackages.${system} is actually implemented as import ./. { inherit system; } — if you're not passing overlays or config options to Nixpkgs, these two forms are equivalent

lolbinarycat commented 7 months ago

it's equivalent for nixpkgs specifically, at the current time, but for other flakes, and possibly future nixpkgs versions, it may be different, so it shouldn't be encouraged.