at 24.11-pre 4.5 kB view raw
1# This is an expression meant to be called from `./repart.nix`, it is NOT a 2# NixOS module that can be imported. 3 4{ lib 5, stdenvNoCC 6, runCommand 7, python3 8, black 9, ruff 10, mypy 11, systemd 12, fakeroot 13, util-linux 14 15 # filesystem tools 16, dosfstools 17, mtools 18, e2fsprogs 19, squashfsTools 20, erofs-utils 21, btrfs-progs 22, xfsprogs 23 24 # compression tools 25, zstd 26, xz 27 28 # arguments 29, name 30, version 31, imageFileBasename 32, compression 33, fileSystems 34, partitionsJSON 35, split 36, seed 37, definitionsDirectory 38, sectorSize 39, mkfsEnv ? {} 40, createEmpty ? true 41}: 42 43let 44 systemdArch = let 45 inherit (stdenvNoCC) hostPlatform; 46 in 47 if hostPlatform.isAarch32 then "arm" 48 else if hostPlatform.isAarch64 then "arm64" 49 else if hostPlatform.isx86_32 then "x86" 50 else if hostPlatform.isx86_64 then "x86-64" 51 else if hostPlatform.isMips32 then "mips-le" 52 else if hostPlatform.isMips64 then "mips64-le" 53 else if hostPlatform.isPower then "ppc" 54 else if hostPlatform.isPower64 then "ppc64" 55 else if hostPlatform.isRiscV32 then "riscv32" 56 else if hostPlatform.isRiscV64 then "riscv64" 57 else if hostPlatform.isS390 then "s390" 58 else if hostPlatform.isS390x then "s390x" 59 else if hostPlatform.isLoongArch64 then "loongarch64" 60 else if hostPlatform.isAlpha then "alpha" 61 else hostPlatform.parsed.cpu.name; 62 63 amendRepartDefinitions = runCommand "amend-repart-definitions.py" 64 { 65 # TODO: ruff does not splice properly in nativeBuildInputs 66 depsBuildBuild = [ ruff ]; 67 nativeBuildInputs = [ python3 black mypy ]; 68 } '' 69 install ${./amend-repart-definitions.py} $out 70 patchShebangs --build $out 71 72 black --check --diff $out 73 ruff --line-length 88 $out 74 mypy --strict $out 75 ''; 76 77 fileSystemToolMapping = { 78 "vfat" = [ dosfstools mtools ]; 79 "ext4" = [ e2fsprogs.bin ]; 80 "squashfs" = [ squashfsTools ]; 81 "erofs" = [ erofs-utils ]; 82 "btrfs" = [ btrfs-progs ]; 83 "xfs" = [ xfsprogs ]; 84 }; 85 86 fileSystemTools = builtins.concatMap (f: fileSystemToolMapping."${f}") fileSystems; 87 88 compressionPkg = { 89 "zstd" = zstd; 90 "xz" = xz; 91 }."${compression.algorithm}"; 92 93 compressionCommand = { 94 "zstd" = "zstd --no-progress --threads=0 -${toString compression.level}"; 95 "xz" = "xz --keep --verbose --threads=0 -${toString compression.level}"; 96 }."${compression.algorithm}"; 97in 98 stdenvNoCC.mkDerivation (finalAttrs: 99 (if (version != null) 100 then { pname = name; inherit version; } 101 else { inherit name; } 102 ) // { 103 __structuredAttrs = true; 104 105 nativeBuildInputs = [ 106 systemd 107 fakeroot 108 util-linux 109 ] ++ lib.optionals (compression.enable) [ 110 compressionPkg 111 ] ++ fileSystemTools; 112 113 env = mkfsEnv; 114 115 inherit partitionsJSON definitionsDirectory; 116 117 # relative path to the repart definitions that are read by systemd-repart 118 finalRepartDefinitions = "repart.d"; 119 120 systemdRepartFlags = [ 121 "--architecture=${systemdArch}" 122 "--dry-run=no" 123 "--size=auto" 124 "--seed=${seed}" 125 "--definitions=${finalAttrs.finalRepartDefinitions}" 126 "--split=${lib.boolToString split}" 127 "--json=pretty" 128 ] ++ lib.optionals createEmpty [ 129 "--empty=create" 130 ] ++ lib.optionals (sectorSize != null) [ 131 "--sector-size=${toString sectorSize}" 132 ]; 133 134 dontUnpack = true; 135 dontConfigure = true; 136 doCheck = false; 137 138 patchPhase = '' 139 runHook prePatch 140 141 amendedRepartDefinitionsDir=$(${amendRepartDefinitions} $partitionsJSON $definitionsDirectory) 142 ln -vs $amendedRepartDefinitionsDir $finalRepartDefinitions 143 144 runHook postPatch 145 ''; 146 147 buildPhase = '' 148 runHook preBuild 149 150 echo "Building image with systemd-repart..." 151 unshare --map-root-user fakeroot systemd-repart \ 152 ''${systemdRepartFlags[@]} \ 153 ${imageFileBasename}.raw \ 154 | tee repart-output.json 155 156 runHook postBuild 157 ''; 158 159 installPhase = '' 160 runHook preInstall 161 162 mkdir -p $out 163 '' 164 # Compression is implemented in the same derivation as opposed to in a 165 # separate derivation to allow users to save disk space. Disk images are 166 # already very space intensive so we want to allow users to mitigate this. 167 + lib.optionalString compression.enable 168 '' 169 for f in ${imageFileBasename}*; do 170 echo "Compressing $f with ${compression.algorithm}..." 171 # Keep the original file when compressing and only delete it afterwards 172 ${compressionCommand} $f && rm $f 173 done 174 '' + '' 175 mv -v repart-output.json ${imageFileBasename}* $out 176 177 runHook postInstall 178 ''; 179 180 passthru = { 181 inherit amendRepartDefinitions; 182 }; 183})