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
+27
-12
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.
|
and `socat` or `nc`; there is no SSH to the guest.
|
||||||
|
|
||||||
```bash
|
```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
|
It refuses to replace an existing base image without `--force`, because the
|
||||||
|
|||||||
+26
-11
@@ -24,7 +24,7 @@
|
|||||||
# install-iso/ (see README.md).
|
# install-iso/ (see README.md).
|
||||||
#
|
#
|
||||||
# Usage: build-windows-base.sh [--force] [--keep-work] [--compress] [--from-img]
|
# 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"
|
# OUTPUT defaults to the path that "download-images.sh --print-path windows11"
|
||||||
# prints.
|
# prints.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
@@ -38,7 +38,7 @@ win_dir="${images_dir}/windows11"
|
|||||||
usage() {
|
usage() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
Usage: $(basename "$0") [--force] [--keep-work] [--compress] [--from-img]
|
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
|
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.
|
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
|
--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 ISO path ending in .img), which reads much faster than
|
||||||
the emulated CD-ROM
|
the emulated CD-ROM
|
||||||
--window Show the guest in a QEMU window (needs a desktop session)
|
--headless Serve the guest screen over VNC on 127.0.0.1:5990 instead of
|
||||||
instead of the VNC display on 127.0.0.1:5990
|
showing a QEMU window (the default; without a desktop
|
||||||
|
session on Linux, VNC is used as well)
|
||||||
-h, --help Show this help
|
-h, --help Show this help
|
||||||
|
|
||||||
Environment variables:
|
Environment variables:
|
||||||
@@ -60,7 +61,7 @@ Environment variables:
|
|||||||
WIN11_VM_DISK_SIZE Size of the system disk (default: 64G)
|
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_CODE OVMF read-only firmware (auto-detected if unset)
|
||||||
WIN11_VM_UEFI_VARS OVMF variable-store template (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)
|
gtk elsewhere)
|
||||||
BASE_BUILD_TMPDIR Parent of the scratch state directory, which needs about
|
BASE_BUILD_TMPDIR Parent of the scratch state directory, which needs about
|
||||||
25 GB (default: /var/tmp)
|
25 GB (default: /var/tmp)
|
||||||
@@ -77,7 +78,7 @@ force=0
|
|||||||
keep_work=0
|
keep_work=0
|
||||||
compress=0
|
compress=0
|
||||||
from_img=0
|
from_img=0
|
||||||
window=0
|
window=1
|
||||||
output=""
|
output=""
|
||||||
while (($#)); do
|
while (($#)); do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
@@ -86,7 +87,7 @@ while (($#)); do
|
|||||||
--keep-work) keep_work=1 ;;
|
--keep-work) keep_work=1 ;;
|
||||||
--compress) compress=1 ;;
|
--compress) compress=1 ;;
|
||||||
--from-img) from_img=1 ;;
|
--from-img) from_img=1 ;;
|
||||||
--window) window=1 ;;
|
--headless) window=0 ;;
|
||||||
-*) usage >&2; exit 2 ;;
|
-*) usage >&2; exit 2 ;;
|
||||||
*) [[ -z "$output" ]] || { usage >&2; exit 2; }; output="$1" ;;
|
*) [[ -z "$output" ]] || { usage >&2; exit 2; }; output="$1" ;;
|
||||||
esac
|
esac
|
||||||
@@ -240,13 +241,15 @@ config_text="$(<"$config_template")"
|
|||||||
for placeholder in uefi_code uefi_vars disk_image monitor_socket; do
|
for placeholder in uefi_code uefi_vars disk_image monitor_socket; do
|
||||||
value="${!placeholder}"
|
value="${!placeholder}"
|
||||||
[[ "$value" != *\"* ]] || die "${placeholder} must not contain double quotes: ${value}"
|
[[ "$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
|
done
|
||||||
printf '%s\n' "$config_text" >"$qemu_config"
|
printf '%s\n' "$config_text" >"$qemu_config"
|
||||||
|
|
||||||
|
if ((window)) && [[ -z "${DISPLAY:-}${WAYLAND_DISPLAY:-}" && "$host_os" != darwin ]]; then
|
||||||
|
window=0
|
||||||
|
fi
|
||||||
if ((window)); then
|
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"
|
if [[ -n "${WIN11_VM_DISPLAY:-}" ]]; then display="$WIN11_VM_DISPLAY"
|
||||||
elif [[ "$host_os" == darwin ]]; then display=cocoa
|
elif [[ "$host_os" == darwin ]]; then display=cocoa
|
||||||
else display=gtk; fi
|
else display=gtk; fi
|
||||||
@@ -263,8 +266,11 @@ qemu_args=(
|
|||||||
-netdev user,id=net0
|
-netdev user,id=net0
|
||||||
-nic none
|
-nic none
|
||||||
-display "$display"
|
-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
|
if [[ "$host_os" == darwin && "$arch" == arm64 ]] && ((!from_img)); then
|
||||||
# With the HVF in-kernel GICv3, QEMU's usb-storage races on the status packet
|
# 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),
|
# and Windows Setup stalls 10 s after every burst of reads (utmapp/UTM#7970),
|
||||||
@@ -308,7 +314,16 @@ press_key() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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[@]}"
|
"$qemu_binary" "${qemu_args[@]}"
|
||||||
|
fi
|
||||||
if ((!from_img)); then
|
if ((!from_img)); then
|
||||||
(
|
(
|
||||||
deadline=$((SECONDS + 30))
|
deadline=$((SECONDS + 30))
|
||||||
|
|||||||
Reference in new issue
Block a user