nixos/default.nix: accept build and host arguments#246690
Conversation
It is now possible to cross compile the *entire* NixOS installer image (see #194153). Unfortunately the incantation for doing this is quite awkward and cryptic (it took me many tries to come up with something that worked!): ``` nix-build nixos \ -A config.system.build.sdImage \ --arg configuration '{config,lib,pkgs,...}@Args: (import ./nixos/modules/installer/sd-card/sd-image-mips64el.nix args) // { nixpkgs.hostPlatform = lib.systems.examples.octeon; nixpkgs.buildPlatform = builtins.currentSystem; }' ``` That last line is pretty un-user-friendly. Let's give *optional* command line arguments `build` and `host` (just like `./configure`) to `nixos/default.nix`, so users can instead type something more readable: ``` nix-build nixos \ -A config.system.build.sdImage \ -I nixos-config=nixos/modules/installer/sd-card/sd-image-mips64el.nix \ --arg host '(import ./lib).systems.examples.octeon' ``` Note that `--arg system` will request a native build, which will fail unless you are using remote builders. Also, it will never produce a cross-compiled build. Using `--arg host` and `--arg build` provides more intuitive behavior, and is the only way to get cross-compiled builds.
roberth
left a comment
There was a problem hiding this comment.
Unfortunately this is a change in the wrong direction, which makes the use of NixOS less declarative and harder to learn.
This is based on a couple of observations
-
The command line interface isn't declarative. You write something, something happens and then what you wrote is gone.
-
Declarative doesn't just imply things like pure functions and hermeticity, but also composition. CLI arguments don't compose with modules, unless you bridge them generically, which I wouldn't recommend because of (1).
-
All additions are a liability and a burden on new users. Let's keep it simple. As the author of the comments in
eval-config.nixputs it:system can be set modularly, would be nice to remove, however, removing or changing this default is too much of a breaking change.
-
Functions also ruin composition and are therefore not declarative. (Like (2) but without the difference in modality)
Instead I suggest we double down on declaring things in files.
Nowadays the platforms are configured automatically in hardware-configuration.nix, so even non-flake users could use system = null;...
If you want to compile a configuration using a builder of a different platform, you should specify it in your configuration file, because it is a significant change that you should track in a file! Many packages are a bit different when cross compiled due to various shortcuts that had to be taken in those package definitions. Notably almost all packages won't run any tests. In other cases, generated docs or completion scripts will be missing.
Finally, there's a learning benefit. Instead of learning CLI flags, we teach users to use options, empowering them to make other changes without burdening them with unnecessary learning material.
I suggest we deprecate the system parameter instead. (and remove build, host, and lib)
|
Independently of this pr, I'd like to leave you with something actionable.
Such a tool has the potential to be even easier to use than the otherwise still cryptic command line, while providing the user with a file that contains their image configuration for further improvement and later reuse. $ nixos image generate
> This wizard generates an image-configuration.nix file in $PWD
> Where would you like to run the image?
> - ENTER for x86_64-linux, your current platform
> - or type examples if you'd like to pick from the list of preconfigured platforms
Configured nixpkgs.hostPlatform = "x86_64-linux";
> Where would you like to build the image? (ENTER for x86_64-linux, your current platform)
Configured nixpkgs.buildPlatform = "x86_64-linux";
> What installation media?
> 1. sd image
> 2. netboot
> ...
> n. kexec tarball
1
Configured system.build.image = config.system.build.sdImage;
> Configuration generated in ./image-configuration.nix
> Build it with
> nixos image build -f ./image-configuration.nixAnd best of all it coexists with the NixOS configuration system instead of fighting it. |
That's fine if you've already installed your system, but how are you supposed to specify a cross-compilation target when building the installer? It seems like your first review comment was written without noticing this. Your second comment appears to have been written after realizing that this is all about building the installer. @samueldr objected to passing these values as module parameters. It seems that you are insisting that I do so. I don't care which approach, but it looks like the two of you disagree about this.
My goal is to be able to pass a
That's nice, but not really relevant to my goal here.
That is quite an unreasonable demand. Launch an entire project simply to pass two arguments to |
|
Also,
Barf. So we're not allowed to cross compile nixos installers noninteractively? |
samueldr
left a comment
There was a problem hiding this comment.
I am also thinking that this change is unneeded, we already have a way to configure NixOS builds, it's the modules system.
For example, currently as things are (and were), nothing stops the current image building from being used declaratively for building cross-built images more succintly:
(Note that this is still using
nixpkgs.crossSystem.systemsince this is from before the deprecation of it, but the same overall mechanisms can be used with the newer semantics. It's been a while since I had to build a cross-compiled image.)
I think @roberth is right here, though removing system as a whole will be a breaking change, which would require some thought to handle a deprecation period first. Otherwise removing that input from <nixpkgs/nixos/default.nix> is a good thing imo. Having only configuration as an input shows that yes, this is the only way to configure NixOS behaviours.
Though against @roberth's ideations here, I wouldn't even talk about image generation here, it only serves to make the discussion harder with entirely orthogonal and way more complex and nuanced topics.
Image generation implementation is an entirely unique topic, and then having an approachable UX for that is another entirely independent thing (though requires having the proper semantics in image building to make things possible).
|
As for objecting, I objected to cross-compilation being the pre-configured semantics in the image generation. That's because every one of those image builders are made under the assumption that they are done through a native build. Though I left unsaid that if needed, a cross-compilation can be configured within the modules system. |
... which this PR does not do. Since this PR now has two reviews by people who don't seem to have read and/or understood the diff, I need to make a time management decision and focus on other things. |
|
I was responding to this bit by @roberth:
Maybe you need to read and/or understand his comment. |
Description of changes
It is now possible to cross compile the entire NixOS installer image (see #194153). This means you can do builds for every platform at the speed of your fastest builders, no matter what architecture they belong to.
Unfortunately the incantation for doing this is quite awkward and cryptic (it took me many tries to come up with something that worked!):
That last line is pretty un-user-friendly.
Let's give optional command line arguments
buildandhost(just like./configure) tonixos/default.nix, so users can instead type something more readable:Note that
--arg systemwill always produce a native build, never a cross build. This will fail unless you are using remote builders (or unless you pass--arg system builtins.currentSystem, in which case the argument is pointless).Using
--arg hostand--arg buildprovides more intuitive behavior, and is the only way to get cross-compiled builds.hostisbuild.buildisbuiltins.localSystem.So
--arg build fooby itself gives you nativefoo-build--arg host fooby itself gives you cross builds usingbuiltins.currentSystemas thebuildPlatformandfooas thehostPlatform.--arg buildand--arg hosttogether let you specify any kind of build (most explicit form). In particular, if you have remote builders whosebuiltins.currentSystemdoesn't match your local machine'sbuiltins.currentSystem, you want to use this form.Things done
sandbox = trueset innix.conf? (See Nix manual)nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/)