···116117The [`class` argument](#module-system-lib-evalModules-param-class).
1180000000000119## Module arguments {#module-system-module-arguments}
120121Module arguments are the attribute values passed to modules when they are evaluated.
···116117The [`class` argument](#module-system-lib-evalModules-param-class).
118119+#### `graph` {#module-system-lib-evalModules-return-value-graph}
120+121+Represents all the modules that took part in the evaluation.
122+It is a list of `ModuleGraph` where `ModuleGraph` is defined as an attribute set with the following attributes:
123+124+- `key`: `string` for the purpose of module deduplication and `disabledModules`
125+- `file`: `string` for the purpose of error messages and warnings
126+- `imports`: `[ ModuleGraph ]`
127+- `disabled`: `bool`
128+129## Module arguments {#module-system-module-arguments}
130131Module arguments are the attribute values passed to modules when they are evaluated.
···245 };
246 };
247248- merged =
249- let
250- collected =
251- collectModules class (specialArgs.modulesPath or "") (regularModules ++ [ internalModule ])
252- (
253- {
254- inherit
255- lib
256- options
257- specialArgs
258- ;
259- _class = class;
260- _prefix = prefix;
261- config = addErrorContext "if you get an infinite recursion here, you probably reference `config` in `imports`. If you are trying to achieve a conditional import behavior dependent on `config`, consider importing unconditionally, and using `mkEnableOption` and `mkIf` to control its effect." config;
262- }
263- // specialArgs
264- );
265- in
266- mergeModules prefix (reverseList collected);
0267268 options = merged.matchedOptions;
269···359 options = checked options;
360 config = checked (removeAttrs config [ "_module" ]);
361 _module = checked (config._module);
0362 inherit extendModules type class;
363 };
364 in
365 result;
366367- # collectModules :: (class: String) -> (modulesPath: String) -> (modules: [ Module ]) -> (args: Attrs) -> [ Module ]
368 #
369 # Collects all modules recursively through `import` statements, filtering out
370 # all modules in disabledModules.
···424 else
425 m: m;
42600000000000000000000000000000427 /**
428- Collects all modules recursively into the form
429430 {
431 disabled = [ <list of disabled modules> ];
···493 modulesPath:
494 { disabled, modules }:
495 let
496- moduleKey =
497- file: m:
498- if isString m then
499- if substring 0 1 m == "/" then m else toString modulesPath + "/" + m
500-501- else if isConvertibleWithToString m then
502- if m ? key && m.key != toString m then
503- throw "Module `${file}` contains a disabledModules item that is an attribute set that can be converted to a string (${toString m}) but also has a `.key` attribute (${m.key}) with a different value. This makes it ambiguous which module should be disabled."
504- else
505- toString m
506-507- else if m ? key then
508- m.key
509-510- else if isAttrs m then
511- throw "Module `${file}` contains a disabledModules item that is an attribute set, presumably a module, that does not have a `key` attribute. This means that the module system doesn't have any means to identify the module that should be disabled. Make sure that you've put the correct value in disabledModules: a string path relative to modulesPath, a path value, or an attribute set with a `key` attribute."
512- else
513- throw "Each disabledModules item must be a path, string, or a attribute set with a key attribute, or a value supported by toString. However, one of the disabledModules items in `${toString file}` is none of that, but is of type ${typeOf m}.";
514-515- disabledKeys = concatMap ({ file, disabled }: map (moduleKey file) disabled) disabled;
516- keyFilter = filter (attrs: !elem attrs.key disabledKeys);
517 in
518 map (attrs: attrs.module) (genericClosure {
519 startSet = keyFilter modules;
520 operator = attrs: keyFilter attrs.modules;
521 });
52200000000000000523 in
524- modulesPath: initialModules: args:
525- filterModules modulesPath (collectStructuredModules unknownModule "" initialModules args);
00526527 /**
528 Wrap a module with a default location for reporting errors.
···245 };
246 };
247248+ # This function takes an empty attrset as an argument.
249+ # It could theoretically be replaced with its body,
250+ # but such a binding is avoided to allow for earlier grabage collection.
251+ doCollect =
252+ { }:
253+ collectModules class (specialArgs.modulesPath or "") (regularModules ++ [ internalModule ]) (
254+ {
255+ inherit
256+ lib
257+ options
258+ specialArgs
259+ ;
260+ _class = class;
261+ _prefix = prefix;
262+ config = addErrorContext "if you get an infinite recursion here, you probably reference `config` in `imports`. If you are trying to achieve a conditional import behavior dependent on `config`, consider importing unconditionally, and using `mkEnableOption` and `mkIf` to control its effect." config;
263+ }
264+ // specialArgs
265+ );
266+267+ merged = mergeModules prefix (reverseList (doCollect { }).modules);
268269 options = merged.matchedOptions;
270···360 options = checked options;
361 config = checked (removeAttrs config [ "_module" ]);
362 _module = checked (config._module);
363+ inherit (doCollect { }) graph;
364 inherit extendModules type class;
365 };
366 in
367 result;
368369+ # collectModules :: (class: String) -> (modulesPath: String) -> (modules: [ Module ]) -> (args: Attrs) -> ModulesTree
370 #
371 # Collects all modules recursively through `import` statements, filtering out
372 # all modules in disabledModules.
···426 else
427 m: m;
428429+ # isDisabled :: String -> [ { disabled, file } ] -> StructuredModule -> bool
430+ #
431+ # Figures out whether a `StructuredModule` is disabled.
432+ isDisabled =
433+ modulesPath: disabledList:
434+ let
435+ moduleKey =
436+ file: m:
437+ if isString m then
438+ if substring 0 1 m == "/" then m else toString modulesPath + "/" + m
439+440+ else if isConvertibleWithToString m then
441+ if m ? key && m.key != toString m then
442+ throw "Module `${file}` contains a disabledModules item that is an attribute set that can be converted to a string (${toString m}) but also has a `.key` attribute (${m.key}) with a different value. This makes it ambiguous which module should be disabled."
443+ else
444+ toString m
445+446+ else if m ? key then
447+ m.key
448+449+ else if isAttrs m then
450+ throw "Module `${file}` contains a disabledModules item that is an attribute set, presumably a module, that does not have a `key` attribute. This means that the module system doesn't have any means to identify the module that should be disabled. Make sure that you've put the correct value in disabledModules: a string path relative to modulesPath, a path value, or an attribute set with a `key` attribute."
451+ else
452+ throw "Each disabledModules item must be a path, string, or a attribute set with a key attribute, or a value supported by toString. However, one of the disabledModules items in `${toString file}` is none of that, but is of type ${typeOf m}.";
453+454+ disabledKeys = concatMap ({ file, disabled }: map (moduleKey file) disabled) disabledList;
455+ in
456+ structuredModule: elem structuredModule.key disabledKeys;
457+458 /**
459+ Collects all modules recursively into a `[ StructuredModule ]` and a list of disabled modules:
460461 {
462 disabled = [ <list of disabled modules> ];
···524 modulesPath:
525 { disabled, modules }:
526 let
527+ keyFilter = filter (attrs: !isDisabled modulesPath disabled attrs);
00000000000000000000528 in
529 map (attrs: attrs.module) (genericClosure {
530 startSet = keyFilter modules;
531 operator = attrs: keyFilter attrs.modules;
532 });
533534+ toGraph =
535+ modulesPath:
536+ { disabled, modules }:
537+ let
538+ isDisabledModule = isDisabled modulesPath disabled;
539+540+ toModuleGraph = structuredModule: {
541+ disabled = isDisabledModule structuredModule;
542+ inherit (structuredModule) key;
543+ file = structuredModule.module._file;
544+ imports = map toModuleGraph structuredModule.modules;
545+ };
546+ in
547+ map toModuleGraph (filter (x: x.key != "lib/modules.nix") modules);
548 in
549+ modulesPath: initialModules: args: {
550+ modules = filterModules modulesPath (collectStructuredModules unknownModule "" initialModules args);
551+ graph = toGraph modulesPath (collectStructuredModules unknownModule "" initialModules args);
552+ };
553554 /**
555 Wrap a module with a default location for reporting errors.
+22-1
lib/tests/modules.sh
···20pass=0
21fail=0
22000023# loc
24# prints the location of the call of to the function that calls it
25# loc n
···55 local attr=$1
56 shift
57 local script="import ./default.nix { modules = [ $* ];}"
58- nix-instantiate --timeout 1 -E "$script" -A "$attr" --eval-only --show-trace --read-write-mode --json
59}
6061reportFailure() {
···104 fi
105 return 1
106 }
00000000000000107}
108109checkConfigError() {
···336checkConfigOutput '^12$' config.value ./declare-coerced-value-unsound.nix
337checkConfigError 'A definition for option .* is not of type .*. Definition values:\n\s*- In .*: "1000"' config.value ./declare-coerced-value-unsound.nix ./define-value-string-bigint.nix
338checkConfigError 'toInt: Could not convert .* to int' config.value ./declare-coerced-value-unsound.nix ./define-value-string-arbitrary.nix
000339340# Check mkAliasOptionModule.
341checkConfigOutput '^true$' config.enable ./alias-with-priority.nix
···20pass=0
21fail=0
2223+local-nix-instantiate() {
24+ nix-instantiate --timeout 1 --eval-only --show-trace --read-write-mode --json "$@"
25+}
26+27# loc
28# prints the location of the call of to the function that calls it
29# loc n
···59 local attr=$1
60 shift
61 local script="import ./default.nix { modules = [ $* ];}"
62+ local-nix-instantiate -E "$script" -A "$attr"
63}
6465reportFailure() {
···108 fi
109 return 1
110 }
111+}
112+113+checkExpression() {
114+ local path=$1
115+ local output
116+ {
117+ output="$(local-nix-instantiate --strict "$path" 2>&1)" && ((++pass))
118+ } || {
119+ logStartFailure
120+ echo "$output"
121+ ((++fail))
122+ logFailure
123+ logEndFailure
124+ }
125}
126127checkConfigError() {
···354checkConfigOutput '^12$' config.value ./declare-coerced-value-unsound.nix
355checkConfigError 'A definition for option .* is not of type .*. Definition values:\n\s*- In .*: "1000"' config.value ./declare-coerced-value-unsound.nix ./define-value-string-bigint.nix
356checkConfigError 'toInt: Could not convert .* to int' config.value ./declare-coerced-value-unsound.nix ./define-value-string-arbitrary.nix
357+358+# Check `graph` attribute
359+checkExpression './graph/test.nix'
360361# Check mkAliasOptionModule.
362checkConfigOutput '^true$' config.enable ./alias-with-priority.nix
···12 Perform OCR on a screenshot that contains text.
13 Returns a string with all words that could be found.
14 """
15- variants = perform_ocr_variants_on_screenshot(screenshot_path, False)[0]
16- if len(variants) != 1:
17- raise MachineError(f"Received wrong number of OCR results: {len(variants)}")
18- return variants[0]
192021def perform_ocr_variants_on_screenshot(
···12 Perform OCR on a screenshot that contains text.
13 Returns a string with all words that could be found.
14 """
15+ return perform_ocr_variants_on_screenshot(screenshot_path, False)[0]
000161718def perform_ocr_variants_on_screenshot(
···202 # to be built eventually, we would still like to get the error early and without
203 # having to wait while nix builds a derivation that might not be used.
204 # See also https://github.com/NixOS/nix/issues/4629
205- optionalAttrs (attrs ? disallowedReferences) {
206- disallowedReferences = map unsafeDerivationToUntrackedOutpath attrs.disallowedReferences;
207- }
208- // optionalAttrs (attrs ? disallowedRequisites) {
209- disallowedRequisites = map unsafeDerivationToUntrackedOutpath attrs.disallowedRequisites;
210- }
211- // optionalAttrs (attrs ? allowedReferences) {
212- allowedReferences = mapNullable unsafeDerivationToUntrackedOutpath attrs.allowedReferences;
213- }
214- // optionalAttrs (attrs ? allowedRequisites) {
215- allowedRequisites = mapNullable unsafeDerivationToUntrackedOutpath attrs.allowedRequisites;
216 };
217218 makeDerivationArgument =
···478479 derivationArg =
480 removeAttrs attrs removedOrReplacedAttrNames
481- // (optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) {
482- name =
483 let
484 # Indicate the host platform of the derivation if cross compiling.
485 # Fixed-output derivations like source tarballs shouldn't get a host
···507 ) "The `version` attribute cannot be null.";
508 "${attrs.pname}${staticMarker}${hostSuffix}-${attrs.version}"
509 );
510- })
511- // {
512 builder = attrs.realBuilder or stdenv.shell;
513 args =
514 attrs.args or [
···556 inherit doCheck doInstallCheck;
557558 inherit outputs;
559- }
560- // optionalAttrs (__contentAddressed) {
561- inherit __contentAddressed;
562- # Provide default values for outputHashMode and outputHashAlgo because
563- # most people won't care about these anyways
564- outputHashAlgo = attrs.outputHashAlgo or "sha256";
565- outputHashMode = attrs.outputHashMode or "recursive";
566- }
567- // optionalAttrs (enableParallelBuilding) {
568- inherit enableParallelBuilding;
569- enableParallelChecking = attrs.enableParallelChecking or true;
570- enableParallelInstalling = attrs.enableParallelInstalling or true;
571- }
572- // optionalAttrs (hardeningDisable != [ ] || hardeningEnable != [ ] || stdenv.hostPlatform.isMusl) {
573- NIX_HARDENING_ENABLE = builtins.concatStringsSep " " enabledHardeningOptions;
574- }
575- //
00000576 # TODO: remove platform condition
577 # Enabling this check could be a breaking change as it requires to edit nix.conf
578 # NixOS module already sets gccarch, unsure of nix installers and other distributions
579- optionalAttrs
580- (
581 stdenv.buildPlatform ? gcc.arch
582 && !(
583 stdenv.buildPlatform.isAarch64
···589 stdenv.buildPlatform.gcc.arch == "armv8-a"
590 )
591 )
592- )
593- {
594- requiredSystemFeatures = attrs.requiredSystemFeatures or [ ] ++ [
595- "gccarch-${stdenv.buildPlatform.gcc.arch}"
596- ];
597- }
000598 // optionalAttrs (stdenv.buildPlatform.isDarwin) (
599 let
600 allDependencies = concatLists (concatLists dependencies);
···202 # to be built eventually, we would still like to get the error early and without
203 # having to wait while nix builds a derivation that might not be used.
204 # See also https://github.com/NixOS/nix/issues/4629
205+ {
206+ ${if (attrs ? disallowedReferences) then "disallowedReferences" else null} =
207+ map unsafeDerivationToUntrackedOutpath attrs.disallowedReferences;
208+ ${if (attrs ? disallowedRequisites) then "disallowedRequisites" else null} =
209+ map unsafeDerivationToUntrackedOutpath attrs.disallowedRequisites;
210+ ${if (attrs ? allowedReferences) then "allowedReferences" else null} =
211+ mapNullable unsafeDerivationToUntrackedOutpath attrs.allowedReferences;
212+ ${if (attrs ? allowedRequisites) then "allowedRequisites" else null} =
213+ mapNullable unsafeDerivationToUntrackedOutpath attrs.allowedRequisites;
00214 };
215216 makeDerivationArgument =
···476477 derivationArg =
478 removeAttrs attrs removedOrReplacedAttrNames
479+ // {
480+ ${if (attrs ? name || (attrs ? pname && attrs ? version)) then "name" else null} =
481 let
482 # Indicate the host platform of the derivation if cross compiling.
483 # Fixed-output derivations like source tarballs shouldn't get a host
···505 ) "The `version` attribute cannot be null.";
506 "${attrs.pname}${staticMarker}${hostSuffix}-${attrs.version}"
507 );
508+0509 builder = attrs.realBuilder or stdenv.shell;
510 args =
511 attrs.args or [
···553 inherit doCheck doInstallCheck;
554555 inherit outputs;
556+557+ # When the derivations is content addressed provide default values
558+ # for outputHashMode and outputHashAlgo because most people won't
559+ # care about these anyways
560+ ${if __contentAddressed then "__contentAddressed" else null} = __contentAddressed;
561+ ${if __contentAddressed then "outputHashAlgo" else null} = attrs.outputHashAlgo or "sha256";
562+ ${if __contentAddressed then "outputHashMode" else null} = attrs.outputHashMode or "recursive";
563+564+ ${if enableParallelBuilding then "enableParallelBuilding" else null} = enableParallelBuilding;
565+ ${if enableParallelBuilding then "enableParallelChecking" else null} =
566+ attrs.enableParallelChecking or true;
567+ ${if enableParallelBuilding then "enableParallelInstalling" else null} =
568+ attrs.enableParallelInstalling or true;
569+570+ ${
571+ if (hardeningDisable != [ ] || hardeningEnable != [ ] || stdenv.hostPlatform.isMusl) then
572+ "NIX_HARDENING_ENABLE"
573+ else
574+ null
575+ } =
576+ builtins.concatStringsSep " " enabledHardeningOptions;
577+578 # TODO: remove platform condition
579 # Enabling this check could be a breaking change as it requires to edit nix.conf
580 # NixOS module already sets gccarch, unsure of nix installers and other distributions
581+ ${
582+ if
583 stdenv.buildPlatform ? gcc.arch
584 && !(
585 stdenv.buildPlatform.isAarch64
···591 stdenv.buildPlatform.gcc.arch == "armv8-a"
592 )
593 )
594+ then
595+ "requiredSystemFeatures"
596+ else
597+ null
598+ } =
599+ attrs.requiredSystemFeatures or [ ] ++ [
600+ "gccarch-${stdenv.buildPlatform.gcc.arch}"
601+ ];
602+ }
603 // optionalAttrs (stdenv.buildPlatform.isDarwin) (
604 let
605 allDependencies = concatLists (concatLists dependencies);
+2
pkgs/top-level/aliases.nix
···588 dtv-scan-tables_linuxtv = dtv-scan-tables; # Added 2023-03-03
589 dtv-scan-tables_tvheadend = dtv-scan-tables; # Added 2023-03-03
590 du-dust = dust; # Added 2024-01-19
00591 dump1090 = dump1090-fa; # Added 2024-02-12
592 dwfv = throw "'dwfv' has been removed due to lack of upstream maintenance";
593 dylibbundler = throw "'dylibbundler' has been renamed to/replaced by 'macdylibbundler'"; # Converted to throw 2024-10-17
···588 dtv-scan-tables_linuxtv = dtv-scan-tables; # Added 2023-03-03
589 dtv-scan-tables_tvheadend = dtv-scan-tables; # Added 2023-03-03
590 du-dust = dust; # Added 2024-01-19
591+ duckstation = throw "'duckstation' has been removed due to being unmaintained"; # Added 2025-08-03
592+ duckstation-bin = throw "'duckstation-bin' has been removed due to being unmaintained"; # Added 2025-08-03
593 dump1090 = dump1090-fa; # Added 2024-02-12
594 dwfv = throw "'dwfv' has been removed due to lack of upstream maintenance";
595 dylibbundler = throw "'dylibbundler' has been renamed to/replaced by 'macdylibbundler'"; # Converted to throw 2024-10-17