2026-05-15 08:37:57 +02:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
# Phase 13.1 — bootstrap runtime test : copie compositor + client tiers
|
|
|
|
|
# dans l'image Redox, démonte, lance `make qemu`.
|
|
|
|
|
#
|
|
|
|
|
# Usage :
|
|
|
|
|
# ./run-qemu.sh # cycle complet (mount, copy, umount, qemu)
|
|
|
|
|
# ./run-qemu.sh --no-qemu # juste mount + copy + umount (pas de boot)
|
|
|
|
|
# REDOX_SRC=/autre/chemin ./run-qemu.sh
|
|
|
|
|
#
|
|
|
|
|
# Pré-requis :
|
|
|
|
|
# - Avoir cross-compilé les deux binaires :
|
|
|
|
|
# cd crates/redox-wl-compositor && redoxer build --release
|
|
|
|
|
# cd crates/redox-wl-real-client-simple-window && redoxer build --release
|
|
|
|
|
# - redoxfs accessible dans REDOX_SRC/build/fstools/bin/
|
|
|
|
|
# - L'image harddrive.img présente dans REDOX_SRC/build/x86_64/desktop/
|
2026-05-16 10:59:35 +02:00
|
|
|
# - /dev/fuse disponible sur l'hôte
|
2026-05-15 08:37:57 +02:00
|
|
|
# - PAS de QEMU déjà ouvert sur la même image (corromprait le disque).
|
|
|
|
|
#
|
|
|
|
|
# Une fois Redox bootée :
|
|
|
|
|
# Ctrl+Alt+F2 → VT 2 (texte, sans Orbital)
|
|
|
|
|
# login root / password
|
|
|
|
|
# RUST_LOG=info redox-wl-compositor &
|
|
|
|
|
# sleep 1
|
|
|
|
|
# redox-wl-real-client-simple-window
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
ROOT="$(cd "$(dirname "$0")" && pwd)"
|
|
|
|
|
REDOX_SRC="${REDOX_SRC:-$HOME/Projets/Redox/redox-src}"
|
2026-05-16 10:59:35 +02:00
|
|
|
IMAGE="${IMAGE:-$REDOX_SRC/build/x86_64/desktop/harddrive.img}"
|
|
|
|
|
REDOXFS="${REDOXFS:-$REDOX_SRC/build/fstools/bin/redoxfs}"
|
2026-05-15 08:37:57 +02:00
|
|
|
MOUNT="${MOUNT:-/tmp/redox-mnt}"
|
|
|
|
|
|
|
|
|
|
COMPOSITOR_BIN="$ROOT/crates/redox-wl-compositor/target/x86_64-unknown-redox/release/redox-wl-compositor"
|
|
|
|
|
CLIENT_BIN="$ROOT/crates/redox-wl-real-client-simple-window/target/x86_64-unknown-redox/release/redox-wl-real-client-simple-window"
|
🎉 Phase 13.2.a — wl_output v3 complet (gating v1/v2/v3 validé en natif)
Dette protocolaire transversale comblée : wl_output n'était pas déclaré
comme global, plusieurs toolkits client (sctk, GTK, Qt) le considèrent
implicitement requis. Maintenant exposé à v3 avec gating conforme :
- geometry, mode : envoyés à toutes les versions (>= 1)
- scale : seulement si bind >= 3 (gating conservateur)
- done : seulement si bind >= 2
Mode flags = CURRENT | PREFERRED, refresh 60 000 mHz, scale_factor=1,
transform Normal, subpixel Unknown, make=Redox, model=redox-wl-output:0.
Position (0,0), single output, taille pixel issue de screen_w/screen_h
(setté par set_screen_size au boot compositor).
Nouveau crate de validation : redox-wl-test-wl-output. Deux niveaux :
1. Client autonome pour test runtime dans QEMU (bind aux 3 versions,
dump events, PASS/FAIL via exit code)
2. Test natif (cargo test, tourne sur l'hôte sans QEMU) qui simule
serveur+client en-process via UnixStream::pair() et valide les 11
assertions du gating. Vérifié PASS le 2026-05-16 sur CachyOS.
Le test natif sert de garde-fou anti-régression pour CI ultérieur. Plus
besoin de relancer QEMU pour valider ce path.
run-qemu.sh : copie maintenant aussi le test client si compilé (skip
silencieux sinon).
Leyoda 2026 – GPLv3
2026-05-16 12:51:11 +02:00
|
|
|
# Phase 13.2.a : client de test version-gating wl_output (optionnel, skip
|
|
|
|
|
# silencieusement si pas compilé).
|
|
|
|
|
TEST_OUTPUT_BIN="$ROOT/crates/redox-wl-test-wl-output/target/x86_64-unknown-redox/release/redox-wl-test-wl-output"
|
Phase 13.2.b.3 — client de test visuel pour wl_subsurface
Nouveau crate redox-wl-test-client-subcompositor : client Wayland qui
crée un toplevel parent 300×200 bleu nuit avec bordure noire, et lui
attache une subsurface 60×60 rouge à l'offset (50, 50).
Si le rendering 13.2.b.2 fonctionne, on doit voir visuellement dans la
fenêtre QEMU : la fenêtre bleue avec un carré rouge incrusté en haut-
gauche, exactement 50px depuis le bord du parent.
Cycle complet :
1. Bind 5 globals : wl_compositor, wl_shm, xdg_wm_base, wl_seat,
wl_subcompositor (le client échouera si compositor manque l'un d'eux)
2. Parent xdg_toplevel avec ack_configure
3. SHM buffer 300×200 bleu + attach + commit parent
4. wl_compositor.create_surface pour le child
5. wl_subcompositor.get_subsurface(child, parent) + set_position(50,50)
+ set_desync (pour qu'un commit child suffise à rendre les changements)
6. SHM buffer 60×60 rouge + attach + commit child
7. Re-commit parent (force redraw)
8. Event loop avec ESC → exit propre
Reprend le pattern d'event-loop tolérant Interrupted/BrokenPipe de la
phase 13.1.b (5e adaptation Redox côté client).
run-qemu.sh copie maintenant aussi ce binaire dans /usr/bin de l'image
(optionnel, skip silencieux si non compilé).
Les 2 tests natifs continuent de PASSer en non-régression.
Leyoda 2026 – GPLv3
2026-05-16 14:19:53 +02:00
|
|
|
# Phase 13.2.b.3 : client de test visuel subcompositor.
|
|
|
|
|
TEST_SUBCOMP_BIN="$ROOT/crates/redox-wl-test-client-subcompositor/target/x86_64-unknown-redox/release/redox-wl-test-client-subcompositor"
|
2026-05-15 08:37:57 +02:00
|
|
|
|
|
|
|
|
NO_QEMU=0
|
|
|
|
|
for arg in "$@"; do
|
|
|
|
|
case "$arg" in
|
|
|
|
|
--no-qemu) NO_QEMU=1 ;;
|
|
|
|
|
-h|--help)
|
|
|
|
|
awk '/^# / { sub(/^# ?/, ""); print; next } /^[^#]/ { exit }' "$0"
|
|
|
|
|
exit 0
|
|
|
|
|
;;
|
|
|
|
|
*)
|
|
|
|
|
echo "ERR : option inconnue : $arg" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
cleanup() {
|
|
|
|
|
local exit_code=$?
|
|
|
|
|
if mountpoint -q "$MOUNT" 2>/dev/null; then
|
|
|
|
|
echo "==> cleanup : umount $MOUNT"
|
|
|
|
|
fusermount -u "$MOUNT" 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
if [[ -d "$MOUNT" ]] && ! mountpoint -q "$MOUNT" 2>/dev/null; then
|
|
|
|
|
rmdir "$MOUNT" 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
exit $exit_code
|
|
|
|
|
}
|
|
|
|
|
trap cleanup EXIT INT TERM
|
|
|
|
|
|
|
|
|
|
# --- 1. Pré-vérifs ---
|
|
|
|
|
missing=0
|
|
|
|
|
for f in "$IMAGE" "$REDOXFS" "$COMPOSITOR_BIN" "$CLIENT_BIN"; do
|
|
|
|
|
if [[ ! -e "$f" ]]; then
|
|
|
|
|
echo "ERR : introuvable : $f" >&2
|
|
|
|
|
missing=1
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
if [[ $missing -ne 0 ]]; then
|
|
|
|
|
echo >&2
|
|
|
|
|
echo "Si un binaire manque, cross-compile via :" >&2
|
|
|
|
|
echo " cd crates/<crate> && redoxer build --release" >&2
|
|
|
|
|
echo "Si redoxfs/image manquent, ajuste REDOX_SRC=... (actuel : $REDOX_SRC)" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2026-05-16 10:59:35 +02:00
|
|
|
if [[ ! -e /dev/fuse ]]; then
|
|
|
|
|
echo "ERR : /dev/fuse absent sur l'hôte" >&2
|
|
|
|
|
echo "RedoxFS en a besoin pour monter l'image avant le boot QEMU." >&2
|
|
|
|
|
echo "Sur Linux, charge le module fuse ou exécute sur un host où FUSE est disponible." >&2
|
|
|
|
|
exit 3
|
|
|
|
|
fi
|
|
|
|
|
|
2026-05-16 11:48:14 +02:00
|
|
|
# Phase 13.1.c B.4 : warn si l'image est trop petite. L'image desktop par
|
|
|
|
|
# défaut fait ~680 Mo et sature dès qu'on tente `pkg update` (cf. session
|
|
|
|
|
# de la phase 13.1.b). Pour confort, recommandation : 4 Go minimum, idéal
|
|
|
|
|
# 10 Go. La grossir avec :
|
|
|
|
|
# qemu-img resize -f raw <image> 10G
|
|
|
|
|
# <redox-src>/build/fstools/bin/redoxfs-resize <image>
|
|
|
|
|
IMAGE_SIZE_BYTES=$(stat -c %s "$IMAGE" 2>/dev/null || echo 0)
|
|
|
|
|
MIN_IMAGE_SIZE=$((4 * 1024 * 1024 * 1024)) # 4 GiB
|
|
|
|
|
if [[ "$IMAGE_SIZE_BYTES" -gt 0 && "$IMAGE_SIZE_BYTES" -lt "$MIN_IMAGE_SIZE" ]]; then
|
|
|
|
|
image_size_human=$(numfmt --to=iec --suffix=B "$IMAGE_SIZE_BYTES" 2>/dev/null || echo "${IMAGE_SIZE_BYTES} octets")
|
|
|
|
|
echo "WARN : image $IMAGE de taille ${image_size_human} (< 4 GiB recommandés)" >&2
|
|
|
|
|
echo " Tu risques 'No space left on device' au moindre pkg update." >&2
|
|
|
|
|
echo " Pour la grossir :" >&2
|
|
|
|
|
echo " qemu-img resize -f raw $IMAGE 10G" >&2
|
|
|
|
|
echo " $REDOX_SRC/build/fstools/bin/redoxfs-resize $IMAGE" >&2
|
|
|
|
|
echo " (warning seulement, on continue)" >&2
|
|
|
|
|
fi
|
|
|
|
|
|
2026-05-15 08:37:57 +02:00
|
|
|
# --- 2. Mount ---
|
|
|
|
|
mkdir -p "$MOUNT"
|
|
|
|
|
echo "==> monter $IMAGE -> $MOUNT"
|
|
|
|
|
"$REDOXFS" "$IMAGE" "$MOUNT" &
|
|
|
|
|
REDOXFS_PID=$!
|
|
|
|
|
|
|
|
|
|
# Attendre que le mount soit effectif (redoxfs prend ~100-500 ms à se setup)
|
|
|
|
|
for i in {1..50}; do
|
|
|
|
|
if mountpoint -q "$MOUNT"; then
|
|
|
|
|
break
|
|
|
|
|
fi
|
|
|
|
|
sleep 0.1
|
|
|
|
|
if [[ $i -eq 50 ]]; then
|
|
|
|
|
echo "ERR : mount $MOUNT n'a pas abouti après 5s" >&2
|
|
|
|
|
kill $REDOXFS_PID 2>/dev/null || true
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
echo " monté (pid redoxfs=$REDOXFS_PID)"
|
|
|
|
|
|
|
|
|
|
# --- 3. Copy ---
|
|
|
|
|
echo "==> copier les binaires dans /usr/bin/"
|
|
|
|
|
cp -v "$COMPOSITOR_BIN" "$MOUNT/usr/bin/"
|
|
|
|
|
cp -v "$CLIENT_BIN" "$MOUNT/usr/bin/"
|
🎉 Phase 13.2.a — wl_output v3 complet (gating v1/v2/v3 validé en natif)
Dette protocolaire transversale comblée : wl_output n'était pas déclaré
comme global, plusieurs toolkits client (sctk, GTK, Qt) le considèrent
implicitement requis. Maintenant exposé à v3 avec gating conforme :
- geometry, mode : envoyés à toutes les versions (>= 1)
- scale : seulement si bind >= 3 (gating conservateur)
- done : seulement si bind >= 2
Mode flags = CURRENT | PREFERRED, refresh 60 000 mHz, scale_factor=1,
transform Normal, subpixel Unknown, make=Redox, model=redox-wl-output:0.
Position (0,0), single output, taille pixel issue de screen_w/screen_h
(setté par set_screen_size au boot compositor).
Nouveau crate de validation : redox-wl-test-wl-output. Deux niveaux :
1. Client autonome pour test runtime dans QEMU (bind aux 3 versions,
dump events, PASS/FAIL via exit code)
2. Test natif (cargo test, tourne sur l'hôte sans QEMU) qui simule
serveur+client en-process via UnixStream::pair() et valide les 11
assertions du gating. Vérifié PASS le 2026-05-16 sur CachyOS.
Le test natif sert de garde-fou anti-régression pour CI ultérieur. Plus
besoin de relancer QEMU pour valider ce path.
run-qemu.sh : copie maintenant aussi le test client si compilé (skip
silencieux sinon).
Leyoda 2026 – GPLv3
2026-05-16 12:51:11 +02:00
|
|
|
# Phase 13.2.a : test client wl_output (optionnel)
|
|
|
|
|
if [[ -e "$TEST_OUTPUT_BIN" ]]; then
|
|
|
|
|
cp -v "$TEST_OUTPUT_BIN" "$MOUNT/usr/bin/"
|
|
|
|
|
fi
|
Phase 13.2.b.3 — client de test visuel pour wl_subsurface
Nouveau crate redox-wl-test-client-subcompositor : client Wayland qui
crée un toplevel parent 300×200 bleu nuit avec bordure noire, et lui
attache une subsurface 60×60 rouge à l'offset (50, 50).
Si le rendering 13.2.b.2 fonctionne, on doit voir visuellement dans la
fenêtre QEMU : la fenêtre bleue avec un carré rouge incrusté en haut-
gauche, exactement 50px depuis le bord du parent.
Cycle complet :
1. Bind 5 globals : wl_compositor, wl_shm, xdg_wm_base, wl_seat,
wl_subcompositor (le client échouera si compositor manque l'un d'eux)
2. Parent xdg_toplevel avec ack_configure
3. SHM buffer 300×200 bleu + attach + commit parent
4. wl_compositor.create_surface pour le child
5. wl_subcompositor.get_subsurface(child, parent) + set_position(50,50)
+ set_desync (pour qu'un commit child suffise à rendre les changements)
6. SHM buffer 60×60 rouge + attach + commit child
7. Re-commit parent (force redraw)
8. Event loop avec ESC → exit propre
Reprend le pattern d'event-loop tolérant Interrupted/BrokenPipe de la
phase 13.1.b (5e adaptation Redox côté client).
run-qemu.sh copie maintenant aussi ce binaire dans /usr/bin de l'image
(optionnel, skip silencieux si non compilé).
Les 2 tests natifs continuent de PASSer en non-régression.
Leyoda 2026 – GPLv3
2026-05-16 14:19:53 +02:00
|
|
|
# Phase 13.2.b.3 : test client subcompositor (optionnel)
|
|
|
|
|
if [[ -e "$TEST_SUBCOMP_BIN" ]]; then
|
|
|
|
|
cp -v "$TEST_SUBCOMP_BIN" "$MOUNT/usr/bin/"
|
|
|
|
|
fi
|
2026-05-15 08:37:57 +02:00
|
|
|
|
2026-05-16 14:33:27 +02:00
|
|
|
# Phase 13.2.b.4 : scripts ion raccourcis (test-subc, test-sw, test-out).
|
|
|
|
|
# Copiés depuis tools/redox-scripts/ pour invocation 1-ligne dans le shell
|
|
|
|
|
# Redox. Chmod +x conservé via cp -p.
|
|
|
|
|
for script in "$ROOT/tools/redox-scripts"/*; do
|
|
|
|
|
if [[ -f "$script" ]]; then
|
|
|
|
|
cp -vp "$script" "$MOUNT/usr/bin/"
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
|
2026-05-16 17:27:35 +02:00
|
|
|
# SSH : injecter la pubkey hôte dans /home/root/.ssh/authorized_keys du
|
|
|
|
|
# guest. ATTENTION : sous Redox le homedir de root est /home/root/ (pas
|
|
|
|
|
# /root/ comme Linux). sshd cherche bien sur le path Redox, sinon publickey
|
|
|
|
|
# est silencieusement ignoré.
|
|
|
|
|
# Permet `ssh root@localhost -p 8022` sans password une fois sshd lancé.
|
2026-05-16 17:20:31 +02:00
|
|
|
SSH_DIR_HOST="$HOME/.ssh"
|
|
|
|
|
PUBKEYS_FOUND=()
|
|
|
|
|
for k in id_ed25519.pub id_rsa.pub id_ecdsa.pub; do
|
|
|
|
|
if [[ -f "$SSH_DIR_HOST/$k" ]]; then
|
|
|
|
|
PUBKEYS_FOUND+=("$SSH_DIR_HOST/$k")
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
if [[ ${#PUBKEYS_FOUND[@]} -gt 0 ]]; then
|
2026-05-16 17:27:35 +02:00
|
|
|
GUEST_ROOT_SSH="$MOUNT/home/root/.ssh"
|
|
|
|
|
mkdir -p "$GUEST_ROOT_SSH"
|
|
|
|
|
chmod 700 "$GUEST_ROOT_SSH"
|
|
|
|
|
: > "$GUEST_ROOT_SSH/authorized_keys"
|
2026-05-16 17:20:31 +02:00
|
|
|
for k in "${PUBKEYS_FOUND[@]}"; do
|
2026-05-16 17:27:35 +02:00
|
|
|
echo "==> injecter pubkey hôte $k dans /home/root/.ssh/authorized_keys (homedir Redox)"
|
|
|
|
|
cat "$k" >> "$GUEST_ROOT_SSH/authorized_keys"
|
2026-05-16 17:20:31 +02:00
|
|
|
done
|
2026-05-16 17:27:35 +02:00
|
|
|
chmod 600 "$GUEST_ROOT_SSH/authorized_keys"
|
2026-05-16 17:20:31 +02:00
|
|
|
else
|
|
|
|
|
echo "WARN : aucune pubkey hôte trouvée dans $SSH_DIR_HOST/. SSH par password seulement." >&2
|
|
|
|
|
fi
|
|
|
|
|
|
2026-05-16 17:29:31 +02:00
|
|
|
# SSH : déployer le service file init Redox pour démarrer sshd au boot.
|
|
|
|
|
# Pré-requis : openssh déjà installé via pkg + host keys générées dans
|
|
|
|
|
# /etc/ssh/ (cf docs/SSH-setup.md à venir). Si openssh manque, sshd
|
|
|
|
|
# crashera au boot mais le système continuera (les autres services ne
|
|
|
|
|
# sont pas bloqués car requires_weak).
|
|
|
|
|
for service in "$ROOT/tools/redox-services"/*; do
|
|
|
|
|
if [[ -f "$service" ]]; then
|
|
|
|
|
echo "==> installer service init $(basename "$service") dans /usr/lib/init.d/"
|
|
|
|
|
mkdir -p "$MOUNT/usr/lib/init.d"
|
|
|
|
|
cp -vp "$service" "$MOUNT/usr/lib/init.d/"
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
|
2026-05-15 08:37:57 +02:00
|
|
|
# --- 4. umount avant make qemu (sinon QEMU et FUSE se battent sur le même fichier) ---
|
|
|
|
|
echo "==> démonter $MOUNT"
|
|
|
|
|
sync
|
|
|
|
|
fusermount -u "$MOUNT"
|
|
|
|
|
rmdir "$MOUNT" 2>/dev/null || true
|
|
|
|
|
trap - EXIT INT TERM # plus rien à cleaner
|
|
|
|
|
|
|
|
|
|
if [[ $NO_QEMU -eq 1 ]]; then
|
|
|
|
|
echo "==> --no-qemu : on s'arrête là."
|
|
|
|
|
exit 0
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# --- 5. Boot QEMU ---
|
|
|
|
|
echo "==> lancer make qemu (Ctrl+Alt+F2 pour VT2 ; login root / password)"
|
2026-05-16 16:40:18 +02:00
|
|
|
echo " SSH guest:22 → host:8022 (via net=redir). Connect : ssh root@localhost -p 8022"
|
2026-05-15 08:37:57 +02:00
|
|
|
cd "$REDOX_SRC"
|
2026-05-16 16:40:18 +02:00
|
|
|
# net=redir : active hostfwd dans mk/qemu.mk (8022 → 22 SSH, 8080 → 80 HTTP,
|
|
|
|
|
# + ports 8081-8083 et 64126 gdbserver). Sans ça, l'invité est en NAT pur
|
|
|
|
|
# sans port exposé côté hôte → impossible de SSH dans Redox.
|
|
|
|
|
exec make qemu audio=no net=redir QEMU_USER_FLAGS="-k fr"
|