Skip to content

[Reference only][Draft] AI-assisted native Linux experiment#1342

Draft
tc-imba wants to merge 43 commits into
UE4SS-RE:mainfrom
tc-imba:linux-port
Draft

[Reference only][Draft] AI-assisted native Linux experiment#1342
tc-imba wants to merge 43 commits into
UE4SS-RE:mainfrom
tc-imba:linux-port

Conversation

@tc-imba

@tc-imba tc-imba commented Jul 15, 2026

Copy link
Copy Markdown

Caution

Reference-only draft: this branch was planned and implemented with Codex/GPT-5.6 and superpowers. It has not received complete human line-by-line validation and is not a merge candidate. The purpose of this PR is to preserve a working experiment, collect technical feedback, and identify small changes that can be independently reimplemented and reviewed.

The original description is preserved below as a historical technical record; its merge plan, cleanup commitments, and scope statements are superseded by this notice.

The xmake changes are out of scope because maintainers no longer support that build path. Any real Linux PRs will be recreated from current upstream branches, use CMake only, disclose AI assistance, and contain no unrelated formatting or Palworld-specific product work.

Description

This PR is completely planned and implemented by codex with gpt-5.6-sol + superpowers, and it is still in progress.

This draft publishes my current native Linux port for maintainer review and integration planning. It is intentionally not presented as a request to merge the entire branch into main in one step.

The branch currently contains 38 commits touching 149 files, with approximately 11,378 additions and 779 deletions. The implementation is based on current main and references ideas and earlier investigation from #384 by @Yangff, while adding a fresh implementation, broader automated coverage, process-scoped preload behavior, and live Palworld dedicated-server validation.

Palworld is the binding validation target for this milestone because it provides a real native Unreal Engine 5.1 dedicated-server environment. It is not intended to become a permanent game-specific dependency of the core project. I will clean up the code later, including removing or relocating Palworld-specific contents, test assets, reports, hard-coded validation details, and the separate building-mod design material before a final merge.

What this branch implements

Native Linux build and platform boundary

  • Adds native x86-64 Linux build modes to CMake and xmake.
  • Uses clang and C++23 for the supported Linux configuration.
  • Splits the Windows DLL entry point into the Win32 platform directory and adds a Linux shared-object entry point.
  • Establishes a headless Linux compile boundary that excludes Windows-only proxy generation, GUI code, UVTD, and Windows system libraries.
  • Adds Linux CI coverage for the CMake/CTest and xmake build paths.
  • Documents supported toolchains, ABI requirements, staging, launching, diagnostics, and current limitations.

Linux loading and startup lifecycle

  • Builds UE4SS as libUE4SS.so and loads it through LD_PRELOAD.
  • Adds a launcher that validates the requested command, preserves server arguments, supports paths containing spaces, and can distinguish a wrapper script from the actual host ELF.
  • Adds process-scoped preload startup policy. Wrapper interpreters skip initialization; the intended host initializes UE4SS; launcher-added preload state and private variables are removed before later helper processes are created.
  • Preserves manually supplied LD_PRELOAD behavior while providing a safer supported launcher workflow.
  • Adds top-level fail-soft handling so missing engine metadata or required signatures deactivate UE4SS instead of terminating the host server.

Portable runtime services

  • Implements POSIX-backed Linux file handling and native file tests.
  • Adds inotify-based filesystem watching.
  • Adds Linux signal crash reporting and native backtraces.
  • Introduces a shared-library abstraction backed by dlopen, dlsym, and dlclose on Linux and the existing Win32 APIs on Windows.
  • Adds Linux C++ mod discovery and loading for shared objects.
  • Updates paths, mod-list parsing, generated-output handling, string conversion, formatting, and Lua boundaries for Linux.
  • Separates Unreal character types from system wchar_t behavior, which differs between Windows and Linux.

Unreal ABI, hooks, and layouts

The main branch depends on a companion UEPseudo branch containing:

  • Linux, Unix, and clang platform types, compiler setup, atomics, math, memory, and string support.
  • Generic wide/system string formatting needed for the Linux character model.
  • ELF-compatible detour traits and hook handling.
  • Linux Unreal member and virtual layout support.
  • Runtime ABI corrections validated against the Palworld dedicated server, including LoadMap variants, FName, property layouts, allocator/vtable behavior, and process-local script-function resolution.
  • Bounded signature retry behavior and structured signature diagnostics.

ELF discovery and signature resolution

  • Ports the single-pass scanner from PE/module assumptions to ELF executable segments discovered through dl_iterate_phdr.
  • Adds synthetic ELF scanning and cross-reference fixtures.
  • Extends patternsleuth consumption to include ELF image support and Linux engine-version/signature resolution.
  • Adds an ELF ConsoleManagerSingleton resolver by following references to stable console-variable strings.
  • Reports engine detection and individual required/optional signature results with addresses and explicit inactive reasons.
  • Adds tooling to extract a reproducible Palworld signature report.

Lua and C++ mod validation

  • Exercises Lua mod discovery and Linux-safe Lua/Unreal string boundaries.
  • Validates Blueprint hooks, object enumeration, property reads/writes, FName construction, and object-construction callbacks against a live server.
  • Loads a native C++ shared-object probe mod and validates lifecycle/update callbacks.
  • Keeps required-signature failures fail-soft so an unmodded host can continue running.

Tests and diagnostics

The branch adds native tests covering, among other areas:

  • POSIX file operations and ELF scanning.
  • Linux hooks, FName hooks, allocator/property/enum/vtable layouts, and LoadMap ABI variants.
  • Filesystem watching, crash probes, shared-library loading, and C++ mod loading.
  • Lua mod discovery and process-local script-function resolution.
  • Startup policy, launcher behavior, preload scope, hostile personality conflicts, and fail-soft initialization.
  • Offline Palworld signatures when a local proprietary server fixture is available.
  • A scripted Palworld acceptance harness and recorded live verification reports.

Dependency branches

The main branch currently points at commits published in these forks:

These dependency commits are not yet present in their upstream default branches. A recursive checkout using only the upstream submodule URLs may therefore fail until the dependency changes are reviewed and published upstream, or until an integration workflow temporarily remaps those submodules to the fork branches.

Suggested merge plan

I do not recommend squash-merging this complete draft directly into main. My preferred approach is:

  1. Create an upstream integration branch such as linux-port or linux-preview and retarget this draft to that branch while the work is decomposed.
  2. Review the UEPseudo and patternsleuth changes independently. Land those first, or maintain temporary upstream integration branches for them, then update the main repository gitlinks to reachable upstream commits.
  3. Merge a build-foundation slice:
    • Win32 entry-point relocation.
    • Linux platform/build-mode definitions.
    • Headless compile boundary.
    • Basic Linux CI and documentation.
  4. Merge a portable-core slice:
    • POSIX file implementation.
    • Portable paths, strings, formatting, and shared-library abstraction.
    • Filesystem watcher and crash-reporting platform backends.
  5. Merge the Unreal/ELF slice:
    • UEPseudo Linux/Unix/clang support.
    • ELF module discovery and signature scanning.
    • Hook, layout, and ABI corrections.
    • Engine detection and patternsleuth resolvers.
  6. Merge the runtime-integration slice:
    • Linux entry/bootstrap.
    • Launcher and process-scoped preload policy.
    • Lua and C++ mod loading.
    • Fail-soft diagnostics.
  7. Merge generic tests and CI first. Keep proprietary-binary and Palworld-specific validation optional or move it to a separate validation repository/workflow.
  8. Rebase and clean each slice, run Windows and Linux CI, add changelog entries, and only then merge the integration branch into main.

The existing commit order already follows much of this progression and can be used as a starting point for cherry-picking or rebuilding smaller reviewable PRs.

Cleanup and follow-up I intend to do

Before asking for final merge readiness, I intend to:

  • Split cross-cutting commits into smaller reviewable changes where practical.
  • Remove or relocate Palworld-specific scripts, fixtures, hashes, reports, and acceptance assets that do not belong in the generic core.
  • Remove the Palworld building-mod design and implementation-plan documents from the Linux port scope.
  • Convert useful Palworld-derived cases into generic synthetic tests or optional external-fixture tests.
  • Reduce remaining clang warnings, especially ignored Microsoft export/import attributes.
  • Revisit duplicated CMake/xmake logic and normalize platform abstractions.
  • Rebase dependency branches on their current upstream defaults and submit focused dependency PRs after maintainers agree on the direction.
  • Run and fix Windows CI regressions; Windows builds have not been reproduced locally in this Linux environment.
  • Apply project formatting/style expectations and add the appropriate changelog entry.
  • Squash fixup/history-only commits as each integration slice is finalized.

Current limitations

  • Native x86-64 Linux only.
  • Palworld's headless Unreal Engine 5.1 dedicated server is the validated target. Other Linux Unreal versions and games remain experimental.
  • clang is required; GCC is not currently supported.
  • The current build baseline expects a recent glibc/libstdc++ environment.
  • GUI tools, keyboard/mouse hooks, UVTD/PDB tooling, and attach injection are not included.
  • Linux crash output is a signal/backtrace report rather than a Windows minidump.
  • Broad engine-version and game coverage is not yet established.
  • Some Microsoft import/export attributes still produce ignored-attribute warnings under clang.
  • The full patternsleuth workspace test is not a valid Linux/stable-Rust gate because an unrelated scanner/example dependency uses nightly and Windows-only retour ABIs. The patternsleuth package and feature set consumed by RE-UE4SS does build and its doc tests pass.
  • The proprietary Palworld executable cannot be distributed to public CI. Its signature test skips when the local fixture is absent.
  • Final client-side/manual acceptance gates remain outstanding.

Review findings that currently block promotion from draft

An independent review of the published branch identified the following issues that should be resolved before this is treated as a generally mergeable Linux implementation:

  • Upstream CI cannot recursively check out the current fork-only UEPseudo and patternsleuth gitlink commits. Dependency commits must become reachable through their upstream URLs, or a temporary integration checkout must remap those URLs.
  • Both Linux build paths currently link a static C++ runtime into the LD_PRELOAD library. The resulting shared object exports C++ runtime, allocation, exception, iostream, and RTTI symbols that may interpose on the host process or C++ mods. These symbols need isolation, for example through linker visibility/version-script work or a revised runtime-linking strategy.
  • Linux unload and shutdown need a defined thread-lifetime contract. Initialization and event processing involve background threads, while DSO cleanup deletes global program state. Until cleanup and joining are made safe, the supported model should be process-lifetime preload only, without dlclose-style unloading.
  • Linux Lua hot reload has a watcher callback contract mismatch: the watcher reports the changed file, while the consumer derives the mod from a watched-directory path. Delivery is tested, but end-to-end mod reload needs a regression test and fix.
  • Several UEPseudo layout, vtable, and LoadMap ABI decisions are heuristics validated primarily against one Palworld UE 5.1 server. They should be isolated behind explicit platform/version metadata or clearly marked experimental before claiming broad UE 5.1+ support.
  • C++ mods with sibling shared-library dependencies currently rely on their own origin-relative RUNPATH; this differs from Windows dependent-library lookup and needs documentation plus a fixture.
  • The dlopen notification/interposition path observes global program/mod state from arbitrary loader threads and needs explicit lifecycle synchronization.
  • Before focused dependency PRs, UEPseudo should be rebased on its current main and patternsleuth on its current master.

These findings reinforce the proposed integration-branch approach: dependency reachability, symbol isolation, shutdown safety, hot reload, and ABI scoping should be explicit gates before the Linux integration branch is promoted toward main.

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Is/requires documentation update
  • Other: draft platform port and integration proposal

How has this been tested?

Fresh verification on the published branch:

  • CMake Linux build completed successfully with the existing Game__Shipping__Linux test configuration.
  • CTest: 32 of 32 tests passed; PalworldSignatureTests was reported as skipped because the local proprietary-binary fixture was not supplied.
  • xmake Linux configuration and UE4SS build completed successfully.
  • Both CMake and xmake libUE4SS.so outputs pass ldd -r with no unresolved symbols.
  • The patternsleuth package with the process-internal, image-pe, and image-elf features used by RE-UE4SS passes cargo test and doc tests.
  • git diff --check reports no whitespace errors.

Recorded live Palworld dedicated-server evidence is available here:

Those reports document live server startup, signature resolution, hook activity, Lua and C++ mod probes, object/header/USMAP generation, process isolation, and fail-soft behavior. They also clearly identify the remaining manual acceptance work.

Checklist

  • I have commented my code, particularly in hard-to-understand areas.
  • I have made corresponding changes to the documentation.
  • I have added the necessary description of this PR to the changelog, and I have followed the same format as other entries.
  • Any dependent changes have been merged and published in downstream modules.

Screenshots

Not applicable; the current Linux milestone is headless.

Additional context

This draft is primarily asking maintainers for direction on:

  • Whether an upstream integration branch is acceptable.
  • Which dependency and foundation slices should be reviewed first.
  • How much Palworld-based validation should remain in-tree versus move to an external optional test repository.
  • Whether this should supersede, collaborate with, or selectively incorporate the still-open [Draft] Linux Porting #384 draft.

I am happy to reorganize the branch around the maintainers' preferred merge sequence before requesting full review.

tc-imba added 30 commits July 14, 2026 14:57
….cpp

File moved verbatim (100% rename); CMake now compiles only the current
platform's src/Platform/<OS>/ directory. Zero Windows behavior change.
Constructor-based bootstrap (LD_PRELOAD) that spawns the init thread,
mirroring EntryWin32's thread_dll_start. Not yet compiled into a target;
linking libUE4SS.so on Linux is blocked on:
- UEPseudo Linux platform headers (exist in UEPseudo PR UE4SS-RE#79, fetched as
  pr-79-linux in the submodule)
- UE_BUILD_*/UBT_COMPILED_PLATFORM defines from the Linux build modes
- -fms-extensions for __declspec in RC_*_API macros
- ASM_MASM only enabled on Windows
- UE4SS_PLATFORM_TYPES: Win64 on Windows, Linux elsewhere (CI grep takes
  first declaration via -m1)
- Linux platform defines: PLATFORM_LINUX/PLATFORM_UNIX/LINUX,
  OVERRIDE_PLATFORM_HEADER_NAME=Linux, UBT_COMPILED_PLATFORM=Linux
- UNICODE/_UNICODE defines are Windows-only; Linux uses FORCE_U16 char16_t
- clang.cmake: -gdwarf/-fPIC on Linux instead of -gcodeview
- Gate on WIN32: raw_pdb, UVTD, cppmods, proxy_generator, Win32 system libs
- New UE4SS_GUI option gates ImGui/GLFW/glad (headless Linux M1)
- Linux links dl + pthread

Native configure (clang+Ninja, Game__Shipping__Linux) passes.
- LuaRaw luauser.c: pthread recursive-mutex Lua lock (POSIX branch);
  Windows CRITICAL_SECTION branch unchanged
- ParserBase/IniParser/LuaMadeSimple: add missing <algorithm>/<memory>/
  <stdexcept> includes (transitively provided by MSVC headers)
- JSON TokenParser: cast stoll result to int64_t (long long is a distinct
  type from int64_t on LP64, making the Number ctor ambiguous)
- printf_s/wprintf_s mapped to printf/wprintf via Linux platform defines
  (~110 call sites; approach from PR UE4SS-RE#384)
- Input: Win32AsyncInputSource compiled/registered only on Windows;
  GLFW3InputSource and QueueInputSource remain on all platforms
Full FileInterface implementation over open/write/mmap/fstat/unlink:
- fd-based handle (int), identifying properties from fstat
  (dev/inode/mtime/size) replacing the Windows volume/file-index scheme
- UTF-16 <-> UTF-8 conversion at the file boundary; read_all does a
  proper UTF-8 decode (Helpers' to_u16string widens byte-wise and
  mangles non-ASCII, so LinuxFile carries its own codecvt decode)
- serialization cache logic mirrors WinFile.cpp 1:1

tests/: new UE4SS_BUILD_TESTS option + ctest-wired FileTests covering
roundtrip (incl. non-ASCII), append, mmap, missing-file throw, delete,
nested directory creation. All pass natively.
Pin Palworld Steam build 24088465.

PalServer-Linux-Shipping SHA-256: a05788ead7619db22a1509c43241c16d289ed7040e8bcbb2e36e13e223e822f9

ELF build ID: 217802a00653a9c4
@UE4SS

UE4SS commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Note that this PR was made with AI, and is very large, so extreme attention is required, and I have a low confidence level for the quality of these changes.

Also note that the author did not disclose the use of AI (unless I missed it somewhere ?), but they also left obvious traces such as the "superpowers" files, and the formatting of the PR description, so I don't think the intention was to hide the use of AI.

The PR also contains changes to the now unsupported xmake buildsystem, anyone looking at this PR should ignore those changes.

There are also unrelated formatting changes that muddies up the PR.

The changes in the UEPseudo repo contain changes to one of the MemberVariableLayout files without corresponding changes to UVTD, this is not allowed because these file are generated by UVTD and will be overridden from time to time.
It also fundamentally misunderstands how the member variable system works by making changes directly to the offsets depending on the platform.
The correct solution is to generate, or otherwise manufacture the member variable files specifically for Linux.

This PR is obviously impossible to merge due to scope, size, and large-scale AI usage, however, it might be a usable reference for actual implementations, with very careful double checking of everything.

@tc-imba

tc-imba commented Jul 15, 2026

Copy link
Copy Markdown
Author

Note that this PR was made with AI, and is very large, so extreme attention is required, and I have a low confidence level for the quality of these changes.

Also note that the author did not disclose the use of AI (unless I missed it somewhere ?), but they also left obvious traces such as the "superpowers" files, and the formatting of the PR description, so I don't think the intention was to hide the use of AI.

The PR also contains changes to the now unsupported xmake buildsystem, anyone looking at this PR should ignore those changes.

There are also unrelated formatting changes that muddies up the PR.

The changes in the UEPseudo repo contain changes to one of the MemberVariableLayout files without corresponding changes to UVTD, this is not allowed because these file are generated by UVTD and will be overridden from time to time. It also fundamentally misunderstands how the member variable system works by making changes directly to the offsets depending on the platform. The correct solution is to generate, or otherwise manufacture the member variable files specifically for Linux.

This PR is obviously impossible to merge due to scope, size, and large-scale AI usage, however, it might be a usable reference for actual implementations, with very careful double checking of everything.

This PR is completely planned and implemented by codex with gpt-5.6-sol + superpowers, and it is still in progress. Though it seems that it is already working on the Palworld Linux server, it is not intended to be merged into the repo. It should be served as a reference of a working implmentation, so I create a draft here mainly for feedbacks and discussions.

Regarding the AI usage, I think in 2026, AI generated fixes and features are generally acceptable after careful review (which I will do later, and I may ask for the maintainer's help).

Thanks for your feedbacks on the current changes, I will rewrite these parts based on them, and I may have some further questions later. Before making real PRs, I will appreciate if you could give a guideline or suggestions about what should be done first.

@tc-imba tc-imba changed the title [Draft] Native Linux support with Palworld dedicated-server validation [Reference only][Draft] AI-assisted native Linux experiment Jul 15, 2026
@narknon

narknon commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the reference. We accept AI-based PRs when the creator understands the subjects themselves and just used AI to assist with the coding and tedium. If the user just prompted AI until it worked without understanding anything, we don't really want to merge, because ofc we have AI tools available as well and could do that ourselves but (hopefully) with a more thorough understanding.

Will be interested in seeing where this goes.

@Shirowwww

Copy link
Copy Markdown

@tc-imba heads up on a hole in the Linux StartupPolicy, found running your linux-port on a Palworld dedicated server under box64 (ARM64).

evaluate() returns LegacyStart when UE4SS_LAUNCH_TARGET_EXE is missing:

const auto* expected_value = std::getenv(TargetExecutableEnv);
if (!expected_value) return {.kind = DecisionKind::LegacyStart};

and EntryLinux only skips on TargetMismatch/InvalidLauncherState, so LegacyStart means "init unconditionally". The argv[0] fallback you added for emulated hosts never gets a chance to run.

That bites with Palworld's Sentry crashpad_handler. PalServer spawns it with a scrubbed env, so UE4SS_LAUNCH_TARGET_EXE is gone, but box64 re-injects its own BOX64_LD_PRELOAD into the child, so libUE4SS.so still gets preloaded into crashpad. No target var, LegacyStart, UE4SS initializes inside the crash handler. It obviously can't find the engine, so it retries the scan ~80/s until SecondsToScanBeforeGivingUp (30s), burning CPU and flooding the shared UE4SS.log, which is annoying because it drowns the real server's log lines.

The game itself is fine, it's just the helper process. I'm working around it by making crashpad_handler non-executable, but that's ugly and it makes PalServer log a (non fatal) posix_spawn failure.

Not sure what the right fix is on your side. Making LegacyStart not unconditional would need UE4SS to know what the game is, which is the whole point of the var. Maybe the launcher could pass the target through something box64 propagates, or LegacyStart could bail out if argv[0] is clearly a known helper. Your call, just wanted it documented since it's easy to hit on any Unreal game with a crash reporter.

@tc-imba

tc-imba commented Jul 19, 2026

Copy link
Copy Markdown
Author

@Shirowwww Resolved in 421411a and a789c17. I traced the failure to marker-free LegacyStart combined with Box64s separate BOX64_LD_PRELOAD list. The Linux constructor now passes its actual loaded module identity into StartupPolicy; when the target marker is missing and BOX64_LD_PRELOAD positively names that UE4SS module, startup fails closed before creating logs, scan threads, or mods and diagnose mode reports reason=box64_target_missing.

Native marker-free LD_PRELOAD behavior and marker-present launcher decisions are unchanged. This is intentionally a narrow safety guard rather than full Box64 support; deliberate marker-free UE4SS injection through BOX64_LD_PRELOAD is rejected.

The regression coverage exercises exact, basename, symlink, hard-link, unrelated, and marker-precedence cases, plus a real preload process test that verifies no UE4SS.log is created. Final local CTest result: 32/32 configured tests passed, with PalworldSignatureTests retaining its environment-dependent skip.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants