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