small fixes, esp. for cross-building

This commit is contained in:
Niklas Gollenstede 2023-02-05 22:59:39 +01:00
parent 9edfe9c9d8
commit c001ad7f51
11 changed files with 83 additions and 59 deletions

View File

@ -77,13 +77,14 @@ in rec {
entryPath ? null, config ? null, preface ? null, entryPath ? null, config ? null, preface ? null,
inputs ? { }, overlays ? (getOverlaysFromInputs inputs), modules ? (getModulesFromInputs inputs), inputs ? { }, overlays ? (getOverlaysFromInputs inputs), modules ? (getModulesFromInputs inputs),
peers ? { }, nixosSystem ? inputs.nixpkgs.lib.nixosSystem, localSystem ? null, 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 ... }: let
preface = args.preface or (getSystemPreface inputs entryPath (specialArgs // { inherit name; })); preface = args.preface or (getSystemPreface inputs entryPath (specialArgs // { inherit name; }));
targetSystem = "${preface.hardware}-linux"; buildSystem = if localSystem != null then localSystem else targetSystem; targetSystem = "${preface.hardware}-linux"; buildSystem = if localSystem != null then localSystem else targetSystem;
specialArgs = (args.specialArgs or { }) // { specialArgs = (args.specialArgs or { }) // {
nodes = peers; # NixOPS 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 { in let system = { inherit preface; } // (nixosSystem {
system = buildSystem; # (this actually does nothing more than setting »config.nixpkgs.system« and can be null here) 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). # 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, 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: ## 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 ... }: 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); nixosConfigurations = if builtins.isList systems then mergeAttrsUnique (map (systems: mkNixosConfigurations (otherArgs // systems)) systems) else mkNixosConfigurations (otherArgs // systems);
in let outputs = { in let outputs = {
inherit nixosConfigurations; inherit nixosConfigurations;
@ -207,11 +208,11 @@ in rec {
packages.all-systems = pkgs.runCommandLocal "all-systems" { } '' packages.all-systems = pkgs.runCommandLocal "all-systems" { } ''
${'' ${''
mkdir -p $out/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 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 != { }) '' ${lib.optionalString (inputs != { }) ''
mkdir -p $out/inputs mkdir -p $out/inputs
@ -220,7 +221,7 @@ in rec {
''; '';
checks.all-systems = packages.all-systems; 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; nixosConfigurations = mapMerge (k: v: { ${renameOutputs k} = v; }) outputs.nixosConfigurations;
} // (forEachSystem [ "aarch64-linux" "x86_64-linux" ] (localSystem: { } // (forEachSystem [ "aarch64-linux" "x86_64-linux" ] (localSystem: {
apps = mapMerge (k: v: { ${renameOutputs k} = v; }) outputs.apps.${localSystem}; apps = mapMerge (k: v: { ${renameOutputs k} = v; }) outputs.apps.${localSystem};

View File

@ -98,7 +98,7 @@ in rec {
wrap-script = args@{ pkgs, src, deps, ... }: let wrap-script = args@{ pkgs, src, deps, ... }: let
name = args.name or (builtins.baseNameOf (builtins.unsafeDiscardStringContext "${src}")); name = args.name or (builtins.baseNameOf (builtins.unsafeDiscardStringContext "${src}"));
in pkgs.runCommandLocal name { 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}''; } ''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. # Simplifies a path (or any other string) such that it can be used as a systemd unit name.

View File

@ -16,12 +16,13 @@ function prepare-installer { # (void)
: ${argv[0]:?"Required: Target disk or image paths."} : ${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 [[ "$(id -u)" != '0' ]] ; then
if [[ ! ${args[no-vm]:-} ]] ; then reexec-in-qemu || return ; \exit 0 ; fi 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 echo 'Script must be run as root or in qemu (without »--no-vm«).' 1>&2 ; \return 1
fi fi
if [[ ${args[vm]:-} ]] ; then reexec-in-qemu || return ; \exit 0 ; 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 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 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 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[@]}"' )} 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« else # use Nix by absolute path, as it won't be on »$PATH«
PATH=$PATH:@{native.nix}/bin PATH=$PATH:@{native.nix}/bin
@ -50,6 +51,8 @@ function prepare-installer { # (void)
## Re-executes the current system's installation in a qemu VM. ## Re-executes the current system's installation in a qemu VM.
function reexec-in-qemu { 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) # (not sure whether this works for block devices)
ensure-disks "${argv[0]}" 1 || return ensure-disks "${argv[0]}" 1 || return
qemu=( -m 2048 ) ; declare -A qemuDevs=( ) qemu=( -m 2048 ) ; declare -A qemuDevs=( )
@ -65,16 +68,19 @@ function reexec-in-qemu {
let index+=1 let index+=1
done done
args[vm]='' args[vm]='' ; args[no-vm]=1
newArgs=( ) ; for arg in "${!args[@]}" ; do newArgs+=( --"$arg"="${args[$arg]}" ) ; done newArgs=( ) ; for arg in "${!args[@]}" ; do newArgs+=( --"$arg"="${args[$arg]}" ) ; done
devSpec= ; for name in "${!qemuDevs[@]}" ; do devSpec+="$name"="${qemuDevs[$name]}": ; done devSpec= ; for name in "${!qemuDevs[@]}" ; do devSpec+="$name"="${qemuDevs[$name]}": ; done
newArgs+=( ${devSpec%:} ) ; (( ${#argv[@]} > 1 )) && args+=( "${argv[@]:1}" ) newArgs+=( ${devSpec%:} ) ; (( ${#argv[@]} > 1 )) && args+=( "${argv[@]:1}" )
#local output=@{inputs.self}'#'nixosConfigurations.@{outputName:?}.config.system.build.vmExec #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 output=@{config.system.build.vmExec.drvPath!unsafeDiscardStringContext} # 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 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 $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) # 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 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 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 (by default) expects the "interpreter" at »/usr/bin/qemu-@{config.wip.preface.hardware}-static«. # 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 fi
# Copy system closure to new nix store: # Copy system closure to new nix store:

View File

@ -54,7 +54,7 @@ function run-qemu { # 1: diskImages, ...: qemuArgs
local qemu=( ) local qemu=( )
if [[ @{pkgs.system} == "@{native.system}" ]] ; then 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 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. # 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 ) 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 echo "KVM is not available (for the current user). Running without hardware acceleration." 1>&2
fi fi
qemu+=( -machine accel=tcg ) # this may suppress warnings that qemu is using tcg (slow) instead of kvm 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 fi
else 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 qemu=( $( build-lazy @{native.qemu_full.drvPath!unsafeDiscardStringContext} )/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
fi 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} ) qemu+=( -m ${args[mem]:-2048} )
if [[ ${args[smp]:-} ]] ; then qemu+=( -smp ${args[smp]} ) ; fi if [[ ${args[smp]:-} ]] ; then qemu+=( -smp ${args[smp]} ) ; fi
if [[ @{config.boot.loader.systemd-boot.enable} || ${args[efi]:-} ]] ; then # UEFI. Otherwise it boots SeaBIOS. 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). #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 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 ) 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} 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 ) 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 # https://lists.gnu.org/archive/html/qemu-discuss/2018-04/msg00045.html
fi fi
# if [[ @{config.wip.preface.hardware} == aarch64 ]] ; then # if [[ @{config.wip.preface.hardware} == aarch64 ]] ; then
@ -99,14 +92,18 @@ function run-qemu { # 1: diskImages, ...: qemuArgs
if [[ $diskImages == */ ]] ; then 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 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 else disks=( ${diskImages//:/ } ) ; fi
[[ ' '"@{boot.initrd.availableKernelModules[@]}"' ' != *' 'virtio_blk' '* ]] || args[virtio-blk]=1
local index ; for index in ${!disks[@]} ; do 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+=( -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 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
-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« if [[ ! ${args[virtio-blk]:-} ]] ; then
#-device ide-hd,drive=drive${index},bus=ahci${index}.${index} # attach IDE?! disk driveX as device X on bus »ahciX« qemu+=( -device ahci,acpi-index=${index},id=ahci${index} ) # create an (ich9-)AHCI bus named »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+=( -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 done
if [[ ${args[share]:-} ]] ; then # e.g. --share='foo:/home/user/foo,readonly=on bar:/tmp/bar' 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 if [[ ! -e $disk ]] ; then args[install]=always ; fi
done ; fi done ; fi
if [[ ${args[install]:-} == always ]] ; then if [[ ${args[install]:-} == always ]] ; then
local verbosity=--quiet ; if [[ ${args[debug]:-} ]] ; then verbosity=--debug ; fi local verbosity=--quiet ; if [[ ${args[trace]:-} ]] ; then verbosity=--trace ; fi ; if [[ ${args[debug]:-} ]] ; then verbosity=--debug ; fi
${args[dry-run]:+echo} $0 install-system "$diskImages" $verbosity --no-inspect || return hostPath=${hostPath:-} ${args[dry-run]:+echo} $0 install-system "$diskImages" $verbosity --no-inspect || return
fi fi
qemu+=( "${argv[@]}" ) qemu+=( "${argv[@]}" )

View File

@ -102,3 +102,9 @@ function run-hook-script {( set -eu # 1: title, 2: scriptPath
fi fi
source "$2" 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}
}

View File

@ -23,10 +23,9 @@ in {
bashInit = lib.mkEnableOption "pretty defaults for interactive bash shells" // { default = true; example = false; }; bashInit = lib.mkEnableOption "pretty defaults for interactive bash shells" // { default = true; example = false; };
}; }; }; };
# Bugfix: 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 // {
imports = [ (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)
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). }; }));
}; })) ];
config = let config = let

View File

@ -97,7 +97,7 @@ in {
fi fi
done 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 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 fi
else else
: # delete library files? : # delete library files?

View File

@ -71,18 +71,18 @@ in {
fs.disks.partitioning = let fs.disks.partitioning = let
partition-disk = { name = "partition-disk"; text = lib.wip.extractBashFunction (builtins.readFile lib.wip.setup-scripts.disk) "partition-disk"; }; 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}" { } '' 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) set -u ; mkdir -p $out ; declare -A args=([debug]=1)
${lib.concatStrings (lib.mapAttrsToList (name: disk: '' ${lib.concatStrings (lib.mapAttrsToList (name: disk: ''
name=${esc name} ; img=$name.img 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)} partition-disk "$name" "$img" ${toString (lib.wip.parseSizeSuffix disk.size)}
${pkgs.gptfdisk}/bin/sgdisk --backup=$out/"$name".backup "$img" ${native.gptfdisk}/bin/sgdisk --backup=$out/"$name".backup "$img"
${pkgs.gptfdisk}/bin/sgdisk --print "$img" >$out/"$name".gpt ${native.gptfdisk}/bin/sgdisk --print "$img" >$out/"$name".gpt
${if disk.mbrParts != null then '' ${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 ""} '' else ""}
'') cfg.devices)} '') cfg.devices)}
''; '';

View File

@ -29,23 +29,23 @@ nix run .../nixos-config'#'nixosConfigurations.${hostName}.config.system.build.v
```nix ```nix
#*/# end of MarkDown, beginning of NixOS module: #*/# 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; prefix = inputs.config.prefix;
cfg = config.virtualisation.vmVariantExec; cfg = config.virtualisation.vmVariantExec;
in { in let hostModule = {
options = { virtualisation.vmVariantExec = lib.mkOption { options = { virtualisation.vmVariantExec = lib.mkOption {
description = lib.mdDoc ''Machine configuration to be added to the system's qemu exec VM.''; 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"; default = { }; visible = "shallow";
}; }; }; };
config = { config = {
system.build.vmExec = (let vmPkgs = pkgs; in let system.build.vmExec = (let hostPkgs = pkgs; in let
name = "run-${config.system.name}-vm-exec"; name = "run-${config.system.name}-vm-exec";
launch = "${cfg.system.build.vm}/bin/${cfg.system.build.vm.meta.mainProgram}"; 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" { in pkgs.runCommand "nixos-vm" {
preferLocalBuild = true; meta.mainProgram = name; preferLocalBuild = true; meta.mainProgram = name;
} '' } ''
@ -79,8 +79,11 @@ in {
''} $out/bin/${name} ''} $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: # Instead of tearing down the initrd environment, adjust some mounts and run the »command« in the initrd:
boot.initrd.postMountCommands = '' boot.initrd.postMountCommands = ''
@ -150,9 +153,21 @@ in {
}; }; }; };
virtualisation.diskSize = 4; #MB, not needed at all 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 # tag this to make clearer what's what
system.nixos.tags = [ "vmExec" ]; system.nixos.tags = [ "vmExec" ];
system.build.isVmExec = true; system.build.isVmExec = true;
}) ]; }; }) ];
}
}; in hostModule

View File

@ -31,8 +31,8 @@ in {
owner = "sbabic"; repo = pname; rev = "ba7564f5006d09bec51058cf4f5ac90d4dc18b3c"; # 2018-11-18 owner = "sbabic"; repo = pname; rev = "ba7564f5006d09bec51058cf4f5ac90d4dc18b3c"; # 2018-11-18
hash = "sha256-6cHkr3s7/2BVXBTn9bUfPFbYAfv9VYh6C9GAbWILNjs="; hash = "sha256-6cHkr3s7/2BVXBTn9bUfPFbYAfv9VYh6C9GAbWILNjs=";
}; };
nativeBuildInputs = [ pkgs.cmake ]; nativeBuildInputs = [ pkgs.buildPackages.cmake ];
buildInputs = [ pkgs.cmake pkgs.zlib ]; buildInputs = [ pkgs.zlib ];
outputs = [ "out" "lib" ]; outputs = [ "out" "lib" ];
meta = { meta = {

View File

@ -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. # 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" { mkEnv = env: pkgs.runCommandLocal "uboot-env.img" {
env = envTxt (defaultEnv' // env); 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" ([ extraConfig = (old.extraConfig or "") + "${lib.concatStringsSep "\n" ([