Skip to content

Commit 7b5cdd9

Browse files
Mic92mergify[bot]
authored andcommitted
add support for foreigen guest-system
On macos this allows us the following: ./bin/nixos-shell --build-system aarch64-darwin --guest-system riscv64-linux examples/vm.nix This is not doing any cross-compilation, meaning the host machine needs to have a remote builder setup.
1 parent b7e8a0c commit 7b5cdd9

File tree

4 files changed

+57
-31
lines changed

4 files changed

+57
-31
lines changed

bin/nixos-shell

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ usage() {
1414
vm.nix" 1>&2
1515
}
1616

17-
nixos_config=vm.nix
17+
nixos_config=
1818
while [[ $# -gt 0 ]]; do
1919
i="$1"; shift 1
2020
case "$i" in
@@ -40,21 +40,35 @@ while [[ $# -gt 0 ]]; do
4040
--show-trace|--keep-failed|-K|--keep-going|-k|--verbose|-v|-vv|-vvv|-vvvv|-vvvvv|--fallback|--repair|-L|--refresh|--no-net|--impure)
4141
extraBuildFlags+=("$i")
4242
;;
43+
--guest-system)
44+
j="$1"; shift 1
45+
extraBuildFlags+=("--argstr" "guestSystem" "$j")
46+
;;
47+
--host-system)
48+
j="$1"; shift 1
49+
extraBuildFlags+=("--argstr" "hostSystem" "$j")
50+
;;
4351
--option)
4452
j="$1"; shift 1
4553
k="$1"; shift 1
4654
extraBuildFlags+=("$i" "$j" "$k")
4755
;;
4856
*)
57+
if [[ -n "$nixos_config" ]]; then
58+
usage
59+
exit 1
60+
fi
4961
nixos_config="$i"
5062
;;
5163
esac
5264
done
65+
nixos_config=${nixos_config:-vm.nix}
5366

5467
unset NIXOS_CONFIG
5568

5669
if [[ -z "$flake_uri" ]]; then
5770
extraBuildFlags+=(
71+
--extra-experimental-features "nix-command"
5872
-I "nixos-config=$nixos_config"
5973
)
6074
else

share/modules/nixos-shell-config.nix

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
let
44
cfg = config.nixos-shell;
5-
5+
home = builtins.getEnv "HOME";
66
mkVMDefault = lib.mkOverride 900;
77
in {
88
config =
@@ -23,9 +23,6 @@ in {
2323
})
2424

2525
(
26-
let
27-
home = builtins.getEnv "HOME";
28-
in
2926
lib.mkIf (home != "" && cfg.mounts.mountHome) {
3027
users.extraUsers.root.home = lib.mkVMOverride home;
3128
}
@@ -75,16 +72,16 @@ in {
7572
"-mon chardev=char0,mode=readline"
7673
"-device virtconsole,chardev=char0,nr=0"
7774
] ++
78-
lib.optional cfg.mounts.mountHome "-virtfs local,path=/home,security_model=none,mount_tag=home" ++
75+
lib.optional cfg.mounts.mountHome "-virtfs local,path=${home},security_model=none,mount_tag=home" ++
7976
lib.optional (cfg.mounts.mountNixProfile && builtins.pathExists nixProfile) "-virtfs local,path=${nixProfile},security_model=none,mount_tag=nixprofile" ++
8077
lib.mapAttrsToList (target: mount: "-virtfs local,path=${builtins.toString mount.target},security_model=none,mount_tag=${mount.tag}") cfg.mounts.extraMounts;
8178
};
8279

8380
# build-vm overrides our filesystem settings in nixos-config
8481
boot.initrd.postMountCommands =
8582
(lib.optionalString cfg.mounts.mountHome ''
86-
mkdir -p $targetRoot/home/
87-
mount -t 9p home $targetRoot/home/ -o trans=virtio,version=9p2000.L,cache=${cfg.mounts.cache},msize=${toString config.virtualisation.msize}
83+
mkdir -p $targetRoot/${lib.escapeShellArg home}
84+
mount -t 9p home $targetRoot/${lib.escapeShellArg home} -o trans=virtio,version=9p2000.L,cache=${cfg.mounts.cache},msize=${toString config.virtualisation.msize}
8885
'') +
8986
(lib.optionalString (user != "" && cfg.mounts.mountNixProfile) ''
9087
mkdir -p $targetRoot/nix/var/nix/profiles/per-user/${user}/profile/
@@ -97,6 +94,12 @@ in {
9794
'')
9895
cfg.mounts.extraMounts);
9996

97+
# avoid leaking incompatible host binaries into the VM
98+
system.activationScripts.shadow-nix-profile = lib.mkIf (options.virtualisation.host.pkgs.isDefined && config.virtualisation.host.pkgs.stdenv.hostPlatform != pkgs.stdenv.hostPlatform) (lib.stringAfter [ "specialfs" "users" "groups" ] ''
99+
mkdir -p ${lib.escapeShellArg home}/.nix-profile/
100+
mount --bind ${config.system.path} ${lib.escapeShellArg home}/.nix-profile/
101+
'');
102+
100103
environment = {
101104
systemPackages = with pkgs; [
102105
xterm # for resize command

share/modules/nixos-shell.nix

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{ lib, modulesPath, pkgs, extendModules, ... }:
1+
{ lib, pkgs, modulesPath, config, options, extendModules, ... }:
22

33
{
44
imports = [
@@ -15,13 +15,14 @@
1515
in {
1616
mountHome = mkOption {
1717
type = types.bool;
18-
default = true;
19-
description = "Whether to mount `/home`.";
18+
default = builtins.getEnv "HOME" != "";
19+
description = "Whether to mount `$HOME`.";
2020
};
2121

2222
mountNixProfile = mkOption {
2323
type = types.bool;
24-
default = true;
24+
# if our host os does not match the guest os, binaries in our nix profile will not work
25+
default = options.virtualisation.host.pkgs.isDefined && config.virtualisation.host.pkgs.stdenv.hostPlatform != pkgs.stdenv.hostPlatform;
2526
description = "Whether to mount the user's nix profile.";
2627
};
2728

share/nixos-shell.nix

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,47 @@
11
{ nixpkgs ? <nixpkgs>
2-
, system ? builtins.currentSystem
2+
, guestSystem ? builtins.currentSystem
3+
, hostSystem ? builtins.currentSystem
34
, configuration ? <nixos-config>
4-
55
, flakeStr ? null # flake as named on the command line
66
, flakeUri ? null
77
, flakeAttr ? null
88
}:
99
let
10-
lib = flake.inputs.nixpkgs.lib or (import nixpkgs { }).lib;
10+
hasFlake = flakeUri != null;
1111

1212
defaultTo = default: e: if e == null then default else e;
1313

14-
getFlakeOutput = path: lib.attrByPath path null flake.outputs;
15-
16-
mkShellSystem = config: import "${if !(flakeUri == null) then (toString flake.inputs.nixpkgs) else (toString nixpkgs)}/nixos/lib/eval-config.nix" {
17-
inherit system;
18-
modules = [
19-
config
20-
./modules/nixos-shell.nix
21-
./modules/nixos-shell-config.nix
22-
];
23-
};
24-
2514
flake = builtins.getFlake flakeUri;
2615

27-
flakeSystem = defaultTo
28-
(getFlakeOutput [ "nixosConfigurations" "${flakeAttr}" ])
29-
(getFlakeOutput [ "packages" "${system}" "nixosConfigurations" "${flakeAttr}" ]);
30-
31-
flakeModule = getFlakeOutput [ "nixosModules" "${flakeAttr}" ];
16+
getFlakeOutput = path: flake.inputs.nixpkgs.lib.attrByPath path null flake.outputs;
3217

3318
nixosShellModules = [
19+
({lib, ...}: lib.optionalAttrs (guestSystem != hostSystem) {
20+
virtualisation.host.pkgs = if hasFlake then
21+
flake.inputs.nixpkgs.legacyPackages.${hostSystem}
22+
else
23+
import nixpkgs { system = hostSystem; };
24+
})
3425
./modules/nixos-shell.nix
3526
./modules/nixos-shell-config.nix
3627
];
28+
29+
nixpkgsPath = if hasFlake then
30+
flake.inputs.nixpkgs
31+
else
32+
nixpkgs;
33+
34+
mkShellSystem = config: import "${toString nixpkgsPath}/nixos/lib/eval-config.nix" {
35+
system = guestSystem;
36+
modules = [ config ] ++ nixosShellModules;
37+
};
38+
39+
flakeSystem = defaultTo
40+
(getFlakeOutput [ "nixosConfigurations" flakeAttr ])
41+
(getFlakeOutput [ "packages" guestSystem "nixosConfigurations" flakeAttr ]);
42+
43+
flakeModule = getFlakeOutput [ "nixosModules" "${flakeAttr}" ];
44+
3745
in
3846
if flakeUri != null then
3947
if flakeSystem != null then

0 commit comments

Comments
 (0)