Skip to content
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

Closed
wants to merge 1 commit into from
Closed

nixos/default.nix: accept build and host arguments #246690

wants to merge 1 commit into from

Conversation

ghost
Copy link

@ghost ghost commented Aug 2, 2023

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!):

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 build builtins.currentSystem \
  --arg host '(import ./lib).systems.examples.octeon'

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.

  • The default value for host is build.
  • The default value for build is builtins.localSystem.

So

  • --arg build foo by itself gives you native foo-build
  • --arg host foo by itself gives you cross builds using builtins.currentSystem as the buildPlatform and foo as the hostPlatform.
  • Both --arg build and --arg host together let you specify any kind of build (most explicit form). In particular, if you have remote builders whose builtins.currentSystem doesn't match your local machine's builtins.currentSystem, you want to use this form.

Things done

  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandbox = true set in nix.conf? (See Nix manual)
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 23.11 Release Notes (or backporting 23.05 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

@github-actions github-actions bot added the 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS label Aug 2, 2023
@ghost ghost added 6.topic: cross-compilation Building packages on a different platform than they will be used on 6.topic: installer Related to graphical Calamares Installer labels Aug 2, 2023
@ghost ghost marked this pull request as ready for review August 2, 2023 02:45
@ghost ghost requested a review from infinisil as a code owner August 2, 2023 02:45
@ghost ghost changed the title nixos/default.nix: accept buildPlatform and hostPlatform arguments nixos/default.nix: accept build and host arguments Aug 2, 2023
@ofborg ofborg bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin 10.rebuild-linux: 1-10 labels Aug 2, 2023
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.
@Artturin Artturin requested a review from roberth August 2, 2023 22:16
Copy link
Member

@roberth roberth left a 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

  1. The command line interface isn't declarative. You write something, something happens and then what you wrote is gone.

  2. 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).

  3. 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.

  4. 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)

@roberth
Copy link
Member

roberth commented Aug 3, 2023

Independently of this pr, I'd like to leave you with something actionable.
To achieve your goal of making images more accessible, I can think of two avenues:

  • Improve documentation; make it more file based
  • Write a scaffolding tool for image configurations.

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.

@ghost
Copy link
Author

ghost commented Aug 5, 2023

Nowadays the platforms are configured automatically in hardware-configuration.nix,

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.

To achieve your goal of making images more accessible

My goal is to be able to pass a buildPlatform and hostPlatform to nixpkgs when building a NixOS installer.

  • Improve documentation; make it more file based

That's nice, but not really relevant to my goal here.

  • Write a scaffolding tool for image configurations.

That is quite an unreasonable demand. Launch an entire project simply to pass two arguments to nixpkgs? Be serious.

@ghost
Copy link
Author

ghost commented Aug 5, 2023

Also,

$ nixos image generate
> This wizard generates an image-configuration.nix file in $PWD

> Where would you like to run the image?

Barf. So we're not allowed to cross compile nixos installers noninteractively?

Copy link
Member

@samueldr samueldr left a 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).

@samueldr
Copy link
Member

samueldr commented Aug 5, 2023

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.

@ghost
Copy link
Author

ghost commented Aug 5, 2023

I think @roberth is right here, though removing system as a whole will be a breaking change,

... 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.

@ghost ghost closed this Aug 5, 2023
@ghost ghost deleted the pr/nixos/toplevel/cross branch August 5, 2023 21:11
@samueldr
Copy link
Member

samueldr commented Aug 6, 2023

I was responding to this bit by @roberth:

I suggest we deprecate the system parameter instead. (and remove build, host, and lib)

Maybe you need to read and/or understand his comment.

This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
6.topic: cross-compilation Building packages on a different platform than they will be used on 6.topic: installer Related to graphical Calamares Installer 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin 10.rebuild-linux: 1-10
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants