Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Idiomatic way to provide a "library" of Nix functions #51

Open
srid opened this issue Aug 12, 2022 · 2 comments
Open

Idiomatic way to provide a "library" of Nix functions #51

srid opened this issue Aug 12, 2022 · 2 comments
Labels
enhancement New feature or request

Comments

@srid
Copy link
Contributor

srid commented Aug 12, 2022

We are using the module system options to expose functions for other modules to use.

For example,

{ self, ... }:
{
  options = {
    mkCheck = lib.mkOption {
      type = lib.types.functionTo lib.types.unspecified;
      default = { package, ... }: 
        abort "TODO: return a derivation that runs the tests for $package";
    };
  };
}

Then we use the mkCheck "library" function from other flake-module.nix modules (there are >10 of them, hence the library function) as:

{ self, ... }: {
  perSystem = { config, ... }: {
    checks.foo = config.mkCheck { ... };
  };
}

Is this the recommended way to use the module system to achieve this?

@roberth
Copy link
Member

roberth commented Aug 13, 2022

I don't think there's an idiomatic way yet, but we can think of a good opinionated way to do it.

Some requirements:

  • good namespacing
  • consider both libraries for internal use and for external use
  • consider libraries that depend on system and those that don't
  • any generic support modules should go in flakeModules.<foo> or a separate repo, not the default module list, which is supposed to be unopinionated, capturing only what nix itself hardcodes

Possible design:

Defining and using public libs (<flake>.lib)

  • Use flake.lib for putting lib attributes that don't necessarily depend on system
  • Use perSystem.lib for lib attributes that do depend on system
  • Expose perSystem.lib in flake.lib.libWithSystem = system: ...
  • Define inputs'.<name>.lib to be inputs.<name>.lib // inputs.<name>.lib.libWithSystem system (or // {} if not exists)
  • Define perSystem module argument libs so that libs.<name> = inputs'.foo.lib

Defining a lib to be used in a <flake>.flakeModule (module to be used in another flake)

  • Option a. Define a <flake>.lib, define flakeModule with withSystem or Add moduleWithSystem flake module parameter #48
    • This lib being public is probably a good thing?
  • Option b. Something else? We can't rely on inputs' because the consumer flake should be free to have the flake inputs it wants with the names it wants.

Defining a lib to be used locally

  • Similar to previous, but libs.self may be ok for non-public flake module. (Similar to how specialArgs should only be used by the final consumer, e.g. <flake>.nixosConfigurations, for this consumer's own purposes only)
    • Need some sort of alias for flake.lib in order not to expose a private lib to the flake.

Does this seem like it would work for you?

@clhodapp
Copy link

Defining a lib to be used in someone else's exported flake module is made a lot more challenging by #104

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants