From 3ea689365998db56cc4c84aa4de4ddd15d550baa Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 29 Aug 2024 13:34:48 +0200 Subject: [PATCH 1/4] refact: Add let binding to flake.nix --- flake.nix | 90 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 43 deletions(-) diff --git a/flake.nix b/flake.nix index 3823d09..b12fa52 100644 --- a/flake.nix +++ b/flake.nix @@ -5,49 +5,53 @@ nixpkgs-lib.url = "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz"; # 9f918d616c5321ad374ae6cb5ea89c9e04bf3e58 /lib from nixos-unstable }; - outputs = { nixpkgs-lib, ... }: { - lib = import ./lib.nix { - inherit (nixpkgs-lib) lib; - # Extra info for version check message - revInfo = - if nixpkgs-lib?rev - then " (nixpkgs-lib.rev: ${nixpkgs-lib.rev})" - else ""; + outputs = { nixpkgs-lib, ... }: + let + lib = import ./lib.nix { + inherit (nixpkgs-lib) lib; + # Extra info for version check message + revInfo = + if nixpkgs-lib?rev + then " (nixpkgs-lib.rev: ${nixpkgs-lib.rev})" + else ""; + }; + templates = { + default = { + path = ./template/default; + description = '' + A minimal flake using flake-parts. + ''; + }; + multi-module = { + path = ./template/multi-module; + description = '' + A minimal flake using flake-parts. + ''; + }; + unfree = { + path = ./template/unfree; + description = '' + A minimal flake using flake-parts importing nixpkgs with the unfree option. + ''; + }; + package = { + path = ./template/package; + description = '' + A flake with a simple package: + - Nixpkgs + - callPackage + - src with fileset + - a check with runCommand + ''; + }; + }; + flakeModules = { + easyOverlay = ./extras/easyOverlay.nix; + flakeModules = ./extras/flakeModules.nix; + }; + in + { + inherit lib templates flakeModules; }; - templates = { - default = { - path = ./template/default; - description = '' - A minimal flake using flake-parts. - ''; - }; - multi-module = { - path = ./template/multi-module; - description = '' - A minimal flake using flake-parts. - ''; - }; - unfree = { - path = ./template/unfree; - description = '' - A minimal flake using flake-parts importing nixpkgs with the unfree option. - ''; - }; - package = { - path = ./template/package; - description = '' - A flake with a simple package: - - Nixpkgs - - callPackage - - src with fileset - - a check with runCommand - ''; - }; - }; - flakeModules = { - easyOverlay = ./extras/easyOverlay.nix; - flakeModules = ./extras/flakeModules.nix; - }; - }; } From c07ef7e578fbb1a2e964615e0faee1949371cd22 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 29 Aug 2024 13:36:47 +0200 Subject: [PATCH 2/4] Dogfood lib.mkFlake --- flake.nix | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/flake.nix b/flake.nix index b12fa52..8952769 100644 --- a/flake.nix +++ b/flake.nix @@ -5,7 +5,7 @@ nixpkgs-lib.url = "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz"; # 9f918d616c5321ad374ae6cb5ea89c9e04bf3e58 /lib from nixos-unstable }; - outputs = { nixpkgs-lib, ... }: + outputs = inputs@{ nixpkgs-lib, ... }: let lib = import ./lib.nix { inherit (nixpkgs-lib) lib; @@ -50,8 +50,11 @@ flakeModules = ./extras/flakeModules.nix; }; in - { - inherit lib templates flakeModules; + lib.mkFlake { inherit inputs; } { + systems = [ ]; + flake = { + inherit lib templates flakeModules; + }; }; } From 0d5122e84c0d7606363f89f0924245317c2fe3a0 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 29 Aug 2024 13:37:23 +0200 Subject: [PATCH 3/4] Add flakeModules.partitions --- extras/partitions.nix | 130 ++++++++++++++++++++++++++++++++++++++++++ flake.nix | 1 + 2 files changed, 131 insertions(+) create mode 100644 extras/partitions.nix diff --git a/extras/partitions.nix b/extras/partitions.nix new file mode 100644 index 0000000..34e04d2 --- /dev/null +++ b/extras/partitions.nix @@ -0,0 +1,130 @@ +{ lib, config, inputs, extendModules, partitionStack, self, ... }: +let + inherit (lib) + literalMD + mapAttrs + mkOption + optionalAttrs + types + ; + + partitionModule = { config, options, name, ... }: { + options = { + extraInputsFlake = mkOption { + type = types.raw; + default = { }; + description = '' + Location of a flake whose inputs to add to the inputs module argument in the partition. + ''; + }; + extraInputs = mkOption { + type = types.lazyAttrsOf types.raw; + description = '' + Extra inputs to add to the inputs module argument in the partition. + + This can be used as a workaround for the fact that transitive inputs are locked in the "end user" flake. + That's not desirable for inputs they don't need, such as development inputs. + ''; + default = { }; + defaultText = literalMD '' + if `extraInputsFlake` is set, then `builtins.getFlake extraInputsFlake`, else `{ }` + ''; + }; + module = mkOption { + type = (extendModules { + specialArgs = + let + inputs2 = inputs // config.extraInputs // { + self = self2; + }; + self2 = self // { + inputs = inputs2; + }; + in + { + inputs = inputs2; + self = self2; + partitionStack = partitionStack ++ [ name ]; + }; + }).type; + default = { }; + description = '' + A re-evaluation of the flake-parts top level modules. + + You may define config definitions, imports, etc here, and it can be read like any other submodule. + ''; + }; + }; + config = { + extraInputs = lib.mkIf options.extraInputsFlake.isDefined ( + let + p = options.extraInputsFlake.value; + flake = + if builtins.typeOf p == "path" + then get-flake p + else builtins.getFlake p; + in + flake.inputs + ); + }; + }; + + # Nix does not recognize that a flake like "${./dev}", which is a content + # addressed store path is a pure input, so we have to fetch and wire it + # manually with get-flake. + # TODO: update this + get-flake = import (builtins.fetchTree { + type = "github"; + owner = "ursi"; + repo = "get-flake"; + rev = "a6c57417d1b857b8be53aba4095869a0f438c502"; + }); + +in +{ + options = { + partitionedAttrs = mkOption { + type = types.attrsOf types.str; + default = { }; + description = '' + A set of flake output attributes that are taken from a partition instead of the default top level flake-parts evaluation. + + The attribute name refers to the flake output attribute name, and the value is the name of the partition to use. + + The flake attributes are overridden with `lib.mkForce` priority. + + See the `partitions` options to understand the purpose. + ''; + }; + partitions = mkOption { + type = types.attrsOf (types.submodule partitionModule); + default = { }; + description = '' + By partitioning the flake, you can avoid fetching inputs that are not + needed for the evaluation of a particular attribute. + + Each partition is a distinct module system evaluation. This allows + attributes of the final flake to be defined by multiple sets of modules, + so that for example the `packages` attribute can be evaluated without + loading development related inputs. + + While the module system does a good job at preserving laziness, the fact + that a development related import can define `packages` means that + in order to evaluate `packages`, you need to evaluate at least to the + point where you can conclude that the development related import does + not actually define a `packages` attribute. While the actual evaluation + is cheap, it can only happen after fetching the input, which is not + as cheap. + ''; + }; + }; + config = { + # Default, overriden with specialArgs inside partitions. + _module.args.partitionStack = [ ]; + flake = optionalAttrs (partitionStack == [ ]) ( + mapAttrs + (attrName: partition: lib.mkForce (config.partitions.${partition}.module.flake.${attrName})) + config.partitionedAttrs + ); + }; +} diff --git a/flake.nix b/flake.nix index 8952769..331450a 100644 --- a/flake.nix +++ b/flake.nix @@ -48,6 +48,7 @@ flakeModules = { easyOverlay = ./extras/easyOverlay.nix; flakeModules = ./extras/flakeModules.nix; + partitions = ./extras/partitions.nix; }; in lib.mkFlake { inherit inputs; } { From 1957ef2c4ba04e213c59380a19e46c9fcee38d0e Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 29 Aug 2024 13:44:04 +0200 Subject: [PATCH 4/4] Dogfood flakeModules.partitions --- ci.nix | 12 ------------ dev/README.md | 6 ------ dev/default.nix | 16 ---------------- dev/flake.nix | 3 ++- dev/repl.nix | 3 --- flake.nix | 9 +++++++++ shell.nix | 3 +-- 7 files changed, 12 insertions(+), 40 deletions(-) delete mode 100644 ci.nix delete mode 100644 dev/README.md delete mode 100644 dev/default.nix delete mode 100644 dev/repl.nix diff --git a/ci.nix b/ci.nix deleted file mode 100644 index a360262..0000000 --- a/ci.nix +++ /dev/null @@ -1,12 +0,0 @@ -# We're doing things a bit differently because Nix doesn't let us -# split out the dev dependencies and subflakes are broken, let alone "superflakes". -# See dev/README.md -let - flake = import ./dev; - inherit (flake.inputs.nixpkgs) lib; -in -{ - inherit (flake) herculesCI; -} // { - checks = lib.recurseIntoAttrs flake.checks.${builtins.currentSystem}; -} diff --git a/dev/README.md b/dev/README.md deleted file mode 100644 index 270517d..0000000 --- a/dev/README.md +++ /dev/null @@ -1,6 +0,0 @@ - -# Separate `dev` flake - -Wouldn't recommend this pattern normally, but I'm trying to keep -deps low for `flake-parts` until we have split dev inputs -that don't carry over to dependent lock files. diff --git a/dev/default.nix b/dev/default.nix deleted file mode 100644 index df712a4..0000000 --- a/dev/default.nix +++ /dev/null @@ -1,16 +0,0 @@ -let - flake = builtins.getFlake (toString ./.); - fmc-lib = (builtins.getFlake (toString ../.)).lib; - args = { - inherit self; - } // flake.inputs; - self = { - inherit (flake) inputs; - outPath = ../.; # used by pre-commit module, etc - outputs = self.config.flake; - } // - fmc-lib.mkFlake - { inputs = args; } - ./flake-module.nix; -in -self.config.flake // { inherit (flake) inputs; } diff --git a/dev/flake.nix b/dev/flake.nix index e6fc8e5..571ebb7 100644 --- a/dev/flake.nix +++ b/dev/flake.nix @@ -3,7 +3,7 @@ inputs = { # Flakes don't give us a good way to depend on .., so we don't. - # As a consequence, this flake is a little non-standard, and + # As a consequence, this flake only provides dependencies, and # we can't use the `nix` CLI as expected. nixpkgs.url = "github:NixOS/nixpkgs"; @@ -16,5 +16,6 @@ { # The dev tooling is in ./flake-module.nix # See comment at `inputs` above. + # It is loaded into partitions.dev by the root flake. }; } diff --git a/dev/repl.nix b/dev/repl.nix deleted file mode 100644 index 4c1b0d5..0000000 --- a/dev/repl.nix +++ /dev/null @@ -1,3 +0,0 @@ -# convenience for loading into nix repl -let self = builtins.getFlake (toString ./.); -in self // { inherit self; } diff --git a/flake.nix b/flake.nix index 331450a..c36b249 100644 --- a/flake.nix +++ b/flake.nix @@ -53,6 +53,15 @@ in lib.mkFlake { inherit inputs; } { systems = [ ]; + imports = [ flakeModules.partitions ]; + partitionedAttrs.checks = "dev"; + partitionedAttrs.devShells = "dev"; + partitionedAttrs.herculesCI = "dev"; + partitions.dev.extraInputsFlake = ./dev; + partitions.dev.extraInputs.flake-parts = inputs.self; + partitions.dev.module = { + imports = [ ./dev/flake-module.nix ]; + }; flake = { inherit lib templates flakeModules; }; diff --git a/shell.nix b/shell.nix index 62bdb7b..8745f50 100644 --- a/shell.nix +++ b/shell.nix @@ -1,2 +1 @@ -# non-idiomatic, see tools/README.md -(import ./dev).devShells.${builtins.currentSystem}.default +(builtins.getFlake ("git+file://" + toString ./.)).devShells.${builtins.currentSystem}.default