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-generate-config: add Rust stub with tests #91353
Conversation
@@ -0,0 +1 @@ | |||
use nix |
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.
This one should also go away.
]; | ||
|
||
buildPhase = '' | ||
ln -sfn ${vendoredCrates}/vendor/ vendor |
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.
See Ma, no cursed fixed-input derivation!
f3cd2d2
to
9fcf18f
Compare
9fcf18f
to
1b7dc49
Compare
Also dropped some unnecessary/one-off imports (such as `use std::string::String`, which is included in the default prelude). For rationale around using write{,ln}! over print{,ln}!, see BurntSushi/advent-of-code#17 -- print! and friends can panic.
I don't see us needing any additional binaries for this, so a folder dedicated to a single binary seems weird.
Because we print the binary name and the relevant error when e.g. `show_help()` or `parse_options()` errors out, we don't need to add the binary name to the error message until we're ready to print it.
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.
Already pinged you over there, but just wanted to make it more obvious to any onlookers -- PR'd some Rust changes to your branch.
show_hardware_config: false, | ||
show_help: false, | ||
}; | ||
loop { |
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.
Did you consider clap
or if you are really against a lot of dependencies perhaps getopts
? Nice thing about clap
is that it can also generate shell completions for you, etc. Plus has nice usage information.
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.
Yeah, I thought about that. Maybe later right now I think it quite significantly adds libraries that we would not have otherwise. And we don't need that many options right now. The current variant is more or less bug compatible with the old code.
@@ -0,0 +1,79 @@ | |||
with import <nixpkgs> {}; |
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.
Instead of relying on a channel, shouldn't this become with import ../../../.. {};
(or whatever the correct level of nesting is)?
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.
Ideally this should be some sort of callPackage
invocation rather than re-importing nixpkgs.
I might add a shell.nix convenience wrapper though for incremental compilation.
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.
This should be a "normal" function like every other package; it shouldn't import nixpkgs at all. Also it shouldn't need a separate shell.nix
, since nix-shell '<nixpkgs/nixos>' -A config.system.build.nixos-generate-config
should work.
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.
Ok. I will document the use of nix-shell
than in a small hacking guide.
# FIXME: | ||
# move nixos-generate-config manpages out of this since users can disable manpages | ||
# and updating manpages generate unnecessary rebuild of this package itself. | ||
nixos-manpages = (import <nixpkgs/nixos> {}).config.system.build.manual.manpages; |
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.
Same here.
I don't think anyone ever mentioned Nim before. To me Nim seems a good alternative to Rust and NimScript (an interpretable subset of Nim) for other scripts. NimScript can also, like Python, be used on e.g. Windows, so it could be very interesting as a stdenv language. Anyway, I'm not saying we should change. I think this here is fine. |
Cannot say much about the language - I assume the binaries will be a bit larger due larger runtime support. However portability is not really a concern since |
$out/bin/nixos-generate-config | ||
''; | ||
|
||
NIXOS_MANPAGES = "${nixos-manpages}/share/man"; |
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.
IMHO this derivation shouldn't install manpages at all, it creates a collision if both config.system.build.manual.manpages
and config.system.build.nixos-generate-config
install the same manpage.
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.
It actually does not, it only capture the path to config.system.build.manual.manpages
, the man page should not be propagated to the nix profile.
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 will decouple this from the binary eventually and move it to an environment variable so that generating a new manpage does not trigger a rebuild of this executable.
let status = try_with!( | ||
Command::new(MAN_EXECUTABLE) | ||
.arg("nixos-generate-config") | ||
.env("MANPATH", NIXOS_MANPAGES) |
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.
Just call man nixos-generate-config
here without MANPATH
.
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.
This would break unit tests and adds minor impurities to nixos-generate-config
. Are you sure about that, given that it should generate any conflict? #91353 (comment)
@@ -0,0 +1,11 @@ | |||
[package] | |||
name = "nixos-generate-config" |
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 think we should have a single crate (and binary) for the Rust NixOS tools. That should cut down on the binary size if we rewrite nixos-rebuild, nixos-install, switch-to-configuration etc. in Rust.
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 thought about the same. A multi-call binary could be added in the future to cover that.
I would leave the tools separate though and have multiple crates that may share common utility crates. But this can be also discussed once we add more Rust ports.
This will greatly hurt the efforts of having the installation image be cross-compilable, until rust cross-compilation works as simply as Being able to cross-compile the image is pretty important to get people started on some platforms. On armv7l, there is simply no cache, so it's the main option available here. On aarch64, there is a cache, but sometimes you're stuck between a rock and a hard place. Let's take for example the Pine64 Pinebook Pro, where at first you needed a kernel with some additions (that were on the path to mainline). Without cross-compiling, it would have been extremely hard for some users to get started in a trustful manner. To help with this, a simple enough expression builds the base image, either natively or cross. No, using the community box is not a good solution, it cannot be trusted. This is why I believe it's important that, for the installer images, we need to be mindful to not add additional hurdles for cross-compilation. For the record, I'm totally fine with Rust, I'd even say I prefer Rust to many other alternatives. But any solution will have to cross-compile (or be trivial to disable, but that's a loss in functionality). (I'm assuming the language selection is an implementation detail, and not a high level design choice.) |
We put some effort into cross-compiling rust in the past, did it broke again? I can have a look at this. I can assure you for sure that the cross compiling story for rust is a lot saner than for perl. It is supported by cargo and since this is the defacto standard one does not have to fix every single package. We also enabled |
I will say that I haven't looked at it since earlier this year, and my lack of experience with Rust may have caused me to do wrong things. But when I tried things with cross-compilation and rust it didn't work as expected. I don't know that right now it is an issue, but I wanted to make my concern known. I don't really know either how to test this correctly :). |
Inspired by crate2nix from @kolloch, I added https://tera.netlify.app/docs as a template engine. |
boot.initrd.kernelModules = {{ initrd_kernel_modules }}; | ||
boot.kernelModules = {{ kernel_modules }}; | ||
boot.extraModulePackages = {{ module_packages }}; | ||
{%- for fs in filesystems %} |
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 would say this is more readable than the concatenation that was used before.
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.
While I don't wish to oppose the use of this Tera, I wonder whether the standard fmt
module would be enough. Was it already tried and determined not to suffice? If not, here's a rough but runnable sketch in the Rust Playground of how this could look.
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 don't think it support loops? This is actually my only concern because we need to do string concatenation again which is not very readable. I will reconsider it later if the binary size is considered too large.
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 had hoped it would be comparably readable to Tera, but it didn't turn out as well as I'd hoped. The explicit string concatenation (line 56) could be replaced with Itertools::format
(adjusted Playground sketch). Using that itertools method for the loop (and also to simplify the Display
implementation for NixList
) increases the number of lines of assembly code to which this minimal example compiles by 11%; presumably the effect would be proportionally smaller for a real program — but then I don't wager Tera will be large enough to be a problem.
Perhaps the largest difference to me between the two approaches (to be clear, I don't mean to say either is superior for it) is that in the Tera templates one has the structure of the output file and loop logic inlined together whereas with fmt
parts of the output file such as the list of filesystems necessarily get broken out, like smaller functions being factored out of a larger function.
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 think the size increase of tera is also due to other crates being linked in, which might end up using later as well i.e. serde. It's good to have an alternative but first I would prioritize finishing the prototype first.
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.
Is there a checklist tracking the progress of this prototype?
I've looked at the original post at the top of the PR but it's unclear what is and isn't complete (or at least implemented and might need future tweaks)
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.
It's not usable yet. I will post updates as I add new features.
I marked this as stale due to inactivity. → More info |
still relevant. |
Relevant is #109094 which would also add rust to the nixos build closure. I think this is a good step to take now, many people know how to write Rust and it’s a very nice language with good stdlib. |
@Mic92 Just wondering what changed since 24 Jan Is this no-longer of use? |
@06kellyjac it would be still nice to have but I don't think I will have time any time soon to actually work on this. |
Motivation for this change
The goal of this PR is:
Please use this PR only for code review and discuss high-level design choices in RFC 70