Most of the work on AQEMU, my Qt front-end for QEMU on Windows (x64 and ARM64) and Linux, isn't in the GUI. It's in the scripts that build QEMU itself with MSYS2 and package it for the Microsoft Store. In October I lost a day to one small feature, and every bug on the way was a Windows build quirk rather than a code bug. Here's the trail, straight from the commit log, in case it saves someone else the same afternoon.
The feature: a guest-agent channel on every VM
For the 1.6.0 file copy work I wanted ordinary VMs to expose a QEMU guest-agent port, so that once qemu-guest-agent is running in the guest, AQEMU can copy a path in and back out. On Linux that's an easy Unix socket. On Windows I wanted a named pipe.
Bug 1: the VM wouldn't start at all
The first attempt broke Windows guests completely. QEMU bound the pipe path as if it were a Unix socket, exited with "network down", and the guest never started. The quick fix was to start Windows VMs without the guest-agent pipe so nothing else was blocked while I did it properly.
The proper fix: a lazy named pipe
The real fix was a small QEMU patch (third_party/patches/0001-win-lazy-named-pipe.patch) so QEMU listens on the Windows pipe without waiting for a client. The VM boots straight away, and the guest agent is there when something connects. Linux keeps the Unix socket. Simple enough, except the patch never actually reached QEMU.
Bug 2: there's no patch in the package shell
The Windows package build runs in a shell that has no patch command, so the step silently did nothing. Switching to git apply fixed that, and broke something else.
Bug 3: Git for Windows and CRLF
Git for Windows had checked the QEMU sources out with carriage returns, so git apply rejected a patch that matched perfectly apart from line endings. I added a CRLF-aware path for that.
Bug 4: MSYS tools hide the carriage returns
It still failed, because MSYS tools quietly hide carriage returns, so the file I thought was fixed was still being handed to git apply as CRLF. The final fix rewrites the affected QEMU sources as LF before applying the patch. Four commits for one pipe.
A bonus one: OpenSSL on PATH
In the same week, another dependency clone in the Windows package build failed in a way that took a while to spot. MinGW's OpenSSL libraries on PATH made git-remote-https abort, the clone left an empty directory, and the build happily compiled nothing. Cloning with MSYS's own git fixed it. If you build anything with MSYS2 and a mixed PATH, check which git and which OpenSSL you're really getting.
The one that mattered most for ARM64
While I was in the build scripts I found the Windows on Arm QEMU build was skipping WHPX, even though QEMU 11 already has the ARM WHPX backend. So Snapdragon guests were stuck on TCG, QEMU's software emulator. Now the ARM64 build enables it, and AQEMU checks that the host reports ARM64 support, then launches matching ARM guests with accel=whpx:tcg and -cpu host only when that QEMU binary actually lists whpx. Otherwise it falls back to TCG. That shipped in 1.6.0.
What I'd tell my past self
- Never assume a step ran just because the script didn't fail. Check the output, or better, make the script fail when the tool is missing.
- On Windows, normalise line endings yourself before patching. Don't trust what your tools show you.
- Probe the QEMU binary for what it supports (
-accel help) instead of assuming a build flag worked.
Where it lives
All of this is in the scripts under scripts/ in the AQEMU repo, which is GPL-2.0. The Windows build is on the Microsoft Store with a 7-day free trial, then a one-time purchase (the Store shows the current price). It bundles QEMU 11, has 195 guest profiles across 29 architectures, uses WHPX on x64 and ARM64 with TCG as the fallback, and KVM on Linux.
If you've fought MSYS2 and QEMU on Windows and found a cleaner way, I'd genuinely like to hear it in the comments or in a GitHub issue.
Top comments (0)