TLDR: Is there a way to make Bevy program work on NixOS without LD_LIBRARY_PATH
pointing to vulkan-loader
?
In a sense this is a continuation of the discussion at Unable to find GPU, but there we focused on development environment, here I’m interested in distribution to end users.
I’m playing with Bevy (Rust game engine) again and again running into Unable to find a GPU!
runtime error. It can be solved by adding vulkan-loader
to LD_LIBRARY_PATH
but I think there is something wrong with this approach.
Setting this variable in my development environment with Nix is fine, but the built program depends on this variable too. If I run it outside the development shell, it crashes, unless I set this variable to contain vulkan-loader shared objects.
For now I did it with home-manager session-variables
like this:
home.sessionVariables = {
LD_LIBRARY_PATH = "\$\{LD_LIBRARY_PATH\}:${ pkgs.lib.makeLibraryPath [ pkgs.vulkan-loader ] }";
}
and I can run the program on my system, but obviously this is not good for other users. For example, on my own system I get this:
$ unset LD_LIBRARY_PATH
$ nix run 'gitlab:tad-lispy/bevy-lion-playground?rev=e29c4f5f7d23a7c6f6d93a9ad81b52599f8ed0ba'
thread 'main' panicked at 'Unable to find a GPU! Make sure you have installed required drivers! For extra information, see: https://github.com/bevyengine/bevy/blob/87722d135fcc7e6058aa4710e7fe5be5f2a6e594/docs/linux_dependencies.md', /build/cargo-vendor-dir/bevy_render-0.9.1/src/renderer/mod.rs:121:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
If I want to distribute my program to other NixOS users via flake, how should I deal with it?
1 Like
I was messing around with wgpu
(specifically, gpgpu
) in Rust a little while ago and found that I needed to have dontPatchELF = true
in my Nix expression. Basically, vulkan-loader
was being added to the executable’s RPATH
, but stdenv
was removing it in the fixup phase because there was no direct shared library dependency on it (I guess it’s loaded with dlopen
). I ended up with a nix expression like this:
{ stdenv
, rustPlatform
, vulkan-loader
, libX11
, libXcursor
, libXrandr
, libXi
, darwin
, lib
}:
rustPlatform.buildRustPackage {
pname = "foobar";
version = "0.1.0";
src = ./foobar;
cargoLock = {
lockFile = ./foobar/Cargo.lock;
outputHashes."gpgpu-0.2.0" = "sha256-qPMPmIWvxPeRFXtzgee+Pbiu65C0q76zPlVBPfivbzE=";
};
buildInputs = lib.optionals stdenv.isLinux [
vulkan-loader
libX11
libXcursor
libXrandr
libXi
] ++ lib.optionals stdenv.isDarwin (with darwin.apple_sdk.frameworks; [
QuartzCore
]);
dontPatchELF = true;
}
2 Likes
Thanks! The dontPatchElf
option didn’t help, but you put me on right path and this seems to work:
postFixup = ''
patchelf --add-rpath ${ pkgs.vulkan-loader }/lib $out/bin/*
'';
1 Like
dontPatchElf
Note that it’s dontPatchELF
, not dontPatchElf
. Also you do need to make sure you’ve got the necessary stuff in buildInputs
. The list in my code block above was what I had to use to get gpgpu
working.
Yeah, my mistake. Thanks.
I’m pretty sure the correct form (dontPatchELF
) is what I had in my nix file. Anyway, adding this one path after the fixup seems better than skipping patchelf altogether.
Also, in my case it seems like the rpath
is not there to begin with, as even running the program built with cargo (without nix build
or patchelf
involved) gives me the same error.
$ cargo build --release
Finished release [optimized] target(s) in 0.24s
$ patchelf --print-rpath target/release/bevy-lyon-playground | sed 's/\:/\n/g'
/home/tad/Projects/bevy-lyon-playground/outputs/out/lib64
/home/tad/Projects/bevy-lyon-playground/outputs/out/lib
/nix/store/rz45273l509rqn3m61pcgc26kaj41nj5-alsa-lib-1.2.7.2/lib
/nix/store/wm0fbn9fg03b1xmaqs6zxxp66yqfp0qh-systemd-252.4/lib
/nix/store/34g510ipxdkznlfscg8mpy58kjd3iyck-libxkbcommon-1.5.0/lib
/nix/store/ijk1lx8cq3sjpbpbl7sjz3218q9waqwz-wayland-1.21.0/lib
/nix/store/c35hf8g5b9vksadym9dbjrd6p2y11m8h-glibc-2.35-224/lib
/nix/store/qbgfsaviwqi2p6jr7an1g2754sv3xqhn-gcc-11.3.0-lib/lib
I’m a bit of a monkey when it comes to compilers, linkers and other systems programming stuff, but I guess lack of vulkan-loader
in the rpath
is the problem, right? And this executable was not patched.
bevy has a nix section that should work out of the box
2 Likes
The link to Jumpy derivation is very helpful and I see it is indeed adding the vulkan-loader to rpath
. Maybe this should be explicitly mentioned in the NixOS section of the Bevy document? Lots of other stuff going on there that I can learn from. Thanks!
IIUC the Bevy document is more about developing, that’s why it only briefly mentions packaging with the jumpy example. The bevy document adds vulkan-loader
(as part of buildInputs
) to LD_LIBRARY_PATH
instead, since it is easier to use when developing.