Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
in
{
lib = lib.extend (final: prev: {

nixos = import ./nixos/lib { lib = final; };

nixosSystem = { modules, ... } @ args:
import ./nixos/lib/eval-config.nix (args // {
modules =
Expand Down
33 changes: 33 additions & 0 deletions nixos/lib/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
let
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Are you sure this is the right place for evaluating NixOS? I'd have expected this to be in nixos/default.nix (but I know that place is already used). Maybe someone else has a good idea but this location makes it seem like importing that file gives me library functions around NixOS and not NixOS

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It is not great, I admit, and as you've noted that's mostly due to nixos/default.nix being taken. I've considered turning the existing nixos/default.nix into a __functor, but I've seen the command line tools behave weird around __functor and I don't want to touch such an essential file for an experimental feature.

I've also considered nixos/eval-config.nix. While familiarity is good, it is too easily confused with nixos/lib/eval-config.nix, which behaves rather differently, both wrt module list and a ton of legacy behavior we don't need.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What about nixos/minimal-eval.nix?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nixos/minimal-eval.nix does sound less confusing. or maybe nixos/lib/minimal-eval.nix? anything that doesn't break the pattern of import ./lib pulling in all lib functions, really.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

anything that doesn't break the pattern of import ./lib pulling in all lib functions

Actually, that's exactly what this is doing, when looking at the flake.nix change. Its lib.nixos is simply this file.
So then it should be lib/default.nix and the fact that the functions are about minimal evaluation is currently a coincidence.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

from the angle of what the flake exports you're totally right. but there's a lot of other stuff in nixos/lib (like that now-standard eval-config.nix) that isn't available from import ./nixos/lib. so i guess it's fine either way, and we retract the suggestion.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Right, I now better understand your suggestion. Depending on whether those are intended for "public" consumption, the functions in those other files can later be exposed through nixos/lib/default.nix or moved to a nixos/common directory where exposure is not desirable.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we have nixos/lib/eval-config.nix, so I would propose nixos/lib/eval-config-minimal.nix. Also nixos/lib/eval-config.nix should be using nixos/lib/eval-config-minimal.nix, so prove it is minimal and therefore the status quo cna be built on top of it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I've moved the implementation as @Ericson2314 suggested, kept nixos/lib/default.nix for the purpose of being lib.nixos in the flake and anyone who likes the lib style.

I'm undecided whether it only proves a point or whether it should be a requirement. If we find a reason to disconnect the two, proving a point shouldn't stop us from doing that. I can imagine that we find a useful change along the way, that we don't want to apply to conventional NixOS, yet I do hope the two can remain as similar as possible.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah if we have need to direct them, sure. I am not yet familiar with the more ambitious plans discussed before.

# The warning is in a top-level let binding so it is only printed once.
minimalModulesWarning = warn "lib.nixos.evalModules is experimental and subject to change. See nixos/lib/default.nix" null;
inherit (nonExtendedLib) warn;
nonExtendedLib = import ../../lib;
in
{ # Optional. Allows an extended `lib` to be used instead of the regular Nixpkgs lib.
lib ? nonExtendedLib,

# Feature flags allow you to opt in to unfinished code. These may change some
# behavior or disable warnings.
featureFlags ? {},

# This file itself is rather new, so we accept unknown parameters to be forward
# compatible. This is generally not recommended, because typos go undetected.
...
}:
let
seqIf = cond: if cond then builtins.seq else a: b: b;
# If cond, force `a` before returning any attr
seqAttrsIf = cond: a: lib.mapAttrs (_: v: seqIf cond a v);

eval-config-minimal = import ./eval-config-minimal.nix { inherit lib; };
in
/*
This attribute set appears as lib.nixos in the flake, or can be imported
using a binding like `nixosLib = import (nixpkgs + "/nixos/lib") { }`.
*/
{
inherit (seqAttrsIf (!featureFlags?minimalModules) minimalModulesWarning eval-config-minimal)
evalModules
;
}
49 changes: 49 additions & 0 deletions nixos/lib/eval-config-minimal.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

# DO NOT IMPORT. Use nixpkgsFlake.lib.nixos, or import (nixpkgs + "/nixos/lib")
{ lib }: # read -^

let

/*
Invoke NixOS. Unlike traditional NixOS, this does not include all modules.
Any such modules have to be explicitly added via the `modules` parameter,
or imported using `imports` in a module.

A minimal module list improves NixOS evaluation performance and allows
modules to be independently usable, supporting new use cases.

Parameters:

modules: A list of modules that constitute the configuration.

specialArgs: An attribute set of module arguments. Unlike
`config._module.args`, these are available for use in
`imports`.
`config._module.args` should be preferred when possible.

Return:

An attribute set containing `config.system.build.toplevel` among other
attributes. See `lib.evalModules` in the Nixpkgs library.

*/
evalModules = {
prefix ? [],
modules ? [],
specialArgs ? {},
}:
# NOTE: Regular NixOS currently does use this function! Don't break it!
# Ideally we don't diverge, unless we learn that we should.
# In other words, only the public interface of nixos.evalModules
# is experimental.
lib.evalModules {
inherit prefix modules;
specialArgs = {
modulesPath = builtins.toString ../modules;
} // specialArgs;
};

in
{
inherit evalModules;
}
12 changes: 8 additions & 4 deletions nixos/lib/eval-config.nix
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ let pkgs_ = pkgs;
in

let
evalModulesMinimal = (import ./default.nix {
inherit lib;
# Implicit use of feature is noted in implementation.
featureFlags.minimalModules = { };
}).evalModules;

pkgsModule = rec {
_file = ./eval-config.nix;
key = _file;
Expand Down Expand Up @@ -70,11 +76,9 @@ let
};
allUserModules = modules ++ legacyModules;

noUserModules = lib.evalModules ({
inherit prefix;
noUserModules = evalModulesMinimal ({
inherit prefix specialArgs;
modules = baseModules ++ extraModules ++ [ pkgsModule modulesModule ];
specialArgs =
{ modulesPath = builtins.toString ../modules; } // specialArgs;
});

# Extra arguments that are useful for constructing a similar configuration.
Expand Down
5 changes: 5 additions & 0 deletions nixos/modules/misc/nixpkgs.nix
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ let
in

{
imports = [
./assertions.nix
./meta.nix
];

options.nixpkgs = {

pkgs = mkOption {
Expand Down
8 changes: 8 additions & 0 deletions nixos/modules/misc/nixpkgs/test.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{ evalMinimalConfig, pkgs, lib, stdenv }:
lib.recurseIntoAttrs {
invokeNixpkgsSimple =
(evalMinimalConfig ({ config, modulesPath, ... }: {
imports = [ (modulesPath + "/misc/nixpkgs.nix") ];
nixpkgs.system = stdenv.hostPlatform.system;
}))._module.args.pkgs.hello;
}
8 changes: 8 additions & 0 deletions nixos/tests/all-tests.nix
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ let
handleTestOn = systems: path: args:
if elem system systems then handleTest path args
else {};

nixosLib = import ../lib {
# Experimental features need testing too, but there's no point in warning
# about it, so we enable the feature flag.
featureFlags.minimalModules = {};
};
evalMinimalConfig = module: nixosLib.evalModules { modules = [ module ]; };
in
{
_3proxy = handleTest ./3proxy.nix {};
Expand Down Expand Up @@ -327,6 +334,7 @@ in
nix-serve-ssh = handleTest ./nix-serve-ssh.nix {};
nixops = handleTest ./nixops/default.nix {};
nixos-generate-config = handleTest ./nixos-generate-config.nix {};
nixpkgs = pkgs.callPackage ../modules/misc/nixpkgs/test.nix { inherit evalMinimalConfig; };
node-red = handleTest ./node-red.nix {};
nomad = handleTest ./nomad.nix {};
novacomd = handleTestOn ["x86_64-linux"] ./novacomd.nix {};
Expand Down