diff --git a/README.md b/README.md index c6cd965..0d0a501 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,7 @@ It needs `qemu`, `qemu-img`, an ISO tool (`xorriso`, `genisoimage` or `mkisofs`) and `socat` or `nc`; there is no SSH to the guest. ```bash -./build-windows-base.sh [--force] [--compress] [--from-img] [--window] [OUTPUT.qcow2] +./build-windows-base.sh [--force] [--compress] [--from-img] [--headless] [OUTPUT.qcow2] ``` It refuses to replace an existing base image without `--force`, because the diff --git a/build-windows-base.sh b/build-windows-base.sh index a567444..54525fd 100755 --- a/build-windows-base.sh +++ b/build-windows-base.sh @@ -24,7 +24,7 @@ # install-iso/ (see README.md). # # Usage: build-windows-base.sh [--force] [--keep-work] [--compress] [--from-img] -# [--window] [OUTPUT.qcow2] +# [--headless] [OUTPUT.qcow2] # OUTPUT defaults to the path that "download-images.sh --print-path windows11" # prints. set -euo pipefail @@ -38,7 +38,7 @@ win_dir="${images_dir}/windows11" usage() { cat <&2; exit 2 ;; *) [[ -z "$output" ]] || { usage >&2; exit 2; }; output="$1" ;; esac @@ -240,13 +241,15 @@ config_text="$(<"$config_template")" for placeholder in uefi_code uefi_vars disk_image monitor_socket; do value="${!placeholder}" [[ "$value" != *\"* ]] || die "${placeholder} must not contain double quotes: ${value}" - config_text="${config_text//"\${${placeholder}}"/"$value"}" + # No outer double quotes: bash 3.2 (macOS) keeps inner quotes literally. + config_text=${config_text//"\${${placeholder}}"/"$value"} done printf '%s\n' "$config_text" >"$qemu_config" +if ((window)) && [[ -z "${DISPLAY:-}${WAYLAND_DISPLAY:-}" && "$host_os" != darwin ]]; then + window=0 +fi if ((window)); then - [[ -n "${DISPLAY:-}${WAYLAND_DISPLAY:-}" || "$host_os" == darwin ]] \ - || die "--window needs a desktop session (DISPLAY or WAYLAND_DISPLAY is not set)." if [[ -n "${WIN11_VM_DISPLAY:-}" ]]; then display="$WIN11_VM_DISPLAY" elif [[ "$host_os" == darwin ]]; then display=cocoa else display=gtk; fi @@ -263,8 +266,11 @@ qemu_args=( -netdev user,id=net0 -nic none -display "$display" - -serial "file:${work}/console.log" -daemonize -pidfile "$pid_file" + -serial "file:${work}/console.log" -pidfile "$pid_file" ) +# The Cocoa/GTK window needs the original process (macOS crashes in fork()), so +# only the VNC display is daemonized; the window runs as a background job. +((window)) || qemu_args+=(-daemonize) if [[ "$host_os" == darwin && "$arch" == arm64 ]] && ((!from_img)); then # With the HVF in-kernel GICv3, QEMU's usb-storage races on the status packet # and Windows Setup stalls 10 s after every burst of reads (utmapp/UTM#7970), @@ -308,7 +314,16 @@ press_key() { fi } -"$qemu_binary" "${qemu_args[@]}" +if ((window)); then + "$qemu_binary" "${qemu_args[@]}" /dev/null || die "QEMU exited before it started the guest." + sleep 0.2 + done +else + "$qemu_binary" "${qemu_args[@]}" +fi if ((!from_img)); then ( deadline=$((SECONDS + 30))