How can I make a module option dependant on another option?

Take this home manager foo module for instance:

{ lib, osConfig, config, ... }: {
  options.foo = {
    enable = lib.mkEnableOption "foo";
    bar.enable = lib.mkEnableOption "bar";
  };

  config = {
    foo = {
      enable = lib.mkDefault osConfig.foo.enable;
      bar.enable = lib.mkForce (config.foo.bar.enable && config.foo.enable);
    };
  };
}

This gives me an infinite recursion error but it does illustrate what I’m trying to do.
I’d use this module by first setting foo.bar.enable in my HM config and foo.enable in my NixOS config and, in theory, if foo.bar.enable is true but bar.enable isn’t, then foo.bar.enable would be set back to false.
The advantage here is that when writing a bar submodule, I’d only have to check if bar.enable was true instead of checking both bar.enable and foo.enable.
Is this possible?

Are you sure this illustrates what you are trying to do?

If you want to make a variable dependent on itself AND another variable, why not just make it dependent on that other variable?

You’re getting infinite recursion because that’s what is happening.

foo.bar.enable depends on itself:

config.foo.bar.enable && config.foo.enable

I’m poor with examples but the idea is that bar is optional.
My actual use case is that I have a gaming module for NixOS (where I enable gpu options), a gaming module for home manager (where I install things like lutris) and an optional game module for OpenMW.
It doesn’t make sense to enable HM gaming if the system doesn’t enable it, and it doesn’t make sense to enable OpenMW if home manager doesn’t enable gaming.

Is there no way that what I’m trying to do here can be done?

If you can show actual example, maybe I can understand what is happening and help.

1 Like

How about this?

{ lib, osConfig, config, ... }: {
  options.foo = {
    enable = lib.mkEnableOption "foo" // { default =  osConfig.foo.enable; };
    bar.enable = lib.mkEnableOption "bar";
    fooAndBarEnabled = lib.mkOption {
      type = lib.types.bool;
      description = "Whether foo & bar are enabled.";
      default = config.foo.bar.enable && config.foo.enable;
      readOnly = true;
    };
  };
}

Then you can check config.foo.fooAndBarEnabled in your other modules, does that work for you?

you just set hm gaming equal to system gaming and openmw gaming equal to hm gaming

If I understand this correctly, your end goal is to make sure that the following assertion hold true, right?

foo.enable && foo.bar.enable == true

If yes, then yes, the way to go is to have the third option foo.fooAndBarEnabled like you have.

1 Like