Skip to content

Precompiled x86_64-linux gem fails on Alpine/musl; please publish a musl variant #806

Description

@dduugg

Problem

rubydex ships precompiled gems for x86_64-linux (glibc), aarch64-linux (glibc), arm64-darwin, x86_64-darwin, and x64-mingw-ucrt, plus a ruby source gem. There is no *-linux-musl precompiled gem, and the glibc-targeted x86_64-linux build fails to load on Alpine / musl libc — even with gcompat installed — because the prebuilt .so references fortify-source symbols (__vsnprintf_chk, etc.) that musl + gcompat do not provide:

Error relocating /usr/local/bundle/gems/rubydex-0.2.3-x86_64-linux/lib/rubydex/3.4/../librubydex_sys.so:
  __vsnprintf_chk: symbol not found
  - /usr/local/bundle/gems/rubydex-0.2.3-x86_64-linux/lib/rubydex/3.4/rubydex.so (LoadError)

This makes bundle install succeed (because bundler considers x86_64-linux compatible with x86_64-linux-musl) but require "rubydex" fail at runtime — which means anything depending on rubydex (e.g. tapioca >= 0.19) is unusable on Alpine-based CI/runtime images.

Reproduce

FROM ruby:3.4-alpine
RUN apk add --no-cache build-essential libyaml-dev git
RUN gem install rubydex -v 0.2.3
RUN ruby -e "require 'rubydex'"

gem install and bundle install both succeed (bundler installs rubydex-0.2.3-x86_64-linux); the final require errors with the __vsnprintf_chk relocation failure shown above.

Workarounds we tried

  1. gcompat — already a documented compatibility shim on Alpine. Does not implement the glibc *_chk fortify-source family, so this approach is a dead end for any prebuilt gem compiled with -D_FORTIFY_SOURCE=2.
  2. Force source build (gem "rubydex", force_ruby_platform: true) — fails on Alpine because the source gem needs cargo, and the alpine Ruby base image does not include the Rust toolchain. Adding it costs ~150 MB and ~60s per fresh build.
  3. Move CI off Alpine to ruby:*-slim (Debian/glibc) — what we ended up doing. Works, but it's a bigger change than the failure warranted.

Suggested fix

Publish an x86_64-linux-musl (and ideally aarch64-linux-musl) precompiled variant alongside the existing x86_64-linux build. Other gems with Rust extensions take this approach (e.g. nokogiri, wasmtime, lz4-ruby); typical implementations cross-compile in CI with a musl Rust target (x86_64-unknown-linux-musl).

If a musl prebuild is out of scope, two smaller mitigations would still help:

  • Either document the Alpine incompatibility prominently in the README, since the runtime symptom (__vsnprintf_chk) is opaque enough that it's hard to trace back to rubydex without doing the relocation analysis.
  • Or build the existing x86_64-linux gem without -D_FORTIFY_SOURCE=2, which would let gcompat carry it. (This degrades hardening on glibc systems, so I lean toward the musl-prebuild option.)

Happy to test a prerelease on an Alpine CI image if that's useful.

Environment

  • rubydex 0.2.3
  • Ruby 3.4 (ruby:3.4-alpine, Alpine 3.20)
  • Bundler 4.0.7

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions