Expand GitHub workflow to build multi platform release - #1
Conversation
|
can you rebase and remove the merge commit |
Should be done |
|
We've also got some fork'ed (vendored) libretro cores that have some custom patches on top of them like (mgba, dolphin, azahar. pcsx_rearmed) those will probably need a build as well as they just build android/windows for now. I can easily build them on Window's WSL for linux x86 and maybe linux arm as well. I'll have to look in to how those can be build for mac as well |
Yeah I flagged some systems, like Mac, as experimental because I knew were unchecked/incomplete. |
2166445 to
2d11629
Compare
… in release.yml Extend the upstream release workflow (preflight/quest/windows/release) with two new jobs, porting the platform tricks from the old implementation but fixing the parts that were broken there: - linux job (blocking, matrix): x86_64 -> ubuntu-24.04 (AppImage), arm64 -> ubuntu-24.04-arm (tar.gz). Builds both debug+release so the editor can load the classes, downloads the arch-correct Godot editor, builds SDL3 3.2.16 from source for arm64 (the vendored SDL3 is a Windows dev package with no source), fetches the arm64 libpdfium, patches libretro-godot and godot-pdfium SConscripts to be arch-aware, and patches godot-cpp for long ar command lines (TEMPFILE). - macos job (experimental, continue-on-error): builds arm64 + x86_64 dylibs and lipos them into universal binaries, exports a universal .app, ad-hoc codesigns with entitlements (disable-library-validation, allow-unsigned-executable-memory, allow-jit), packages a zip. - release job now needs [preflight, quest, windows, linux, macos]. Also: - export_presets.cfg: add Linux and macOS presets (macOS universal, s3tc+etc2, codesign+entitlements), update runnable_presets. - entitlements/macos.entitlements: new plist for ad-hoc signing. - .gdextension files: add linux.arm64 and macos.universal entries (universal listed before per-arch so Godot's tie-break picks it). - README: document the new platforms and the Linux libvlc (vlc-libs) runtime dependency for DVD/VHS playback.
…t runs - checkout v4->v7, setup-java v4->v5, cache v4->v6, upload-artifact v4->v7, download-artifact v4->v8: clears the 'Node.js 20 is deprecated' warnings. - quest: a missing ANDROID_KEYSTORE_BASE64 now only hard-fails tag/publish runs; a plain dispatch warns and exports an unsigned APK so the pipeline can be tested on forks without the signing secrets.
SDL3 3.2.16's CMake hard-errors when neither X11 nor Wayland development headers are found, and the ubuntu-24.04-arm runner ships neither - the configure step died with 'SDL could not find X11 or Wayland development libraries'. Install the usual desktop dev set first so the built libSDL3 matches what distros ship.
…bc++ Two failures from run 32435542472: linux (both arches): the editor could not dlopen libretro_godot - it links SDL3 by soname with no rpath and expects the host to provide libSDL3.so.0, which a bare runner does not have - so every script naming Libretro died with 'could not find type'. Both arches now build SDL3 3.2.16 from source (the committed x86_64 stand-in wants GLIBC_2.43, newer than ubuntu-24.04's own 2.39), stage it next to the built .so where its $ORIGIN RUNPATH finds it, and the gdextension [dependencies] entries bundle it into exports. Also install the GL/Vulkan runtime libs the extension records as needed. macos: Apple clang's libc++ construct_at lacks C++20 P0960 parenthesized aggregate init, so OptionsHandler.cpp's emplace_back() on the aggregate OptionValue failed to compile. Patched to brace init at build time until the fix lands upstream (this account cannot push to XenuIsWatching/libretro-godot).
… patch - The staging step looked for libSDL3.so.0 under RetroXR/libretro-godot, but the SDL3 build writes it into the repo-root submodule tree - the arm64 job died on cp after 'all 10 builds OK'. - Bundle SDL3 into build_out right after export instead of via [dependencies]: those entries would demand the file in every working tree and break local exports whose hosts already have SDL3. - Replace the OptionsHandler.cpp call-site patch with one constructor patch on OptionsHandler.hpp: there are three emplace_back sites and libc++ rejects them all; constructors satisfy every one.
Three failures from run 32440283851:
- linux-arm64: the preset awk reset its in-Linux flag on [preset.N.options]
too - and binary_format/architecture lives in exactly that options block,
so the x86_64->arm64 substitution silently missed and export died copying
a nonexistent x86_64 .so. Anchor the reset on bare [preset.N] headers.
- quest: --export-release refuses to run with no keystore at all ('Code
Signing: Could not find release keystore'), so warn-and-export-unsigned
cannot work. Test dispatches now mint a throwaway keystore instead;
tag/publish runs still hard-require the real secret.
- linux-arm64: the freshly built extensions carry an unversioned DT_NEEDED
libdl.so, which glibc-based distros stopped shipping when dl merged into
libc. patchelf --replace-needed to libdl.so.2 after the build.
The ::warning annotation scrolls away with the log; write the notice to GITHUB_STEP_SUMMARY too so the run report itself says the Quest APK is signed with a one-off keystore. Upstream never takes this branch (the secrets exist there), so PRing this file changes nothing upstream.
A publish dispatch without ANDROID_KEYSTORE_BASE64 died in the export
step ('secret ANDROID_KEYSTORE_BASE64 is unset'). Mint the throwaway
keystore whatever the run kind instead - the ::warning and the Summary
tab entry already say the APK is not upgrade-compatible with a real
release - and drop the now-unused PUBLISHING env.
A dispatch that rebuilds the current version (code=6 after the v0.3.1 tag also carried 6) died in preflight before any build started. Like the keystore and SideQuest steps, the check now lands a ::warning plus a Summary tab entry - bump version/code before tagging or SideQuest will reject the build - and lets the pipeline proceed.
- The release job ran only on tags or publish dispatches, so a plain dispatch threw every built artifact away. Run it whenever the builds succeed: create the release, or refresh the existing one's assets (--clobber) when the tag already exists. - The upstream merge brought its own SCons cache steps back as actions/cache@v4 in quest and windows - bump both to v6 like the rest.
… feature/bug/known-issue sections) to release notes
The PR demoted the preflight version/code comparison to a ::warning, so a tag whose code matched or trailed the previous tag's built for half an hour and then shipped an APK SideQuest will refuse. README promises preflight fails before the build, so a tag push errors again. A publishing workflow_dispatch keeps the warning: it cuts no tag and the listing is not at stake, and a dispatch that deliberately rebuilds the current version has to stay runnable.
The fallback keystore made a test dispatch runnable on a fork with no secrets, but it applied to a tag push too, so a repository that lost its ANDROID_KEYSTORE_BASE64 would ship a release APK signed with a 30-day key minted on the runner. That installs cleanly and then refuses to upgrade over every player's existing install, and nothing before the store would catch it. A run that publishes now errors when the secret is unset; a run that only uploads artifacts keeps the fallback and the warning.
The PR dropped the release job's `if: github.ref_type == 'tag' || inputs.publish` so the job could refresh an existing release's assets rather than throw the artifacts away. What it actually does on a manual run with publish unticked is resolve TAG from the preset's version/name, find the live release of that version, and `gh release upload --clobber` the test build over it - including a Quest APK signed with the throwaway CI keystore. README says a manual run creates no release and touches no listing, and that is the way to test a build, so the guard is back. The artifacts are still on the run itself, which is where that README points.
Two faults in one branch of the same conditional. A tag push created the release with --draft. README says a tag push publishes a GitHub Release and points the SideQuest listing at it, and a draft is neither: it is invisible to the listing the SideQuest step reads back, invisible to anyone following a download link, and the pipeline reports success while no release exists. Staging one by hand is still a click away in the other direction. The other half is `gh release edit "$TAG" --notes-file notes.md` on the existing-release branch. notes.md is the placeholder template - "## Feature name / description / bug 1 / bug 2" - so re-running a tag to replace a bad asset wiped whatever release notes had been written. The template is for a release that does not exist yet; a rerun now refreshes assets only.
Both macOS dependency entries had an empty target, and Godot's macOS exporter copies an empty-target shared object to Contents/Frameworks/<basename>. Both are called libpdfium.dylib, so one overwrote the other - the exported bundle carried a single arm64 libpdfium - and the extension's own load command, set by install_name_tool in godot-pdfium/SConscript, is @loader_path/mac-<arch>/libpdfium.dylib, which resolves inside Contents/Frameworks and found nothing at all. Measured before the change, exporting the macOS preset with Godot 4.7.2 and running the .app: Can't open dynamic library: godot-pdfium/libgodot-pdfium.macos.template_release.universal.dylib Library not loaded: @loader_path/mac-arm64/libpdfium.dylib Reason: tried: '.../Contents/Frameworks/mac-arm64/libpdfium.dylib' (no such file) Error loading extension: 'res://godot-pdfium/godot-pdfium.gdextension' so PDFRenderer never reached ClassDB and books were dead in every exported build. A non-empty target is copied to <app>/<target>/<basename> instead, so naming the two subfolders puts each architecture's library exactly where its own slice asks for it and neither can clobber the other. After the change the bundle carries Contents/Frameworks/mac-arm64/libpdfium.dylib and .../mac-x64/libpdfium.dylib, arm64 and x86_64 respectively, and the app logs "[PDFRenderer] PDFium library initialized." This is the exported bundle only; an editor or non-exported run still loads the two out of RetroXR/godot-pdfium/mac-*/ as before. The android and linux entries are untouched, so the Android libpdfium.so stays in the output root where its [dependencies] block and Quest exports expect it.
The preset set codesign/enable and codesign/entitlements, and neither is an option EditorExportPlatformMacOS declares, so Godot stored them and read nothing. macos.entitlements was never applied to a local export at all; CI hid it by re-signing the bundle with that file afterwards. The real names, from platform/macos/export/export_plugin.cpp at 4.7.2-stable, are codesign/codesign and a set of codesign/entitlements/<name> booleans that Godot renders into an entitlements plist itself. Measured on an exported .app with `codesign -d --entitlements -`. Before, one key, and that one only because Godot force-adds it when an ad-hoc signature meets embedded libraries: com.apple.security.cs.disable-library-validation After, the three the app needs - unsigned downloaded cores, executable callback trampolines, and JIT for dynarec cores: com.apple.security.cs.allow-jit com.apple.security.cs.allow-unsigned-executable-memory com.apple.security.cs.disable-library-validation codesign/entitlements/custom_file is deliberately left empty rather than pointed at RetroXR/entitlements/macos.entitlements: the value is handed to codesign verbatim, with no globalize_path, so a res:// path cannot work and only an absolute host path would - which is not something a committed preset can carry. The committed file stays as the input to the workflow's own re-sign step and lists the same three keys. codesign/codesign=3 (Xcode codesign, ad-hoc while codesign/identity is empty), not 1. Godot's built-in signer produces a bundle this machine kills on exec - SIGKILL, no output, though `codesign --verify --deep --strict` passes - and re-signing the same bundle with /usr/bin/codesign makes it run. Two more dead keys corrected the same way. application/min_macos_version is not an option either; the real ones are per-architecture, and without them the x86_64 slice declared LSMinimumSystemVersion 11.00 while its own dylibs are built with macos_deployment_target=13.0. Both now say 13.0. The rest of the removed lines - texture formats, modify_resources, angle_libraries, bundle_name, export_type, embed_pck - are Windows or Android options that macOS does not declare; macOS takes its texture formats from binary_format/architecture.
30b89c9 to
07abf18
Compare
|
ok, i rebased it and fixed a few small issue with it... but other than that, it looked great, thanks!! Now we have automated linux and mac builds 🥳 |
Features
New plaforms added
These platform are added as experimental releases:
Publishing
Release is published as a draft release and includes a templated do be manually edidte before push.
(based on 0.3.0 release notes).
Key generation
Android: if the signing key the workflow won't stuck: a key will be generated on the fly: the application will appear as a different one, good for testing for contributors to don't mess with the original installation.
A warning in the workflow summary will be posted.
Same for MacOS.
SideQuest
SideQuest is no more blocking: a warning in the workflow summary will be posted instead.
Examples
Example release
Can be found here
Workflow summary
NOTES
The cache will be generated at first successful workflow (release is not needed for cache generation).