Correct include paths in Nixos

I try to use a system library in Nixos. For that I have a nix shell:

{ pkgs? import <nixpkgs> {} }:

pkgs.mkShell {
  buildInputs = [ pkgs.gtk4.dev ];
}

It correctly adds gtk to the include paths of $NIX_CFLAGS_COMPILE and Zig correctly read the env var, except that the include path is off by one directory:

Indeed, in my code, instead of writing:

const gtk = @cImport({
    @cInclude("gtk/gtk.h");
});

I have to write:

const gtk = @cImport({
    @cInclude("gtk-4.0/gtk/gtk.h");
});

Which is not even a solution as include statements from inside the gtk.h assume an include path after gtk-4.0 and not before.

I could manually add each include paths by hand:

    exe.addSystemIncludePath(
        .{ .cwd_relative = "/nix/store/d04arrkcnnwb3k0l8a434xk2q0zxkkjs-gtk4-4.16.7-dev/include/gtk-4.0" },
    );

Which actually works, but I need to include each and every lib in the dependency tree of gtk. It is a nightmare as I have to search with head comes from which package.

There has to be something I am getting wrong. The $NIX_CFLAGS_COMPILE var is definitely the correct way to do things and it is almost right. If I grep the part of it that includes gtk:

-isystem /nix/store/d04arrkcnnwb3k0l8a434xk2q0zxkkjs-gtk4-4.16.7-dev/include

It seems correct, except that the directory doesn’t directly contain gtk/gtk.h but rather gtk-4.0/gtk/gtk.h.

Add pkg-config as a build input alongside gtk4, it should make nix install the pkg-config files for gtk. That should let you use exe.linkSystemLibrary("gtk-whatever").

1 Like

You want the pkg-config in nativeBuildInputs, and in build.zig use linkSystemLibrary2 with .use_pkg_config = .force

Note that your build.zig probably works even without addSystemIncludePath and pkg-config because zig has some nixpkgs specific code in the compiler which I don’t personally agree with but it’s there https://github.com/ziglang/zig/blob/master/lib/std/zig/system/NativePaths.zig#L19

Unless you use mkShellNoCC of course.

1 Like

It works! Thank you both :heart::heart::rocket::rocket:

Here is my shell.nix file:

{ pkgs? import <nixpkgs> {} }:

pkgs.mkShell {
  nativeBuildInputs = [ pkgs.gtk4.dev pkgs.pkg-config ];
}

And here is part of my build.zig file:

const exe = b.addExecutable(.{
    .name = "music",
    .root_source_file = b.path("src/main.zig"),
    .target = target,
    .optimize = optimize,
});
exe.linkSystemLibrary2("gtk4", .{ .use_pkg_config = .force });
exe.linkSystemLibrary("c");