Compiling Godot in a nix shell?

I’m currently trying to compile Godot in a nix shell. Using the following flake.nix:

{
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
  inputs.flake-utils.url = "github:numtide/flake-utils";

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
      in
      {
        devShells.default = pkgs.mkShell {
          packages = with pkgs; [ pkg-config scons ];
        };
      });
}

I can build Godot with nix develop --command bash -c "scons platform=linuxbsd dev_mode=yes dev_build=yes", but running it with ./bin/godot.linuxbsd.editor.dev.x86_64 gives me the following:

libfontconfig.so.1: cannot open shared object file: No such file or directory
Godot Engine v4.2.dev.custom_build.571cd0eb7 - https://godotengine.org
libX11.so.6: cannot open shared object file: No such file or directory
ERROR: Can't load Xlib dynamically.
   at: DisplayServerX11 (platform/linuxbsd/x11/display_server_x11.cpp:5469)
Your video card drivers seem not to support the required OpenGL 3.3 version.

If possible, consider updating your video card drivers.

If you recently updated your video card drivers, try rebooting.
ERROR: Unable to create DisplayServer, all display drivers failed.
   at: setup2 (main/main.cpp:2301)
ERROR: BUG: Unreferenced static string to 0: TextServerDummy
   at: unref (core/string/string_name.cpp:131)
ERROR: BUG: Unreferenced static string to 0: IPUnix
   at: unref (core/string/string_name.cpp:131)
ERROR: BUG: Unreferenced static string to 0: ResourceFormatImporterSaver
   at: unref (core/string/string_name.cpp:131)
ERROR: BUG: Unreferenced static string to 0: MovieWriterMJPEG
   at: unref (core/string/string_name.cpp:131)
ERROR: BUG: Unreferenced static string to 0: interface_added
   at: unref (core/string/string_name.cpp:131)
ERROR: BUG: Unreferenced static string to 0: TextServerAdvanced
   at: unref (core/string/string_name.cpp:131)
ERROR: BUG: Unreferenced static string to 0: ImageFormatLoader
   at: unref (core/string/string_name.cpp:131)
ERROR: BUG: Unreferenced static string to 0: ResourceFormatSaver
   at: unref (core/string/string_name.cpp:131)
ERROR: BUG: Unreferenced static string to 0: GDScriptEditorTranslationParserPlugin
   at: unref (core/string/string_name.cpp:131)
ERROR: BUG: Unreferenced static string to 0: MovieWriterPNGWAV
   at: unref (core/string/string_name.cpp:131)
ERROR: BUG: Unreferenced static string to 0: ScriptLanguage
   at: unref (core/string/string_name.cpp:131)
ERROR: BUG: Unreferenced static string to 0: ResourceFormatLoader
   at: unref (core/string/string_name.cpp:131)
ERROR: Pages in use exist at exit in PagedAllocator: N7Variant5Pools11BucketLargeE
   at: ~PagedAllocator (./core/templates/paged_allocator.h:170)
ERROR: Pages in use exist at exit in PagedAllocator: N7Variant5Pools12BucketMediumE
   at: ~PagedAllocator (./core/templates/paged_allocator.h:170)
ERROR: Pages in use exist at exit in PagedAllocator: N7Variant5Pools11BucketSmallE
   at: ~PagedAllocator (./core/templates/paged_allocator.h:170)

From what I understand, this is caused by libfontconfig and libX11 not being in the compiled binary’s rpath:

$ patchelf --print-rpath $(nix eval --raw nixpkgs#godot_4.outPath)/bin/godot4 | tr ':' '\n'
/nix/store/v7hv6z4vpkzfjqh3d2238xc66lj60byi-vulkan-loader-1.3.261/lib
/nix/store/x4jnkjc5229rawl7kpdhnmyy25y67ssb-libGL-1.6.0/lib
/nix/store/sk3yadd1ah9qw0n6k4zgigw6k93hc1gr-libX11-1.8.6/lib
/nix/store/ki11nw5sq525iyizsfas4sii8ggabqrw-libXcursor-1.2.1/lib
/nix/store/rccxcsz0kd5c6k0sq1zr3bfdq0f75rm5-libXinerama-1.1.5/lib
/nix/store/5wvz9431cdblb0jvzywk240i9kvffl8q-libXext-1.3.5/lib
/nix/store/mb8dmfh437h2khnrdmv31rvi8r0gw5w0-libXrandr-1.5.3/lib
/nix/store/rnz775l115hnrvqpxp231jfy68vfrpc6-libXrender-0.9.11/lib
/nix/store/2bg3x4i0qbpq9s6pif202jlfqmcjskhr-libXi-1.8.1/lib
/nix/store/yf515ggg1sxf1f9ld7yx84l5pbh9cb9f-libXfixes-6.0.1/lib
/nix/store/gj8rdi3zrgvxxdrpvpffjql8kb3cm9lj-libxkbcommon-1.5.0/lib
/nix/store/f4isky6zdbbb899chac6vhxhza9xzqaq-alsa-lib-1.2.9/lib
/nix/store/4h1rxpzjag7a48ba64hz9z8as60p7q42-libpulseaudio-16.1/lib
/nix/store/n085g8g1zr0g89nx5xw7byhv5crb7c11-dbus-1.14.8/lib
/nix/store/wsv1wwrazlb6bjszbfb91xq8h5z17ggk-dbus-1.14.8-lib/lib
/nix/store/a59c551axyl096aa4204cl1phqfzab9v-speech-dispatcher-0.11.5/lib
/nix/store/svw2wwl8cyhfahhvrmrg82njrsv8g8m2-fontconfig-2.14.2-bin/lib
/nix/store/flpxzyk5xp3lbhv5skifh62l1l6q02q3-fontconfig-2.14.2-lib/lib
/nix/store/rjz12jr6wa46vcaj7v2nsi2x17jibipm-systemd-253.6/lib
$ patchelf --print-rpath ./bin/godot.linuxbsd.editor.dev.x86_64 | tr ':' '\n'
/nix/store/lqz6hmd86viw83f9qll2ip87jhb7p1ah-glibc-2.35-224/lib
/nix/store/k88zxp7cvd5gpharprhg9ah0vhz2asq7-gcc-12.2.0-lib/lib

Is there something specific I need to do to add all of these libraries to the compiled binary’s rpath? My understanding is that the compiled binary’s rpath comes from NIX_LDFLAGS, but the only rpath in there inside my develop environment is outputs/out/lib in the working directory.

I tried adding fontconfig and xorg.libX11 to buildInputs like so, but it didn’t change anything:

{
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
  inputs.flake-utils.url = "github:numtide/flake-utils";

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
      in
      {
        devShells.default = pkgs.mkShell {
          buildInputs = with pkgs; [ fontconfig xorg.libX11 ];
          packages = with pkgs; [ pkg-config scons ];
        };
      });
}

So it looks like I just needed to run autoPatchelf on the compiled binary with the correct runtimeDependencies (I assume because Godot uses dlopen)=. Using this flake.nix:

{
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
  inputs.flake-utils.url = "github:numtide/flake-utils";

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
      in
      {
        devShells.default = pkgs.mkShell {
          nativeBuildInputs = with pkgs; [ pkg-config autoPatchelfHook ];
          runtimeDependencies = with pkgs; [
            libGL
            vulkan-loader
            xorg.libX11
            xorg.libXcursor
            xorg.libXext
            xorg.libXi
            xorg.libXrandr
          ];
          buildInputs = with pkgs; [ scons ];
        };
      });
}

I can run nix develop --command scons platform=linuxbsd dev_mode=yes dev_build=yes to build Godot and then nix develop --command bash -c '. $stdenv/setup; autoPatchelf bin' to patch it.

It’s worth noting that the above list of runtime dependencies is the minimal list to get Godot to start - it won’t have audio and will still complain about a bunch of other dependencies (which need adding to runtimeDependencies).