Skip to content

fix(relinker): allow explicit module directories without standard folders - #6231

Merged
oneandonlydean merged 2 commits into
boykopovar:mainfrom
ArjenS-LA:fix/explicit-homebrew-module-directories
Oct 18, 2026
Merged

oneandonlydean merged 2 commits into
boykopovar:mainfrom
ArjenS-LA:fix/explicit-homebrew-module-directories

Conversation

@ArjenS-LA

Copy link
Copy Markdown
Contributor

What

An explicit --module-dir still failed when a bundle had no sce_module, sce_modules or prx directory. Accept validated explicit directories without requiring an empty standard directory. Preserve the missing-directory error when no explicit directory is supplied, and retain path, duplicate and incompatible-option validation.

Tested

Windows 11 x64 (build 26200), WinLibs MinGW-w64 GCC 15.2.0 r7, CMake 4.3.1, Ninja 1.13.2, Python 3.13.7. Baseline: d92a8dad390af1807cc91622b924252141816a5a. Branch: fix/explicit-homebrew-module-directories. Commit: 1800d3892bec857b254ca8c55e912e325e1c6711. Committed-object conventions check passed.

The modified test_guest_module_dir.py fails on unchanged main with sce_module/*.prx was not found and passes fixed. It covers root and nested explicit directories without a standard directory, Linux/Windows output, missing and escaping directories, and unchanged no-option rejection. The full relinker CTest directory has 126 passes and one long_paths skip. Another 26 root-level checks pass. Fourteen root checks that create temporary commits were excluded under the personal commit quota; the targeted regression creates none.

cmake -S . -B build-relinker -G Ninja -DCMAKE_BUILD_TYPE=Release -DANYPS5_RELINKER_ONLY=ON -DBUILD_TESTING=ON -DPython3_EXECUTABLE=$python
cmake --build build-relinker --parallel 8
ctest --test-dir build-relinker -N
ctest --test-dir build-relinker/core/relinker --output-on-failure -j 4

input_magic and other Python-backed tests were registered. Native Linux/macOS and full-library tests were not run locally.

Homebrew evidence

The original extracted Mari0 archive layout was used, with no empty directory, renamed input, substituted library or patched input.

relinker.exe --windows --registry --trap-sdk-syscall-stubs --sce-module-path $Mari0 --module-dir . "$Mari0/love.elf" "$output/output.exe"

Baseline: exit 2 before writing an executable (0.026 s), reporting the missing standard directory. Fixed: exit 0 (11.847 s), producing a PE executable and app0/libOSMesa.so.8.guest.prx. A baseline control with an added empty sce_module also converts successfully, isolating the directory gate. The trap flag remains required: it replaces recognized SDK syscall wrappers with traps and does not implement those syscalls. Timings describe these runs, not a performance claim.

Package: Mari0 1.6.2 from websrv v0.34. Original layout and input hashes were checked before and after conversion; all inputs remained unchanged.

Input SHA-256
Mari0.zip e0331ed5a22e7fe72843d268cd2c8b297d761a75b7c83d828f5cc58a82a72ce3
love.elf 54bcc91670fd759bbd3488284dce351b6421cb83016e9ad8da6b5186da067a39
libOSMesa.so.8 128d2ab20b980b96decb1f20a9ed57d10cc922605259666b63efa52963920f0a

No generated homebrew executable was run. No game startup, gameplay, GPU, commercial-title, or physical-PS5 result is claimed. Synthetic regression tests additionally execute their existing small Windows fixtures; that is separate from homebrew conversion evidence.

Baseline relinker SHA-256: a249e5a38abe9f338f09d6ea09182b5a39cd156dada6771984b85e315fda67c5. Tested fixed relinker SHA-256: 854ebbdbdac8c4fe18d17d4bf4253ac9e3efa9063c6b1c7e81e82e4b0cafba23.

Local logs, exact argv, per-file hashes, source patches, before/after failures and JSON results: C:/Users/arjen/AppData/Local/Temp/anyps5-three-homebrew-20261014 (homebrew-report.json, regression logs and CTest logs). The commands and decisive results are included above so this report does not depend on access to that local folder.

Open PR comparison

Complete paginated inventory: 537 open PRs; main d92a8dad390af1807cc91622b924252141816a5a. Complete changed-file lists and tree-only merge previews used that main as the explicit common base. This change merges with main and both other proposed changes. 16 relevant comparisons merge cleanly; 23 remain inconclusive because the other PR already conflicts with main. No conflict-free claim is made for those PRs.

Exact compared heads and shared-file results
PR Head Shared paths Result
#6190 09afe38730d7b9d40d57b8aa9e13777012d170a3 docs/user/USAGE.md clean
#6171 657f16ea286035a8615e2d56614a354cd4559e31 docs/user/USAGE.md clean
#6156 006e1768128d23f491e78d51c709ecf58d97ed2c core/relinker/cli/src/NativeModules.cpp, core/relinker/relinker/tests/test_guest_module_dir.py clean
#6111 c690012ce1b6f73ab985c061509e7cbfb41127c2 docs/user/USAGE.md clean
#6106 78b906fb67a8edff3969f60d26ced129f981139e core/relinker/relinker/tests/test_guest_module_dir.py clean
#6012 62022e9362a27432e007cea132ecd9ca0909bb2b docs/user/USAGE.md clean
#5962 1f98703dd07a6257c84ea485594d92f5a8e84fba docs/user/USAGE.md clean
#5925 3339ddd3af77cfc336148966657c0d14e87b6ae1 docs/user/USAGE.md inconclusive: existing main conflicts
#5875 569ff84ea2589a9c886dca37b5c9ddcea70049bd docs/user/USAGE.md inconclusive: existing main conflicts
#5835 e4036135ed0823b866969e6e7e688712b0f57fcc docs/user/USAGE.md clean
#5784 9acd5dcc07d8149020bf50fbd5e09f7633a2613f docs/user/USAGE.md clean
#5695 acc228ab4a54fbdc0c816c22b52b82968e42649b docs/user/USAGE.md clean
#5582 2d14128a29ec22d25e0cb308777dd46894a73170 docs/user/USAGE.md clean
#5390 d4fa8367daa0fd826853f440d23c3a604af43449 docs/user/USAGE.md inconclusive: existing main conflicts
#5021 01f2073d06385ca2adb537d4996ad61e8255bd2e docs/user/USAGE.md inconclusive: existing main conflicts
#4891 ab0e383aca0fd9c8d873293ec0ffa170d750baa4 docs/user/USAGE.md inconclusive: existing main conflicts
#4855 82de94cbedc5461de6af731b2a5a9838aca66e48 docs/user/USAGE.md clean
#4847 b05e5cf8ecf4f410750c38a6f281f273babb816d docs/user/USAGE.md clean
#4813 2d6b8ef4341e21d78686bfba9da9a5c6bb14d629 docs/user/USAGE.md inconclusive: existing main conflicts
#4760 1263d7065489fd6b7a15ebbecb1fcf0ee72d21f9 docs/user/USAGE.md inconclusive: existing main conflicts
#4749 07713af3078fcb4e24a15c96bf15c3df4e2b071a docs/user/USAGE.md inconclusive: existing main conflicts
#4740 beb1ba79f2b3a2fc3882bf9d65553e4e754fc03d docs/user/USAGE.md inconclusive: existing main conflicts
#4718 e4b37aa2e22c15e0e07341a7d8c18100cbae55c2 docs/user/USAGE.md inconclusive: existing main conflicts
#4599 8c49e6d6960021ef72e1382d78b9b83914cc7f31 docs/user/USAGE.md inconclusive: existing main conflicts
#4566 16b602cbfb29dcf3fc89b4ed67f228d65a27b20b docs/user/USAGE.md inconclusive: existing main conflicts
#4523 66c8f11a47d64c2db6f514e409e94e91f5ac5309 docs/user/USAGE.md inconclusive: existing main conflicts
#4522 92b12559c64489b556179b651ab4d966c29314ec docs/user/USAGE.md inconclusive: existing main conflicts
#4521 67f9e72d1c663dbc8811cdb6c85753844be02381 docs/user/USAGE.md inconclusive: existing main conflicts
#4520 b339b4f6ca25b1b274555394e73a26f8c8d98347 docs/user/USAGE.md inconclusive: existing main conflicts
#4424 b447062d71dc1748d60edfdc0ec437aa597a5b7d docs/user/USAGE.md inconclusive: existing main conflicts
#4423 bad53434ecca2bf92ee67c43952598c6a108941e docs/user/USAGE.md inconclusive: existing main conflicts
#4422 f9b136024e27d1463a70edee4952553628e5f289 docs/user/USAGE.md inconclusive: existing main conflicts
#4397 5e296b79d94a6312c385890352d7f76e9a0d4380 docs/user/USAGE.md inconclusive: existing main conflicts
#4396 eb34b754de4b65b11c1f7d9beafe58a0d057c45d docs/user/USAGE.md inconclusive: existing main conflicts
#4156 a6cb0cb5f277da258a661bb11792e04941f4c790 docs/user/USAGE.md inconclusive: existing main conflicts
#3998 48bc3322b68ee855d9188f4eefd701e8007dd21b docs/user/USAGE.md clean
#3994 2636a486c2f71d880b69cadb706eac719f9cc670 docs/user/USAGE.md clean
#3891 67f94df827623df9210738a5ba3275b9a59f1c8b docs/user/USAGE.md inconclusive: existing main conflicts
#3786 7b75adc8685edbffaa771e0d436543eaae694b8f docs/user/USAGE.md clean

Source comparisons: #6156 adds filesystem-identity checks and #6106 changes startup dependency selection; neither removes the standard-directory requirement for explicit directories. Both merge cleanly. Shared documentation changes describe other features.

Checklist

  • Based on current main; no other open PR implements the same fix (overlapping changes listed above)
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw; no silent stubs added
  • No notes, investigation files or images added to the repository
  • No new third-party code
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: none (conversion/diagnostic evidence only)
  • GPUs tested: n/a
  • AI-assisted: yes (Codex)

@simonbbby

Copy link
Copy Markdown
Contributor

Independent Linux host conversion verification at exact head 1800d3892bec857b254ca8c55e912e325e1c6711, standalone on its recorded parent, with no other PRs added.

Ubuntu 24.04, kernel 7.0.0-38, Ryzen 9 9950X, GCC 13.3, Ninja Release, ANYPS5_RELINKER_ONLY=ON, BUILD_TESTING=ON:

  • Full relinker-only suite: 172/172 pass, no skips reported, 29.72 s serial wall time with the 30-second CTest timeout.
  • guest_module_dir: 3/3 pass. This covers Linux and Windows output with explicit . and Media/Plugins directories and no standard folder, while retaining no-option rejection, missing/escaping directory checks, duplicate/incompatible option checks and input-byte preservation.
  • Matched negative control: restore only core/relinker/cli/src/NativeModules.cpp from this head's parent, retaining the new test and everything else. Rebuild the relinker: guest_module_dir fails at the first explicit-only Linux case with FAIL: sce_module/*.prx was not found ... Use --skip-sce-module to disable guest module processing.
  • Restore the PR production source byte-for-byte and rebuild: the same fixture passes another 3/3. The checkout is clean.

These are the PR's synthetic conversion fixtures and the full Linux host relinker suite. No new Mari0/package conversion, native homebrew runtime, Windows execution, GPU or title result is claimed.

@screamm

screamm commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Windows check of head 1800d3892, merged onto main db81992c5: clean merge.

Windows 11 Pro 26220, Ryzen 7 5700X, RTX 4070 (driver 596.21), WinLibs MinGW-w64 GCC 15.2.0 r7, Ninja, Release.

  • Build: relinker and libs pass, no new warnings.
  • 17 module, input and registry relinker tests (guest_module_dir, guest_module_directories, relinker_executables, sce_module_path, guest_needed_*modules, guest_registry, guest_module_args, guest_module_identity, windows_import_modules, relinker_conversion, input_*, call_registry, ...), --repeat until-fail:3: 17/17, 3 of 3. The whole core/relinker test directory: 127/127.
  • Negative control: this head's test_guest_module_dir.py with main's relinker fails at the first explicit-only case with sce_module/*.prx was not found.
  • tools/check_conventions.py --base origin/main and git diff --check: pass.

Bundles without sce_module/sce_modules/prx, all with --windows --trap-sdk-syscall-stubs:

Case main main + #6231
romm-sync.elf in its own folder (PPSA76677 assets/rommps), no option exit 2, sce_module/*.prx was not found in: ... identical message
same, --module-dir . exit 2, same message exit 0, app.exe
RetroArch eboot.elf (PPSA99169) with three of its libretro cores in cores/, no option exit 2, same message identical message
same, --module-dir cores exit 2, same message exit 0, app.exe + app0/cores/*_libretro.so.guest.prx (3)
same, --module-dir missing / ../outside exit 2, missing-standard-dir message exit 2, Guest module path is not a directory / --module-dir must be a directory inside the guest module parent directory

The PR's RetroArch output (exe, three .guest.prx files and registries) is byte-identical to what main produces after adding an empty sce_module, so only the directory gate changed. The inputs' SHA-256 values are unchanged.

Regression relinks with the catalog flags, every output file hashed: PPSA28319 (--module-dir Media/Modules --module-dir Media/Plugins, 15 files) and PPSA99169 (--executable picker/picker.bin, 9 files) are byte-identical to main. PPSA99995 (--trap-sdk-syscall-stubs --module-dir win/wine/lib/wine/x86_64-unix) gives the same Unsupported Windows guest TLS instruction refusal as main; that one needs #6102.

Side note: the core registries this produces use plain names ("nid": "calloc"), which main's tools/import_audit.py rejects with invalid NID 'calloc'. #6239 covers that.

Verdict: confirmed. An explicit --module-dir now works without a standard folder, the no-option error is unchanged, and existing conversions are byte-identical.

AI-assisted (Claude Code).

This was referenced Oct 15, 2026
@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 3998 docs/user/USAGE.md
PR 4891 docs/user/USAGE.md
PR 5021 docs/user/USAGE.md
PR 5925 docs/user/USAGE.md
PR 6111 docs/user/USAGE.md
PR 6788 docs/user/USAGE.md
PR 6924 docs/user/USAGE.md
PR 6946 docs/user/USAGE.md
PR 6947 docs/user/USAGE.md
PR 7332 docs/user/USAGE.md

@karimibrahim07 karimibrahim07 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A real bundle for this case: the websrv Quake homebrew (#6698) ships quake.elf and libOSMesa.so.8 side by side, with no sce_module, sce_modules or prx folder. Windows 11 Pro (26300), WinLibs GCC 15.2.0 r7, head 1800d3892 merged onto main 5d9dcc42d (clean merge).

  • main's relinker with --windows --to-intel --trap-sdk-syscall-stubs --module-dir .: FAIL: sce_module/*.prx was not found in: …, exit 2.
  • With this PR, the same command converts the bundle (Converted modules: 1) to app0/libOSMesa.so.8.guest.prx. No sce_module folder is created in the input, and the inputs are unchanged.

When I prototyped that title before this PR I had to create an empty sce_module folder to get past this error, so this removes a real workaround. The one-line condition keeps the old error when no --module-dir is given, and that is what I see on main.

AI-assisted: yes. I ran the conversions above.

@oneandonlydean
oneandonlydean merged commit 883cb1a into boykopovar:main Oct 18, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants