Libusb-1.0.so not found in precompiled library

I have a pre-compiled library (libsomelib.so) and header file that references libusb-1.0.so, and which is a required library for a program I’m developing. As I’m new with nix, I thought I would create a flake to wrap the precompiled library:

flake.nix

{
    description = "A very basic flake";

    inputs = {
        nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
    };

    outputs = { self, nixpkgs }:
    let
      pkgs = nixpkgs.legacyPackages.x86_64-linux;
    in {
        packages.x86_64-linux.somelib = pkgs.stdenv.mkDerivation {
            pname = "somelib";
            version = "2.0.0";

            src = ./.;

            buildPhase = ''
                echo "...nothing to build...";
            '';

            installPhase = ''
                echo "...installing to $out...";

                mkdir -p $out/lib
                mkdir -p $out/include

                cp -r somelibapi/*.h $out/include/
                cp -r somelibapi/*.so* $out/lib/
            '';

            buildInputs = [
                pkgs.libusb1
            ];

            nativeBuildInputs = [
                pkgs.libusb1
            ];
        };

        devShells.x86_64-linux = pkgs.mkShell {
            packages = [
                pkgs.libusb1
                pkgs.pkg-config
            ];

            buildInputs = [
                pkgs.libusb1
                pkgs.pkg-config
            ];

            nativeBuildInputs = [
                pkgs.pkg-config
            ];
        };

    packages.x86_64-linux.default = self.packages.x86_64-linux.somelib;
  };
}

The library seems to “build” correctly into a package and is installed in my nix store. However, when I link it with the larger project (using a separate flake), the linker gives me an warning the libusb-1.0.so.0 is not found.

For the hell of it, I ran ldd on the libsomelib.so file:

ldd: warning: you do not have execution permission for `./libsomelib.so'
        linux-vdso.so.1 (0x00007ffedc764000)
        libusb-1.0.so.0 => not found
        libc.so.6 => /nix/store/p9ysh5rk109gyjj3cn6jr54znvvlahfl-glibc-2.38-66/lib/libc.so.6 (0x00007f7a3cc17000)
        /nix/store/p9ysh5rk109gyjj3cn6jr54znvvlahfl-glibc-2.38-66/lib64/ld-linux-x86-64.so.2 (0x00007f7a3d180000)

Why is libusb-1.0.so.0 not found? It is found in my nix store:

Any help would be appreciated!

Typically, when you compile software in NixOS, the ELF binaries are patched so that their runpath will include the necessary nix store paths to link to their dependencies. This is accomplished often by simply patching the resulting binaries using a tool called patchelf and you can see a lot of uses of patchelf in Nixpkgs. (Not everything needs to care about patchelf, though, as things built using standard Nixpkgs helpers generally get this ‘for free’. This is mainly needed for edge cases.)

There’s also a lot of helpers. In particular interest here, I think you might find autoPatchelfHook to be useful. If you add autoPatchelfHook to your nativeBuildInputs, it should attempt to patch all of the ELF files it can to resolve the unresolved libraries using the buildInputs, during the fixup phase.

If you want to be able to use unmodified software in NixOS, you have other options, too. For example, there are a lot of tools around building FHS environments that can make it easier to run unmodified software expecting things to be in certain places. As well, you can also use Nix-LD if you want random binaries to “just work”, without needing a special flake or derivation, as it will add a special linker to the usual DT_INTERP path so that non-NixOS binaries can have a special library search path injected into them. This won’t help for linking non-NixOS binaries into other derivations, though: for that, you will want to use patchelf in some way, whether directly or indirectly.

1 Like

That worked perfectly! Thank you very much!