@@ -303,17 +303,52 @@ jobs:
303303 #
304304 # The Unix legs name the target without a suffix and this one with,
305305 # because meson names the target after the file it produces.
306- # ⚠️ AND THE INSTALL NEEDS MORE THAN THE EMULATOR. With only that
307- # target built, `meson install --no-rebuild` stops at
306+ ninja -j"$(nproc)" qemu-system-x86_64.exe
307+
308+ # ⚠️ ASSEMBLED BY HAND RATHER THAN BY `meson install`, AND THE REASON
309+ # GENERALISES BEYOND THIS HOST.
310+ #
311+ # `meson install --no-rebuild` stops at the first GENERATED file the
312+ # install list names but the emulator target did not produce:
308313 #
309314 # ERROR: File 'trace/trace-events-all' could not be found
310315 #
311- # which is a GENERATED data file the install step copies. Naming it
312- # here rather than dropping `--no-rebuild` is deliberate: without the
313- # flag, meson rebuilds everything, which is how the unit test that
314- # does not link on MinGW comes back.
315- ninja -j"$(nproc)" qemu-system-x86_64.exe trace/trace-events-all
316- meson install --no-rebuild
316+ # Naming that file makes it stop at the next one. Dropping
317+ # `--no-rebuild` instead makes meson rebuild everything, which brings
318+ # back the unit test that does not link on MinGW. Neither converges.
319+ #
320+ # ⭐ AND THE INSTALL TARGET IS NOT WHAT A PAYLOAD WANTS ANYWAY.
321+ # Measured on linux-x64: stripping took the emulator from 78.7 MB to
322+ # 27.0 MB while the whole installed prefix went only 392 MB to 343 MB,
323+ # so roughly 316 MB of `meson install`'s output is not the emulator.
324+ # A payload has to SELECT, and doing that here makes the contents
325+ # explicit rather than "whatever the install target happened to copy".
326+ #
327+ # What an x86_64 emulator needs: itself, and the firmware blobs in
328+ # `pc-bios` that its machine types load. Those are prebuilt files in
329+ # the tarball, not build outputs.
330+ mkdir -p ../out/bin ../out/share/qemu
331+ cp qemu-system-x86_64.exe ../out/bin/
332+ cp -r "../qemu-${QEMU_VERSION}/pc-bios/." ../out/share/qemu/
333+ # ⚠️ NOTHING IS DELETED HERE, AND RESISTING THAT IS THE POINT. The
334+ # tempting next step is to prune `keymaps` and the firmware
335+ # descriptors — but which of them a machine type loads at run time is
336+ # a question for the descriptor, and answering it by deleting
337+ # directories until something breaks is how a payload ends up missing
338+ # a blob on somebody else's machine. The whole `pc-bios` tree is
339+ # copied and its size is reported below.
340+
341+ # ⚠️ THE DLL CLOSURE IS THE WINDOWS PACKAGING QUESTION, AND IT IS
342+ # ANSWERED BY MEASUREMENT RATHER THAN BY A LIST. The other four hosts
343+ # resolve their dependencies through an rpath inside the payload; a PE
344+ # has no such thing, so every MinGW runtime library the emulator loads
345+ # has to sit beside it. `ldd` under MSYS2 reports the closure; only
346+ # the ones from the UCRT64 prefix are ours to ship.
347+ ldd qemu-system-x86_64.exe \
348+ | awk '/ucrt64/ {print $3}' \
349+ | while read -r dll; do cp -n "$dll" ../out/bin/ 2>/dev/null || true; done
350+ echo "── the MinGW runtime the emulator needs ──"
351+ ls -1 ../out/bin/*.dll 2>/dev/null | wc -l
317352
318353 # ── The check that the artifact is an emulator, not a file ────────────
319354 #
0 commit comments