Breaks `documentation.nixos.includeAllModules`
If you try to evaluate a config with both stylix and documentation.nixos.includeAllModules = true it fails with the following error:
error:
… while evaluating a branch condition
at /nix/store/ycwxxfi2yv4nd8y66bxdc8pww9mhjwgj-source/lib/attrsets.nix:596:13:
595| name: value:
596| if isAttrs value && cond value
| ^
597| then recurse (path ++ [name]) value
… in the right operand of the AND (&&) operator
at /nix/store/ycwxxfi2yv4nd8y66bxdc8pww9mhjwgj-source/lib/attrsets.nix:596:30:
595| name: value:
596| if isAttrs value && cond value
| ^
597| then recurse (path ++ [name]) value
(stack trace truncated; use '--show-trace' to show the full trace)
error: attribute 'lib' missing
at /nix/store/j5w5w667z1lgkh37vi3sydm9hnbah9rx-modules/chromium/nixos.nix:5:5:
4| options.stylix.targets.chromium.enable =
5| config.lib.stylix.mkEnableTarget "Chromium, Google Chrome and Brave" true;
| ^
6|
You can reproduce by building this flake:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
stylix.url = "github:danth/stylix";
home-manager.url = "github:nix-community/home-manager";
};
outputs = { nixpkgs, home-manager, stylix, ... }: {
nixosConfigurations.repro = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
home-manager.nixosModules.home-manager
stylix.nixosModules.stylix
({ pkgs, ... }: {
# Unimportant things to make the config eval
boot.loader.grub.device = "/dev/sda1";
fileSystems."/".device = "tmpfs";
system.stateVersion = "23.05";
# Relevant bits
documentation = {
enable = true;
nixos.includeAllModules = true;
};
stylix.image = pkgs.fetchurl {
url = "https://media.githubusercontent.com/media/lovesegfault/nix-config/bda48ceaf8112a8b3a50da782bf2e65a2b5c4708/users/bemeurer/assets/walls/plants-00.jpg";
hash = "sha256-n8EQgzKEOIG6Qq7og7CNqMMFliWM5vfi2zNILdpmUfI=";
};
})
];
};
};
}
$ nix build .#nixosConfigurations.repro.config.system.build.toplevel
Underlying issue in the stack trace is the same one tackled by #1244, so I've marked that PR as fixing this.
I haven't tested to see if there are any other issues that would also cause includeAllModules to fail, but in theory #1212 should catch most of those.
Maybe to be more robust, a test case should be added that builds nixos docs with includeAllModules?
Maybe to be more robust, a test case should be added that builds nixos docs with
includeAllModules?
Sounds like we could easily enable that in our existing testbeds
Issue still seems to be happening: https://github.com/nix-community/stylix/actions/runs/15538117336/job/43742035089?pr=1471
Issue still seems to be happening: nix-community/stylix/actions/runs/15538117336/job/43742035089?pr=1471
Ah, that's a little more challenging:
error: attribute 'lib' missing
at /nix/store/jhz78vd2zg4qj244slbsrvbqssxy5y4w-source/stylix/overlays.nix:9:36:
8| {
9| options.stylix.overlays.enable = config.lib.stylix.mkEnableTarget "packages via overlays" true;
| ^
10|
TLDR; the docs forbid reading config to evaluate aspects of options that get documented. "Things that get documented" includes option descriptions, defaultText, example, option-type description, but also the attr names of the options tree and whether or not an option exists.
The issue here is that config.lib doesn't exist when evaluating modules for the docs, so you can't use helper functions defined there to declare the options.
Frankly this is a little overzealous of NixOS, since the point of their restriction is to avoid documentation being conditional on "normal" config definitions, rather than to prevent you using custom helpers added to config.lib. But in practice there's no distinction.
Maybe we could get an exception merged in nixpkgs, so the NixOS docs would permit using config.lib.
Without that, the only solution will be to completely migrate away from using config.lib.* to declare options.
Frankly this is a little overzealous of NixOS, since the point of their restriction is to avoid documentation being conditional on "normal" config definitions, rather than to prevent you using custom helpers added to
config.lib. But in practice there's no distinction.Maybe we could get an exception merged in nixpkgs, so the NixOS docs would permit using
config.lib.
That wouldn't really make sense; config.lib can not just contain functions but also other data (e.g. config.lib.stylix.colors), so adding an exception for it would break the restriction.
Without that, the only solution will be to completely migrate away from using
config.lib.*to declare options.
Home Manager gets around it by modifying the standard lib to add their own functions, but we don't have that luxury since we don't control the evalModules invocation.
Alternatively, we could pass our library directly into our modules, at a layer above the module system: but that would prevent anyone being able to add their own Stylix modules outside of our source tree.
Alternatively, we could pass our library directly into our modules, at a layer above the module system: but that would prevent anyone being able to add their own Stylix modules outside of our source tree.
I don't love the idea, but you could use a "lib" fixed outside of the module eval for stylix's internals while still exposing it for end-users in config.lib.
This could be a reasonable compromise, but will mean a lot of importApply and messier modules that need to accept two rounds of "args".
On the flip side, this would mean you could remove some of the hacks for how mkTarget gets mixed in with the module args for autoloaded modules, since if it is coming from a set of functions that is fixed outside the module system, you wouldn't have inf-rec issues with it anymore.
Maybe a helper function could be written to minimise the boilerplate of importApplying stylix's lib?
styLib.import ./foo.nix
let
styLib = {
# imports a module and grants it access to this library
# based on importApply, but assumes the imported module will be unique so it is safe to define `key`
import = file: {
key = file;
_file = file;
imports = [
# you could also use `intersectAttrs (functionArgs (import file))` to make the args optional
(import file { inherit styLib; })
];
};
};
in
styLib