RPM packaging for the Open 3D Engine, targeting Fedora 44+ (including rawhide) and CentOS Stream 10+. Builds run on rpm 4.19 (CS10) and rpm 4.20+ (F44 / F45 / rawhide); spec authoring conventions handle the parser divergence between them (see project_cs10_debuginfo_quirk.md memory note for the two CS10 RPM 4.19 quirks worked around so far).
The same spec produces:
- Stable release builds, from upstream's tagged release tarball (
o3de-<tag>-lfs.tar.gz). These ship tohellaenergy/o3de(the stable channel; broadest audience) and, before they're promoted there, tohellaenergy/o3de-testing(pre-promotion soak; Fedora updates-testing semantics; ~48h soak window for packaging-side fixes queued for stable). Both channels build from the same release tarball; the difference is whether the SRPM has soaked yet. - Snapshot builds, from any git ref of
o3de/o3de. Two upstream branches are common targets and they're not the same thing:stabilization/<X>(currentlystabilization/26100, the 26.10 line cut 2026-08-11), the pre-release stabilization branch for the next tagged release. Ships tohellaenergy/o3de-stabilizationduring the upstream stabilization window (typically a 4-week period before each release tag). Dormant between cycles. When O3DE upstream tags the release (e.g.2610.0), this branch's tip is the release, so snapshots from here are functionally release candidates.development, the bleeding-edge integration branch where new features land daily. Ships tohellaenergy/o3de-development. Its chroots carrydevelopment_snapshot qt6 monolithic, so the build includes the monolithic (release, static) engine permutation and a release game export works from the installed RPM (until 2610.0-127 the exported game aborted when it quit, from static tables in the Maestro gem freed after the engine's allocator; Patch0024 fixed that from 127, the COPR 127 build quits cleanly on F44, F45 and CS10, and since o3de/o3de#20232 merged into development on 2026-10-26 the fix comes from upstream, so the patch now applies only to the stabilization and stable builds; themonolithicbcond graduated here fromo3de-experimentalon 2026-08-03 after two green builds across a dev-tip movement + an end-to-end export validation). Less stable than a stabilization branch; useful for engine contributors testing in-progress work, less appropriate for community testers expecting near-release quality.- Or any other ref, e.g. feature branches, specific commits, tags. Dedicated COPR project per ref rather than overloading the channels above.
Just want to install O3DE? See docs/INSTALL.md for the end-user install steps on Fedora and CentOS Stream. The rest of this README is for building and maintaining the packages.
It also provides an extension point for bundling pre-built O3DE 3rdParty packages into the RPM, gated by per-package --with flags so you only pay for what you use.
o3de-rpm/
├── o3de.spec # the spec
├── README.md # this file
├── ARCHITECTURE.md # source-to-RPM flowchart + design separations
├── Makefile # lint / srpm / copr / test targets
├── FEDORA_ROADMAP.md # path to Fedora inclusion
├── BUNDLED_LIBRARIES.md # per-bundle license + migration status
├── .github/workflows/ # CI
│ ├── lint.yml # spec parse, rpmlint, validators
│ ├── test-installed.yml # integration tests against RPM URL (4h cron)
│ ├── check-deps-drift.yml # weekly dep-pin drift report (Monday 06UTC)
│ └── snapshot-development.yml # weekly dev-tip rebuild into o3de-development (Sunday 06UTC)
├── tests/ # post-install test suite
│ ├── README.md # tier breakdown + community usage
│ ├── integration-test.sh # tiers 1-5 against installed RPM
│ ├── ui-smoke-test.sh # tier 6: Project Manager + Editor smoke under Xvfb
│ └── test-branch.sh # build + install + test from git ref
├── copr-metadata/ # mirror of each COPR project's user-facing docs
│ └── <project>/{description,instructions}.md # pulled/pushed via scripts/copr-metadata.sh
│ {homepage,contact}.txt # make copr-metadata-{pull,diff,push}
├── scripts/ # repo tooling (not packaged into the RPM)
│ ├── copr-metadata.sh # sync copr-metadata/ ↔ live COPR
│ └── copr-download-stats.py # snapshot the COPR download counters as CSV
├── tools/ # repo tooling (not packaged into the RPM)
│ ├── check-deps-drift.py # weekly 3rdParty dep-pin drift report (make check-deps-drift)
│ ├── check-qt6-merge.py # probe: has o3de qt6 merged into development? (make check-qt6-merge)
│ ├── dep-map.yaml # drift detector's package↔dep map
│ └── README.md
└── sources/ # rpm SOURCES dir (sources + patches)
├── o3de-launcher.sh # /usr/bin/o3deNNNN wrapper (Project Manager / Editor GUI)
├── o3de-cli # /usr/bin/o3deNNNN-cli wrapper (project / gem / engine management)
├── rebuild-qt-imageformats.sh # rebuilds bundled Qt6's jpeg/tiff plugins against Fedora libjpeg-turbo/libtiff (o3de#20213)
├── qt{base,imageformats}-everywhere-src-{6.10.2,6.11.2}.tar.xz # plugin sources (6.10.2 stabilization, 6.11.2 development), fetched by `make qt-plugin-sources` (gitignored)
├── o3de.desktop # .desktop entry (Project Manager), mutated to <pkgname>.desktop at install
├── o3de-editor.desktop # .desktop entry (Editor), NoDisplay=true; exists for dock-icon WM_CLASS pairing
├── o3de-material-editor.desktop # .desktop entry (Material Editor), NoDisplay=true; same pattern
├── o3de-material-canvas.desktop # .desktop entry (Material Canvas), NoDisplay=true; same pattern
├── o3de.metainfo.xml # AppStream metainfo, id mutated to org.o3de.O3DE<NNNN> at install
├── o3de{2605,2610}.cdx.json # CycloneDX SBOM, one file per major line (o3de2610 added for 26.10; the spec picks by stable_tag)
├── make-snapshot-tarball.sh # snapshot builder (git clone + git lfs pull + tar; LFS pull is load-bearing)
├── o3de-{16,32,48,64,128,256}x*.png # hicolor app icons (Project Manager, Windows ProjectManager-Icon.ico extract)
├── o3de-editor-{16,32,48,64,128,256}x*.png # hicolor app icons (Editor, Windows o3de_editor.ico extract)
├── o3de-material-editor-*.png # hicolor app icons (Material Editor, Windows MaterialEditor.ico extract)
├── o3de-material-canvas-*.png # hicolor app icons (Material Canvas, Windows MaterialCanvas.ico extract)
├── 0001-clang21-warning-suppressions.patch # 24 patches (0001-0024); see "Patches" section for the table
├── 0002-manifest-py-engine-path-detection.patch # seven carry TIMEBOMB notes (upstream-merged; gated off on the 26.10 base by o3de_base_2610)
├── ... (0003 through 0022) # incl. 0012-v2 (AssetBuilder watchdog); 0014 swap_hook (21-swap gate); 0015 swap_hook Vulkan-layer runtime hunks; 0016 system_tiff (26.05 base only); 0017/0019 system_qt6 (inactive since bundled-Qt6 revert); 0018 pessimizing-move (stabilization + 2610.x release); 0020 newer-clang -Werror; 0021 wayland (not with wayland_ui); 0022 wayland_ui
├── Findmikkelsen-system.cmake # Stage 1 + Stage 2 find-shims (copied to cmake/3rdParty/Find<X>.cmake at %prep
├── Findexpat-system.cmake # when the matching --with system_<lib> bcond is on):
├── FindZLIB-system.cmake # Stage 1: mikkelsen, expat, ZLIB, Freetype, PNG, Lua, lz4, OpenEXR,
├── ... (FindFreetype, FindPNG, FindLua, # Imath, assimp, libsamplerate, poly2tri, SQLite, GoogleBenchmark, TIFF,
├── Find{RapidJSON,xxhash,cityhash}, # RapidJSON (not on CS10: EPEL-10 rapidjson too old), xxhash, cityhash
├── Findlz4, FindOpenEXR, FindImath, # (no vulkan_validation_layers shim, that swap is runtime-discovered
├── Findassimp, Findlibsamplerate, # via VK_LAYER_PATH, no cmake-side find shim)
├── Findpoly2tri, FindSQLite, # Stage 2 library-link: Findmcpp-system.cmake
├── FindGoogleBenchmark) # (which swaps a channel turns on: O3DE_SWAPS in the Makefile)
├── FindTIFF-system.cmake # system_tiff: 26.10 line from 2610.0-123 (a 26.05-base build also needs Patch0016)
├── sqlite-fetchcontent-system.cmake # system_sqlite shim for the FetchContent sqlite (o3de#20072, development)
├── fetchcontent-provider-system.cmake # Source77: replaces development's in-tree rapidjson/xxhash/cityhash/mikktspace providers (o3de#20097)
├── Findmcpp-system.cmake # Stage 2 library-link find shim
└── FindGoogleBenchmark-system.cmake # ACTIVE in stabilization chroots since 2026-05-12
rpmbuild reads sources from _sourcedir, so build invocations point both _sourcedir and _specdir at this checkout, no copying into ~/rpmbuild/SOURCES.
See ARCHITECTURE.md for the source-to-RPM flowchart and the load-bearing design separations (source mode, 3rdParty bundle toggles, system-library swaps, read-only engine + writable user state, multi-channel distribution).
# 1. Compute the upstream tarball SHA256 (one-time per release).
# TAG must match `%global stable_tag` in o3de.spec. stable_tag is currently
# 2610.0 (the 26.10 line, in stabilization; the 26.10.0 tag lands at release,
# targeting Oct 2026). The example below builds the released 26.05.0, so set
# stable_tag=2605.0 to match it.
TAG=2605.0
curl -fLO "https://github.com/o3de/o3de/releases/download/${TAG}/o3de-${TAG}-lfs.tar.gz"
sha256sum "o3de-${TAG}-lfs.tar.gz"
# Paste the hex into o3de.spec under %global stable_sha256.
mv "o3de-${TAG}-lfs.tar.gz" sources/
# 2. Build.
rpmbuild -bb \
--define "_sourcedir $PWD/sources" \
--define "_specdir $PWD" \
o3de.specThe bare rpmbuild above builds with every 3rdParty package bundled. make rpm (and make srpm) build with the stable channel's option set instead, BCONDS_stable in the Makefile (qt6, swap_hook and the system swaps, since 2610.0-122), which is the 26.10 set the hellaenergy/o3de and o3de-testing chroots move to at the 26.10.0 release.
The spec's --with snapshot mode builds from any git ref of o3de/o3de instead of an upstream-tagged release tarball. Which COPR project the resulting RPM lands in depends on the git ref, not on the rpm mode:
stabilization/<release>(currentlystabilization/26100, the 26.10 pre-release branch cut 2026-08-11, the defaultREF) →hellaenergy/o3de-stabilization. Active during the upstream stabilization window (~4 weeks per release cycle); dormant between cycles. Invoke withmake srpm-stabilization/make copr-stabilization. Because 26100 was cut from development tip,srpm-stabilizationnow also sets--with development_snapshotso the dev-aligned carry-patches retire (see Patches).development→hellaenergy/o3de-development(auto-refreshed weekly Sunday 06:00 UTC via.github/workflows/snapshot-development.yml; the workflow dedups against the last successful build so quiet weeks skip). Manual fires:make copr-developmentlocally, or workflow_dispatch from the Actions tab with the optionalforceinput to bypass dedup.- arbitrary other ref (e.g. a one-off feature branch or a release candidate under test) → dedicated COPR project per branch. Build locally with
make srpm-snapshot-ref REF=<other>andcopr-cli builddirectly.
Both paths use --with snapshot under the hood; the project split is a publishing-channel choice, not a build-mode choice. See the bullets at the top of this README for the upstream-branch distinction. o3de-rpm itself is single-branch (main); the channel a build lands in is chosen by its bconds and the upstream engine ref it targets, not by a packaging-repo branch.
# 1. Generate a reproducible snapshot tarball + checksum.
cd sources
./make-snapshot-tarball.sh stabilization/26100 # next-release branch → o3de-stabilization
# ./make-snapshot-tarball.sh development # bleeding-edge → o3de-development
# ./make-snapshot-tarball.sh <commit-sha> # any specific ref → dedicated COPR project
cd ..
# 2. Paste the printed snapshot_commit / snapshot_date / snapshot_sha256
# into the corresponding %global lines in o3de.spec.
# 3. Build.
rpmbuild -bb --with snapshot \
--define "_sourcedir $PWD/sources" \
--define "_specdir $PWD" \
o3de.specThe resulting version string is <stable_tag>^<YYYYMMDD>git<shortsha> (e.g. 2610.0^20260814gita189c8a). The ^ separator marks a post-release snapshot: it sorts after <stable_tag> and before any later release, so a development snapshot of 2610.0 is newer than 2610.0 and older than 2610.1. Stabilization builds use ~ instead (e.g. 2610.0~20261021git701b503), which sorts before <stable_tag>, so dnf upgrades a stabilization build to the tagged release.
The engine fetches its LY_3RDPARTY_PATH packages from O3DE's package server during cmake configure by default. To make the RPM self-contained for an offline target, drop the bundle tarball into sources/ and pass --with thirdparty_<name>.
The spec ships two example toggles (physx, openexr); add more by:
- Drop the package tarball in
sources/, e.g.physx-5.1.1-rev1-linux.tar.xz. - Add a
%bcond_with thirdparty_<name>line. - Add a matching
Source10x: <filename>line. - Add an extract line in
%prep:%{?with_thirdparty_<name>:tar -xf %{SOURCE10x} -C %{_builddir}/%{o3de_source_dir}/3rdParty}
Then build with any subset of toggles:
rpmbuild -bb --with thirdparty_physx --with thirdparty_openexr \
--define "_sourcedir $PWD/sources" \
--define "_specdir $PWD" \
o3de.specThe full list of approved package names and revisions lives in O3DE's cmake/3rdParty/Platform/Linux/BuiltInPackages_linux_x86_64.cmake.
The default build ships only the profile-config binaries (sufficient for end-user game development). To also build debug-config binaries and ship them as the o3deNNNN-debug subpackage (e.g. o3de2605-debug):
rpmbuild -bb --with debug ...This roughly doubles build time (debug compiles all the same TUs at -O0 with full symbols). End users install it with dnf install o3de2605 o3de2605-devel o3de2605-debug to step through engine internals; o3de2605-debug requires the same exact NVR of o3de2605 so they always upgrade in lockstep. Switching the launcher between configs is a runtime concern: O3DE_BUILD_CONFIG=debug o3de2605.
The o3de2605 RPM is split into a small number of subpackages so each install can match the actual workload. Concrete value:
- Smaller default install. The post-split main package is ~1.7 GB compressed (down from ~2.2 GB pre-split, roughly 22% smaller). On disk, runtime-only deployments save ~4 GB by skipping the engine static archives. (The default
dnf install o3de2605still pulls-develviaRecommends:so project authors get a working build out of the box; runtime-only consumers opt out with--setopt=install_weak_deps=False.) - Right tool for your use case. Three orthogonal install dimensions: runtime (the main package's binaries; sufficient to launch Project Manager + the Editor), static-archive link surface for building projects (
-devel; auto-recommended), step-through debuggability of engine internals (-debug). Project authors get the runtime +-develpair by default; engine-internal debuggers add-debug; pure runtime-only deployments opt out of-devel. - CI- and container-friendly. Game distribution servers shipping pre-built games, CI test containers, and minimal Docker images can skip ~4 GB of compiler-side material.
dnf install --setopt=install_weak_deps=False o3de2605opts out of even the project-build*-develsystem Recommends list, the absolute floor for a runtime-only deployment. - Aligned with Fedora packaging guidelines. Fedora's Packaging Guidelines require a
-develsubpackage for any C/C++ package shipping static libraries, and recommend split-by-purpose for large packages. Doing this split proactively (rather than during the Fedora package review) removes one entire class of review friction. Same with the project-build*-develRecommends pattern (clang, mesa-libGL[U]-devel, libxcb-devel, the xcb-util-*-devel suite (xcb-util-devel, xcb-util-image-devel, xcb-util-keysyms-devel, xcb-util-renderutil-devel, xcb-util-wm-devel), libxkbcommon-devel, libxkbcommon-x11-devel, wayland-devel (Qt6 lines, 26.10+), fontconfig-devel, libcurl-devel, pcre2-devel, openssl-devel, libunwind-devel, libzstd-devel, zlib-devel, vim-common, plus per-active Stage 1 swap like mikkelsen-devel): testers get a working build experience by default; minimal users opt out. - Forward-compatible with multi-major. When
o3de2605-develando3de2610-develboth exist someday, they're independent: install the devel surface only for the major you actually develop against, not all of them.
The main RPM ships alongside up to two optional subpackages:
| Package | Contents | When to install |
|---|---|---|
o3de2605 (main) |
Engine binaries (bin/Linux/profile/Default/), runtime cmake config + per-target import files, headers, gem sources, scripts, Templates, Editor assets, Python bootstrap, SBOM. Recommends o3de2605-devel so dnf pulls it in by default. |
Always. The runtime + the materials needed to launch the Editor and Project Manager. |
o3de2605-devel |
Static archives (lib/Linux/profile/Default/*.a, plus lib64/ on 26.05; 26.10 has none), about 178 .a files totalling ~4 GB. Includes libAzGameFramework.a, libAzCore static surfaces, libAtomCore.a, libAssetBuilderSDK.a, and the rest of the engine's .a link surface. |
Always for project authors. Project Manager's "Build" workflow links any GameLauncher / ServerLauncher / HeadlessServerLauncher target against these archives; without -devel the cmake --build step fails at ninja with libAzGameFramework.a, needed by ..., missing. The only case for skipping -devel is a pure runtime-only deployment (e.g., headless server host running pre-built binaries from elsewhere) which is rare. |
o3de2605-debug |
Debug-config binaries (bin/Linux/debug/) + matching static archives (lib/Linux/debug/). Full debug symbols, -O0. |
Add when you need to step through engine code in a debugger. Set O3DE_BUILD_CONFIG=debug to launch the debug build. |
The install instructions name o3de2605-devel explicitly, because every project build links its launchers against the static archives it carries. The main package also pulls it in through Recommends:, which --setopt=install_weak_deps=False turns off; skip -devel only on a machine that never builds a project. The project-build *-devel system packages (clang, mesa-libGL[U]-devel, libxcb-devel, the xcb-util-*-devel suite (xcb-util-devel, xcb-util-image-devel, xcb-util-keysyms-devel, xcb-util-renderutil-devel, xcb-util-wm-devel), libxkbcommon-devel, libxkbcommon-x11-devel, wayland-devel (Qt6 lines, 26.10+), fontconfig-devel, libcurl-devel, pcre2-devel, openssl-devel, libunwind-devel, libzstd-devel, zlib-devel, vim-common, plus the *-devel for any active Stage 1 system-library swap like mikkelsen-devel) are pulled in via the same Recommends: list; installed by default unless you pass --setopt=install_weak_deps=False. From 2610.0-125 the -devel subpackage hard-Requires the swap *-devel packages (19 on Fedora, 18 on CentOS Stream 10), and the installed SDK records which system libraries the engine was built with (LY_USE_SYSTEM_* in cmake/3rdParty/Platform/Linux/BuiltInPackages_linux_*.cmake), so a project build links the same system libraries instead of downloading the bundled packages. Before -125 a project's GameLauncher could link a bundled Lua 5.4 next to the engine's system Lua and crash at startup.
Each major release ships as its own versioned package (o3de2605, o3de2610, …) so multiple O3DE versions can coexist. Two PATH-installed entry points per package; the examples below use 26.05.0 (o3de2605):
| Command | Purpose |
|---|---|
o3de2605 |
Launches the GUI (Project Manager by default). Set O3DE_BUILD_CONFIG=debug for the debug-config engine if o3de2605-debug is also installed. |
o3de2605-cli |
Forwards to the upstream Python CLI at /opt/O3DE/26.05.0/scripts/o3de.sh for project / gem / engine management. |
The CLI covers ~25 sub-commands. Common ones:
o3de2605-cli --help # list sub-commands
o3de2605-cli register --this-engine # one-time per-user setup (o3de2610-cli does it on first use)
o3de2605-cli get-registered -df engines # list registered engines (or projects/gems/templates)
o3de2605-cli create-project --project-path ~/MyGame --project-name MyGame
o3de2605-cli create-gem --gem-path ~/MyGem --gem-name MyGem
o3de2605-cli enable-gem --project-path ~/MyGame --gem-name Atom
o3de2605-cli edit-engine-properties --display-name "My Engine"
o3de2605-cli export-project --project-path ~/MyGame # bundle a runtime build
o3de2605-cli sha256 <file> # compute the hash O3DE expects in package manifestsOn a Wayland desktop the launcher starts Project Manager through XWayland (QT_QPA_PLATFORM=xcb) unless QT_QPA_PLATFORM is already set, so its window class matches the desktop entry and the dock shows the O3DE icon; 26.10 Editor builds support X11 and XWayland only, and the Editor makes the same choice itself. Do not set QT_QPA_PLATFORM=wayland on these builds: the Editor crashes at startup (see Known limitations). Only --with wayland builds (o3de-experimental) leave the choice to Qt.
State written by either command lives under ~/.o3de/ (engine registration manifest, per-user Python venvs keyed by engine path, project user data). The engine root at /opt/O3DE/26.05.0/ is read-only.
The first launch of Project Manager (o3de2605, o3de2610) sets up the per-user Python venv and registers the engine in ~/.o3de. o3de2610-cli does the same on its first run and reruns get_python.sh after an upgrade changes the Python package. With o3de2605-cli, run python/get_python.sh from the engine root and then register --this-engine before the first command; until then create-project fails with "Python has not been downloaded/configured yet" and a project configure with "Engine registration is required".
The /opt/O3DE/<version>/ install layout follows the same pattern as upstream's .deb and Windows installer, so cross-platform users see the same paths on Fedora, Debian/Ubuntu, and Windows. Unlike the .deb, whose package is named o3de for every release (installing 26.10 replaces 26.05), the RPM majors install side by side. dnf treats each major as an independent package:
sudo dnf install o3de2605 o3de2605-devel o3de2610 o3de2610-devel # both majors side-by-side
o3de2605 # launches 26.05.0 Project Manager
o3de2610 # launches 26.10.0 Project Manager
ls /opt/O3DE/ # 26.05.0 26.10.0On the manifest: all installed o3deNNNN majors share engine_name: "o3de" in their engine.json (the name in upstream's source engine.json, so third-party gems' compatible_engines checks resolve; upstream's .deb installs as o3de-sdk instead, and uses one package name for every release, so a new .deb replaces the previous one). Each major adds itself to ~/.o3de/o3de_manifest.json when its Project Manager starts or its CLI first runs, and both majors then stay registered. A project configures against the newest registered engine that its project.json engine field accepts, and a new project gets a plain "engine": "o3de", which accepts either major. So once 26.10 is registered, a 26.05 project builds against 26.10 at its next configure. To keep a project on 26.05, pin it:
# writes engine_path to <project>/user/project.json; the configure then uses that engine
o3de2610-cli edit-project-properties -pp ~/MyGame --user --engine-path /opt/O3DE/26.05.0
# remove the pin (with o3de2610-cli: 26.05's o3de.sh drops empty arguments)
o3de2610-cli edit-project-properties -pp ~/MyGame --user --engine-path ""register --this-engine only moves an engine to the front of the manifest's list; it does not change which engine a project uses. register --this-engine --remove takes an engine out of the list until its Project Manager or CLI runs again. Checked on Fedora 44 with 2605.0-95 and 2610.0-126 installed together (2026-10-21).
Subpackages follow the same versioning: o3de2605-debug and o3de2610-debug are independent and co-installable. Cross-major dnf upgrades are intentionally NOT automatic: different majors are different engine lines and you opt in explicitly with dnf install o3de2610 when ready.
This RPM ships the engine plus the ~117 gems sourced from the o3de/o3de repository. Additional gems live in o3de/o3de-extras and are discovered automatically by Project Manager via a default-registered remote gem repository. They appear in the gem catalog with a download-cloud icon and fetch on demand into ~/.o3de/gems/<gem-name>/ when you click "Download Gem". Some of those remote gems require external runtime libraries the engine RPM does NOT bundle (most notably the ROS 2 family, AudioEngineWwise, OpenXRVk). See docs/GEMS_WITH_SYSTEM_DEPS.md for which gems need what, install paths for each runtime on Fedora 44+ / CentOS Stream 10+, and the project-build workflow. For the ROS 2 Gems on 26.10 and newer, sudo dnf copr enable hellaenergy/ros2 && sudo dnf install ros-lyrical-o3de-gem-deps installs everything they link against; the engine package lists it as a Suggests:.
The o3de RPM has four distribution targets, in order of how soon each is reachable. The first (COPR) is itself a multi-channel layout (eight projects) with a clear promotion flow described below.
The interim distribution channel. Five engine COPR projects (plus two debug-config siblings and a dependencies project), each with a distinct purpose:
hellaenergy/o3de-dependencies. Fedora-clean SRPMs for O3DE 3rdParty packages that aren't in Fedora proper (custom Qt 5.15-rev9, PhysX, AWSNativeSDK, azslc, mikkelsen, the Stage 2 rebuilds o3de-dxc-spirv / o3de-spirv-cross / o3de-mcpp-az / o3de-cityhash, ...).enable_net=false. Built first; consumed by the engine projects viaadditional_reposat build time andruntime_dependenciesat consume time (so users get it auto-enabled when they enable any engine project).hellaenergy/o3de. stable channel. Trackso3de/o3de:main(the upstream release branch where tagged releases land:2510.2,2605.0, etc.). End users on Fedora shoulddnf copr enablethis for a stable, supportable install. SeePOST_RELEASE.mdfor the post-release-ceremony runbook.hellaenergy/o3de-testing. pre-promotion soak channel for stable. Same engine source tag as stable, with packaging-side bug fixes and minor enhancements that are queued for promotion tohellaenergy/o3de. Mirrors Fedora'supdates-testingsemantics: enable this channel if you want to validate the next set of packaging fixes a couple of days before they reach the broader stable channel. Promotion flow:main HEAD -> testing (~48h soak) -> stable. Pick ONE ofo3deoro3de-testingto enable; enabling both is technically possible butdnfwill always install the higher NVR (testing's) which defeats the purpose of stable.hellaenergy/o3de-stabilization. pre-release validation builds from upstream'sstabilization/<release>branch. Active during the 4-week pre-release window when an upstream release is being stabilized (stabilization/26050was active April-May 2026; currently active forstabilization/26100, the 26.10 line cut 2026-08-11, targeting an Oct 28 release). Dormant between release cycles. The community testers' channel during active windows.hellaenergy/o3de-development. ad-hoc cadence builds from upstream'sdevelopmentbranch (bleeding-edge engine). Chroots carrydevelopment_snapshot qt6 monolithicplusswap_hookand the system swaps (themonolithicbcond was promoted here fromo3de-experimentalon 2026-08-03), so the build ships the monolithic (release, static) engine permutation and a release game export works from the installed RPM. For arbitrary other engine refs (e.g. a one-off feature branch or release candidate under test) we'd create a dedicated COPR project per branch rather than overload this one.hellaenergy/o3de-experimental. packagers' sandbox for work not yet ready for the community channels. Realigned 2026-07-24 ontoo3de/development(off its former Stage-1 system-swap base;stabilization/26050shipped as 26.05.0 and is frozen). It now carries the native-Wayland preview: its chroots (F44 and F45, plus rawhide and CentOS Stream 10 since 2610.0-125) build the same dev-snapshot aso3de-developmentwithdevelopment_snapshot qt6 swap_hook wayland wayland_ui(Patch0021/Patch0022), withoutmonolithic(which graduated too3de-developmenton 2026-08-03). Distinguished by the-development.<commit>channel marker. Not for end-user testing; internal to the packaging effort.hellaenergy/o3de-testing-debugandhellaenergy/o3de-development-debug. debug-config siblings ofo3de-testingando3de-development. Each builds the identical NVR as its namesake plus theo3de2605-debugsubpackage (the--with debugengine config:-O0+ full debug symbols), so a tester who hits a crash candnf install o3de2605-debugand report a real stack trace instead of a profile build silently closing. Enable alongside the namesake channel (the-debugsubpackage hard-requires the matching main package's exact NVR, so the two projects are refreshed in lockstep from the same SRPM). AppStream is off so the debug repo's copy of the main package doesn't show as a duplicate app in GNOME Software.make copr-testing-debug/make copr-development-debugrefresh them.
Every engine project builds with the same system-library swap list (O3DE_SWAPS in the Makefile). Since 2610.0-123 that is 21 libraries on the 26.10 line (18 Stage 1 + 3 Stage 2; 20 on CentOS Stream 10, which keeps the bundled rapidjson because EPEL-10's is too old), adding rapidjson, xxhash, cityhash and libtiff to the earlier 17. o3de-development, o3de-experimental and o3de-development-debug carry it since 2610.0-123 and o3de-stabilization since 2610.0-125; o3de / o3de-testing get it with the 26.10.0 release (planned 2026-10-28). Until then the stable channels ship 26.05.0 with the 17 plus rapidjson, xxhash and cityhash.
All the engine projects use enable_net=true so cmake can still fetch the remaining bundles from packages.o3de.org. The licensing-restricted set is now two packages (NvCloth's NVIDIA license, squish-ccr's BC7 patent encumbrance); DXC retired from this set on 2026-05-08 when the license-clean DXC rebuild shipped in o3de-dependencies. poly2tri was a fourth restricted entry until the 2026-05-07 audit reframed it as a Stage 1 swap candidate; it now resolves through Fedora's poly2tri-devel when the swap is active.
The official O3DE binary distribution, serving the .deb / snap / Windows packages for direct download. Since 2026-10-19 it also carries RPM install instructions that point to the COPR channels and docs/INSTALL.md; it does not host the RPMs themselves. Upstreaming the spec into the O3DE source tree (likely under cmake/Platform/Linux/Packaging/) so O3DE's own CI builds the RPM is still the goal, but a recent constraint reshapes what "host it there" can mean. Unlike the .deb and snap, which are self-contained bundles, this RPM resolves dependencies from a repository at install time: it Requires the o3de-dependencies packages (the license-clean DXC, mcpp, SPIRV-Cross, and cityhash rebuilds), which are not in Fedora, alongside the Fedora system libraries it swaps to. o3debinaries.org is a static download host, not a dnf repository, so a loose .rpm published there would fail dependency resolution on dnf install (nothing provides the o3de-dependencies packages).
Making o3debinaries.org a real distribution point therefore needs one of: O3DE standing up an actual dnf repo (with repodata) carrying both the engine RPM and the o3de-dependencies packages; those dependencies landing in Fedora proper so they resolve from the distro; or folding them into the RPM itself (which fights the Fedora-clean, no-bundling direction). Until one of those exists, the working end-user path stays the COPR channels, which auto-enable hellaenergy/o3de-dependencies via runtime_dependencies, and, longer term, Fedora proper.
What carries over regardless of the host: align the spec with O3DE's packaging conventions, drop hellaenergy/-specific assumptions (the spec itself stays distribution-agnostic; Makefile targets stay local), and get it accepted by O3DE's release engineering. Most Fedora-inclusion prep applies directly (Stage 1 system-lib migration, the license-clean DXC rebuild).
See FEDORA_ROADMAP.md for the staged plan. Six stages from system-lib migration through OpenSSL 3.x port, debuginfo subpackages, and Bundling Library Exception filings (current set: Qt 5.15-rev9 (26.05 line), Qt6 6.10.2 (26.10 line: the system_qt6 swap is implemented but blocked for shipping by the bundled PySide6's Qt_6_PRIVATE_API pin, so Qt6 ships bundled until Option B), squish-ccr, NvCloth; DXC retired 2026-05-28 after the license-clean rebuild shipped; libtiff retired 2026-06-05 when Patch0016's TIFF_DISABLE_DEPRECATED unblocked the system_tiff swap; upstream merged it as o3de/o3de#19825, and system_tiff ships on the 26.10 line from 2610.0-123) before the package review submission.
A Flatpak build is planned in a sibling repo, not started yet. Findings from this RPM that carry over are collected as working notes (FLATPAK_NOTES.md, kept out of git) so that repo starts from what the RPM already learned.
The spec is RPM / DNF / mock-conformant with no Fedora-edition-specific assumptions, so it should build on any Fedora-derivative that consumes Fedora sources via the standard packaging pipeline. We don't currently target any beyond the four covered above (F44, F45, rawhide, CS10), and we won't pre-emptively add chroots, but if a downstream community (e.g. the Fedora Hummingbird SIG targeting cloud-native builders, or any other RPM-based derivative) signals a felt need for an O3DE-on-X variant, the spec is ready to be a starting point. Likely-narrow shapes for those follow-ons: headless server-launcher containers, or asset-bake CI images that ship o3de2605 without the Editor/UI subset. The wider Editor + GUI workload is a poor fit for distroless / minimal-image targets.
To consume (end users):
# Pick ONE channel. Don't enable multiple at the same time.
#
# hellaenergy/o3de stable. Most users want this. Tracks
# upstream tagged releases (26.05.0,
# 26.05.1, ...) and post-soak promotions
# from o3de-testing.
#
# hellaenergy/o3de-testing pre-promotion soak for stable. Same
# engine source tag, slightly newer
# packaging fixes queued for stable.
# ~48h soak window. Enable this if you
# want to validate packaging fixes a
# couple of days before they reach
# stable users; report regressions if
# you hit any.
#
# hellaenergy/o3de-stabilization
# pre-release engine validation, active
# during the 4-week upstream stabilization
# window per release cycle. Dormant
# between cycles. Enable only when an
# upstream stabilization branch is
# active and you want to validate the
# NEXT release candidate.
sudo dnf copr enable hellaenergy/o3de # change to o3de-testing if you want pre-stable soak
sudo dnf install o3de2605 o3de2605-devel # ~2 GB main + ~4 GB -devel; project builds need -devel
o3de2605 # launch Project Manager (GUI)
o3de2605-cli --help # CLI for project / gem / engine managementThe package name follows a o3deNNNN convention (postgresql-style): NNNN is the upstream major as YYMM (2605 for 26.05.x, 2610 for the next major). The install path under /opt/O3DE/<DISPLAY_VERSION>/ matches what the upstream .deb and Windows .msi installers ship: same path mental model across distros and OSes.
hellaenergy/o3de-dependencies auto-enables alongside the engine project (via the engine project's runtime_dependencies setting), no separate dnf copr enable needed.
On CentOS Stream 10, enable CRB and EPEL 10 before installing: they provide assimp, google-benchmark, libunwind and poly2tri, and without them dnf stops with "nothing provides" errors. The EPEL repo in the CS10 chroot config only applies at COPR build time, not on the user's machine (verified by a dnf dry run in a clean centos:stream10 container, 2026-10-19).
sudo dnf install dnf-plugins-core
sudo dnf config-manager --set-enabled crb
sudo dnf install epel-release
sudo dnf copr enable hellaenergy/o3de centos-stream-10-x86_64 # name the chroot: a plain enable looks for epel-10-x86_64 and failsThe per-user Python venv bootstraps on first launch automatically; pre-bootstrap manually with /opt/O3DE/26.05.0/python/get_python.sh if preferred.
When O3DE upstream tags a stable release, swap o3de-stabilization for o3de (the package name stays the same, o3de2610 for 26.10; only the COPR project changes). Skip o3de-development (dev-branch builds) and o3de-experimental (packaging work) unless you have a specific reason to test those.
To publish from this checkout:
make snapshot REF=stabilization/26100 # generate tarball + print pin values
$EDITOR o3de.spec # paste the printed snapshot_* macros
make copr-stabilization # SRPM → hellaenergy/o3de-stabilization (testers)
make copr-stabilization-and-test # same + watch build + fire CI tests on success
make copr-development # SRPM → hellaenergy/o3de-development (dev-branch tip + monolithic)
make copr-development-and-test # same + watch + fire CI tests
make copr-experimental # SRPM → hellaenergy/o3de-experimental (development + monolithic)
make copr-experimental-and-test # same + watch + fire CI tests
make copr-stable # SRPM → hellaenergy/o3de (when tagged)
make trigger-tests BUILD_ID=N # fire CI tests against an existing COPR buildA make copr-init target prints the one-time setup commands for all the COPR projects (chroot configs, runtime-repo-dependency, --rpmbuild-with flags for active Stage 1 migrations). One swap list, O3DE_SWAPS in the Makefile, feeds every channel's flag set, and make -s print-copr-with CHANNEL=<stable|stabilization|development|experimental> [CHROOT=<chroot>] prints the full --rpmbuild-with list a chroot should carry (CS10 drops rapidjson). Run make help for the full target list.
CI (.github/workflows/lint.yml) runs spec-parse (default + stable-channel + snapshot + stabilization + experimental modes) + rpmlint + desktop-file-validate + appstream-util validate + shell-syntax checks on every push, against a Fedora 44 container. CI (.github/workflows/test-installed.yml) runs the integration test suite (Tiers 1-6) against an existing COPR RPM URL in clean F44 + F45 + rawhide containers, triggered manually, by make trigger-tests, or by a 4-hourly cron polling o3de-testing for new builds. The full RPM build itself is too heavy for free runners (>2 hours, 14 GB output). The COPR projects do that.
The longer-term goal is inclusion in Fedora proper. The roadmap lives in FEDORA_ROADMAP.md and the per-bundle Fedora-readiness status in BUNDLED_LIBRARIES.md.
A tiered post-install test suite lives in tests/. It exists for three audiences:
- This repo's maintainer: catch regressions between spec changes
- O3DE engine contributors: validate that your branch builds and runs as a Fedora RPM before merging
- O3DE release engineering: gate releases on "does this work as a packaged engine on Fedora?"
The same suite serves all three. Differences are only in which git ref produced the RPM under test.
sudo dnf install -y ./o3de2605-*.rpm # or whichever o3deNNNN.rpm
# Quick pass (rpm-level + install integrity + engine smoke, no state changes)
make test
# Add per-user setup (downloads the bundled-Python venv, registers the engine)
make test-setup
# Full end-to-end (also creates a project + cmake-configures it)
make test-full
# UI smoke: Project Manager launches under Xvfb without crashing
sudo dnf install -y xorg-x11-server-Xvfb scrot xorg-x11-utils
make test-ui
# UI smoke + Editor scripted automation
make test-ui-fullTier 6 (UI) uses Xvfb (virtual display) and Mesa lavapipe (software Vulkan in CI containers; real GPU on user workstations). Tier 11 (post-load liveness: launcher survives N seconds after level load without crash/freeze, catches "level loaded but engine froze immediately" failures Tier 9/10 can't detect) was implemented 2026-05-22; invoke via make test-tier11 (default project NewspaperDeliveryGame) or make test-tier11-multiplayer. Tier 12 (render correctness: Vulkan render vs reference image; needs GPU-equipped runners) and Tier 13 (visual regression: screenshots → pixel-diff against per-Fedora-version baselines) are documented as future work in tests/README.md.
Two community O3DE samples are wired up as end-to-end tests on Fedora:
make test-multiplayer-sample # Tier 9: o3de-multiplayersample
make test-newspaper-delivery # Tier 10: NewspaperDeliveryGame (Paper_Kid)NewspaperDeliveryGame is fully playable on Fedora 44 against the installed o3de2605 RPM as of 2026-05-21 (title screen, character control, score / lives / home-time HUD, the neighborhood with houses + delivery truck + props all render and run cleanly).
MultiplayerSample is playable on Linux against the installed o3de2605 RPM as of 2026-05-22: launcher loads startmenu, MULTIPLAYER SAMPLE title screen renders with the cyberpunk UI, network stack initializes, and (with make play-mps-host + make play-mps-client) a full host+connect session over loopback runs the actual NewStarbase gameplay. For Tier 9 to find AssetProcessor's BehaviorContext for scriptcanvas baking, build BOTH MultiplayerSample.GameLauncher and the bare MultiplayerSample target (the test script does this automatically; the upstream README at line 200+ now documents the requirement for manual builds via PR #502).
The test scripts auto-recover from common upstream-side issues (LFS server transients, working-tree pointer files, AWS Lambda batch-size limits, level startup overrides), so a clean clone + RPM install exercises the build and bake path without manual intervention. Wall time: Tier 9 ~60-90 min cold-cache (full C++ build + asset bake), ~3-10 min warm. Tier 10 ~30-60 min cold, ~3-10 min warm.
After running, launch the working sample directly:
# Paper_Kid: Newspaper Delivery Game (single-player, plays clean)
/opt/O3DE/26.05.0/bin/Linux/profile/Default/O3DE.GameLauncher \
--project-path=$HOME/PROJECTS/NewspaperDeliveryGame \
--engine-path=/opt/O3DE/26.05.0 \
--regset="/O3DE/Autoexec/ConsoleCommands/LoadLevel=Neighborhood" \
--regset="/O3DE/Autoexec/ConsoleCommands/bg_ConnectToAssetProcessor=0"
# MultiplayerSample client only (loads startmenu; for full host+join, use 'make play-mps-host' below)
$HOME/PROJECTS/o3de-multiplayersample/build/linux/bin/profile/MultiplayerSample.GameLauncher \
--project-path=$HOME/PROJECTS/o3de-multiplayersample \
--regset="/O3DE/Autoexec/ConsoleCommands/bg_ConnectToAssetProcessor=0"make test-multiplayer-sample (Tier 9) builds the full multiplayer harness: client + headless server + spectator-mode server + the bare gem AssetProcessor needs. After it completes, you can host + join a session on a single machine via three make targets:
make play-mps-host # starts the headless server (NewStarbase, listens on UDP 33450)
make play-mps-client # starts the windowed client (auto-connects to loopback)
make play-mps-stop # kills all MPS launcher processesThe targets check for the binaries being built and bail with a helpful error if Tier 9 hasn't run yet. Variables MPSAMPLE_PLAY_DIR and MPSAMPLE_ENGINE let you override the project clone location or engine install path.
Behind the scenes the targets use MultiplayerSample.HeadlessServerLauncher (no GUI) + MultiplayerSample.GameLauncher with r_fullscreen=0. This is the configuration that's stable for sustained play; see FOLLOW_UPS.md for the diagnosis of why the graphical ServerLauncher variant + client + in-game settings menu hit a dual-respawn crash. For dev/debug needing a server-side spectator view, run MultiplayerSample.ServerLauncher directly (built by Tier 9 alongside the other binaries) but don't touch the client's settings menu while it's up.
The project ships two console-command files at its root that drive the launch:
launch_server.cfg: loadsLevels/NewStarbase/NewStarbase.spawnableand enables multithreaded connection updateslaunch_client.cfg: issuesconnectwith no IP, which defaults to loopback127.0.0.1
The launchers can also be invoked directly with explicit flags if you want a different config (different level, remote server IP, etc.). See Makefile play-mps-* targets for the canonical command shape.
For O3DE engine contributors who want to know "does my branch work as a Fedora RPM":
git clone https://github.com/nickschuetz/o3de-rpm
cd o3de-rpm
make test-branch REF=stabilization/26100 # or any git ref / release tagThis builds the snapshot tarball, patches the spec with the right pin values, runs rpmbuild, installs the resulting RPM, then runs the full test suite. Plan ~30-40 minutes for the build on a 32 GB workstation, plus ~10 minutes for install + test. tests/test-branch.sh builds with --with snapshot only: no system swaps, and no development_snapshot, so on a 26.10-base ref (stabilization/26100, development) the spec still declares the 26.05-base carry-patches and %prep is expected to fail at Patch0001 (see FOLLOW_UPS.md, 2026-10-21). ~70 GB free disk space required for the build tree + cached packages.
.github/workflows/test-installed.yml runs the test suite in clean Fedora containers (matrix: fedora-44, fedora-45, fedora-rawhide, extending as releases ship) against an RPM URL, typically a COPR build artifact. Trigger via GitHub UI with an rpm_url input. The CentOS Stream 10 chroot is exercised per-build on COPR (its own centos-stream-10-x86_64 build of every SRPM) but not currently in the GH-Actions matrix; CS10 builds going green on COPR is the gate for that chroot.
For automated COPR → CI integration, configure a COPR webhook to fire this workflow on every successful build, giving any branch a "healthy on Fedora" signal.
See tests/README.md for the full tier breakdown and contribution guide.
| Concern | Mitigation |
|---|---|
| Tampered upstream tarball | %prep verifies Source0 against %global stable_sha256 (or snapshot_sha256) with sha256sum -c before extraction. |
| Tampered snapshot | make-snapshot-tarball.sh is reproducible (sorted, fixed mtime, numeric owner); re-running for the same commit produces a byte-identical tarball. The committed sha256 is the binding root of trust. |
World-writable files under /usr |
Removed. /opt/O3DE/<version>/ is fully read-only after install; all writable state is per-user under ~/.o3de/. |
| Network during build | LFS objects are bundled into the source tarball before build; no git lfs pull runs in %build. O3DE's own LY_PACKAGE_SERVER_URLS 3rdParty fetcher still runs at cmake configure unless every needed package is pre-bundled; see "3rdParty packages" above. |
| ⚠ Bundled OpenSSL 1.1.1t (EOL since 2023-09-11) | Not our packaging defect; upstream O3DE pins it. Tracked as a hard blocker for Fedora inclusion in FEDORA_ROADMAP.md (stage 4). Surfaced here so consumers see it clearly. |
Hardening flags (RELRO / BIND_NOW / stack-protector / _FORTIFY_SOURCE) |
Restored explicitly via CMAKE_*_LINKER_FLAGS_INIT after unsetting Fedora's CFLAGS/CXXFLAGS/LDFLAGS bundle (the bundle's annobin specs file breaks clang feature tests). O3DE's Configurations_clang.cmake already supplies stack-protector and _FORTIFY_SOURCE. |
| Runtime escalation paths | Launcher wrapper is /usr/bin/o3deNNNN and CLI wrapper is /usr/bin/o3deNNNN-cli, both mode 0755, no setuid. All mkdir -p targets are under $HOME. |
| Patch reviewability | Real .patch files with From:/Subject: rationales, reviewable with git log or interdiff. |
| Source provenance auditability | CycloneDX 1.6 SBOM at /usr/share/o3deNNNN/sbom/o3deNNNN.cdx.json documents every bundled component, with purl, license expression, and EOL flags where applicable. |
| First-run state migration | Launcher's <project>/user/project.json rewrite is JSON-aware (python3 -c json.load/dump), only mutates known legacy prefixes, and is gated by a per-prefix marker file. Failures are silenced so a malformed home dir can't block the editor. |
A static CycloneDX 1.6 JSON SBOM is committed per major (sources/o3de2605.cdx.json, sources/o3de2610.cdx.json; the spec picks the file by stable_tag) and installed at /usr/share/o3deNNNN/sbom/o3deNNNN.cdx.json. It documents:
- The package itself (
pkg:rpm/fedora/o3deNNNN@<version>-<release>) with its license expression and source URLs. - Build dependencies (cmake, ninja-build, gcc-c++, python3-devel, git-lfs).
- Direct runtime dependencies (Qt5, Vulkan, mesa, libcurl, openssl, …).
- Bundled components currently itemized in the SBOM JSON (26.05 file; the 26.10 file lists bundled Qt 6.10.2 and PySide6 in place of Qt 5.15 and pyside2): custom Qt 5.15-rev9 (with the Fedora Bundling Library Exception flag), embedded clang toolchain, bundled Python 3.10, bundled OpenSSL 1.1.1t, and googletest (test-scaffolding fetch). Smaller bundled 3rdParty (pyside2/shiboken2, OpenEXR, OpenImageIO, OpenColorIO, PhysX, etc.) are NOT individually itemized today; adding them is tracked as SBOM completeness work in
FEDORA_ROADMAP.md. - EOL flags for bundled OpenSSL 1.1.1t.
To consume:
# After install (replace 2605 with whichever major is installed):
cyclonedx validate --input-file /usr/share/o3de2605/sbom/o3de2605.cdx.json
# Generate a runtime augmentation from the actual built RPM:
syft /opt/O3DE/26.05.0 -o cyclonedx-jsonRe-generate the static SBOM when bumping the version: edit sources/o3deNNNN.cdx.json (or copy it to sources/o3deMMMM.cdx.json for a new major) to update metadata.component.version, the version field at the top level, the name/purl/bom-ref fields, and any external references.
Twenty-four patches declared (the applied set varies by bcond: 0023 and 0024 apply everywhere; 0014 is swap_hook, the central hook that carries the 21-library swap set (O3DE_SWAPS in the Makefile) on the 26.10 line; 0015 is swap_hook-only and, since 2610.0-123, applies on the 26.10 base too; 0016 is system_tiff-only on the 26.05 base, gated off on the 26.10 base since 2610.0-123 because upstream merged it as o3de/o3de#19825; 0017/0019 are system_qt6-only, so currently inactive since the 2026-08-17 revert to bundled Qt6; 0018 applies on the stabilization channel and, since 2610.0-122, on 2610.x release builds; 0020 applies everywhere; 0021 applies only with wayland and without wayland_ui, and 0022 is wayland_ui-only, so o3de-experimental, which sets both, applies 0022 and skips 0021). On the 26.10 base the applied sets are (from rpmspec -P with each channel's flags, 2026-10-21): stable, testing and stabilization 0003 0010 0011 0014 0015 0018 0020 0023 0024; development 0003 0010 0011 0014 0015 0020 0023 0024; experimental 0003 0010 0011 0014 0015 0020 0022 0023 0024 (0023 since 2610.0-124, 0024 since 2610.0-127). Seven carry TIMEBOMB notes: upstream-equivalents merged to development but NOT to stabilization/26050; they retire for a given channel once that channel's engine ref rebases onto the 26.10 base (stabilization/26100 when it opens, then the 26.10 release tarball, both branch from development and already carry the fix). NOTE (post-26.05.0): stabilization/26050 shipped AS 26.05.0 and is frozen; it will not backport these dev-only merges, so "NOT to stabilization/26050" is provenance, not a wait-on-26050 trigger. The seven: Patch0001 (clang21, #19748 merged 2026-05-14), Patch0002 (manifest.py env var, #19751 merged 2026-05-14), Patch0004 (LYPython sdist install, #19752 merged 2026-06-09), Patch0005 (AzQtComponents title, #19750 merged 2026-05-14), Patch0007 (libtiff C99, #19734 merged 2026-05-08), Patch0008 (AzCore lobject include, #19733 merged 2026-05-08), Patch0012 v2 (AssetBuilder watchdog, #19747 merged 2026-05-15). The --with development_snapshot bcond (2026-05-18) gates all seven off so dev-branch-tip builds (make copr-development, and make copr-experimental since experimental was realigned onto development + monolithic on 2026-07-24) succeed without patch-apply rejects; since 2026-08-11 make srpm-stabilization sets it too, because stabilization/26100 was cut from development tip and already carries these merges. It is default OFF. Since 2610.0-122 the spec gates on its o3de_base_2610 macro instead, which is on for any development_snapshot build and for a tagged-release build once stable_tag is 2610.0 or later, so the stable and testing channels retire the seven with the 26.10.0 tarball; only builds from the 26.05 base still apply them. Patch0013 v4 gates the vulkan-validationlayers Stage 1 swap (three-hunk: cmake gate + PAL_linux variable + Instance.cpp env-var fix), validated end-to-end on build 10457745 (2026-05-13/14). See CONTRIBUTING.md for the full table including each patch's upstream-worthy assessment. Quick summary:
| # | Target | Purpose |
|---|---|---|
| 0001 | cmake/Platform/Common/Clang/Configurations_clang.cmake |
Suppress clang 21+ -Werror failures. TIMEBOMB: #19748 merged to development 2026-05-14 (release-cherry-pick candidate per nick-l-o3de). |
| 0002 | scripts/o3de/o3de/manifest.py |
Honor O3DE_ENGINE_PATH for engine-root detection. TIMEBOMB: #19751 merged to development 2026-05-14. |
| 0003 | python/get_python.sh |
Per-user venv linkage + engine-id reconciliation |
| 0004 | cmake/LYPython.cmake |
Non-editable pip install for read-only engine roots. TIMEBOMB: superseded upstream by #19752 (LYPython sdist install when engine is installed) merged to development 2026-06-09; gated off on the 26.10 base (o3de_base_2610; applying it against dev tip now reports "previously applied"). |
| 0005 | Code/Framework/AzQtComponents/.../WindowDecorationWrapper.cpp |
Propagate guest title to WM-drawn titlebar in OptionDisabled mode. TIMEBOMB: #19750 merged to development 2026-05-14. |
| 0006 | cmake/3rdParty/Platform/Linux/BuiltInPackages_linux_x86_64.cmake |
Establish the LY_USE_SYSTEM_<X> gating convention used by Stage 1 system-library swaps |
| 0007 | .../TIFFLoader.cpp + Code/Editor/Util/ImageTIF.cpp |
Migrate legacy libtiff uint8/uint16/uint32 typedefs to standard C99 (libtiff 4.5+ deprecates the legacy names). TIMEBOMB: upstream merged #19734 into development on 2026-05-08 but not into stabilization/26050; retires when the channel rebases onto the 26.10 base (see the retirement note above the table). |
| 0008 | Code/Framework/AzCore/.../ScriptContext.cpp |
Drop the redundant <lua/lobject.h> include broken by Lua 5.5 layout changes. TIMEBOMB: upstream merged #19733 into development on 2026-05-08 but not into stabilization/26050; retires when the channel rebases onto the 26.10 base (see the retirement note above the table). |
| 0009 | Gems/PhysX/.../physx-pal-platform.cmake |
Gate the upstream poly2tri association on the system_poly2tri swap |
| 0010 | Code/Framework/AzCore/Script/ScriptContext.cpp |
Add a Lua 5.5 lua_newstate signature shim (warnflag arg added in 5.5) |
| 0011 | Code/Tools/LuaIDE/.../WatchesPanel.cpp |
Restore LUA_NUMTAGS macro for the LuaIDE compile path under Lua 5.5 |
| 0012 | Code/Tools/AssetProcessor/AssetBuilder/main.cpp |
Child-side parent-death watchdog. AssetBuilder polls getppid() every 2s; when reparented (AP died), _exit(0). Replaces a withdrawn v1 attempt that used m_tetherLifetime/prctl(PR_SET_PDEATHSIG). That approach broke because the kernel binds PDEATHSIG to the forking thread, not the parent process, and AP forks from short-lived TaskWorker threads. v1 patch file retained in sources/0012-assetprocessor-tether-resident-builders.patch as reference; v2 is what ships. TIMEBOMB: #19747 merged to development 2026-05-15. |
| 0013 | cmake/3rdParty/Platform/Linux/BuiltInPackages_linux_x86_64.cmake + Gems/Atom/RHI/Vulkan/Code/Source/Platform/Linux/PAL_linux.cmake + Gems/Atom/RHI/Vulkan/Code/Source/RHI/Instance.cpp |
Three-hunk gate for the system_vulkan_validation_layers Stage 1 swap. Skips the bundled ly_associate_package, leaves VULKAN_VALIDATION_LAYER unset (so ${VULKAN_VALIDATION_LAYER} in the gem's BUILD_DEPENDENCIES expands to nothing), and flips the VK_LAYER_PATH SetEnv overwrite flag from 1 to 0 so distro/Flatpak launchers pre-setting VK_LAYER_PATH=/usr/share/vulkan/explicit_layer.d win over the engine's exeDirectory default. v1-v3 were partial; v4 added the PAL_linux variable gate after cmake configure failed at find_package(vulkan-validationlayers). |
| 0014 | cmake/3rdPartyPackages.cmake |
swap_hook prototype: central LY_USE_SYSTEM_<NAME> guard in ly_download_associated_package(), replaces Patch0006's per-line gating when enabled. Proposed upstream as #19815. |
| 0015 | vulkan PAL_linux + Instance.cpp | swap_hook companion: Patch0013's runtime hunks minus the BuiltInPackages gate (unnecessary under the lazy model). Applies on the 26.10 base since 2610.0-123; through -122 it was gated off with the upstream-merged carry-patches, so 26.10 builds shipped the bundled libVkLayer_khronos_validation.so 1.2.198 next to Requires: vulkan-validation-layers. |
| 0016 | the three <tiffio.h> consumer TUs |
TIFF_DISABLE_DEPRECATED before the include: removes the libtiff legacy-typedef collision with CryCommon that parked system_tiff since -17. Validated 2026-06-05 (3 chroots + Tier 2 swap-health). Merged upstream as o3de/o3de#19825 (development, 2026-06-06), so gated off on the 26.10 base since 2610.0-123 (it rejects there); still applies to a 26.05-base build with system_tiff. |
| 0017 | Gems/LmbrCentral/.../lrelease_linux.cmake |
Skip the LmbrCentral lrelease POST_BUILD rpath-patch under LY_USE_SYSTEM_QT (system lrelease has no rpath; the $ORIGIN/../lib RPATH_CHANGE fatally fails). system_qt6-only, so currently inactive since the 2026-08-17 revert to bundled Qt6. Upstream-worthy (system-Qt build path). |
| 0018 | Code/Editor/FileChangeMonitor.cpp |
Drop a pessimizing std::move on QDir::entryInfoList()'s temporary that Fedora clang rejects under -Werror,-Wpessimizing-move. NOT Qt-specific; gated on development_snapshot + stabilization since 2026-10-06, because development dropped the same std::move in o3de/o3de#20085 and only stabilization/26100 still has it; since 2610.0-122 it also applies to 2610.x release builds, whose tarball comes from that branch. Upstream-worthy (clang-strictness family, cf. 0001). |
| 0019 | cmake/.../Install_linux.cmake |
Companion to 0017: skip the second lrelease rpath-change, the %install-time ly_copy RPATH_CHANGE. Same reason (system lrelease has no rpath). system_qt6-only, so currently inactive since the 2026-08-17 revert to bundled Qt6. |
| 0020 | cmake/Platform/Common/Clang/Configurations_clang.cmake |
Demote the newer-clang -Werror promotions -Wunused-template and -Wunused-but-set-global back to warnings (clang 23 on Fedora 45 and rawhide). Extends the -Wno-error= block upstream merged as o3de/o3de#19748. Applied on all channels. |
| 0021 | Gems/Atom/RHI/Vulkan/.../WSISurface_Linux.cpp |
Use VK_RESULT_ASSERT in the Wayland surface branch; o3de/o3de#17169 removed AssertSuccess() but missed this call, so no Wayland-enabled build compiles. Applied only under --with wayland without wayland_ui (off on every shipping channel; o3de-experimental skips it because 0022's base already has the fix, o3de/o3de#20204). |
| 0022 | Code/Framework/AzQtComponents/..., Code/Editor/..., Gems/Atom/RHI/Vulkan/..., Gems/Atom/Tools/AtomToolsFramework/..., Code/Framework/AzToolsFramework/... |
Editor UI fixes for native Wayland and XWayland, sixteen local commits squashed into one diff against development 74006f539d (rebased 2026-10-19 from 0af429a2ea): window move and tile snapping, floating panel move and dock, viewport and camera fixes, Vulkan surface fixes for the Particle Editor and the standalone Atom tools. Only under --with wayland_ui (experimental channel); replaces 0021 there. Not yet proposed upstream. |
| 0023 | Code/Legacy/CrySystem/XML/xml.cpp |
Build against expat 2.9.0 (Fedora rawhide since 2026-10): it deprecates XML_GetCurrentLineNumber() for XML_GetCurrentLineNumber64(), and the three calls failed %build under -Werror (stabilization 2610.0-120 on rawhide, COPR 11182169). Uses the 64-bit call only with expat 2.9 or newer, so it is ungated. Since 2610.0-124. Upstream-worthy. |
| 0024 | Gems/Maestro/Code/Source/Cinematics/... |
Release Maestro's file-scope node parameter tables and post-FX descriptions in ~CMovieSystem(). In a monolithic build the exit handlers freed them after the SystemAllocator, so an exported release game aborted on quit with "pure virtual method called" (o3de-development 2610.0-126, 2026-10-22). Ungated. Since 2610.0-127. Upstream-worthy. |
Each patch carries a From:/Subject: header with the rationale. Stage 1 system-library swaps additionally ship companion Find<X>-system.cmake shims in sources/ (Findmikkelsen-system.cmake, Findexpat-system.cmake, FindZLIB-system.cmake, etc.), installed into cmake/3rdParty/Find<X>.cmake during %prep when the matching --with system_<lib> is enabled. On development, rapidjson, xxhash, cityhash and mikktspace are built from in-tree providers under Code/3rdParty/, which resolve ahead of any Find module since o3de/o3de#20097, so %prep also copies sources/fetchcontent-provider-system.cmake (Source77, since 2610.0-123) over each provider's CMakeLists.txt where it exists; before that those swaps, including the long-active system_mikkelsen, had no effect on development. sqlite-fetchcontent-system.cmake does the same job for the FetchContent sqlite.
- O3DE's 3rdParty package fetcher still runs at cmake configure unless every package is pre-bundled. Fully hermetic offline builds (mock without
--enable-net) require staging every package the engine pulls; seeFEDORA_ROADMAP.md. - Two upstream-bundled packages (
NvCloth,squish-ccr) cannot be hosted in Fedora or COPR for licensing reasons (NVIDIA license; BC7 patent encumbrance). The Fedora-shippable variant routes around them via feature-gated builds; seeFEDORA_ROADMAP.md§ "Restricted bundles".DirectXShaderCompilerDxcwas a third entry until 2026-05-08, when the license-clean DXC rebuild shipped inhellaenergy/o3de-dependenciesand replaced the bundle via thesystem_dxcswap.poly2triwas a fourth entry until the 2026-05-07 audit reframed it as a Stage 1 swap; it now resolves via Fedora'spoly2tri-devel. - Bundled OpenSSL 1.1.1t is end-of-life. Tracked for migration to system OpenSSL 3.x in
FEDORA_ROADMAP.md(stage 4); likely upstream-blocked. debuginfo/debugsourcesubpackages are suppressed (%global debug_package %{nil}). Debug symbols are present in the binaries but not extracted into a separate package. Unblocking this is on the Fedora roadmap (stage 5).- The Editor stalls at viewport creation under VirtualBox + software 3D + lavapipe Vulkan. Engine inits its RHI against
llvmpipe, then hangs when creating the Editor's render viewport.QT_QPA_PLATFORM=xcbdoes not help; the engine forces XCB anyway. No known workaround; affects anyone running O3DE in a VM without GPU passthrough. Bare-metal Linux + native GPU +vulkan-loaderis unaffected. - Bundled Qt 5.15-rev9 has no Wayland platform plugin.
QT_QPA_PLATFORM=waylandfails withCould not find the Qt platform plugin 'wayland'; onlyxcb,offscreen, andminimalare present in the bundle'splugins/platforms/. Systemqt5-qtwaylanddoes not help because the bundled Qt is isolated from system Qt plugins (the engine bundles its own Qt 5.15 with custom O3DE patches; system Qt 5 is not a substitute for this engine version). GNOME / KDE Wayland users get XCB via XWayland, which works for the Editor and Project Manager. Community report from a tester on Fedora 44 / GNOME Wayland / Ryzen 5500 + RX 5700XT, 2026-05-28. - 26.10 (Qt 6): the Editor crashes at startup when forced onto native Wayland with
QT_QPA_PLATFORM=wayland(o3de/o3de#19835). Not GPU-vendor specific (seen on NVIDIA and AMD). 26.10 Editor builds support X11 and XWayland only; on a Wayland desktop the Editor uses XWayland automatically, so leaveQT_QPA_PLATFORMunset or set it toxcb. Native Wayland for the Editor is experimental: it needs-DPAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND=ONplus o3de/o3de#20204 (merged to development, not in 26.10), and the Material Editor and other Atom tools still crash there.o3de-experimentalcarries that preview (--with wayland --with wayland_ui). Tracked upstream in o3de/o3de#18513. - Qt 5.15-rev9 auto-DPI mis-detection on Wayland XWayland. Without
QT_FONT_DPI=100, fonts in Project Manager render at the wrong scale on some HiDPI / 4K Wayland setups. The launcher now sets this automatically on Wayland sessions (whenXDG_SESSION_TYPE=waylandand the user hasn't already setQT_FONT_DPI). The upstream Debian .deb package needs the same workaround. Manual override is still possible viaexport QT_FONT_DPI=<value>before launch. Qt5-only: on qt6-era builds (detected at runtime vialibQt6Core.so.6in the engine's bin dir) the launcher skips this, because a fixedQT_FONT_DPIwould suppress Qt 6's correct per-monitor scaling and the underlying Qt 5.15 bug does not exist there. - ROS2 environment autodetect. Projects using the ROS2 gem need the ROS environment (
AMENT_PREFIX_PATH,librcl/librmwon the library path) at Editor and AssetProcessor runtime. Terminal users source/opt/ros/<distro>/setup.bashthemselves; menu launches used to arrive with a clean environment and fail with unsatisfiedlibrcldeps. The launcher now detects/opt/ros/<distro>/(Open Robotics packages and thehellaenergy/ros2*COPR RPMs share this layout) and imports the ROS environment via whitelist. Newest distro wins by default (ROS 2 codenames are alphabetical by release);O3DE_ROS_DISTRO=<name>pins one;O3DE_DISABLE_ROS2=1opts out entirely.PYTHONPATHis deliberately not imported: the distro setup points it at system-Python site-packages, which segfault when imported into the engine's bundled Python 3.10 venv. The gem's C++ side needs only the library path, so ROS-via-C++ works without ROS Python. - Project Manager helper tools need extra packages a default install pulls in via
Recommends:. The per-project menu in the Project Manager (Open Export Settings, Open Android Project Generator, Open CMake GUI, Build) shells out to tooling the engine RPM does not ship. Two distinct cases: (1) Export Settings and Android Project Generator drive the editor's bundled Python viatkinter, whose_tkinteris built against Tk 8.6 (libtk8.6.so/libtcl8.6.so); Fedora 44 moved the defaulttk/tclto 9.x and split the 8.6 runtime intotk8/tcl8(EL10 still ships 8.6 astk/tcl, so the EL10 build recommends those from 2610.0-126), and Export Settings additionally needstix. The launcher setsTCLLIBPATH=/usr/lib64/tclso the bundled Tcl finds Fedora's Tix (installed outside the bundled Tcl's default search path). (2) Open CMake GUI execs the systemcmake-guibinary, which on Fedora is a separate package fromcmake; Build uses the Ninja generator (ninja-build); and Open Project folder (plus the build/export-log links) uses Qt'sQDesktopServices::openUrl, which shells out toxdg-openfromxdg-utils. A defaultdnf install o3de2605pullstk8,tcl8,tix,cmake-gui,ninja-build, andxdg-utilsautomatically; minimal installs that opt out of weak deps (--setopt=install_weak_deps=False) must install those by hand. Upstream's.deb/ Snap declare neither a Tk runtime norcmake-gui, so these tools are broken on a clean Debian / Ubuntu install too. Community reports on Fedora 44, 2026-05-29. - Editor windows do not respond to GNOME / KDE mouse-drag tile-snap gestures on Linux. Dragging the Editor's title bar to a screen edge releases at the cursor instead of half-tiling; dragging to the top releases instead of maximizing. Project Manager (same Qt 5.15 bundle) interacts with the window manager normally; only the Editor is affected. Root cause (confirmed by code read, 2026-06-04): on Linux the Editor's main window is wrapped by
AzQtComponents::WindowDecorationWrapperwith a custom Qt-renderedTitleBar(theOptionDisablednative-decoration path is macOS-only), and that title bar implements dragging as a client-side programmaticmove()(Titlebar.cppdragWindow()), so the window manager never participates in the drag and its edge gestures can never trigger. The fix shape is Qt 5.15'sQWindow::startSystemMove(), which hands the drag to the WM (and is also the wayland-correct primitive for the Qt 6 era). Workaround: keyboard shortcuts go through the WM and work correctly. On GNOME:Super+Upto maximize / un-maximize,Super+Left/Super+Rightto half-tile,Alt+F7to enter keyboard-driven move mode. Covers most of the tile-snap UX. KDE bindings are similar (Meta+Up,Meta+Left,Meta+Rightby default). Patch0022 (--with wayland_ui,o3de-experimentalonly) carries a fix for window move and tile snapping; it is not yet proposed upstream.
This packaging is Apache-2.0 OR MIT to match upstream O3DE. The packaging files (o3de.spec, sources/*, patches/*) are dedicated under the same dual license.