I’m working on a Nix module that exposes different options based on content retrieved from a flake using a path that involves specifying a particular system. That is to say, theFlake.x86_64-linux.packages will have different content from theFlake.aarch64-darwin.packages, and I’m populating options from my module based on that content.
Using builtins.currentSystem isn’t appropriate, because we want to be building a system with options appropriate to the target; however, trying to refer to pkgs.system from inside options (instead of config) throws an infinite recursion error (as makes sense: reviewing nixos/lib/eval-config.nix we see that pkgs.system is set up via lib.mkDefault so it’s able to be overridden, and doesn’t yet have a known value early in evaluation).
Trying to pass something like config._module.args.forceSystem runs into the same problem – we don’t have a config yet when options are being evaluated. Do I need to restructure my code to be able to pass an extra copy of the target architecture via specialArgs to nixos/lib/eval-config.nix?
To be clear, you can define options in terms of config, so long as the relevant bits are sufficiently separate. I’ve done it.
Are you trying to import different modules based on system? or just defined different options? I would expect the former to fail but the latter to succeed.
(import <nixpkgs/nixos>) {
configuration = { pkgs, ... }: {
options = builtins.trace "Building a system with system ${pkgs.system}" {};
};
system = "x86_64-linux";
}
…which, when evaluated on a darwin host (and possibly others, haven’t checked), results in:
In the real-world use case, I’m introspecting a flake – investigating someFlake.packages.${pkgs.system} to find packages for which to generate configuration options.
Here’s a simple non-reproducer, demonstrating my point:
(import <nixpkgs/nixos>) {
configuration = { pkgs, ... }: {
options.foo = builtins.trace "Building a system with system ${pkgs.system}" {};
};
system = "x86_64-linux";
}
Remember that pkgs actually gets determined in terms of the nixpkgs.* options, so whatever you set inside options must be sufficiently separated from those to avoid infinite recursion.