Zig can't see Nix Includes

This is sort of a workflow question for those of you who use both Nix and Zig together. I’ve been working on a games project with a friend using Nix as our development environment to ensure reproducible builds. Its my understanding that I could add a nix pkg, say for SDL3 to our projects flake and that would provide the headers and source. And for SDL and vulkan that appeared to work and the zig compiler was able to find those and build.

This doesn’t appear to be the case for every library. I can’t tell if it because of how the nix pkg defines its output but things like volk, slang, assimp, etc can’t be found by zig while just trying to do native compilation.

For those of you who do use Nix and Zig together especially working with C/C++ code, whats your process/workflow?

Are there good default zig hooks to make working with C code easier?

How do you include source when cross compiling? Zig intentionally doesn’t use system headers when cross compiling so we’re explicitly (sort of messily) copy them into the build environment when doing a Nix build.

There’s not a lot of resources out there so I’m hoping someone here has some recommendations. Thanks!

You need to rely on pkg-config. For devshells you must set pkg config env vars yourself. For packaging nix sandbox does it for you. If you want ready solution you can use zig2nix, which makes both packaging and dev envs slightly easier.

Generally if you can though. Consider relying on build.zig more and compile your whole chain. Zig package manager is already sort of like nix itself.

2 Likes

For pkgs that don’t provide a pc I thought it was sort of bad practice to create that yourself, but thats the way to go?
I will also give zig2nix a look, thank you.

Without pc youre kinda out of luck as zig does not provide way to override per system library search paths, and theres no CFLAGS LDFLAGS equivalent. You could perhaps work something with --search-prefix or --sysroot, latter is kinda janky in 0.16 tho.

Zig does read some nixpkgs flags if you target native which is bit weird, but if you were ever wondering why that (nix-shell) works then that’s the reason https://codeberg.org/ziglang/zig/src/branch/master/lib/std/zig/system/NativePaths.zig#L26-L80

You can set the LD_LIBRARY_PATH environment variable so that it’s findable, or create some other variable with the path to the shared object/static library and then directly link it to that provided path.

Depending on how you specified that dependency in Nix, it may or may not have actually put it in the load path.