Ubuntu 26.04 でビルドしたあとの「version `GLIBC_2.43' not found」
ubuntu-latest は、2026年10月19日から11月19日にかけて Ubuntu 24.04 から 26.04 に移ります(ほかに変わること)。glibc は 2.39 から 2.43 に上がります(11月4日の Ubuntu のパッケージの一覧)。glibc に対してビルドしたプログラムは、リンクした glibc のシンボルのうちいちばん新しい版を求めます。そのため、26.04 でビルドしたバイナリは、ソースを変えていなくても GLIBC_2.42 や GLIBC_2.43 を求めることがあります。ランナーの glibc は 2.43 なので、ジョブは緑のままです。失敗はリリースのあと、利用者のマシンで表に出ます。Ubuntu 24.04 は 2.39、Debian 13 は 2.41、Ubuntu 22.04 は 2.35 です。
どう見えるか
./app: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.42' not found (required by ./app) ./app: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.43' not found (required by ./app)
Electron のアプリでは、メッセージが1段ずれます。node-pty は Failed to load native module: pty.node と出し、pty.node を直接読み込むと version `GLIBC_2.42' not found が見えます。AppImage は、新しい glibc を求める同梱のライブラリを並べて出します。
GLIBC_2.42 と GLIBC_2.43 はどこから来るか
libc.so.6のGLIBC_2.42:glibc 2.42 で<termios.h>が任意のボーレートを受け付けるようになり(glibc の NEWS)、cfgetispeed・cfgetospeed・cfsetispeed・cfsetospeed・cfsetspeedに新しい版ができました。端末を設定するコードはこれらを呼びます。node-pty のpty.nodeはcfsetospeed@GLIBC_2.42を求め(muster-code #680)、libedit のような行の編集のライブラリも呼びます。libm.so.6のGLIBC_2.43:glibc 2.43 は、acosf・asinf・atan2f・log10f・sqrtf・sinhf・coshf・lgammaf・tgammaf・remainderなどにあった古い SVID のエラー処理を、互換用のシンボルに移しました。2.43 でビルドしたプログラムがどれかを呼ぶと、新しいGLIBC_2.43の版にリンクされます。よく使われる関数なので、同梱のライブラリにも入ります(Decktector #3 の WebKitGTK と Little CMS)。msealやopenat2のような新しい関数もGLIBC_2.43ですが、それを求めるのは呼んでいるコードだけです。
報告のあったもの
- リリースのバイナリ:MicroPython と CircuitPython のインタープリター(pydevices #391)、ある MySQL のディストリビューションの tarball の mysql クライアント(villagesql-server #1505)、
GLIBC_2.43を求めるようになった Rust のテストランナーなど(turbo-test #221・wisp #15・Amber-widget #8)。ある Go のプロジェクトでは、CGO_ENABLED=0でビルドしたバイナリは問題なく、cgo で llama.cpp をリンクするバイナリがGLIBC_2.43を求めました(la-roca #596)。 - node-pty を使う Electron のアプリ:.deb が Ubuntu 24.04 で起動しませんでした(aios-app #93・devhub #67)。あるプロジェクトでは、週1回の prebuild の実行が 26.04 に当たって公開済みの node-pty の prebuild を置き換えたので、それをダウンロードするインストールも壊れました(ws-scrcpy-web #989)。
- コンテナのイメージ:ランナーでビルドして
debian:trixie-slim(glibc 2.41)にコピーしたバイナリが、コンテナの起動時に落ちます(hyperi-ci #747)。
直し方:リリースは対応するいちばん古いイメージでビルドする
jobs:
build-linux:
runs-on: ubuntu-22.04 # glibc 2.35。2.39 なら ubuntu-24.04
glibc は古いシンボルの版を残しているので、古い glibc に対してビルドしたバイナリは新しい glibc でも動きます。上の報告もこの形で直しました。turbo-test は ubuntu-22.04 と ubuntu-22.04-arm、wisp と muster-code は ubuntu-24.04 です。移すのは配るものをビルドするジョブだけで足ります。GitHub がそのイメージを終えるまでは使えます。
または、古いコンテナの中で、または glibc の版を決めてビルドする
jobs:
build-linux:
runs-on: ubuntu-latest
container: ubuntu:22.04
ランナーのイメージが何であっても、バイナリがリンクするのはコンテナの glibc です。イメージには最低限のものしか入っていないので、先に apt-get でコンパイラを入れます。Python の拡張の wheel なら、manylinux のイメージが同じ役目をします。
Rust なら、cargo-zigbuild がターゲットの後ろに glibc の版を付けられます(cargo-zigbuild):
cargo zigbuild --release --target x86_64-unknown-linux-gnu.2.28
*-musl のターゲットや、CGO_ENABLED=0 の Go のビルドは、そもそも glibc に頼りません。
CI で下限を確かめる
どの直し方でも、対応する版より新しい glibc を求めるバイナリがあればジョブを落とすステップを足します。次にイメージが変わったとき、利用者に届く前にリリースが止まります:
- name: Check the glibc floor
run: |
need=$(objdump -T dist/app | grep -oE 'GLIBC_[0-9]+(\.[0-9]+)+' | sed 's/GLIBC_//' | sort -uV | tail -n 1)
echo "dist/app needs glibc $need"
[ "$(printf '%s\n' "$need" 2.35 | sort -V | tail -n 1)" = 2.35 ]
Electron のパッケージの中の .node のアドオンも含めて、配るネイティブのファイルすべてにかけます。どのシンボルが原因かは、次で分かります:
objdump -T dist/app | grep -E 'GLIBC_2\.4[23]'
残りは、いちばん古いイメージのジョブでパッケージを実際に起動すれば見つかります。muster-code では、ubuntu-24.04 のスモークテストのジョブがこれを見つけました。
CI の中で同じメッセージ:もう一方のイメージのキャッシュ
ビルドした実行ファイルや共有ライブラリを持つキャッシュには、保存したイメージの glibc が付いてきます。あるプロジェクトでは、ubuntu-latest のジョブが Cabal のストアを ubuntu-22.04 のジョブと同じキーで保存し、それを復元したジョブが GLIBC_2.42 not found (required by .../libHSunix-....so) で落ちました(wasp #5221)。11月19日までは ubuntu-latest のジョブがどちらのイメージにも当たるので、同じキーを一方が保存してもう一方が復元することがあります。キーに glibc の版を入れます:
- id: glibc
run: echo "version=$(getconf GNU_LIBC_VERSION | cut -d' ' -f2)" >> "$GITHUB_OUTPUT"
- uses: actions/cache@v4
with:
path: ~/.cabal/store
key: cabal-${{ runner.os }}-glibc-${{ steps.glibc.outputs.version }}-${{ hashFiles('**/*.cabal') }}
見分け方
- 利用者のマシンでの「version `GLIBC_2.4x' not found」:バイナリが新しい glibc でビルドされています。そのマシンで
ldd --versionを実行すると glibc の版が、バイナリにobjdump -Tをかけると求める版が分かります。 - 同じメッセージがランナーで出るなら、もう一方のイメージのキャッシュやアーティファクトです。
- リンクのときの
undefined reference to `cfgetispeed@GLIBC_2.42':自分の古い glibc を持つツールチェーンが、26.04 のシステムのライブラリにリンクしています(tinygo #6125 の Nix の binutils とランナーの libedit)。 - 逆向き、つまり 24.04 のバイナリやキャッシュを 26.04 で使うと、「cannot open shared object file」で落ちます(libxml2 と ICU)。
- リリースの実行の「Set up job」の Runner Image の欄にイメージが出ます。11月19日までは、リリースが 24.04 に当たって動くことがあるので、1回動いたリリースは次のリリースについて何も確かめたことになりません。
ほかの 26.04 の失敗
- Ubuntu 26.04 の Docker で Postgres が起動しない:7.0.0-42 などの新しいカーネルはコンテナのプロセスを
docker-default//&unconfinedとして動かすので、プロセスどうしでシグナルを送れず、gosuが CPU 100% で止まります。いまのところ報告はセルフホストのランナーです。 - Ubuntu 26.04 の rpmbuild:rpm が 6.0.1 なので、
%installがパッケージごとのビルドのディレクトリで動いて Electron Forge の RPM の maker が「cp: cannot stat 'usr/*'」で落ち、_rpmformat 4を渡さなければパッケージは v6 になります。 - Ubuntu 26.04 の「cannot enable executable stack」:glibc 2.43 は、実行可能なスタックを求めるライブラリを
dlopenで読み込まないので、Julia 1.10.0〜1.10.8・conda-forge の TensorFlow 2.19・一部の MEX ファイルが「Invalid argument」で落ちます。 - Ubuntu 26.04 の「cannot open shared object file」:libxml2 は
libxml2.so.16、ICU は 78 なので、24.04 で保存したキャッシュや 24.04 向けのバイナリがlibxml2.so.2やlibicudata.so.74を見つけられません。 - Ubuntu 26.04 の GCC 15 で通らなくなった C と C++ のビルド:既定の gcc が 13 から 15 に上がるので、C は C23 としてコンパイルされ、古い警告の6つがエラーになり、C++ のヘッダーは
<cstdint>を読み込んでくれなくなります。 - Ubuntu 26.04 の apt:名前が変わった・無くなったパッケージ。
失敗したジョブを IntelliJ IDEA から見るなら
Pipeline Inbox for GitHub Actions Workflows は、Lesstep が作っている JetBrains IDE(2024.1 以降)のプラグインです。すべてのリポジトリの実行を、ジョブ・ステップと一緒に IDE のツールウィンドウに並べ、いまのブランチの実行はステータスバーに出ます。読むのは無料、失敗したジョブの再実行・キャンセル・ワークフローの実行・デプロイのレビューは Pro(月 US$1.50・30日の無料試用つき)です。
GitHub と GitHub Actions は GitHub, Inc. の商標、Ubuntu は Canonical Ltd. の商標、Debian は Software in the Public Interest, Inc. の登録商標、Electron は OpenJS Foundation の商標、IntelliJ IDEA は JetBrains s.r.o. の商標です。このページは GitHub, Inc.・Canonical・Software in the Public Interest・OpenJS Foundation・GNU C Library のプロジェクト・JetBrains のいずれとも提携しておらず、承認も受けていません。
ほかに:「The ubuntu-latest label will migrate to Ubuntu 26」 · Ubuntu 26.04 の「cannot open shared object file」 · IntelliJ IDEA で使える GitHub Actions のプラグインの比較 · English