I am a beginner user of nixos. I’ve been configuring my desktop for a while and everything has been quite well, including nodejs, golang, etc.
But now I am having issues building a personal project using rust and sqlite. I have sqlite installed (in the configuration.nix file), along with gcc, rustc, and cargo in environment.systemPackages. This works well in other linux distributions like arch / ubuntu.
When I run cargo build, I get this error:
/nix/store/pndi5gr1b9p591vmr7dvijymi8faclck-binutils-2.40/bin/ld: cannot find -lsqlite3: No such file or directory
collect2: error: ld returned 1 exit status
Maybe it is an obvious question, but do I need to set up anything in my local rust project to be able to build? Any nix or nixos command that could help to debug this issue further? Many thanks
NixOS by default does not install development headers for packages added to environment.systemPackages. If you want that you need to add the sqlite.dev package as well. This is similar to how you probably needed to add something like libsqlite-dev on ubuntu, just NixOS’ packages are a bit stricter about this IME.
That said, I’m not sure that will actually correctly make it available at build time. It also means that you wouldn’t spot potentially unrecorded dependencies anymore, since you just have libsql lying around.
The intended way to make a library available is to provide a development environment for the project in question, using pkgs.mkShell, which will provide all the development headers. You would add a shell.nix flake to your project, and then before you compile run nix-shell once:
You can also put your other project-specific dependencies in here, and remove them from your system config. Then you can for example garbage collect them away if you don’t often work on the project, and generally you’ll have a better grasp on the exact dependencies of each project.
I don’t think gcc is required, for example.
If you use flakes, you’d do this, and use nix develop instead:
{
# The usual inputs/outputs
devShells.${system}.default = nixpkgs.legacyPackages.${system}.mkShell {
packages = with pkgs; [
sqlite
];
};
}
Finally, since this is such a common pattern and typing nix-shell is annoying, as is having to manually set garbage collection roots, you may want to know about direnv’s support for nix.
Great, thanks a lot for the answer, now I understand this better. In this case it didn’t work with a system-wide sqlite.dev as you guessed, but it worked with the shell.nix approach and I will consider using flake files per project, along with direnv for convenience.
Yeah, I one day need to dig into why that isn’t sufficient. I think the libraries are made available via LD_LIBRARY_PATH, and adding them to environment.systemPackages doesn’t set that variable.
But I wonder if there’s an option which would set it, and why exactly there’s a discrepancy between mkShell and environment.systemPackages.