URLab supports Linux against Unreal Engine 5.7+. The plugin builds and the full automation suite (URLab.*) passes 177/177 with a working editor — but the build flow is more involved than on Windows because UE's bundled clang + libc++ require the third-party dependencies to be ABI-compatible.
This page is a one-time setup walkthrough. Jump to Day-to-day workflow once you have a working build; the Troubleshooting / Advanced section covers debugging tips and the build flags applied internally by build_all.sh --engine.
If you hit anything not covered here please open an issue.
You have two options. The binary is dramatically faster to set up; the source build is useful when you want to debug into the engine itself.
Epic ships a precompiled UE5 binary for Linux — no source build, no GitHub access, no Setup.sh.
-
Sign in to your Epic Games account at https://www.unrealengine.com/linux (top of the page).
-
Download Linux Unreal Engine — currently a single
.zipnamed likeLinux_Unreal_Engine_5.7.x.zip, ~25 GB compressed / ~43 GB extracted. -
Extract anywhere. The rest of this guide refers to the extract root as
$UE_ROOT(e.g./home/<user>/UnrealEngine). -
Confirm the editor binary exists and is executable:
ls -la $UE_ROOT/Engine/Binaries/Linux/UnrealEditor
Lets you set breakpoints in engine code, step through UBT, and patch UE itself. Costs a multi-hour clone + compile and ~150 GB disk; rarely needed for plugin work but invaluable when you do need it.
-
Link your Epic Games account to GitHub so you can access https://github.com/EpicGames/UnrealEngine.
-
Clone the
5.7branch (orreleasefor whatever Epic considers stable):git clone -b 5.7 https://github.com/EpicGames/UnrealEngine.git cd UnrealEngine -
Run the bundled setup + project-files scripts:
./Setup.sh # downloads ~30 GB of binary deps via Git LFS ./GenerateProjectFiles.sh # generates Makefile / IDE project files make UnrealEditor # ~hours on first build, parallel-safe
-
$UE_ROOTis yourUnrealEngine/clone root for the rest of this doc.
- Disk-space rule of thumb: 70 GB free for option A initial setup is comfortable (~43 GB UE binaries + ~10–20 GB shader / DDC cache + a few GB for project + plugin). Option B needs ~150 GB.
- Display: the editor needs a Wayland or X11 session. On a headless server, common options are NICE DCV, X2Go, or a TigerVNC
:1display (export DISPLAY=:1before launching). - System libs: UE bundles most of what it needs (libc++, ICU, etc.). On a fresh Ubuntu 22.04 you may still need
apt install libsdl2-2.0-0 libvulkan1if the editor can't open a window — that's the symptom you'd see after launch with a missing-library message in the log.
-
CMake 3.24+ — Ubuntu 22.04 ships 3.22, which is below CoACD's minimum. Easiest fix:
pip install --user "cmake>=3.24,<4" export PATH="$HOME/.local/bin:$PATH"
-
A host UE5 C++ project with
UnrealRoboticsLabcloned into itsPlugins/(or symlinked there). The host project must be C++; if your project is Blueprints-only, add a dummy C++ class in the editor first (Tools → New C++ Class).
The plugin's third-party submodules (MuJoCo, CoACD, libzmq) must be initialised:
cd UnrealRoboticsLab
git submodule update --init --recursiveUE on Linux uses its own bundled clang (currently 20.1.x at $UE_ROOT/Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/...) and links against its bundled libc++. If you build the third-party libs with the system gcc + libstdc++ (which is what third_party/build_all.sh does without --engine), the resulting .so files have a different C++ ABI than the UE plugin link expects, and you'll get a wall of std::* undefined-symbol errors at link time.
build_all.sh --engine $UE_ROOT points the third-party CMake builds at UE's clang + libc++. Once the libs are built that way, the plugin links and runs against them cleanly.
UE_ROOT=/path/to/UnrealEngine
URLAB_ROOT=$UE_ROOT/../URLabTest/Plugins/UnrealRoboticsLab # adjust to your layoutcd "$URLAB_ROOT/third_party"
./build_all.sh --engine "$UE_ROOT"Expected on success: third_party/install/{MuJoCo,CoACD,libzmq}/ populated with headers + .so files.
--engine makes the script glob Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64/v*_clang-*/ (version-sorted, so future UE bumps from v26 → v27 are picked up automatically), then export CC / CXX / AR / RANLIB / CFLAGS / CXXFLAGS / LDFLAGS for each per-dep build.sh.
cd "$UE_ROOT"
Engine/Build/BatchFiles/Linux/GenerateProjectFiles.sh -project=/path/to/HostProject.uproject -game -engine
Engine/Build/BatchFiles/Linux/Build.sh HostProjectEditor Linux Development -Project=/path/to/HostProject.uprojectThe third-party .so files (libmujoco, lib_coacd, libzmq) get symlinked into the plugin's Binaries/Linux/ automatically by each per-dep build.sh and by Scripts/build_and_test_linux.sh — see How runtime staging works in Troubleshooting / Advanced if you need to do it manually.
DISPLAY=:1 "$UE_ROOT/Engine/Binaries/Linux/UnrealEditor" /path/to/HostProject.uprojectURLab should appear under loaded plugins, the MuJoCo asset category should register, and the MJCF importer should respond when you drag an .xml into the Content Browser.
After the one-time setup, normal iteration is just:
git pull
./Scripts/build_and_test_linux.sh \
--engine "$UE_ROOT" \
--project /path/to/HostProject.uprojectThat builds the editor target (incremental), re-stages the runtime symlinks if a third-party dep was rebuilt, runs the URLab.* automation suite, and emits the build+test summary block to paste into a PR. Expected: 177 / 177 passed.
Close the editor before running — the test harness needs the project lock free.
If you only changed plugin C++ and want to skip the test pass, the editor Build.sh step from one-time setup #2 is the inner loop.
UE on Linux doesn't auto-stage RuntimeDependencies for editor builds, and UBT's auto-computed RPATH for plugins symlinked outside the host project can resolve incorrectly. URLab works around this by symlinking the third-party .so files into the plugin's Binaries/Linux/ so the loader resolves them via ${ORIGIN} (which UBT does add correctly).
The helper Scripts/setup_runtime_linux.sh does the symlinking. It's idempotent and warn-skips when Binaries/Linux/ doesn't exist yet (first-time fresh checkout, before the plugin .so has been built). You don't normally call it directly — both build_all.sh (via each per-dep build.sh) and Scripts/build_and_test_linux.sh invoke it after their respective build steps.
You'd run it manually only if you fiddled with third_party/install/<pkg>/lib/ outside of those scripts and need to re-sync the symlinks:
"$URLAB_ROOT/Scripts/setup_runtime_linux.sh"For packaged (non-editor) builds, RuntimeDependencies.Add("$(BinaryOutputDir)/...", LibFile, NonUFS) from URLab.Build.cs stages the libs through BuildCookRun, and UBT's ${ORIGIN} RPATH resolves them — no manual step needed.
Reference, in case you need to debug a per-dep failure or replicate the build manually:
-Wno-unknown-warning-optionlets clang ignore-Werror=stringop-overflow(a GCC-only flag) that TBB (CoACD's transitive dep) tries to use.-Wno-missing-template-arg-list-after-template-kwkeeps clang 20 from rejecting OpenVDB'sOpT::template eval(...)syntax.-Qunused-argumentsquiets MuJoCo's-Werror -Wunused-command-line-argumentnoise from-stdlib=libc++on compile-only steps.BUILD_STATIC=OFFis applied automatically for libzmq on Linux (inthird_party/libzmq/build.sh) — the static archive'smailbox_safe.cpppullspthread_cond_clockwaitwhich UE's link sysroot can't resolve, and the.soworks fine.
If you want to rebuild only one dep with the same flags build_all.sh --engine would apply (e.g. iterating on MuJoCo locally), the equivalent invocation is:
UE_TC=$(ls -d "$UE_ROOT/Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64"/v*_clang-*/x86_64-unknown-linux-gnu | sort -V | tail -1)
CC="$UE_TC/bin/clang" \
CXX="$UE_TC/bin/clang++" \
AR="$UE_TC/bin/llvm-ar" \
RANLIB="$UE_TC/bin/llvm-ranlib" \
CFLAGS="-fPIC -Qunused-arguments -Wno-unknown-warning-option" \
CXXFLAGS="-stdlib=libc++ -nostdinc++ -isystem $UE_TC/include/c++/v1 -fPIC -Qunused-arguments -Wno-unknown-warning-option -Wno-missing-template-arg-list-after-template-kw" \
LDFLAGS="-stdlib=libc++ -fuse-ld=lld -L$UE_TC/lib64 -Wl,-rpath,$UE_TC/lib64" \
bash third_party/MuJoCo/build.sh- Plugin must be located inside (or symlinked inside) the host project's
Plugins/directory. UBT's auto-RPATH calculation makes assumptions about the relative position of the plugin and the engine; we work around them by staging libs into${ORIGIN}, but the plugin still needs to be findable to UBT through the host project's tree. - PIE editor first launch compiles Vulkan SM5 shaders + a derived-data cache (~10–20 GB). Plan for it; subsequent launches are fast.
- The
urlab_bridgePython package (separate repo) hasn't been smoke-tested against this Linux flow yet. Open an issue if you hit problems.