Automatically generate smaller base nixpkgs module list

My objective is to have a smaller baseModules passed to nixosSystem and something similar for home-manager for faster evaluation times. I don’t want to manually pick the modules from nixpkgs to include, but rather have a script (that isn’t ran every rebuild, of course) that I can use to find out which nixpkgs modules my config is using.

I could only come up with the following method, which is probably not such a good one:

  1. Wrap all baseModules passed to nixosSystem like this (or similarly):
# Assuming the module is a function, otherwise no need to wrap
let
  mapConfig = lib.mapAttrsRecursive (path: value: lib.warn "-| ${lib.showOption path} |-" value);
in module: {
  __functor = _: x: module (x // { config = mapConfig x.config; });
  __functionArgs = lib.functionArgs module;
}
  1. Evaluate system.build.toplevel in a script and parse the warnings to find out which config options were evaluated as a “dependency” of system.build.toplevel.
  2. Use options.<the-option>.files and options.<the-option>.declarations to find out which files define and set the options found in step 2.
  3. Make a list of baseModules containing only those files.

While this may work (I haven’t tried it), it sounds like a very bad solution.

Is there any better way to do something of the sort?

Thank you in advance for any help.

I regrettably don’t think there’s an easy solution to get a working NixOS system from evaluating a small module set yet. The main hurdle is death by a thousand (or “just” hundreds?) cuts due to implicit dependencies between various modules.

I think NixOS always imports all modules · Issue #137168 · NixOS/nixpkgs · GitHub and `nixos-rebuild --switch` too slow, tracking issue · Issue #57477 · NixOS/nixpkgs · GitHub might be good entrypoints into the discussion around these issues.

4 Likes