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 - name: Install build dependencies
run: | run: |
apt-get update 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 \ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
ca-certificates curl git jq xz-utils zstd binutils tar \ 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 # 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. # 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 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 baked in at build time.** O3DE normally downloads its Python runtime - **Python is per-user, not baked in.** On first launch O3DE downloads its Python
into its own install tree on first use, but that tree is read-only inside a runtime and builds a venv under `~/.o3de` (writable), pip-installing its deps
Flatpak. The manifest runs `python/get_python.sh` during the build (with network there. The build does **not** bundle Python — the venv is keyed to the user's
access) so Python is part of the immutable image. **This is the most likely step home path, so it can only be created at runtime.
to need tweaking** — verify it on the first real CI build. - **The editable-install patch.** O3DE installs its own `o3de` CLI with
- **Runtime writes into the install tree may still fail.** Anything O3DE tries to `pip install -e`, which writes an `egg-info` next to the source under read-only
`pip install` or generate *inside* `/opt/O3DE/...` at runtime (e.g. per-gem `/app` and fails. The build patches `cmake/LYPython.cmake` to use a normal
Python deps when building certain projects) will hit the read-only `/app`. Base (non-editable) install, which builds in a temp dir and lands in the `~/.o3de`
project building should work; exotic gems may not. This is the main open risk. venv. If a future O3DE release renames that variable, the build prints a warning
- **No launcher icon yet.** The `.deb` ships only in-editor asset icons, so the and Python setup will fail at runtime — that's the line to re-check.
desktop entry uses a generic icon. Drop a real O3DE logo into the repo and - **Other runtime writes into the install tree may still fail.** Anything else
install it in the manifest to fix this. 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 - **GPU / drivers:** the renderer needs working GPU access. The manifest grants
`--device=dri`/`--device=all`; on some setups you may also want the matching `--device=dri`/`--device=all`; on some setups you may also want the matching
GPU driver extension from Flathub. 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: modules:
- name: o3de - name: o3de
buildsystem: simple 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: build-commands:
# The .deb is an `ar` archive containing data.tar.{gz,xz,zst}. # The .deb is an `ar` archive containing data.tar.{gz,xz,zst}.
- ar x o3de.deb - ar x o3de.deb
@@ -42,25 +37,22 @@ modules:
# is kept for robustness in case a future release adds desktop glue there.) # 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/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' - '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 # On first launch O3DE pip-installs its 'o3de' CLI editable ('pip install
# tree. That tree is read-only at runtime in a Flatpak, so bake Python in now # -e'), which writes an egg-info into read-only /app and fails. Force a
# while ${FLATPAK_DEST} is still writable. # normal install (built in a temp dir, lands in the writable ~/.o3de venv).
- | - |
set -e set -e
ENGINE_DIR=$(find "${FLATPAK_DEST}/opt/O3DE" -mindepth 1 -maxdepth 1 -type d | head -n1) LYPYTHON=$(find "${FLATPAK_DEST}/opt/O3DE" -path '*/cmake/LYPython.cmake' | head -n1)
echo "Engine dir: ${ENGINE_DIR}" if [ -n "$LYPYTHON" ] && grep -q 'set(_pip_install_mode_args "-e")' "$LYPYTHON"; then
if [ -x "${ENGINE_DIR}/python/get_python.sh" ]; then sed -i 's/set(_pip_install_mode_args "-e")/set(_pip_install_mode_args "")/' "$LYPYTHON"
( cd "${ENGINE_DIR}" && HOME="${PWD}" ./python/get_python.sh )
else else
echo "::warning:: get_python.sh not found; Python may fail at runtime" echo "::warning:: editable-install line not found in LYPython.cmake"
fi fi
# Launcher + AppStream + desktop entry under the Flatpak app-id. # Launcher + AppStream + desktop entry under the Flatpak app-id.
- install -Dm755 o3de-wrapper.sh "${FLATPAK_DEST}/bin/o3de-wrapper.sh" - 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.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" - 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), - install -Dm644 org.o3de.O3DE.png "${FLATPAK_DEST}/share/icons/hicolor/256x256/apps/org.o3de.O3DE.png"
# 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.
sources: sources:
- type: file - type: file
path: o3de.deb path: o3de.deb
@@ -70,3 +62,5 @@ modules:
path: org.o3de.O3DE.desktop path: org.o3de.O3DE.desktop
- type: file - type: file
path: org.o3de.O3DE.metainfo.xml 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" mkdir -p "$DEST/opt"
cp -a data/opt/. "$DEST/opt/" cp -a data/opt/. "$DEST/opt/"
echo ">> baking O3DE's Python runtime into the image" echo ">> patching the editable pip install (read-only /app workaround)"
# O3DE fetches Python into its install tree on first use, but that tree is # On first launch O3DE sets up a per-user Python venv in ~/.o3de and pip-installs
# read-only at runtime in a Flatpak, so populate it now while it is writable. # its 'o3de' CLI with 'pip install -e' (editable). Editable mode writes an
ENGINE_DIR=$(find "$DEST/opt/O3DE" -mindepth 1 -maxdepth 1 -type d | head -n1) # egg-info next to the source under /app, which is read-only in a Flatpak, so it
echo " engine dir: $ENGINE_DIR" # fails. Force a normal (non-editable) install instead: pip builds in a temp dir
if [ -x "$ENGINE_DIR/python/get_python.sh" ]; then # and installs into the writable ~/.o3de venv. (Nothing Python-related needs to
( cd "$ENGINE_DIR" && HOME="$PWD" ./python/get_python.sh ) # 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 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 fi
echo ">> installing launcher + metadata" echo ">> installing launcher + metadata"
install -Dm755 o3de-wrapper.sh "$DEST/bin/o3de-wrapper.sh" 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.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.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)" echo ">> build-finish (command + sandbox permissions)"
flatpak build-finish build-dir \ flatpak build-finish build-dir \