ggezをバージョンアップしたらnix-shell上でプログラムが起動しなくなった話
タイトルはggez
だけど、エラーメッセージはglutin
とwinit
から出ているからそれ関係なら使えるはず。
解決策
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
が足りないのかと思ったから、buildInputs
に
xorg.libXcursor
を追加してみたが改善しなかった。
ここでメッセージをちゃんと読むと動的ライブラリのlibXcursor
がないと出ている。
ということはLD_LIBRARY_PATH
が通っていないと思い、試しにecho $LD_LIBRARY_PATH
をしたところ案の定だった。2
$ echo $LD_LIBRARY_PATH /run/opengl-driver/lib
そこでlibXcursor
をLD_LIBRARY_PATH
へ追加した。
LD_LIBRARY_PATH = "${xorg.libXcursor}/lib";
上の「動的ライブラリがない」エラーがlibXrandr
とlibXi
で出たから同様のことを繰り返す。
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
を起動してみることにした。glxgears
はmesa
のデモプログラムで、その名の通り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
がある。これはこの記事を書く前にもう一度動作確認してみたところ何故か足りないと言われてしまったので追加したから。理由は謎。