run-iso-qemu.sh 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. #!/usr/bin/env bash
  2. # Boots mjdev-desktop-<version>.iso in QEMU so the wayland desktop can be tried
  3. # without touching the host session. Uses KVM and virtio-gpu GL acceleration
  4. # when available (the desktop needs GL), falls back to plain emulation.
  5. #
  6. # ./run-iso-qemu.sh # boots releases/<app>-<version>.iso (local gtk window)
  7. # ./run-iso-qemu.sh path/to.iso # boots a specific image
  8. # ./run-iso-qemu.sh --vnc # headless: expose the screen over VNC for remote
  9. # # grab + control (127.0.0.1:5900). egl-headless keeps
  10. # # GL working without a host display. Connect with any
  11. # # VNC client / vncsnapshot / gvncviewer.
  12. # MJDEV_QEMU_VNC=1 ./run-iso-qemu.sh # same via env
  13. # MJDEV_QEMU_VNC_DISPLAY=2 ./run-iso-qemu.sh --vnc # 127.0.0.1:5902
  14. # MJDEV_QEMU_VNC_HOST=0.0.0.0 ./run-iso-qemu.sh --vnc # listen on all interfaces
  15. set -euo pipefail
  16. HERE="$(cd "$(dirname "$0")" && pwd)"
  17. CATALOG="$HERE/gradle/libs.versions.toml"
  18. read_catalog() { sed -n "s/^$1 *= *\"\(.*\)\"/\1/p" "$CATALOG"; }
  19. APP_NAME="$(read_catalog app-name)"
  20. VERSION="$(read_catalog app-pkg-version)"
  21. VNC="${MJDEV_QEMU_VNC:-0}"
  22. ISO=""
  23. for a in "$@"; do
  24. case "$a" in
  25. --vnc) VNC=1;;
  26. *) ISO="$a";;
  27. esac
  28. done
  29. ISO="${ISO:-$HERE/releases/$APP_NAME-$VERSION.iso}"
  30. RAM="${MJDEV_QEMU_RAM:-4096}"
  31. CPUS="${MJDEV_QEMU_CPUS:-4}"
  32. VNC_HOST="${MJDEV_QEMU_VNC_HOST:-127.0.0.1}"
  33. VNC_DISPLAY="${MJDEV_QEMU_VNC_DISPLAY:-0}"
  34. command -v qemu-system-x86_64 >/dev/null 2>&1 || { echo "qemu-system-x86_64 not found (apt install qemu-system-x86)"; exit 1; }
  35. [ -f "$ISO" ] || { echo "iso not found: $ISO"; echo "build it first: ./gradlew makeIso"; exit 1; }
  36. ARGS=(
  37. -m "$RAM"
  38. -smp "$CPUS"
  39. -cdrom "$ISO"
  40. -boot d
  41. )
  42. # hardware acceleration when the host exposes it
  43. if [ -w /dev/kvm ]; then
  44. ARGS+=(-enable-kvm -cpu host)
  45. echo ">> KVM enabled"
  46. else
  47. echo ">> /dev/kvm not available - software emulation (slow)"
  48. fi
  49. if [ "$VNC" = "1" ]; then
  50. # headless screen grab + control over VNC. egl-headless renders the guest GPU
  51. # output (so the wayland compositor still gets real GL) and hands the framebuffer
  52. # to qemu's built-in VNC server; VNC injects keyboard/pointer back into the guest.
  53. # Independent of the guest compositor — no in-image vnc server / wlroots screencopy
  54. # needed. Listens on $VNC_HOST:(5900+$VNC_DISPLAY).
  55. if qemu-system-x86_64 -display help 2>/dev/null | grep -q egl-headless; then
  56. ARGS+=(-device virtio-vga-gl -display "egl-headless,gl=on")
  57. else
  58. echo ">> egl-headless unavailable - VNC without GL (compositor falls back to llvmpipe)"
  59. ARGS+=(-device virtio-vga)
  60. fi
  61. ARGS+=(-vnc "$VNC_HOST:$VNC_DISPLAY")
  62. echo ">> VNC: connect to $VNC_HOST:$((5900 + VNC_DISPLAY)) (e.g. vncviewer $VNC_HOST:$VNC_DISPLAY)"
  63. # virtio-gpu with GL gives the wayland compositor a real GPU path; gtk display
  64. # with gl=on renders it on the host. Fall back to a plain virtio-gpu if the
  65. # host qemu has no GL display backend.
  66. elif qemu-system-x86_64 -display help 2>/dev/null | grep -q gtk; then
  67. ARGS+=(-device virtio-vga-gl -display gtk,gl=on)
  68. else
  69. ARGS+=(-device virtio-vga -display sdl)
  70. fi
  71. echo ">> booting $ISO"
  72. exec qemu-system-x86_64 "${ARGS[@]}"