Development shells with Nix: four quick examples

4 Likes

Section 4 doesn’t mention forAllSystems, which is the canonical solution. It also has the added benefit of not increasing your flake.lock bloat, leading to faster eval time.

{
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";

  outputs = { self, nixpkgs }:
  let
    lib = nixpkgs.lib;

    forAllSystems = function: lib.genAttrs
      [ "x86_64-linux" "aarch64-darwin" ] # any systems you want
      (system: function nixpkgs.legacyPackages.${system});
  in {
    devShells = forAllSystems (pkgs: {
      default = pkgs.mkShell {
        packages = with pkgs; [
          # Explicitly list pkg-config so that mkShell will arrange
          # for the PKG_CONFIG_PATH to find the .pc files.
          pkg-config
          opencv
        ];
      };
    });
  };
}
1 Like

Indeed, this is a cleaner solution.

Why not (system: import nixpkgs {inherit system;});? As in, is there any meaningful difference if you don’t add overlays at this stage (which here we don’t)?

That recomputes the output - see Using nixpkgs.legacyPackages.${system} vs import. Ideally Nix would memoise function applications given the same input - but that’s not the case, so we want to reuse our result where possible.

2 Likes

Ahh that’s what i was worried about. Thanks for the info :slight_smile: