Bootstrap the per-user Python venv from the wrapper

The Project Manager GUI does not set up O3DE's Python venv itself; it only
errors ("Missing python venv file .../pyvenv.cfg") when it's absent, which
cascades into "Failed to get engine info" / "Failed to initialize". Nothing
was running get_python.sh on launch.

The wrapper now runs python/get_python.sh when python.sh reports the venv is
missing/stale. get_python.sh downloads Python, creates the venv under the
writable ~/.o3de, and installs the o3de CLI from the prebuilt sdist. It is
idempotent and self-heals a half-built venv (venv creation uses --clear).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-16 03:04:52 +02:00
parent 3146cab449
commit d83526cbf0
2 changed files with 27 additions and 4 deletions
+7 -4
View File
@@ -127,10 +127,13 @@ These were confirmed by inspecting the v26.05 package (`opt/O3DE/26.05/…`):
engine compiles project code at runtime. Those live in the SDK. Users therefore engine compiles project code at runtime. Those live in the SDK. Users therefore
pull the SDK runtime (larger than Platform) on install — Flatpak does this pull the SDK runtime (larger than Platform) on install — Flatpak does this
automatically from Flathub. automatically from Flathub.
- **Python is per-user, not baked in.** On first launch O3DE downloads its Python - **Python is per-user, not baked in.** O3DE needs a Python venv under `~/.o3de`
runtime and builds a venv under `~/.o3de` (writable), pip-installing its deps (writable), keyed to the engine path, so it can only be created at runtime — the
there. The build does **not** bundle Python — the venv is keyed to the user's build can't bundle it. The Project Manager GUI does **not** create it itself, so
home path, so it can only be created at runtime. the wrapper (`o3de-wrapper.sh`) runs `python/get_python.sh` on launch when the
venv is missing or stale. The **first launch downloads Python and can take
several minutes with no window on screen** — that's expected; subsequent launches
are instant. (cmake, which `get_python.sh` needs, comes from the Sdk runtime.)
- **The o3de CLI install (read-only `/app`).** On first launch O3DE installs its - **The o3de CLI install (read-only `/app`).** On first launch O3DE installs its
own `o3de` CLI from `scripts/o3de` into the per-user `~/.o3de` venv. By default own `o3de` CLI from `scripts/o3de` into the per-user `~/.o3de` venv. By default
`python/get_python.sh` does an *editable* install (`pip install -e`), which `python/get_python.sh` does an *editable* install (`pip install -e`), which
+20
View File
@@ -27,4 +27,24 @@ fi
# Make libraries that sit next to the binary discoverable too. # Make libraries that sit next to the binary discoverable too.
export LD_LIBRARY_PATH="$(dirname "$O3DE_BIN"):${LD_LIBRARY_PATH}" export LD_LIBRARY_PATH="$(dirname "$O3DE_BIN"):${LD_LIBRARY_PATH}"
# Bootstrap O3DE's per-user Python venv if needed. The Project Manager GUI does
# NOT set this up itself - it just errors out ("Missing python venv file ...") if
# the venv is absent. So we ensure it here. python.sh exits non-zero when the
# venv for this engine is missing/stale; get_python.sh then downloads Python,
# creates the venv (~/.o3de/Python, writable) and installs the 'o3de' CLI from
# the prebuilt sdist. It is idempotent and self-healing (recreates a broken venv
# with --clear). cmake, needed for the engine-id calc, ships in the Sdk runtime.
PYTHON_SH=$(find "$O3DE_ROOT" -type f -path '*/python/python.sh' 2>/dev/null | head -n 1)
GET_PYTHON=$(find "$O3DE_ROOT" -type f -path '*/python/get_python.sh' 2>/dev/null | head -n 1)
if [ -n "$GET_PYTHON" ]; then
if ! "$PYTHON_SH" --version >/dev/null 2>&1; then
echo "O3DE: setting up the per-user Python environment." >&2
echo "O3DE: first launch downloads Python and can take several minutes..." >&2
if ! "$GET_PYTHON"; then
echo "error: O3DE Python setup failed (see the log above)." >&2
exit 1
fi
fi
fi
exec "$O3DE_BIN" "$@" exec "$O3DE_BIN" "$@"