Fix read-only /app failure + add app icon

On first launch O3DE pip-installs its 'o3de' CLI with 'pip install -e'
(editable), which writes an egg-info next to the source under read-only
/app and fails ([Errno 30] Read-only file system), leaving the venv broken
("unable to install O3DE's built-in Python").

- Patch cmake/LYPython.cmake at build time to force a normal (non-editable)
  install, which builds in a temp dir and lands in the writable ~/.o3de venv.
- Drop the build-time get_python "bake": the venv is per-user (keyed to
  $HOME), so it can only be created at runtime; baking under a throwaway
  build HOME did nothing. Speeds up CI; removes cmake/python3 build deps and
  the network build-arg.
- Add a real launcher icon (org.o3de.O3DE.png).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-15 12:02:41 +02:00
parent 759c49bbeb
commit f4d2dddd02
5 changed files with 41 additions and 39 deletions
+1 -3
View File
@@ -26,11 +26,9 @@ jobs:
- name: Install build dependencies
run: |
apt-get update
# cmake + python3: O3DE's get_python.sh (run on the host, not in the
# sandbox) uses cmake to fetch its Python runtime.
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
ca-certificates curl git jq xz-utils zstd binutils tar \
flatpak cmake python3
flatpak
# Done as a plain git clone instead of actions/checkout@v4: the bare
# ubuntu image has no Node.js, so JavaScript actions fail with exit 127.
+17 -12
View File
@@ -127,18 +127,23 @@ 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
pull the SDK runtime (larger than Platform) on install — Flatpak does this
automatically from Flathub.
- **Python is baked in at build time.** O3DE normally downloads its Python runtime
into its own install tree on first use, but that tree is read-only inside a
Flatpak. The manifest runs `python/get_python.sh` during the build (with network
access) so Python is part of the immutable image. **This is the most likely step
to need tweaking** — verify it on the first real CI build.
- **Runtime writes into the install tree may still fail.** Anything O3DE tries to
`pip install` or generate *inside* `/opt/O3DE/...` at runtime (e.g. per-gem
Python deps when building certain projects) will hit the read-only `/app`. Base
project building should work; exotic gems may not. This is the main open risk.
- **No launcher icon yet.** The `.deb` ships only in-editor asset icons, so the
desktop entry uses a generic icon. Drop a real O3DE logo into the repo and
install it in the manifest to fix this.
- **Python is per-user, not baked in.** On first launch O3DE downloads its Python
runtime and builds a venv under `~/.o3de` (writable), pip-installing its deps
there. The build does **not** bundle Python — the venv is keyed to the user's
home path, so it can only be created at runtime.
- **The editable-install patch.** O3DE installs its own `o3de` CLI with
`pip install -e`, which writes an `egg-info` next to the source under read-only
`/app` and fails. The build patches `cmake/LYPython.cmake` to use a normal
(non-editable) install, which builds in a temp dir and lands in the `~/.o3de`
venv. If a future O3DE release renames that variable, the build prints a warning
and Python setup will fail at runtime — that's the line to re-check.
- **Other runtime writes into the install tree may still fail.** Anything else
O3DE tries to generate *inside* `/opt/O3DE/...` at runtime (e.g. certain per-gem
Python deps, or the engine-level asset cache) hits the read-only `/app`. Project
data lives in your writable home dir, so normal project work should be fine;
this is the main remaining open risk.
- **Launcher icon** is shipped as `org.o3de.O3DE.png` (the `.deb` itself contains
only in-editor asset icons, none suitable as an app icon).
- **GPU / drivers:** the renderer needs working GPU access. The manifest grants
`--device=dri`/`--device=all`; on some setups you may also want the matching
GPU driver extension from Flathub.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

+10 -16
View File
@@ -28,11 +28,6 @@ finish-args:
modules:
- name: o3de
buildsystem: simple
# The Python bootstrap step (below) downloads O3DE's Python runtime into the
# install tree, so this module needs network access during the build.
build-options:
build-args:
- --share=network
build-commands:
# The .deb is an `ar` archive containing data.tar.{gz,xz,zst}.
- ar x o3de.deb
@@ -42,25 +37,22 @@ modules:
# is kept for robustness in case a future release adds desktop glue there.)
- 'if [ -d data/opt ]; then mkdir -p "${FLATPAK_DEST}/opt"; cp -a data/opt/. "${FLATPAK_DEST}/opt/"; fi'
- 'if [ -d data/usr ]; then cp -a data/usr/. "${FLATPAK_DEST}/"; fi'
# O3DE fetches its own Python runtime on first use, writing into its install
# tree. That tree is read-only at runtime in a Flatpak, so bake Python in now
# while ${FLATPAK_DEST} is still writable.
# On first launch O3DE pip-installs its 'o3de' CLI editable ('pip install
# -e'), which writes an egg-info into read-only /app and fails. Force a
# normal install (built in a temp dir, lands in the writable ~/.o3de venv).
- |
set -e
ENGINE_DIR=$(find "${FLATPAK_DEST}/opt/O3DE" -mindepth 1 -maxdepth 1 -type d | head -n1)
echo "Engine dir: ${ENGINE_DIR}"
if [ -x "${ENGINE_DIR}/python/get_python.sh" ]; then
( cd "${ENGINE_DIR}" && HOME="${PWD}" ./python/get_python.sh )
LYPYTHON=$(find "${FLATPAK_DEST}/opt/O3DE" -path '*/cmake/LYPython.cmake' | head -n1)
if [ -n "$LYPYTHON" ] && grep -q 'set(_pip_install_mode_args "-e")' "$LYPYTHON"; then
sed -i 's/set(_pip_install_mode_args "-e")/set(_pip_install_mode_args "")/' "$LYPYTHON"
else
echo "::warning:: get_python.sh not found; Python may fail at runtime"
echo "::warning:: editable-install line not found in LYPython.cmake"
fi
# Launcher + AppStream + desktop entry under the Flatpak app-id.
- install -Dm755 o3de-wrapper.sh "${FLATPAK_DEST}/bin/o3de-wrapper.sh"
- install -Dm644 org.o3de.O3DE.desktop "${FLATPAK_DEST}/share/applications/org.o3de.O3DE.desktop"
- install -Dm644 org.o3de.O3DE.metainfo.xml "${FLATPAK_DEST}/share/metainfo/org.o3de.O3DE.metainfo.xml"
# NOTE: the .deb ships no clean application icon (only in-editor asset icons),
# so none is installed; the desktop entry falls back to a generic icon. Drop a
# real logo into the repo and install it here to fix the launcher icon.
- install -Dm644 org.o3de.O3DE.png "${FLATPAK_DEST}/share/icons/hicolor/256x256/apps/org.o3de.O3DE.png"
sources:
- type: file
path: o3de.deb
@@ -70,3 +62,5 @@ modules:
path: org.o3de.O3DE.desktop
- type: file
path: org.o3de.O3DE.metainfo.xml
- type: file
path: org.o3de.O3DE.png
+13 -8
View File
@@ -29,21 +29,26 @@ tar -C data -xf data.tar.*
mkdir -p "$DEST/opt"
cp -a data/opt/. "$DEST/opt/"
echo ">> baking O3DE's Python runtime into the image"
# O3DE fetches Python into its install tree on first use, but that tree is
# read-only at runtime in a Flatpak, so populate it now while it is writable.
ENGINE_DIR=$(find "$DEST/opt/O3DE" -mindepth 1 -maxdepth 1 -type d | head -n1)
echo " engine dir: $ENGINE_DIR"
if [ -x "$ENGINE_DIR/python/get_python.sh" ]; then
( cd "$ENGINE_DIR" && HOME="$PWD" ./python/get_python.sh )
echo ">> patching the editable pip install (read-only /app workaround)"
# On first launch O3DE sets up a per-user Python venv in ~/.o3de and pip-installs
# its 'o3de' CLI with 'pip install -e' (editable). Editable mode writes an
# egg-info next to the source under /app, which is read-only in a Flatpak, so it
# fails. Force a normal (non-editable) install instead: pip builds in a temp dir
# and installs into the writable ~/.o3de venv. (Nothing Python-related needs to
# be baked into the image; it all lives per-user under ~/.o3de.)
LYPYTHON=$(find "$DEST/opt/O3DE" -path '*/cmake/LYPython.cmake' | head -n1)
if [ -n "$LYPYTHON" ] && grep -q 'set(_pip_install_mode_args "-e")' "$LYPYTHON"; then
sed -i 's/set(_pip_install_mode_args "-e")/set(_pip_install_mode_args "")/' "$LYPYTHON"
echo " patched: $LYPYTHON"
else
echo " WARNING: get_python.sh not found; Python may fail at runtime" >&2
echo " WARNING: editable-install line not found in LYPython.cmake; O3DE layout may have changed" >&2
fi
echo ">> installing launcher + metadata"
install -Dm755 o3de-wrapper.sh "$DEST/bin/o3de-wrapper.sh"
install -Dm644 org.o3de.O3DE.desktop "$DEST/share/applications/$APP_ID.desktop"
install -Dm644 org.o3de.O3DE.metainfo.xml "$DEST/share/metainfo/$APP_ID.metainfo.xml"
install -Dm644 org.o3de.O3DE.png "$DEST/share/icons/hicolor/256x256/apps/$APP_ID.png"
echo ">> build-finish (command + sandbox permissions)"
flatpak build-finish build-dir \