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

lib/modules: Document _module.args #165540

Merged
merged 1 commit into from
Apr 5, 2022
Merged

Conversation

infinisil
Copy link
Member

@infinisil infinisil commented Mar 24, 2022

Description of changes

Documents the _module.args option, motivated by many usages in Flakes, especially with the deprecation of extraArgs

Click for screenshot of the documentation

Screen Shot 2022-03-24 at 14 33 07

Ping @roberth

Things done
  • Built the manual with nix-build nixos/release.nix -A manualHTML.x86_64-linux and checked the resulting result/share/doc/nixos/options.html

@infinisil infinisil added the 6.topic: module system About "NixOS" module system internals label Mar 24, 2022
@infinisil infinisil requested review from edolstra and nbp as code owners March 24, 2022 01:57
@infinisil infinisil changed the title lib/modules: Document _module.args lib/modules: Document _module.args Mar 24, 2022
@github-actions github-actions bot added the 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS label Mar 24, 2022
Copy link
Contributor

@pennae pennae left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice! would clarify how args works for submodules a little bit though and mention the name argument since it's really useful but apparently not documented anywhere either.

Copy link
Member

@roberth roberth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We actually need to discourage use of module arguments :(

lib/modules.nix Outdated
description = ''
Additional arguments passed to each module in addition to ones
like <literal>lib</literal>, <literal>config</literal>,
<literal>pkgs</literal>, <literal>modulesPath</literal> for
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are NixOS-specific and don't belong in the generated documentation of other configuration systems.
They are better documented as freeform options.

Suggested change
<literal>pkgs</literal>, <literal>modulesPath</literal> for

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These arguments are not evaluated by the module system.

What does this mean?

Technically the module system doesn't evaluate anything, as it is a library or embedded dsl.
Maybe "they aren't processed by the module system", but that's still vague. Probably best to remove this sentence.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are NixOS-specific and don't belong in the generated documentation of other configuration systems. They are better documented as freeform options.

I should reword this sentence (there's a for nixpkgs afterwards, but it's very ambiguous). I think it's valid to mention pkgs and modulesPath in this documentation because there's no other place where these are documented currently, and NixOS modules are by far the most common use case. With a freeform type we should be able to make this documentation NixOS-specific in the future though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just dropped the for nixpkgs. This sentence specifically says "ones like ...", which indicates that it's just an example of some arguments the reader might be familiar with. I think this should be fine

lib/modules.nix Outdated
example = literalExpression ''
{
unstable = import nixpkgs {};
myLib = { addOne = x: x + 1; };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually an antipattern. It works for "split configuration" but is a bad idea for reusable modules.
It's better than lib.extend by virtue of being slightly more composable, but still vulnerable to name collisions.
The most robust method of using "libraries" is to import them directly into the lexical scope: let myLib = import ./myLlib; in ...... The root values in file imports are cached, so there's no loss of performance. Function invocations are not, so we need an alternative place to memoize those and internal options fit that purpose, without the risk of name collisions or organic accumulation of "utils" junk libraries.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have suggestions for better examples? Or should we drop examples completely?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I honestly don't know of a good example. The ones in nixpkgs itself aren't actually good either. They're highly specific and/or workarounds.

unstable is the best example I know of, only slightly better than myLib. I'd call it pkgsUnstable though.

I think we need to clarify what are the "acceptable" use cases:

  • end user configurations that are not intended to be included into anything that isn't defined "locally". Here convenience wins over reusability, but it does mean turning configs into modules will be harder.
  • specific features of configuration systems, maybe?
    • for example NixOS defines noUserModules to solve quite a NixOS-specific problem (maybe I should have used an internal specialisations option instead? I guess that namespace was taken by an attrsOf. Is that sufficient reason?
    • is baseModules any better?

I'm really trying to like it, but not succeeding.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the example altogether for now. We can still add one later if we have a good one.

@infinisil infinisil force-pushed the module-args-docs branch 3 times, most recently from ecdf336 to 2f218ed Compare March 24, 2022 14:38
@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/tweag-nix-dev-update-27/18433/1

Documents the _module.args option, motivated by many usages in Flakes,
especially with the deprecation of extraArgs
(NixOS@78ada83)

The documentation rendering for this option had to be handled a bit
specially, since it's not declared in nixos/modules like all the other
NixOS options.

Co-Authored-By: pennae <[email protected]>
Co-Authored-By: Robert Hensing <[email protected]>
@infinisil
Copy link
Member Author

@roberth Good to merge?

@ofborg ofborg bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin 10.rebuild-linux: 1-10 labels Apr 5, 2022
Copy link
Member

@roberth roberth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One final thing it seems.
Otherwise lgtm.

</listitem>
<listitem>
<para>
<varname>config</varname>: The results of all options after merging the values from all modules together.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Subtle but important.

Suggested change
<varname>config</varname>: The results of all options after merging the values from all modules together.
<varname>config</varname>: The results of all options after merging the values from all modules together. In the context of a submodule, "all modules" does not include the parent module that contains the submodule.
</para>
<para>
The module arguments of the parent can be accessed through the lexical scope instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that something is missing from my terminology here. I can't find a word for what's like a level of modules, corresponding to an evalModules invocation, whether through lib or types.submodule. "Modules" is too vague "configuration" is a little more accurate but deemphasizes the options. "Configuration fixpoint" will send our readers studying for a day ;). Not sure what to do.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"modules are merged according to the longest common option path prefix"? that covers both configurations (prefix 𝜀) and submodules (nested or not)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While that is true, it does not indicate where config starts or equivalently: what is the result of "all options" and which options are "all".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this clarification is needed because it's fairly obvious, submodules have a completely separate option set. This would fit better into the full NixOS documentation, this here should only be a very short explanation, only in relation to _module.args.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fair enough 🚀

</listitem>
<listitem>
<para>
<varname>options</varname>: The options declared in all modules.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<varname>options</varname>: The options declared in all modules.
<varname>options</varname>: The options declared in all modules, where "all modules" is defined the same as in <varname>config</varname>.

@roberth roberth merged commit c705953 into NixOS:master Apr 5, 2022
@infinisil infinisil deleted the module-args-docs branch April 5, 2022 19:52
@roberth
Copy link
Member

roberth commented Apr 7, 2022

Making this opt-out in #167776 so arion doesn't have to deal with docbook in its asciidoc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
6.topic: module system About "NixOS" module system internals 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin 10.rebuild-linux: 1-10
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants