diff --git a/.gitea/workflows/build-flatpak.yml b/.gitea/workflows/build-flatpak.yml index 6c27d379e..3f55e0b8b 100644 --- a/.gitea/workflows/build-flatpak.yml +++ b/.gitea/workflows/build-flatpak.yml @@ -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. diff --git a/README.md b/README.md index 4aa75d254..1c68e3d05 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/org.o3de.O3DE.png b/org.o3de.O3DE.png new file mode 100644 index 000000000..a9b9d0e0b Binary files /dev/null and b/org.o3de.O3DE.png differ diff --git a/org.o3de.O3DE.yaml b/org.o3de.O3DE.yaml index 11fe19524..0956020cc 100644 --- a/org.o3de.O3DE.yaml +++ b/org.o3de.O3DE.yaml @@ -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 diff --git a/scripts/make-flatpak.sh b/scripts/make-flatpak.sh index f467dfc3c..e0a6f19a4 100755 --- a/scripts/make-flatpak.sh +++ b/scripts/make-flatpak.sh @@ -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 \