build-windows-base.sh: show a window by default, fix macOS bash 3.2 and fork crashes
Replace --window with --headless (VNC); the window is the default. Fill the QEMU config placeholders without nested quotes (bash 3.2 kept them literally), and run QEMU as a background job instead of -daemonize when it shows a window (Cocoa crashes in fork()). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4eb26e3a96
commit
91ae8cb147
2 files changed
+28
-13
No files matched your search
@@ -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
|
||||
|
||||
+27
-12
@@ -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 <<EOF
|
||||
Usage: $(basename "$0") [--force] [--keep-work] [--compress] [--from-img]
|
||||
[--window] [OUTPUT.qcow2]
|
||||
[--headless] [OUTPUT.qcow2]
|
||||
|
||||
Install Windows 11 from the ISO, generalize it with sysprep and store the disk
|
||||
as the read-only, generic base image that VM disks are cloned from.
|
||||
@@ -49,8 +49,9 @@ as the read-only, generic base image that VM disks are cloned from.
|
||||
--from-img Install from the disk image made by build-windows-install-disk.sh
|
||||
(the ISO path ending in .img), which reads much faster than
|
||||
the emulated CD-ROM
|
||||
--window Show the guest in a QEMU window (needs a desktop session)
|
||||
instead of the VNC display on 127.0.0.1:5990
|
||||
--headless Serve the guest screen over VNC on 127.0.0.1:5990 instead of
|
||||
showing a QEMU window (the default; without a desktop
|
||||
session on Linux, VNC is used as well)
|
||||
-h, --help Show this help
|
||||
|
||||
Environment variables:
|
||||
@@ -60,7 +61,7 @@ Environment variables:
|
||||
WIN11_VM_DISK_SIZE Size of the system disk (default: 64G)
|
||||
WIN11_VM_UEFI_CODE OVMF read-only firmware (auto-detected if unset)
|
||||
WIN11_VM_UEFI_VARS OVMF variable-store template (auto-detected if unset)
|
||||
WIN11_VM_DISPLAY QEMU display with --window (default: cocoa on macOS,
|
||||
WIN11_VM_DISPLAY QEMU window display (default: cocoa on macOS,
|
||||
gtk elsewhere)
|
||||
BASE_BUILD_TMPDIR Parent of the scratch state directory, which needs about
|
||||
25 GB (default: /var/tmp)
|
||||
@@ -77,7 +78,7 @@ force=0
|
||||
keep_work=0
|
||||
compress=0
|
||||
from_img=0
|
||||
window=0
|
||||
window=1
|
||||
output=""
|
||||
while (($#)); do
|
||||
case "$1" in
|
||||
@@ -86,7 +87,7 @@ while (($#)); do
|
||||
--keep-work) keep_work=1 ;;
|
||||
--compress) compress=1 ;;
|
||||
--from-img) from_img=1 ;;
|
||||
--window) window=1 ;;
|
||||
--headless) window=0 ;;
|
||||
-*) usage >&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 &
|
||||
qemu_job=$!
|
||||
until [[ -s "$pid_file" ]]; do
|
||||
kill -0 "$qemu_job" 2>/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))
|
||||
|
||||
Reference in new issue
Block a user