From c001ad7f51c0e2f7daba6ac7ff0c235fdaebe7ed Mon Sep 17 00:00:00 2001 From: Niklas Gollenstede Date: Sun, 5 Feb 2023 22:59:39 +0100 Subject: [PATCH] small fixes, esp. for cross-building --- lib/flakes.nix | 13 +++++----- lib/scripts.nix | 2 +- lib/setup-scripts/install.sh | 22 ++++++++++------ lib/setup-scripts/maintenance.sh | 41 ++++++++++++++---------------- lib/setup-scripts/utils.sh | 6 +++++ modules/base.nix.md | 7 +++-- modules/bootloader/extlinux.nix.md | 2 +- modules/fs/disks.nix.md | 12 ++++----- modules/vm-exec.nix.md | 31 ++++++++++++++++------ overlays/libubootenv.nix.md | 4 +-- overlays/uboot-with-mmc-env.nix.md | 2 +- 11 files changed, 83 insertions(+), 59 deletions(-) diff --git a/lib/flakes.nix b/lib/flakes.nix index 282bd49..b549c1f 100644 --- a/lib/flakes.nix +++ b/lib/flakes.nix @@ -77,13 +77,14 @@ in rec { entryPath ? null, config ? null, preface ? null, inputs ? { }, overlays ? (getOverlaysFromInputs inputs), modules ? (getModulesFromInputs inputs), peers ? { }, nixosSystem ? inputs.nixpkgs.lib.nixosSystem, localSystem ? null, + renameOutputs ? (name: null), # If not supplied (explicitly or as »false« by »mkSystemsFlake«), assume the system is not exported. ... }: let preface = args.preface or (getSystemPreface inputs entryPath (specialArgs // { inherit name; })); targetSystem = "${preface.hardware}-linux"; buildSystem = if localSystem != null then localSystem else targetSystem; specialArgs = (args.specialArgs or { }) // { nodes = peers; # NixOPS }; - outputName = if args?renameOutputs then args.renameOutputs name else name; + outputName = if renameOutputs != false then renameOutputs name else name; in let system = { inherit preface; } // (nixosSystem { system = buildSystem; # (this actually does nothing more than setting »config.nixpkgs.system« and can be null here) @@ -190,9 +191,9 @@ in rec { # If provided, then cross compilation is enabled for all hosts whose target architecture is different from this. Since cross compilation currently fails for (some stuff in) NixOS, better don't set »localSystem«. Without it, building for other platforms works fine (just slowly) if »boot.binfmt.emulatedSystems« on the building system is configured for the respective target(s). localSystem ? null, ## If provided, then change the name of each output attribute by passing it through this function. Allows exporting of multiple variants of a repo's hosts from a single flake: - renameOutputs ? null, + renameOutputs ? false, ... }: let - otherArgs = args // { inherit inputs overlays modules specialArgs nixosSystem localSystem; }; + otherArgs = args // { inherit inputs overlays modules specialArgs nixosSystem localSystem renameOutputs; }; nixosConfigurations = if builtins.isList systems then mergeAttrsUnique (map (systems: mkNixosConfigurations (otherArgs // systems)) systems) else mkNixosConfigurations (otherArgs // systems); in let outputs = { inherit nixosConfigurations; @@ -207,11 +208,11 @@ in rec { packages.all-systems = pkgs.runCommandLocal "all-systems" { } '' ${'' mkdir -p $out/systems - ${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: system: "ln -sT ${system.config.system.build.toplevel} $out/systems/${name}") nixosConfigurations)} + ${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: system: "ln -sT ${system.config.system.build.toplevel} $out/systems/${if renameOutputs == false then name else renameOutputs name}") nixosConfigurations)} ''} ${'' mkdir -p $out/scripts - ${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: system: "ln -sT ${outputs.apps.${localSystem}.${name}.program} $out/scripts/${name}") nixosConfigurations)} + ${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: system: "ln -sT ${outputs.apps.${localSystem}.${name}.program} $out/scripts/${if renameOutputs == false then name else renameOutputs name}") nixosConfigurations)} ''} ${lib.optionalString (inputs != { }) '' mkdir -p $out/inputs @@ -220,7 +221,7 @@ in rec { ''; checks.all-systems = packages.all-systems; - })); in if renameOutputs == null then outputs else { + })); in if renameOutputs == false then outputs else { nixosConfigurations = mapMerge (k: v: { ${renameOutputs k} = v; }) outputs.nixosConfigurations; } // (forEachSystem [ "aarch64-linux" "x86_64-linux" ] (localSystem: { apps = mapMerge (k: v: { ${renameOutputs k} = v; }) outputs.apps.${localSystem}; diff --git a/lib/scripts.nix b/lib/scripts.nix index 7d87e48..fc85ff5 100644 --- a/lib/scripts.nix +++ b/lib/scripts.nix @@ -98,7 +98,7 @@ in rec { wrap-script = args@{ pkgs, src, deps, ... }: let name = args.name or (builtins.baseNameOf (builtins.unsafeDiscardStringContext "${src}")); in pkgs.runCommandLocal name { - script = src; nativeBuildInputs = [ pkgs.makeWrapper ]; + script = src; nativeBuildInputs = [ pkgs.buildPackages.makeWrapper ]; } ''makeWrapper $script $out/bin/${name} --prefix PATH : ${lib.makeBinPath deps}''; # Simplifies a path (or any other string) such that it can be used as a systemd unit name. diff --git a/lib/setup-scripts/install.sh b/lib/setup-scripts/install.sh index c6dfabb..f4ba3b9 100644 --- a/lib/setup-scripts/install.sh +++ b/lib/setup-scripts/install.sh @@ -16,12 +16,13 @@ function prepare-installer { # (void) : ${argv[0]:?"Required: Target disk or image paths."} + umask g-w,o-w # Ensure that files created without explicit permissions are not writable for group and other (0022). + if [[ "$(id -u)" != '0' ]] ; then if [[ ! ${args[no-vm]:-} ]] ; then reexec-in-qemu || return ; \exit 0 ; fi echo 'Script must be run as root or in qemu (without »--no-vm«).' 1>&2 ; \return 1 fi if [[ ${args[vm]:-} ]] ; then reexec-in-qemu || return ; \exit 0 ; fi - umask 0022 # Ensure consistent umask (default permissions for new files). if [[ -e "/run/keystore-@{config.networking.hostName!hashString.sha256:0:8}" ]] ; then echo "Keystore »/run/keystore-@{config.networking.hostName!hashString.sha256:0:8}/« is already open. Close it and remove the mountpoint before running the installer." 1>&2 ; \return 1 ; fi @@ -33,7 +34,7 @@ function prepare-installer { # (void) if @{native.zfs}/bin/zfs get -o value -H name "$poolName" &>/dev/null ; then echo "ZFS pool »$poolName« is already imported. Export the pool before running the installer." 1>&2 ; \return 1 ; fi done - if [[ ${SUDO_USER:-} ]] ; then # use Nix as the user who called this script, as Nix may not be set up for root + if [[ ${SUDO_USER:-} && $( PATH=$hostPath which su 2>/dev/null ) ]] ; then # use Nix as the user who called this script, as Nix may not be set up for root function nix {( set +x ; declare -a args=("$@") ; PATH=$hostPath su - "$SUDO_USER" -c "$(declare -p args)"' ; nix "${args[@]}"' )} else # use Nix by absolute path, as it won't be on »$PATH« PATH=$PATH:@{native.nix}/bin @@ -50,6 +51,8 @@ function prepare-installer { # (void) ## Re-executes the current system's installation in a qemu VM. function reexec-in-qemu { + if [[ @{pkgs.buildPackages.system} != "@{native.system}" ]] ; then echo "VM installation (implicit when not running as root) of a system built on a different ISA than the current host's is not supported (yet)." 1>&2 ; \return 1 ; fi + # (not sure whether this works for block devices) ensure-disks "${argv[0]}" 1 || return qemu=( -m 2048 ) ; declare -A qemuDevs=( ) @@ -65,16 +68,19 @@ function reexec-in-qemu { let index+=1 done - args[vm]='' + args[vm]='' ; args[no-vm]=1 newArgs=( ) ; for arg in "${!args[@]}" ; do newArgs+=( --"$arg"="${args[$arg]}" ) ; done devSpec= ; for name in "${!qemuDevs[@]}" ; do devSpec+="$name"="${qemuDevs[$name]}": ; done newArgs+=( ${devSpec%:} ) ; (( ${#argv[@]} > 1 )) && args+=( "${argv[@]:1}" ) #local output=@{inputs.self}'#'nixosConfigurations.@{outputName:?}.config.system.build.vmExec - local output=@{config.system.build.vmExec.drvPath} # this is more accurate, but also means another system needs to get evaluated every time - local command="$0 install-system $( printf '%q ' "${newArgs[@]}" ) || exit" + local output=@{config.system.build.vmExec.drvPath!unsafeDiscardStringContext} # this is more accurate, but also means another system needs to get evaluated every time + local scripts=$0 ; if [[ @{pkgs.system} != "@{native.system}" ]] ; then + scripts=$( build-lazy @{inputs.self}'#'apps.@{pkgs.system}.@{outputName:?}.derivation ) + fi + local command="$scripts install-system $( printf '%q ' "${newArgs[@]}" ) || exit" - local runInVm ; runInVm=$( @{native.nix}/bin/nix --extra-experimental-features nix-command build --no-link --json ${args[quiet]:+--quiet} $output | @{native.jq}/bin/jq -r .[0].outputs.out )/bin/run-@{config.system.name}-vm-exec || return + local runInVm ; runInVm=$( build-lazy $output )/bin/run-@{config.system.name}-vm-exec || return $runInVm ${args[vm-shared]:+--shared="${args[vm-shared]}"} ${args[debug]:+--initrd-console} ${args[trace]:+--initrd-console} ${args[quiet]:+--quiet} -- "$command" "${qemu[@]}" || return # --initrd-console } @@ -118,8 +124,8 @@ function install-system-to {( set -u # 1: mnt # Support cross architecture installation (not sure if this is actually required) if [[ $(cat /run/current-system/system 2>/dev/null || echo "x86_64-linux") != "@{config.wip.preface.hardware}"-linux ]] ; then - mkdir -p $mnt/run/binfmt || exit ; [[ ! -e /run/binfmt/"@{config.wip.preface.hardware}"-linux ]] || cp -a {,$mnt}/run/binfmt/"@{config.wip.preface.hardware}"-linux || exit - # Ubuntu (by default) expects the "interpreter" at »/usr/bin/qemu-@{config.wip.preface.hardware}-static«. + mkdir -p $mnt/run/binfmt || exit ; [[ ! -e /run/binfmt/"@{config.wip.preface.hardware}"-linux ]] || cp -a {,$mnt}/run/binfmt/"@{config.wip.preface.hardware}"-linux || exit # On NixOS, this is a symlink or wrapper script, pointing to the store. + # Ubuntu (20.04, by default) uses a statically linked, already loaded qemu binary (F-flag), which therefore does not need to be reference-able from within the chroot. fi # Copy system closure to new nix store: diff --git a/lib/setup-scripts/maintenance.sh b/lib/setup-scripts/maintenance.sh index 2f6781c..6f18076 100644 --- a/lib/setup-scripts/maintenance.sh +++ b/lib/setup-scripts/maintenance.sh @@ -54,7 +54,7 @@ function run-qemu { # 1: diskImages, ...: qemuArgs local qemu=( ) if [[ @{pkgs.system} == "@{native.system}" ]] ; then - qemu=( $( @{native.nix}/bin/nix --extra-experimental-features nix-command build --no-link --json @{native.qemu_kvm.drvPath} | @{native.jq}/bin/jq -r .[0].outputs.out )/bin/qemu-kvm ) || return + qemu=( $( build-lazy @{native.qemu_kvm.drvPath!unsafeDiscardStringContext} )/bin/qemu-kvm ) || return if [[ ! ${args[no-kvm]:-} && -r /dev/kvm && -w /dev/kvm ]] ; then # For KVM to work, vBox must not be running anything at the same time (and vBox hangs on start if qemu runs). Pass »--no-kvm« and accept ~10x slowdown, or stop vBox. qemu+=( -enable-kvm -cpu host ) @@ -64,32 +64,25 @@ function run-qemu { # 1: diskImages, ...: qemuArgs echo "KVM is not available (for the current user). Running without hardware acceleration." 1>&2 fi qemu+=( -machine accel=tcg ) # this may suppress warnings that qemu is using tcg (slow) instead of kvm - if [[ @{pkgs.system} == aarch64-* ]] ; then qemu+=( -cpu max ) ; fi - fi - if [[ @{pkgs.system} == aarch64-* ]] ; then - qemu+=( -machine type=virt -cpu max ) # aarch64 has no default, but this seems good fi else - qemu=( $( @{native.nix}/bin/nix --extra-experimental-features nix-command build --no-link --json @{native.qemu_full.drvPath} | @{native.jq}/bin/jq -r .[0].outputs.out )/bin/qemu-system-@{config.wip.preface.hardware} ) || return - if [[ @{config.wip.preface.hardware} == aarch64 ]] ; then # assume it's a raspberry PI (or compatible) - # TODO: this does not work yet: - qemu+=( -machine type=raspi3b -m 1024 ) ; args[no-nat]=1 - # ... and neither does this: - #qemu+=( -machine type=virt -m 1024 -smp 4 -cpu cortex-a53 ) ; args[no-nat]=1 - fi + qemu=( $( build-lazy @{native.qemu_full.drvPath!unsafeDiscardStringContext} )/bin/qemu-system-@{config.wip.preface.hardware} ) || return fi + if [[ @{pkgs.system} == aarch64-* ]] ; then + qemu+=( -machine type=virt ) # aarch64 has no default, but this seems good + fi ; qemu+=( -cpu max ) qemu+=( -m ${args[mem]:-2048} ) if [[ ${args[smp]:-} ]] ; then qemu+=( -smp ${args[smp]} ) ; fi if [[ @{config.boot.loader.systemd-boot.enable} || ${args[efi]:-} ]] ; then # UEFI. Otherwise it boots SeaBIOS. - local ovmf ; ovmf=$( @{native.nix}/bin/nix --extra-experimental-features nix-command build --no-link --json @{native.OVMF.drvPath} | @{native.jq}/bin/jq -r .[0].outputs.fd ) || return + local ovmf ; ovmf=$( build-lazy @{pkgs.OVMF.drvPath!unsafeDiscardStringContext} fd ) || return #qemu+=( -bios ${ovmf}/FV/OVMF.fd ) # This works, but is a legacy fallback that stores the EFI vars in /NvVars on the EFI partition (which is really bad). local fwName=OVMF ; if [[ @{pkgs.system} == aarch64-* ]] ; then fwName=AAVMF ; fi # fwName=QEMU qemu+=( -drive file=${ovmf}/FV/${fwName}_CODE.fd,if=pflash,format=raw,unit=0,readonly=on ) local efiVars=${args[efi-vars]:-${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/qemu-@{outputName:-@{config.system.name}}-VARS.fd} qemu+=( -drive file="$efiVars",if=pflash,format=raw,unit=1 ) - if [[ ! -e "$efiVars" ]] ; then cat ${ovmf}/FV/${fwName}_VARS.fd >"$efiVars" || return ; fi + if [[ ! -e "$efiVars" ]] ; then mkdir -pm700 "$( dirname "$efiVars" )" ; cat ${ovmf}/FV/${fwName}_VARS.fd >"$efiVars" || return ; fi # https://lists.gnu.org/archive/html/qemu-discuss/2018-04/msg00045.html fi # if [[ @{config.wip.preface.hardware} == aarch64 ]] ; then @@ -99,14 +92,18 @@ function run-qemu { # 1: diskImages, ...: qemuArgs if [[ $diskImages == */ ]] ; then disks=( ${diskImages}primary.img ) ; for name in "@{!config.wip.fs.disks.devices[@]}" ; do if [[ $name != primary ]] ; then disks+=( ${diskImages}${name}.img ) ; fi ; done else disks=( ${diskImages//:/ } ) ; fi + + [[ ' '"@{boot.initrd.availableKernelModules[@]}"' ' != *' 'virtio_blk' '* ]] || args[virtio-blk]=1 local index ; for index in ${!disks[@]} ; do # qemu+=( -drive format=raw,if=ide,file="${disks[$index]/*=/}" ) # »if=ide« is the default, which these days isn't great for driver support inside the VM - qemu+=( # not sure how correct the interpretations of the command are - -drive format=raw,file="${disks[$index]/*=/}",media=disk,if=none,index=${index},id=drive${index} # create the disk drive, without attaching it, name it driveX - #-device ahci,acpi-index=${index},id=ahci${index} # create an (ich9-)AHCI bus named »ahciX« - #-device ide-hd,drive=drive${index},bus=ahci${index}.${index} # attach IDE?! disk driveX as device X on bus »ahciX« - -device virtio-blk-pci,drive=drive${index},disable-modern=on,disable-legacy=off # alternative to the two lines above (implies to be faster, but seems to require guest drivers) - ) + qemu+=( -drive format=raw,file="${disks[$index]/*=/}",media=disk,if=none,index=${index},id=drive${index} ) # create the disk drive, without attaching it, name it driveX + + if [[ ! ${args[virtio-blk]:-} ]] ; then + qemu+=( -device ahci,acpi-index=${index},id=ahci${index} ) # create an (ich9-)AHCI bus named »ahciX« + qemu+=( -device ide-hd,drive=drive${index},bus=ahci${index}.${index} ) # attach IDE?! disk driveX as device X on bus »ahciX« + else + qemu+=( -device virtio-blk-pci,drive=drive${index},disable-modern=on,disable-legacy=off ) # this should be faster, but seems to require guest drivers + fi done if [[ ${args[share]:-} ]] ; then # e.g. --share='foo:/home/user/foo,readonly=on bar:/tmp/bar' @@ -144,8 +141,8 @@ function run-qemu { # 1: diskImages, ...: qemuArgs if [[ ! -e $disk ]] ; then args[install]=always ; fi done ; fi if [[ ${args[install]:-} == always ]] ; then - local verbosity=--quiet ; if [[ ${args[debug]:-} ]] ; then verbosity=--debug ; fi - ${args[dry-run]:+echo} $0 install-system "$diskImages" $verbosity --no-inspect || return + local verbosity=--quiet ; if [[ ${args[trace]:-} ]] ; then verbosity=--trace ; fi ; if [[ ${args[debug]:-} ]] ; then verbosity=--debug ; fi + hostPath=${hostPath:-} ${args[dry-run]:+echo} $0 install-system "$diskImages" $verbosity --no-inspect || return fi qemu+=( "${argv[@]}" ) diff --git a/lib/setup-scripts/utils.sh b/lib/setup-scripts/utils.sh index 9f365e8..451d9f0 100644 --- a/lib/setup-scripts/utils.sh +++ b/lib/setup-scripts/utils.sh @@ -102,3 +102,9 @@ function run-hook-script {( set -eu # 1: title, 2: scriptPath fi source "$2" )} + +## Lazily builds a nix derivation at run time, instead of when building the script. +# When maybe-using packages that take long to build, instead of »at{some.package.out}«, use: »$( build-lazy at{some.package.drvPath!unsafeDiscardStringContext} out )« +function build-lazy { # 1: drvPath, 2?: output + PATH=$PATH:@{native.openssh}/bin @{native.nix}/bin/nix --extra-experimental-features nix-command build --no-link --json ${args[quiet]:+--quiet} $1 | @{native.jq}/bin/jq -r .[0].outputs.${2:-out} +} diff --git a/modules/base.nix.md b/modules/base.nix.md index 1dff30e..2a67db7 100644 --- a/modules/base.nix.md +++ b/modules/base.nix.md @@ -23,10 +23,9 @@ in { bashInit = lib.mkEnableOption "pretty defaults for interactive bash shells" // { default = true; example = false; }; }; }; - # Bugfix: - imports = [ (lib.wip.overrideNixpkgsModule "misc/extra-arguments.nix" { } (old: { config._module.args.utils = old._module.args.utils // { - escapeSystemdPath = s: builtins.replaceStrings [ "/" "-" " " "." ] [ "-" "\\x2d" "\\x20" "\\x2e" ] (lib.removePrefix "/" s); # BUG(PR): The original function does not escape ».«, resulting in mismatching names with units generated from paths with ».« in them (e.g. overwrites for implicit mount units). - }; })) ]; + imports = lib.optional ((builtins.substring 0 5 inputs.nixpkgs.lib.version) <= "22.05") (lib.wip.overrideNixpkgsModule "misc/extra-arguments.nix" { } (old: { config._module.args.utils = old._module.args.utils // { + escapeSystemdPath = s: let n = builtins.replaceStrings [ "/" "-" " " ] [ "-" "\\x2d" "\\x20" ] (lib.removePrefix "/" s); in if lib.hasPrefix "." n then "\\x2e" (lib.substring 1 (lib.stringLength (n - 1)) n) else n; # (a better implementation has been merged in 22.11) + }; })); config = let diff --git a/modules/bootloader/extlinux.nix.md b/modules/bootloader/extlinux.nix.md index 81adc54..742d6e0 100644 --- a/modules/bootloader/extlinux.nix.md +++ b/modules/bootloader/extlinux.nix.md @@ -97,7 +97,7 @@ in { fi done if ! ${pkgs.gnugrep}/bin/grep -qP '^UI ' ${esc cfg.targetDir}/extlinux/extlinux.conf ; then # `extlinux-conf-builder` above would have recreated this, so the check should always be true - ${pkgs.perl}/bin/perl -i -pe 's/TIMEOUT/UI menu.c32\nTIMEOUT/' ${esc cfg.targetDir}/extlinux/extlinux.conf + ${pkgs.gnused}/bin/sed -i 's/^TIMEOUT /UI menu.c32\nTIMEOUT /' ${esc cfg.targetDir}/extlinux/extlinux.conf fi else : # delete library files? diff --git a/modules/fs/disks.nix.md b/modules/fs/disks.nix.md index 9a6fa96..af7aedf 100644 --- a/modules/fs/disks.nix.md +++ b/modules/fs/disks.nix.md @@ -71,18 +71,18 @@ in { fs.disks.partitioning = let partition-disk = { name = "partition-disk"; text = lib.wip.extractBashFunction (builtins.readFile lib.wip.setup-scripts.disk) "partition-disk"; }; - esc = lib.escapeShellArg; + esc = lib.escapeShellArg; native = pkgs.buildPackages; in pkgs.runCommand "partitioning-${config.networking.hostName}" { } '' - ${lib.wip.substituteImplicit { inherit pkgs; scripts = [ partition-disk ]; context = { inherit config; native = pkgs; }; }} # inherit (builtins) trace; + ${lib.wip.substituteImplicit { inherit pkgs; scripts = [ partition-disk ]; context = { inherit config native; }; }} # inherit (builtins) trace; set -u ; mkdir -p $out ; declare -A args=([debug]=1) ${lib.concatStrings (lib.mapAttrsToList (name: disk: '' name=${esc name} ; img=$name.img - ${pkgs.coreutils}/bin/truncate -s ${esc disk.size} "$img" + ${native.coreutils}/bin/truncate -s ${esc disk.size} "$img" partition-disk "$name" "$img" ${toString (lib.wip.parseSizeSuffix disk.size)} - ${pkgs.gptfdisk}/bin/sgdisk --backup=$out/"$name".backup "$img" - ${pkgs.gptfdisk}/bin/sgdisk --print "$img" >$out/"$name".gpt + ${native.gptfdisk}/bin/sgdisk --backup=$out/"$name".backup "$img" + ${native.gptfdisk}/bin/sgdisk --print "$img" >$out/"$name".gpt ${if disk.mbrParts != null then '' - ${pkgs.util-linux}/bin/fdisk --type mbr --list "$img" >$out/"$name".mbr + ${native.util-linux}/bin/fdisk --type mbr --list "$img" >$out/"$name".mbr '' else ""} '') cfg.devices)} ''; diff --git a/modules/vm-exec.nix.md b/modules/vm-exec.nix.md index e0dd744..c4bc312 100644 --- a/modules/vm-exec.nix.md +++ b/modules/vm-exec.nix.md @@ -29,23 +29,23 @@ nix run .../nixos-config'#'nixosConfigurations.${hostName}.config.system.build.v ```nix #*/# end of MarkDown, beginning of NixOS module: -dirname: inputs: { config, pkgs, lib, modulesPath, extendModules, ... }: let inherit (inputs.self) lib; in let +dirname: inputs: { config, options, pkgs, lib, modulesPath, extendModules, ... }: let inherit (inputs.self) lib; in let prefix = inputs.config.prefix; cfg = config.virtualisation.vmVariantExec; -in { +in let hostModule = { options = { virtualisation.vmVariantExec = lib.mkOption { description = lib.mdDoc ''Machine configuration to be added to the system's qemu exec VM.''; - inherit (extendModules { modules = [ "${modulesPath}/virtualisation/qemu-vm.nix" ]; }) type; + inherit (extendModules { modules = [ "${modulesPath}/virtualisation/qemu-vm.nix" vmModule ]; }) type; default = { }; visible = "shallow"; }; }; config = { - system.build.vmExec = (let vmPkgs = pkgs; in let + system.build.vmExec = (let hostPkgs = pkgs; in let name = "run-${config.system.name}-vm-exec"; launch = "${cfg.system.build.vm}/bin/${cfg.system.build.vm.meta.mainProgram}"; - pkgs = if cfg.virtualisation?host.pkgs then cfg.virtualisation.host.pkgs else vmPkgs; + pkgs = if cfg.virtualisation?host.pkgs then cfg.virtualisation.host.pkgs else hostPkgs; in pkgs.runCommand "nixos-vm" { preferLocalBuild = true; meta.mainProgram = name; } '' @@ -79,8 +79,11 @@ in { ''} $out/bin/${name} ''); + }; - } // { virtualisation.vmVariantExec = lib.mkMerge [ ({ +}; vmModule = { config, ... }: { + _file = "${dirname}/vm-exec.nix.md#vmModule"; + imports = [ ({ # Instead of tearing down the initrd environment, adjust some mounts and run the »command« in the initrd: boot.initrd.postMountCommands = '' @@ -150,9 +153,21 @@ in { }; }; virtualisation.diskSize = 4; #MB, not needed at all + }) ({ + + virtualisation = if (lib.fileContents "${pkgs.path}/.version") > "22.05" then { host.pkgs = pkgs.buildPackages; } else { }; + }) ({ + virtualisation.qemu.package = lib.mkIf (pkgs.buildPackages.system != pkgs.system) cfg.virtualisation.host.pkgs.qemu_full; + + }) ({ + + specialisation = lib.mkForce { }; + services.qemuGuest.enable = lib.mkForce false; + # tag this to make clearer what's what system.nixos.tags = [ "vmExec" ]; system.build.isVmExec = true; - }) ]; }; -} + }) ]; + +}; in hostModule diff --git a/overlays/libubootenv.nix.md b/overlays/libubootenv.nix.md index b7c9f28..a48c033 100644 --- a/overlays/libubootenv.nix.md +++ b/overlays/libubootenv.nix.md @@ -31,8 +31,8 @@ in { owner = "sbabic"; repo = pname; rev = "ba7564f5006d09bec51058cf4f5ac90d4dc18b3c"; # 2018-11-18 hash = "sha256-6cHkr3s7/2BVXBTn9bUfPFbYAfv9VYh6C9GAbWILNjs="; }; - nativeBuildInputs = [ pkgs.cmake ]; - buildInputs = [ pkgs.cmake pkgs.zlib ]; + nativeBuildInputs = [ pkgs.buildPackages.cmake ]; + buildInputs = [ pkgs.zlib ]; outputs = [ "out" "lib" ]; meta = { diff --git a/overlays/uboot-with-mmc-env.nix.md b/overlays/uboot-with-mmc-env.nix.md index 081d5d4..b737df3 100644 --- a/overlays/uboot-with-mmc-env.nix.md +++ b/overlays/uboot-with-mmc-env.nix.md @@ -35,7 +35,7 @@ in { # Creates a (user) env blob for this u-boot by merging »env« over its »defaultEnv«. The resulting file can be flashed to »CONFIG_ENV_OFFSET« to replace the default env. mkEnv = env: pkgs.runCommandLocal "uboot-env.img" { env = envTxt (defaultEnv' // env); - } "${pkgs.ubootTools}/bin/mkenvimage -p 0x00 -s ${toString envSize} -o $out $env"; + } "${pkgs.buildPackages.ubootTools}/bin/mkenvimage -p 0x00 -s ${toString envSize} -o $out $env"; }; extraConfig = (old.extraConfig or "") + "${lib.concatStringsSep "\n" ([