diff options
| author | Daiderd Jordan <daiderd@gmail.com> | 2023-07-09 12:34:19 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-07-09 12:34:19 +0200 |
| commit | 66a3047fa88eb6aa5c5a2e675de91f0431fbe561 (patch) | |
| tree | fe02b1b923540b82a7cc03488eaa4d5059863aa6 | |
| parent | 4e3fc1864712a534d30ef074d695e968f1fb1487 (diff) | |
| parent | f9724c4543035d6190c00168ebfa93f0b2e927d0 (diff) | |
Merge pull request #723 from emilazy/rationalize-nixpkgs-handling
Rationalize handling of Nixpkgs
| -rw-r--r-- | README.md | 24 | ||||
| -rw-r--r-- | default.nix | 19 | ||||
| -rw-r--r-- | doc/manual/default.nix | 30 | ||||
| -rw-r--r-- | eval-config.nix | 35 | ||||
| -rw-r--r-- | flake.nix | 48 | ||||
| -rw-r--r-- | modules/documentation/default.nix | 14 | ||||
| -rw-r--r-- | modules/examples/flake/flake.nix | 10 | ||||
| -rw-r--r-- | modules/nix/nixpkgs.nix | 312 | ||||
| -rw-r--r-- | modules/system/flake-overrides.nix | 20 | ||||
| -rw-r--r-- | modules/system/version.nix | 84 |
10 files changed, 394 insertions, 202 deletions
@@ -85,39 +85,29 @@ A minimal example of using an existing configuration.nix: darwin.inputs.nixpkgs.follows = "nixpkgs"; }; - outputs = { self, darwin, nixpkgs }: { + outputs = inputs@{ self, darwin, nixpkgs }: { darwinConfigurations."Johns-MacBook" = darwin.lib.darwinSystem { - system = "x86_64-darwin"; modules = [ ./configuration.nix ]; }; }; } ``` -Inputs from the flake can also be passed to `darwinSystem`. These inputs are then +Inputs from the flake can also be passed into `darwinSystem`. These inputs are then accessible as an argument `inputs`, similar to `pkgs` and `lib`, inside the configuration. ```nix +# in flake.nix darwin.lib.darwinSystem { - system = "x86_64-darwin"; modules = [ ./configuration.nix ]; - inputs = { inherit darwin dotfiles nixpkgs; }; + specialArgs = { inherit inputs; }; } -# in configuration.nix: -{ pkgs, lib, inputs }: -# inputs.darwin, inputs.dotfiles, and inputs.nixpkgs can be accessed here ``` -Alternatively, `specialArgs` could be used: - ```nix -darwin.lib.darwinSystem { - system = "x86_64-darwin"; - modules = [ ./configuration.nix ]; - specialArgs = { inherit darwin dotfiles nixpkgs; }; -} -# in configuration.nix: -{ pkgs, lib, darwin, dotfiles, nixpkgs }: +# in configuration.nix +{ pkgs, lib, inputs }: +# inputs.self, inputs.darwin, and inputs.nixpkgs can be accessed here ``` Since the installer doesn't work with flakes out of the box yet, nix-darwin will need to diff --git a/default.nix b/default.nix index 11c686b..7c7e06b 100644 --- a/default.nix +++ b/default.nix @@ -6,19 +6,16 @@ }: let - evalConfig = import ./eval-config.nix { inherit lib; }; - - eval = evalConfig { - inherit system; - modules = [ configuration nixpkgsRevisionModule ]; - inputs = { inherit nixpkgs; }; + eval = import ./eval-config.nix { + inherit lib; + modules = [ + configuration + { nixpkgs.source = lib.mkDefault nixpkgs; } + ] ++ lib.optional (system != null) { + nixpkgs.system = lib.mkDefault system; + }; }; - nixpkgsRevisionModule = - if nixpkgs?rev && lib.isString nixpkgs.rev - then { system.nixpkgsRevision = nixpkgs.rev; } - else { }; - # The source code of this repo needed by the [un]installers. nix-darwin = lib.cleanSource ( lib.cleanSourceWith { diff --git a/doc/manual/default.nix b/doc/manual/default.nix index 2225b51..5a0072a 100644 --- a/doc/manual/default.nix +++ b/doc/manual/default.nix @@ -13,28 +13,30 @@ with pkgs; let lib = pkgs.lib; + gitHubDeclaration = user: repo: ref: subpath: + # Default to `master` if we don't know what revision the system + # configuration is using (custom nixpkgs, etc.). + let urlRef = if ref != null then ref else "master"; + in { + url = "https://github.com/${user}/${repo}/blob/${urlRef}/${subpath}"; + name = "<${repo}/${subpath}>"; + }; + optionsDoc = buildPackages.nixosOptionsDoc { - inherit options revision; + inherit options; transformOptions = opt: opt // { # Clean up declaration sites to not refer to the nix-darwin source tree. # TODO: handle `extraSources`? (it's not set anywhere) declarations = map (decl: if lib.hasPrefix (toString prefix) (toString decl) then - let - subpath = lib.removePrefix "/" - (lib.removePrefix (toString prefix) (toString decl)); - in { - url = "https://github.com/LnL7/nix-darwin/blob/${revision}/${subpath}"; - name = "<nix-darwin/${subpath}>"; - } + gitHubDeclaration "LnL7" "nix-darwin" revision + (lib.removePrefix "/" + (lib.removePrefix (toString prefix) (toString decl))) # TODO: handle this in a better way (may require upstream # changes to nixpkgs) else if decl == "lib/modules.nix" then - { - url = "https://github.com/NixOS/nixpkgs/blob/${nixpkgsRevision}/${decl}"; - name = "<nixpkgs/${decl}>"; - } + gitHubDeclaration "NixOS" "nixpkgs" nixpkgsRevision decl else decl) opt.declarations; }; @@ -73,7 +75,7 @@ in rec { cp -r ${pkgs.documentation-highlighter} $dst/highlightjs substitute ${./manual.md} manual.md \ - --replace '@DARWIN_VERSION@' "${version}"\ + --replace '@DARWIN_VERSION@' "${version}" \ --replace \ '@DARWIN_OPTIONS_JSON@' \ ${optionsJSON}/share/doc/darwin/options.json @@ -82,7 +84,7 @@ in rec { nixos-render-docs -j $NIX_BUILD_CORES manual html \ --manpage-urls ${pkgs.writeText "manpage-urls.json" "{}"} \ --revision ${lib.escapeShellArg revision} \ - --generator "nixos-render-docs ${pkgs.lib.version}" \ + --generator "nixos-render-docs ${lib.version}" \ --stylesheet style.css \ --stylesheet overrides.css \ --stylesheet highlightjs/mono-blue.css \ diff --git a/eval-config.nix b/eval-config.nix index 4b71303..9663849 100644 --- a/eval-config.nix +++ b/eval-config.nix @@ -1,13 +1,5 @@ -{ lib }: -let - nixpkgs-lib = lib; -in - -{ system ? builtins.currentSystem or "x86_64-darwin" -, pkgs ? null -, lib ? nixpkgs-lib +{ lib , modules -, inputs , baseModules ? import ./modules/module-list.nix , specialArgs ? { } , check ? true @@ -18,32 +10,13 @@ let _file = ./eval-config.nix; config = { _module.args = { - inherit baseModules inputs modules; + inherit baseModules modules; }; }; }; - pkgsModule = { config, inputs, ... }: { - _file = ./eval-config.nix; - config = { - assertions = [ { - # Ensure that nixpkgs.* options are not set when pkgs is set - assertion = pkgs == null || (config.nixpkgs.config == { } && config.nixpkgs.overlays == [ ]); - message = '' - `nixpkgs` options are disabled when `pkgs` is supplied through `darwinSystem`. - ''; - } ]; - - _module.args.pkgs = if pkgs != null then pkgs else import inputs.nixpkgs config.nixpkgs; - - # This permits the configuration to override the passed-in - # system. - nixpkgs.system = lib.mkDefault system; - }; - }; - - eval = lib.evalModules (builtins.removeAttrs args [ "lib" "inputs" "pkgs" "system" ] // { - modules = modules ++ [ argsModule pkgsModule ] ++ baseModules; + eval = lib.evalModules (builtins.removeAttrs args [ "lib" ] // { + modules = modules ++ [ argsModule ] ++ baseModules; specialArgs = { modulesPath = builtins.toString ./modules; } // specialArgs; }); in @@ -4,22 +4,36 @@ outputs = { self, nixpkgs }: { lib = { - # TODO handle multiple architectures. - evalConfig = import ./eval-config.nix { inherit (nixpkgs) lib; }; - - darwinSystem = - { modules, inputs ? { } - , system ? throw "darwin.lib.darwinSystem now requires 'system' to be passed explicitly" - , ... - }@args: - self.lib.evalConfig (args // { - inherit system; - inputs = { inherit nixpkgs; darwin = self; } // inputs; - modules = modules ++ [ self.darwinModules.flakeOverrides ]; - }); + evalConfig = import ./eval-config.nix; + + darwinSystem = args@{ modules, ... }: self.lib.evalConfig ( + { inherit (nixpkgs) lib; } + // nixpkgs.lib.optionalAttrs (args ? pkgs) { inherit (args.pkgs) lib; } + // builtins.removeAttrs args [ "system" "pkgs" "inputs" ] + // { + modules = modules + ++ nixpkgs.lib.optional (args ? pkgs) ({ lib, ... }: { + _module.args.pkgs = lib.mkForce args.pkgs; + }) + # Backwards compatibility shim; TODO: warn? + ++ nixpkgs.lib.optional (args ? system) ({ lib, ... }: { + nixpkgs.system = lib.mkDefault args.system; + }) + # Backwards compatibility shim; TODO: warn? + ++ nixpkgs.lib.optional (args ? inputs) { + _module.args.inputs = args.inputs; + } + ++ [ ({ lib, ... }: { + nixpkgs.source = lib.mkDefault nixpkgs; + + system.checks.verifyNixPath = lib.mkDefault false; + + system.darwinVersionSuffix = ".${self.shortRev or "dirty"}"; + system.darwinRevision = lib.mkIf (self ? rev) self.rev; + }) ]; + }); }; - darwinModules.flakeOverrides = ./modules/system/flake-overrides.nix; darwinModules.hydra = ./modules/examples/hydra.nix; darwinModules.lnl = ./modules/examples/lnl.nix; darwinModules.ofborg = ./modules/examples/ofborg.nix; @@ -32,8 +46,10 @@ checks = nixpkgs.lib.genAttrs ["aarch64-darwin" "x86_64-darwin"] (system: let simple = self.lib.darwinSystem { - inherit system; - modules = [ self.darwinModules.simple ]; + modules = [ + self.darwinModules.simple + { nixpkgs.hostPlatform = system; } + ]; }; in { simple = simple.system; diff --git a/modules/documentation/default.nix b/modules/documentation/default.nix index 4a4bcdc..2f3bb9a 100644 --- a/modules/documentation/default.nix +++ b/modules/documentation/default.nix @@ -1,4 +1,4 @@ -toplevel@{ config, lib, pkgs, baseModules, modules, ... }: +{ config, lib, pkgs, baseModules, modules, ... }: with lib; @@ -25,15 +25,7 @@ let inherit pkgs config; version = config.system.darwinVersion; revision = config.system.darwinRevision; - nixpkgsRevision = - if toplevel.options.system.nixpkgsRevision.isDefined - then config.system.nixpkgsRevision - - # If user does not use flakes and does not add rev to nixpkgs, we don't - # know which revision or even branch they're on. In this case we still want - # to link somewhere, so we hope that master hasn't changed too much. - else "master"; - + inherit (config.system) nixpkgsRevision; options = let scrubbedEval = evalModules { @@ -54,7 +46,7 @@ let # TODO: Remove this when dropping 22.11 support. manual = realManual // - lib.optionalAttrs (lib.versionOlder lib.version "23.05-pre") rec { + lib.optionalAttrs (!pkgs.buildPackages ? nixos-render-docs) rec { optionsJSON = pkgs.writeTextFile { name = "options.json-stub"; destination = "/share/doc/darwin/options.json"; diff --git a/modules/examples/flake/flake.nix b/modules/examples/flake/flake.nix index 0ada852..bacdcf5 100644 --- a/modules/examples/flake/flake.nix +++ b/modules/examples/flake/flake.nix @@ -1,9 +1,9 @@ { - description = "Example darwin system flake"; + description = "Example Darwin system flake"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs"; - darwin.url = "github:lnl7/nix-darwin"; + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + darwin.url = "github:LnL7/nix-darwin"; darwin.inputs.nixpkgs.follows = "nixpkgs"; }; @@ -30,6 +30,9 @@ # Used for backwards compatibility, please read the changelog before changing. # $ darwin-rebuild changelog system.stateVersion = 4; + + # The platform the configuration will be used on. + nixpkgs.hostPlatform = "x86_64-darwin"; }; in { @@ -37,7 +40,6 @@ # $ darwin-rebuild build --flake .#simple darwinConfigurations."simple" = darwin.lib.darwinSystem { modules = [ configuration ]; - system = "x86_64-darwin"; }; # Expose the package set, including overlays, for convenience. diff --git a/modules/nix/nixpkgs.nix b/modules/nix/nixpkgs.nix index 77f69b2..52aec9a 100644 --- a/modules/nix/nixpkgs.nix +++ b/modules/nix/nixpkgs.nix @@ -1,8 +1,53 @@ -{ config, lib, pkgs, ... }: +{ config, options, lib, pkgs, ... }: with lib; let + + # Backport from Nixpkgs 23.05 + defaultOverridePriority = + lib.modules.defaultOverridePriority or lib.modules.defaultPriority; + + # Backport from Nixpkgs 23.11 + mergeAttrDefinitionsWithPrio = lib.mergeAttrDefinitionsWithPrio or (opt: + let + # Inlined to avoid warning about using internal APIs 🥴 + pushDownProperties = cfg: + if cfg._type or "" == "merge" then + concatMap pushDownProperties cfg.contents + else if cfg._type or "" == "if" then + map (mapAttrs (n: v: mkIf cfg.condition v)) (pushDownProperties cfg.content) + else if cfg._type or "" == "override" then + map (mapAttrs (n: v: mkOverride cfg.priority v)) (pushDownProperties cfg.content) + else # FIXME: handle mkOrder? + [ cfg ]; + + defsByAttr = + lib.zipAttrs ( + lib.concatLists ( + lib.concatMap + ({ value, ... }@def: + map + (lib.mapAttrsToList (k: value: { ${k} = def // { inherit value; }; })) + (pushDownProperties value) + ) + opt.definitionsWithLocations + ) + ); + in + assert opt.type.name == "attrsOf" || opt.type.name == "lazyAttrsOf"; + lib.mapAttrs + (k: v: + let merging = lib.mergeDefinitions (opt.loc ++ [k]) opt.type.nestedTypes.elemType v; + in { + value = merging.mergedValue; + inherit (merging.defsFinal') highestPrio; + }) + defsByAttr); + + cfg = config.nixpkgs; + opt = options.nixpkgs; + isConfig = x: builtins.isAttrs x || lib.isFunction x; @@ -16,26 +61,27 @@ let lhs = optCall lhs_ { inherit pkgs; }; rhs = optCall rhs_ { inherit pkgs; }; in - lhs // rhs // + recursiveUpdate lhs rhs // optionalAttrs (lhs ? packageOverrides) { packageOverrides = pkgs: optCall lhs.packageOverrides pkgs // - optCall (attrByPath ["packageOverrides"] ({}) rhs) pkgs; + optCall (attrByPath [ "packageOverrides" ] { } rhs) pkgs; } // optionalAttrs (lhs ? perlPackageOverrides) { perlPackageOverrides = pkgs: optCall lhs.perlPackageOverrides pkgs // - optCall (attrByPath ["perlPackageOverrides"] ({}) rhs) pkgs; + optCall (attrByPath [ "perlPackageOverrides" ] { } rhs) pkgs; }; configType = mkOptionType { - name = "nixpkgs config"; + name = "nixpkgs-config"; + description = "nixpkgs config"; check = x: let traceXIfNot = c: if c x then true else lib.traceSeqN 1 x false; in traceXIfNot isConfig; - merge = args: fold (def: mergeConfig def.value) {}; + merge = args: foldr (def: mergeConfig def.value) {}; }; overlayType = mkOptionType { @@ -44,72 +90,260 @@ let check = lib.isFunction; merge = lib.mergeOneOption; }; + + # TODO: Remove backwards compatibility hack when dropping + # 22.11 support. + pkgsType = types.pkgs or (types.uniq types.attrs) // { + # This type is only used by itself, so let's elaborate the description a bit + # for the purpose of documentation. + description = "An evaluation of Nixpkgs; the top level attribute set of packages"; + }; + + hasBuildPlatform = opt.buildPlatform.highestPrio < (mkOptionDefault {}).priority; + hasHostPlatform = opt.hostPlatform.isDefined; + hasPlatform = hasHostPlatform || hasBuildPlatform; + + # Context for messages + hostPlatformLine = optionalString hasHostPlatform "${showOptionWithDefLocs opt.hostPlatform}"; + buildPlatformLine = optionalString hasBuildPlatform "${showOptionWithDefLocs opt.buildPlatform}"; + + legacyOptionsDefined = + optional (opt.system.highestPrio < (mkDefault {}).priority) opt.system + ; + + defaultPkgs = + if opt.hostPlatform.isDefined + then + let isCross = cfg.buildPlatform != cfg.hostPlatform; + systemArgs = + if isCross + then { + localSystem = cfg.buildPlatform; + crossSystem = cfg.hostPlatform; + } + else { + localSystem = cfg.hostPlatform; + }; + in + import cfg.source ({ + inherit (cfg) config overlays; + } // systemArgs) + else + import cfg.source { + inherit (cfg) config overlays; + localSystem = { inherit (cfg) system; }; + }; + + finalPkgs = if opt.pkgs.isDefined then cfg.pkgs.appendOverlays cfg.overlays else defaultPkgs; + in { - options = { - nixpkgs.config = mkOption { + options.nixpkgs = { + pkgs = mkOption { + type = pkgsType; + example = literalExpression "import <nixpkgs> {}"; + description = lib.mdDoc '' + If set, the pkgs argument to all nix-darwin modules is the value of + this option, extended with `nixpkgs.overlays`, if + that is also set. The nix-darwin and Nixpkgs architectures must + match. Any other options in `nixpkgs.*`, notably `config`, + will be ignored. + + The default value imports the Nixpkgs from + [](#opt-nixpkgs.source). The `config`, `overlays`, `localSystem`, + and `crossSystem` are based on this option's siblings. + + This option can be used to increase + the performance of evaluation, or to create packages that depend + on a container that should be built with the exact same evaluation + of Nixpkgs, for example. Applications like this should set + their default value using `lib.mkDefault`, so + user-provided configuration can override it without using + `lib`. + ''; + }; + + config = mkOption { default = {}; example = literalExpression '' - { firefox.enableGeckoMediaPlayer = true; - packageOverrides = pkgs: { - firefox60Pkgs = pkgs.firefox60Pkgs.override { - enableOfficialBranding = true; - }; - }; - } + { allowBroken = true; allowUnfree = true; } ''; type = configType; description = lib.mdDoc '' The configuration of the Nix Packages collection. (For details, see the Nixpkgs documentation.) It allows you to set - package configuration options, and to override packages - globally through the {var}`packageOverrides` - option. The latter is a function that takes as an argument - the *original* Nixpkgs, and must evaluate - to a set of new or overridden packages. + package configuration options. + + Ignored when `nixpkgs.pkgs` is set. ''; }; - nixpkgs.overlays = mkOption { - type = types.listOf overlayType; + overlays = mkOption { default = []; - example = literalExpression '' - [ (self: super: { - openssh = super.openssh.override { - hpnSupport = true; - withKerberos = true; - kerberos = self.libkrb5; - }; - }; - ) ] - ''; + example = literalExpression + '' + [ + (self: super: { + openssh = super.openssh.override { + hpnSupport = true; + kerberos = self.libkrb5; + }; + }) + ] + ''; + type = types.listOf overlayType; description = lib.mdDoc '' List of overlays to use with the Nix Packages collection. (For details, see the Nixpkgs documentation.) It allows - you to override packages globally. This is a function that + you to override packages globally. Each function in the list takes as an argument the *original* Nixpkgs. The first argument should be used for finding dependencies, and the second should be used for overriding recipes. + + If `nixpkgs.pkgs` is set, overlays specified here + will be applied after the overlays that were already present + in `nixpkgs.pkgs`. + ''; + }; + + hostPlatform = mkOption { + type = types.either types.str types.attrs; # TODO utilize lib.systems.parsedPlatform + example = { system = "aarch64-darwin"; config = "aarch64-apple-darwin"; }; + # Make sure that the final value has all fields for sake of other modules + # referring to this. TODO make `lib.systems` itself use the module system. + apply = lib.systems.elaborate; + description = lib.mdDoc '' + Specifies the platform where the nix-darwin configuration will run. + + To cross-compile, set also `nixpkgs.buildPlatform`. + + Ignored when `nixpkgs.pkgs` is set. + ''; + }; + + buildPlatform = mkOption { + type = types.either types.str types.attrs; # TODO utilize lib.systems.parsedPlatform + default = cfg.hostPlatform; + example = { system = "x86_64-darwin"; config = "x86_64-apple-darwin"; }; + # Make sure that the final value has all fields for sake of other modules + # referring to this. + apply = lib.systems.elaborate; + defaultText = literalExpression + ''config.nixpkgs.hostPlatform''; + description = lib.mdDoc '' + Specifies the platform on which nix-darwin should be built. + By default, nix-darwin is built on the system where it runs, but you can + change where it's built. Setting this option will cause nix-darwin to be + cross-compiled. + + For instance, if you're doing distributed multi-platform deployment, + or if you're building machines, you can set this to match your + development system and/or build farm. + + Ignored when `nixpkgs.pkgs` is set. ''; }; - nixpkgs.system = mkOption { + system = mkOption { type = types.str; example = "x86_64-darwin"; + default = + if opt.hostPlatform.isDefined + then + throw '' + Neither ${opt.system} nor any other option in nixpkgs.* is meant + to be read by modules and configurations. + Use pkgs.stdenv.hostPlatform instead. + '' + else + throw '' + Neither ${opt.hostPlatform} nor the legacy option ${opt.system} has been set. + The option ${opt.system} is still fully supported for interoperability, + but will be deprecated in the future, so we recommend to set ${opt.hostPlatform}. + ''; + defaultText = lib.literalMD '' + Traditionally `builtins.currentSystem`, but unset when invoking nix-darwin through `lib.darwinSystem`. + ''; description = lib.mdDoc '' - Specifies the Nix platform type for which NixOS should be built. - If unset, it defaults to the platform type of your host system. - Specifying this option is useful when doing distributed - multi-platform deployment, or when building virtual machines. + Specifies the Nix platform type on which nix-darwin should be built. + It is better to specify `nixpkgs.hostPlatform` instead. + + Ignored when `nixpkgs.pkgs` or `nixpkgs.hostPlatform` is set. + ''; + }; + + # nix-darwin only + + source = mkOption { + type = types.path; + defaultText = literalMD '' + `<nixpkgs>` or nix-darwin's `nixpkgs` flake input + ''; + description = lib.mdDoc '' + The path to import Nixpkgs from. If you're setting a custom + [](#opt-nixpkgs.pkgs) or `_module.args.pkgs`, setting this + to something with `rev` and `shortRev` attributes (such as a + flake input or `builtins.fetchGit` result) will also set + `system.nixpkgsRevision` and related options. + (nix-darwin only) + ''; + }; + + constructedByUs = mkOption { + type = types.bool; + internal = true; + description = '' + Whether `pkgs` was constructed by this module. This is false when any of + `nixpkgs.pkgs` or `_module.args.pkgs` is set. (nix-darwin only) ''; }; }; config = { + _module.args = { + pkgs = + # We explicitly set the default override priority, so that we do not need + # to evaluate finalPkgs in case an override is placed on `_module.args.pkgs`. + # After all, to determine a definition priority, we need to evaluate `._type`, + # which is somewhat costly for Nixpkgs. With an explicit priority, we only + # evaluate the wrapper to find out that the priority is lower, and then we + # don't need to evaluate `finalPkgs`. + lib.mkOverride defaultOverridePriority + finalPkgs.__splicedPackages; + }; - # _module.args.pkgs is defined in ../../eval-config.nix + nixpkgs.constructedByUs = + # We set it with default priority and it can not be merged, so if the + # pkgs module argument has that priority, it's from us. + (mergeAttrDefinitionsWithPrio options._module.args).pkgs.highestPrio + == defaultOverridePriority + # Although, if nixpkgs.pkgs is set, we did forward it, but we did not construct it. + && !opt.pkgs.isDefined; + assertions = [ + ( + let + pkgsSystem = finalPkgs.stdenv.targetPlatform.system; + in { + assertion = cfg.constructedByUs -> !hasPlatform -> cfg.system == pkgsSystem; + message = "The nix-darwin nixpkgs.pkgs option was set to a Nixpkgs invocation that compiles to target system ${pkgsSystem} but nix-darwin was configured for system ${darwinExpectedSystem} via nix-darwin option nixpkgs.system. The nix-darwin system settings must match the Nixpkgs target system."; + } + ) + { + assertion = cfg.constructedByUs -> hasPlatform -> legacyOptionsDefined == []; + message = '' + Your system configures nixpkgs with the platform parameter${optionalString hasBuildPlatform "s"}: + ${hostPlatformLine + }${buildPlatformLine + } + However, it also defines the legacy options: + ${concatMapStrings showOptionWithDefLocs legacyOptionsDefined} + For a future proof system configuration, we recommend to remove + the legacy definitions. + ''; + } + ]; }; } diff --git a/modules/system/flake-overrides.nix b/modules/system/flake-overrides.nix deleted file mode 100644 index df3eb16..0000000 --- a/modules/system/flake-overrides.nix +++ /dev/null @@ -1,20 +0,0 @@ -{ lib, inputs, ... }: - -with lib; - -let - inherit (inputs) darwin nixpkgs; -in - -{ - config = { - system.checks.verifyNixPath = mkDefault false; - system.checks.verifyNixChannels = mkDefault false; - - system.darwinVersionSuffix = ".${darwin.shortRev or "dirty"}"; - system.darwinRevision = mkIf (darwin ? rev) darwin.rev; - - system.nixpkgsVersionSuffix = ".${substring 0 8 (nixpkgs.lastModifiedDate or nixpkgs.lastModified or "19700101")}.${nixpkgs.shortRev or "dirty"}"; - system.nixpkgsRevision = mkIf (nixpkgs ? rev) nixpkgs.rev; - }; -} diff --git a/modules/system/version.nix b/modules/system/version.nix index 6801918..e45f667 100644 --- a/modules/system/version.nix +++ b/modules/system/version.nix @@ -1,4 +1,4 @@ -{ options, config, lib, pkgs, ... }: +{ options, config, lib, ... }: with lib; @@ -7,27 +7,28 @@ let defaultStateVersion = options.system.stateVersion.default; - parseGit = path: - if pathExists "${path}/.git" then rec { - rev = commitIdFromGitRepo "${path}/.git"; - shortRev = substring 0 7 rev; - } - else if pathExists "${path}/.git-revision" then rec { - rev = fileContents "${path}/.git-revision"; - shortRev = substring 0 7 rev; - } - else { - shortRev = "0000000"; - }; - - darwin = parseGit (toString ../..); - nixpkgs = parseGit (toString pkgs.path); - - releaseFile = "${toString pkgs.path}/.version"; - suffixFile = "${toString pkgs.path}/.version-suffix"; - - nixpkgsSuffix = if pathExists suffixFile then fileContents suffixFile - else ".git." + nixpkgs.shortRev; + # Based on `lib.trivial.revisionWithDefault` from nixpkgs. + gitRevision = path: + if pathIsGitRepo "${path}/.git" + then commitIdFromGitRepo "${path}/.git" + else if pathExists "${path}/.git-revision" + then fileContents "${path}/.git-revision" + else null; + + nixpkgsSrc = config.nixpkgs.source; + + # If `nixpkgs.constructedByUs` is true, then Nixpkgs was imported from + # `nixpkgs.source` and we can use revision information (flake input, + # `builtins.fetchGit`, etc.) from it. Otherwise `pkgs` could be + # anything and we can't reliably determine exact version information, + # but if the configuration explicitly sets `nixpkgs.source` we + # trust it. + useSourceRevision = + (config.nixpkgs.constructedByUs + || options.nixpkgs.source.highestPrio < (lib.mkDefault {}).priority) + && isAttrs nixpkgsSrc + && (nixpkgsSrc._type or null == "flake" + || isString (nixpkgsSrc.rev or null)); in { @@ -56,62 +57,67 @@ in system.darwinVersion = mkOption { internal = true; type = types.str; - description = lib.mdDoc "The full darwin version (e.g. `darwin4.master`)."; + default = "darwin${toString cfg.stateVersion}${cfg.darwinVersionSuffix}"; + description = lib.mdDoc "The full darwin version (e.g. `darwin4.2abdb5a`)."; }; system.darwinVersionSuffix = mkOption { internal = true; type = types.str; + default = if cfg.darwinRevision != null + then ".${substring 0 7 cfg.darwinRevision}" + else ""; description = lib.mdDoc "The short darwin version suffix (e.g. `.2abdb5a`)."; }; system.darwinRevision = mkOption { internal = true; - type = types.str; - default = "master"; + type = types.nullOr types.str; + default = gitRevision (toString ../..); description = lib.mdDoc "The darwin git revision from which this configuration was built."; }; system.nixpkgsRelease = mkOption { readOnly = true; type = types.str; + default = lib.trivial.release; description = lib.mdDoc "The nixpkgs release (e.g. `16.03`)."; }; system.nixpkgsVersion = mkOption { internal = true; type = types.str; + default = cfg.nixpkgsRelease + cfg.nixpkgsVersionSuffix; description = lib.mdDoc "The full nixpkgs version (e.g. `16.03.1160.f2d4ee1`)."; }; system.nixpkgsVersionSuffix = mkOption { internal = true; type = types.str; + default = if useSourceRevision + then ".${lib.substring 0 8 (nixpkgsSrc.lastModifiedDate or nixpkgsSrc.lastModified or "19700101")}.${nixpkgsSrc.shortRev or "dirty"}" + else lib.trivial.versionSuffix; description = lib.mdDoc "The short nixpkgs version suffix (e.g. `.1160.f2d4ee1`)."; }; system.nixpkgsRevision = mkOption { internal = true; - type = types.str; + type = types.nullOr types.str; + default = if useSourceRevision && nixpkgsSrc ? rev + then nixpkgsSrc.rev + else lib.trivial.revisionWithDefault null; description = lib.mdDoc "The nixpkgs git revision from which this configuration was built."; }; }; config = { - - # These defaults are set here rather than up there so that - # changing them would not rebuild the manual + # This default is set here rather than up there so that the options + # documentation is not reprocessed on every commit system.darwinLabel = mkDefault "${cfg.nixpkgsVersion}+${cfg.darwinVersion}"; - system.darwinVersion = mkDefault "darwin${toString cfg.stateVersion}${cfg.darwinVersionSuffix}"; - system.darwinVersionSuffix = mkDefault ".${darwin.shortRev}"; - system.darwinRevision = mkIf (darwin ? rev) (mkDefault darwin.rev); - - system.nixpkgsVersion = mkDefault "${cfg.nixpkgsRelease}${cfg.nixpkgsVersionSuffix}"; - system.nixpkgsRelease = mkDefault (fileContents releaseFile); - system.nixpkgsVersionSuffix = mkDefault nixpkgsSuffix; - system.nixpkgsRevision = mkIf (nixpkgs ? rev) (mkDefault nixpkgs.rev); - - assertions = [ { assertion = cfg.stateVersion <= defaultStateVersion; message = "system.stateVersion = ${toString cfg.stateVersion}; is not a valid value"; } ]; + assertions = [ { + assertion = cfg.stateVersion <= defaultStateVersion; + message = "system.stateVersion = ${toString cfg.stateVersion}; is not a valid value"; + } ]; }; } |
