かくことない

かもしれない

ggezをバージョンアップしたらnix-shell上でプログラムが起動しなくなった話

タイトルはggezだけど、エラーメッセージはglutinwinitから出ているからそれ関係なら使えるはず。

解決策

shell.nixに以下のような設定を加える。

LD_LIBRARY_PATH = lib.makeLibraryPath [
  "/run/opengl-driver"
  xorg.libX11
  xorg.libXcursor xorg.libXrandr xorg.libXi libGL
];

Rustなどその他もろもろも入れるとこうなる。

let
  moz_overlay = import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz);
  nixpkgs = import <nixpkgs> { overlays = [ moz_overlay ]; };
  rust = nixpkgs.rustChannels.stable.rust;
in
  with nixpkgs;
  mkShell {
    buildInputs = [
      rust alsaLib pkgconfig SDL2 libudev
    ];
    LD_LIBRARY_PATH = lib.makeLibraryPath [
      "/run/opengl-driver"
      xorg.libX11
      xorg.libXcursor xorg.libXrandr xorg.libXi libGL
    ];
  }

事の顛末

ggezを0.5.0-rc0にバージョンアップしたら、1 以下のエラーが出て自分のプログラムが動かなくなってしまった。

thread 'main' panicked at 'Failed to initialize any backend! Wayland status: NoCompositorListening X11 status: LibraryOpenError(OpenError { kind: Library, detail: "opening library failed (libXcursor.so.1: cannot open shared object file: No such file or directory); opening library failed (libXcursor.so: cannot open shared object file: No such file or directory)" })', /home/ix/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.18.0/src/platform/linux/mod.rs:437:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.

最初は依存関係にlibXcursorが足りないのかと思ったから、buildInputsxorg.libXcursorを追加してみたが改善しなかった。

ここでメッセージをちゃんと読むと動的ライブラリlibXcursorがないと出ている。 ということはLD_LIBRARY_PATHが通っていないと思い、試しにecho $LD_LIBRARY_PATHをしたところ案の定だった。2

$ echo $LD_LIBRARY_PATH
/run/opengl-driver/lib

そこでlibXcursorLD_LIBRARY_PATHへ追加した。

LD_LIBRARY_PATH = "${xorg.libXcursor}/lib";

上の「動的ライブラリがない」エラーがlibXrandrlibXiで出たから同様のことを繰り返す。

LD_LIBRARY_PATH = "${xorg.libXcursor}/lib:${xorg.libXrandr}/lib:${xorg.libXi}/lib";

これで直ったかと思いきや、次は以下のようなエラーが出た。

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: NotSupported("both libglx and libEGL not present")', libcore/result.rs:1009:5
note: Run with `RUST_BACKTRACE=1` for a backtra

libEGLは字面から見て関係なさそうだから、3あとのlibglxが問題なはず。

libglxはGLXの実装でOpenGLをX Window System上で使うためのものっぽい

何も考えずnix search libglxをしたところ何も見つからなかった。でもlibGLなるものはあったからこれを前のようにLD_LIBRARY_PATHに入れてみる。

LD_LIBRARY_PATH = "${xorg.libXcursor}/lib:${xorg.libXrandr}/lib:${xorg.libXi}/lib:${xorg.libGL}/lib";

そうすると次は以下のようなエラーが出た。

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: OsError("`glXQueryExtensionsString` found no glX extensions")', libcore/result.rs:1009:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.

こんどはglX extensionsなるものがないらしい。

GLX extensionはグラフィックドライバによってサポートされるものらしいから試しにパソコンを変えてみたけれど変わらなかった。つまり、ドライバの問題ではないはず。

ここで、試しにglxgearsを起動してみることにした。glxgearsmesaのデモプログラムで、その名の通りGLXで歯車が描画される。

やってみたところ、エラーが出て起動しなかった。ただ、nix-shellを使っていない状態では問題なく起動できた。

ならばnix-shellを使っていない状態に何か手がかりがあるかもしれない。nix-shell抜きでLD_LIBRARY_PATHを確認してみる。

$ echo $LD_LIBRARY_PATH
/run/opengl-driver/lib

あ、なんかopenglとか書いてあるしそれっぽい……。

というわけで上で出てきたものをshell.nixに追加したらめでたく動いた。

LD_LIBRARY_PATH = "${xorg.libXcursor}/lib:${xorg.libXrandr}/lib:${xorg.libXi}/lib:${xorg.libGL}/lib:/run/opengl-driver/lib";

ただ、なんだか記述が野暮ったくて気に入らないので既存のパッケージを色々見てみたところ、lib.makeLibraryPathというそのまんまな関数があったので早速使う。4

LD_LIBRARY_PATH = lib.makeLibraryPath [
  "/run/opengl-driver"
  xorg.libXcursor xorg.libXrandr xorg.libXi libGL
];

冒頭のコードにはこれに加えてxorg.libX11がある。これはこの記事を書く前にもう一度動作確認してみたところ何故か足りないと言われてしまったので追加したから。理由は謎。


  1. これはテスト版だけど、0.4から多くの変更がAPIに加えられているらしいから移行の手間を省くためにあえてバージョンアップした

  2. ここ伏線

  3. OpenGL ESは組み込み用って書いてある

  4. Nixpkgs Manualにはこの関数のマニュアルが書いてなかったけど、当該関数のコードを見てみるとちゃんと書いてあった。ネットのマニュアルはどうやら自動生成のようなので、多分、次のリリース時にオンラインでも見れるようになるはず。