ldd can return non-zero / empty for statically-linked or symlinked binaries
(e.g. the distro usbip tool), which under set -o pipefail aborted the build.
Copy the dynamic loader plus a comprehensive set of libc/usbip libraries
explicitly, and drive the ldd-based copy via process substitution so it
never aborts. Also follow the usbip symlink and preserve its real path.
Under set -o pipefail, 'find ... | head -1' aborts with SIGPIPE once head
reads one line, which happened after installing linux-modules-extra (a large
tree). Use find -print -quit instead of piping to head, and add an ERR trap
for clearer diagnostics.
The GitHub runner uses an Azure kernel that does not ship the usbip /
cdc-acm modules by default; on Ubuntu those live in the separate
linux-modules-extra package. Install it and make the initramfs builder /
guest loader accept compressed kernel modules (.ko.zst, .ko.xz, .ko.gz).
Boot a real Linux inside QEMU and confirm that simulated USB/IP devices
work against a real kernel (vhci-hcd + cdc_acm):
- Add examples/demo.rs: a single server exporting a HID keyboard and a
CDC ACM serial device on port 3240.
- Add scripts/qemu/: build a minimal initramfs (host kernel + busybox +
usbip tool + demo server), boot it in QEMU, attach the simulated devices
over 127.0.0.1, and verify:
* the serial port emits 'a' (0x61) -> SERIAL_TEST
* the keyboard generates a KEY_1 input event -> KEYBOARD_TEST
- Add .github/workflows/qemu.yml to run this in CI (KVM when available,
TCG fallback otherwise), uploading the serial console log as an artefact.