-
-
Notifications
You must be signed in to change notification settings - Fork 14.9k
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
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.nix
puts 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.nix And 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? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.system
since 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
build
andhost
(just like./configure
) tonixos/default.nix
, so users can instead type something more readable:Note that
--arg system
will 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 host
and--arg build
provides more intuitive behavior, and is the only way to get cross-compiled builds.host
isbuild
.build
isbuiltins.localSystem
.So
--arg build foo
by itself gives you nativefoo
-build--arg host foo
by itself gives you cross builds usingbuiltins.currentSystem
as thebuildPlatform
andfoo
as thehostPlatform
.--arg build
and--arg host
together let you specify any kind of build (most explicit form). In particular, if you have remote builders whosebuiltins.currentSystem
doesn't match your local machine'sbuiltins.currentSystem
, you want to use this form.Things done
sandbox = true
set 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/
)