fix(ci): build Linux natives against a pinned glibc floor - #24
Conversation
CMakeLists.txt already links libgcc and libstdc++ statically, so glibc is the only dynamic dependency left in the published `.so` — which makes the build host's glibc the minimum supported Linux for every consumer, and Terasology ships these natives to players. MovingBlocks#23 moved the Linux matrix from `ubuntu-20.04` to `ubuntu-24.04` to replace retired runner images, raising that floor from glibc 2.31 to 2.39 as a side effect. The result fails to load on anything older: `libm.so.6: version 'GLIBC_2.38' not found`, seen on Terasology's Debian-based build agents (MovingBlocks/Terasology#5359) and on any player distro below Ubuntu 24.04. Building inside `ubuntu:22.04` decouples the floor from whichever runner image GitHub currently offers, so the next retirement can't move it silently. There is no `ubuntu-20.04-arm` runner, so a container is also the only way to give the new `linux_aarch64` target the same floor as amd64. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Container jobs default to `sh` rather than `bash`, since GitHub cannot assume bash exists in an arbitrary image. The OS-dispatch steps use `==`, which dash rejects with `[: Linux: unexpected operator` — and the `else` branch then exits 1 claiming the OS is unsupported, which reads as a platform problem rather than a shell one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`${{ github.workspace }}` resolves to the host path even in a container job, so the PATH entry pointed at `/home/runner/work/...` while the container only has `/__w/...` — `swig: command not found` despite a reported cache hit. `actions/cache` maps the two itself, which is why its `path:` input works and this step did not.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…bc floor The container pins the floor; nothing yet proves the output honours it. This reads the symbol versions back off the built `.so` and fails the job if any exceeds the declared floor, so the next base-image change surfaces here rather than as an `UnsatisfiedLinkError` on a user's machine — which is how MovingBlocks#23 was found. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe GitHub Actions workflow now runs Linux jobs in Ubuntu 22.04 containers, versions the SWIG cache, uses container workspace paths, and rejects Linux native artifacts that require glibc newer than 2.34. ChangesLinux CI portability
Estimated code review effort: 3 (Moderate) | ~20 minutes Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/allInOne.yml:
- Around line 48-50: Update the SWIG cache comment near the ubuntu-24.04 matrix
entry to state that the cached binary runs in the Linux build and publish
containers, removing the outdated reference to a plain runner.
- Around line 12-14: Update the support comment near GLIBC_FLOOR so it matches
the enforced glibc requirement: remove RHEL 9 from the supported-distribution
list, or lower GLIBC_FLOOR to 2.34 if RHEL 9 must remain supported.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 725f8220-1fde-47e7-a9ba-c47aef31c026
📒 Files selected for processing (1)
.github/workflows/allInOne.yml
There was a problem hiding this comment.
Pull request overview
Pins the Linux native build environment by moving Linux builds into an ubuntu:22.04 container, so the produced .so files have an intentional, stable glibc compatibility floor instead of inheriting whatever glibc version the GitHub runner image happens to ship.
Changes:
- Run the
swig,build, andpublishjobs in anubuntu:22.04container for Linux targets, with a bootstrapping step to install missing base tooling. - Version SWIG cache keys to avoid restoring a SWIG binary built against a different libc/PCRE environment.
- Add a post-build check that inspects required
GLIBC_*symbol versions and fails if they exceed a declared floor.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Review round 1, CodeRabbit and Copilot both landing on the same conflation: the header comment used the container's glibc (2.35) as the compatibility claim, then listed RHEL 9 as covered — and RHEL 9 ships 2.34, so the claim contradicted itself. Copilot had the sharper framing: the consumer floor is the highest `GLIBC_*` symbol the linker references, which can be lower than the image's glibc, and here is 2.34. So `GLIBC_FLOOR` drops to that measured value. This makes the check strictly stronger — at 2.35 a change that started referencing 2.35 symbols would have passed while silently dropping RHEL 9. Also per Copilot: the check ran under `-e -o pipefail`, so a `grep` with no matches killed the step with no diagnostic. It now distinguishes "no natives", "objdump failed", and "no versions found" — the last being unverified rather than satisfied, which is the one that could have masked a regression. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Summary
ubuntu:22.04instead of directly on the runner, so their glibc floor is a pinned decision rather than a side effect of whichever runner image GitHub currently offers..soand fails if any exceeds the declared floor — the regression this fixes was only discovered downstream, in someone else's CI.shrather thanbash;${{ github.workspace }}resolves to the host path inside a container while$GITHUB_WORKSPACEresolves per environment; SWIG cache keys need a version component because the cached binary is linked against the environment it was built in.Why
CMakeLists.txtalready links libgcc and libstdc++ statically, so glibc is the only remaining dynamic dependency of the published.so. That makes the build host's glibc the minimum supported Linux for every consumer — and Terasology copies these natives straight into its player distribution (facades/PC/build.gradle.kts).#23 moved the Linux matrix from
ubuntu-20.04toubuntu-24.04to replace runner images GitHub had retired. That was necessary, but it raised the floor from glibc 2.31 to 2.39 as a side effect, and nothing in the build declares or checks a floor. The result cannot load on anything older:That is MovingBlocks/Terasology#5359, where every engine test fails on Debian-based build agents once the static initialiser dies. It would equally affect any player below Ubuntu 24.04.
A container rather than an older runner label, for two reasons: there is no
ubuntu-20.04-armor equivalent, so thelinux_aarch64target added in #23 cannot reach a low floor viaruns-onat all; and pinning the image is what stops the next runner retirement from moving the floor again silently.ubuntu:22.04specifically, rather than something older, becauseLLVM_MINGW_VERSIONis pinned to an ubuntu-22.04 build of llvm-mingw which runs in the same job. Going lower would mean splitting the Windows cross-compile targets into a separate job.Note the image's glibc and the resulting floor are different numbers. The image supplies 2.35, but the linker only ends up referencing symbols up to 2.34 (the release that folded libpthread and libdl into libc), and 2.34 is what the check asserts — so the natives load on Debian 12, Ubuntu 22.04, and RHEL 9. It does drop Ubuntu 20.04 and Debian 11 relative to 1.0.4 — both past end of standard support — so if you would rather keep those, say so and I will split the job and drop the image to
ubuntu:20.04.Test plan
objdump -Ton the built natives yields a highest requirement of2.34on both amd64 and aarch64, exactly the declared floor.GLIBC_FLOORnow at the measured value there is deliberately zero headroom, so any increase fails the job.masterto republish1.0.5-SNAPSHOT; the publish job is gated ongithub.ref, so a green PR build alone does not refresh the artifact.1.0.5-SNAPSHOTis a changing module and the agents start cold.Related