flake-utils icon indicating copy to clipboard operation
flake-utils copied to clipboard

Outputs spec update makes `eachSystemMap` powerful

Open aakropotkin opened this issue 2 years ago • 2 comments

Hey I'm not here to really gripe about anything missing, but more to highlight how recent changes to the flake spec in Nix 2.7.0 make eachSystemMap a really elegant function.

If you agree I I'll PR some README updates to highlight the new patterns, since I think it'd be good to put it front and center.

For context Nix 2.7.0 deprecates defaultXXX.${system} in favor of packages.${system}.default making it easier to wrangle defining defaults. This snippet below is for a trivial project I have with a standard package installation. This flake makes it available to nix-command, or it can be consumed in NixOS/home-manager as a module, or in legacy nix + nixpkgs projects as an overlay.

The boilerplate required previously to handle the defautXXX outputs used to be real ugly.

{
  description = "A handful of useful core utilities and scripts for Linux";

  inputs = {
    nixpkgs.url = github:NixOS/nixpkgs/nixpkgs-unstable;
    utils.url   = github:numtide/flake-utils;
  };

  outputs = { self, nixpkgs, utils }:
    let
      eachDefaultSystemMap = utils.lib.eachSystemMap utils.lib.defaultSystems;
    in {
      packages = eachDefaultSystemMap ( system: rec {
        ak-core =
          ( import nixpkgs { inherit system; } ).callPackage ./default.nix {};
        default = ak-core;
      } );

      overlays.ak-core = final: prev: {
        inherit (self.packages.${final.system}) ak-core;
      };
      overlays.default = self.overlays.ak-core;

      nixosModules.ak-core = { ... }: {
        nixpkgs.overlays = self.overlays.ak-core;
      };
      nixosModule = self.nixosModules.ak-core;
    };
}

aakropotkin avatar Apr 16 '22 04:04 aakropotkin

A second useful example that is backwards compatible with Nix versions < 2.7:

{
  description = "My DWM Config";

  inputs.utils.url = github:numtide/flake-utils;
  inputs.utils.inputs.nixpkgs.follows = "nixpkgs";

  outputs = { self, nixpkgs, utils }:
    let defaultSystemsMap = utils.lib.eachSystemMap utils.lib.defaultSystems;
    in {
      packages = defaultSystemsMap ( system:
        let pkgsFor = import nixpkgs { inherit system; };
        in rec {
          ak-dwm = pkgsFor.stdenv.mkDerivation {
            pname = "ak-dwm";
            version = "0.0.1";
            src  = self;
            depsTargetTarget = with pkgsFor.xorg; [
              libX11 libXinerama libXft
            ];
            prePatch = ''
              sed -i "s,/usr/local,$out," config.mk
            '';
          };
        default = ak-dwm;
      } );
    } // ( if ( ( builtins.compareVersions __nixVersion "2.7.0" ) <= 0 )
           then {
             defaultPackage =
               defaultSystemsMap ( system: self.packages.${system}.default );
           } else {} );
}

This passes all of the following:

nix shell github:NixOS/nix/2.7-maintanence#nix -c nix flake check --impure;
nix shell github:NixOS/nix/2.6-maintanence#nix -c nix flake check --impure;
nix shell github:NixOS/nix/2.7-maintanence#nix -c nix build --impure;
nix shell github:NixOS/nix/2.6-maintanence#nix -c nix build --impure;

Notably it avoids depreciation warnings when run on 2.7 or later which would normally appear for nix flake check in 2.7 or later.

aakropotkin avatar May 15 '22 19:05 aakropotkin

Thanks, I think this will be useful for people who search. (edited your messages to add highlighting on the nix code)

zimbatm avatar May 17 '22 08:05 zimbatm