Linking `ncurses` on NixOS

I am new to zig.

I am trying to play with ncurses in zig and am having troubel setting up my build.zig.

I am on nix and have installed ncurses, when I do ncurses-config -l I get : -L/nix/store/lhfi31nbyv62rw5szbfrh3pdnvcfgxmc-ncurses-6.4/lib -lncursesw

So far, I have tried the following

  1. Naming ncurses in the build script
const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = std.zig.CrossTarget{ .os_tag = .linux, .cpu_arch = .x86_64 };

    const exe = b.addExecutable(.{
        .name = "ncurses_interaction",
        .root_source_file = .{ .path = "ncurses_interaction.zig" },
        .target = target,
    });

    exe.linkLibC();
    exe.linkSystemLibrary("ncursesw");

    b.installArtifact(exe);
}

This prouduced the following error

zig build-exe ncurses_interaction Debug x86_64-linux: error: error: unable to find Dynamic system library 'ncursesw' using strategy 'paths_first'. searched paths: none

zig build-exe ncurses_interaction Debug x86_64-linux: error: the following command exited with error code 1:
/nix/store/19sirdxr263wp244wgp51vb291br0f9k-zig-0.11.0/bin/zig build-exe /home/user/work_in_progress/interactive_job_submission/ncurses_interaction.zig -lncursesw -lc --cache-dir /home/user/work_in_progress/interactive_job_submission/zig-cache --global-cache-dir /home/user/.cache/zig --name ncurses_interaction -target x86_64-linux -mcpu x86_64 --listen=- 
Build Summary: 0/3 steps succeeded; 1 failed (disable with --summary none)
install transitive failure
└─ install ncurses_interaction transitive failure
   └─ zig build-exe ncurses_interaction Debug x86_64-linux failure
error: the following build command failed with exit code 1:
/home/user/work_in_progress/interactive_job_submission/zig-cache/o/0c5ba11c64839b9cab490983a48978f4/build /nix/store/19sirdxr263wp244wgp51vb291br0f9k-zig-0.11.0/bin/zig /home/user/work_in_progress/interactive_job_submission /home/user/work_in_progress/interactive_job_submission/zig-cache /home/user/.cache/zig
  1. Given that I on nix, maybe I need to supply the absolute path?

Tried

const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = std.zig.CrossTarget{ .os_tag = .linux, .cpu_arch = .x86_64 };

    const exe = b.addExecutable(.{
        .name = "ncurses_interaction",
        .root_source_file = .{ .path = "ncurses_interaction.zig" },
        .target = target,
    });

    exe.linkLibC();
    exe.linkSystemLibrary("/nix/store/lhfi31nbyv62rw5szbfrh3pdnvcfgxmc-ncurses-6.4/lib");

    b.installArtifact(exe);
}

only to get the following error

zig build-exe ncurses_interaction Debug x86_64-linux: error: error: cannot use absolute path as a system library: /nix/store/lhfi31nbyv62rw5szbfrh3pdnvcfgxmc-ncurses-6.4/lib

zig build-exe ncurses_interaction Debug x86_64-linux: error: the following command exited with error code 1:
/nix/store/19sirdxr263wp244wgp51vb291br0f9k-zig-0.11.0/bin/zig build-exe /home/user/work_in_progress/interactive_job_submission/ncurses_interaction.zig -l/nix/store/lhfi31nbyv62rw5szbfrh3pdnvcfgxmc-ncurses-6.4/lib -lc --cache-dir /home/user/work_in_progress/interactive_job_submission/zig-cache --global-cache-dir /home/user/.cache/zig --name ncurses_interaction -target x86_64-linux -mcpu x86_64 --listen=- 
Build Summary: 0/3 steps succeeded; 1 failed (disable with --summary none)
install transitive failure
└─ install ncurses_interaction transitive failure
   └─ zig build-exe ncurses_interaction Debug x86_64-linux failure
error: the following build command failed with exit code 1:
/home/user/work_in_progress/interactive_job_submission/zig-cache/o/3869acd914a32a7765428aa0049827be/build /nix/store/19sirdxr263wp244wgp51vb291br0f9k-zig-0.11.0/bin/zig /home/user/work_in_progress/interactive_job_submission /home/user/work_in_progress/interactive_job_submission/zig-cache /home/user/.cache/zig
  1. Maybe just link the library on the prompt?

zig build-exe -lc -L/nix/store/lhfi31nbyv62rw5szbfrh3pdnvcfgxmc-ncurses-6.4/lib ncurses_interaction.zig

Which produced the error

ncurses_interaction.zig:1:11: error: C import failed
const c = @cImport({
          ^~~~~~~~
referenced by:
    main: ncurses_interaction.zig:6:9
    callMain: /nix/store/19sirdxr263wp244wgp51vb291br0f9k-zig-0.11.0/lib/zig/std/start.zig:574:32
    remaining reference traces hidden; use '-freference-trace' to see all reference traces
/home/user/work_in_progress/interactive_job_submission/zig-cache/o/eb535b6a823fe09c497bc546f3146db7/cimport.h:1:10: error: 'ncurses.h' file not found
#include <ncurses.h>

Could someone give me some pointers on what the right way is to get started with linking older libs in Zig is?

1 Like

Hey @RijanHasTwoEars7 (does rijan have two ears?)… welcome to Ziggit, lol.

You can add system library paths to your build using the following:

// note that LazyPath.relative is unnecssary, you can build the lazy path in place
// try putting your absolute path to where your library is here
obj.addLibraryPath(std.Build.LazyPath.relative("deps/cuda/lib64"));

Here’s documentation on LazyPath: Zig Documentation

And that will be used when you link your library:

exe.linkSystemLibrary("stuff"); // links libstuff

I’m not sure how this will workout if your lib is literally called “lib” as that’s used as part of the search prefix for finding libraries. Maybe someone here can speak to that.

Hi Andy! I do have two ears!

I have changed my build script to the following

const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = std.zig.CrossTarget{ .os_tag = .linux, .cpu_arch = .x86_64 };

    const exe = b.addExecutable(.{
        .name = "ncurses_interaction",
        .root_source_file = .{ .path = "ncurses_interaction.zig" },
        .target = target,
    });

    exe.addLibraryPath(std.Build.LazyPath.relative("/nix/store/lhfi31nbyv62rw5szbfrh3pdnvcfgxmc-ncurses-6.4/lib"));
    exe.linkLibC();
    exe.linkSystemLibrary("ncursesw");

    b.installArtifact(exe);
}

Looks like I have moved a little further, though I am not entirely sure if the issue now is in my copy of ncurses or the build script or this repo issue suggests the issue might be my code (not surprising)

What I know for sure is that the error is no longer saying I do not have the correct library linked.

thread 91394 panic: reached unreachable code
/nix/store/19sirdxr263wp244wgp51vb291br0f9k-zig-0.11.0/lib/zig/std/debug.zig:343:14: 0x29b322 in assert (build)
    if (!ok) unreachable; // assertion failure
             ^
/nix/store/19sirdxr263wp244wgp51vb291br0f9k-zig-0.11.0/lib/zig/std/Build.zig:1693:25: 0x30420c in relative (build)
        std.debug.assert(!std.fs.path.isAbsolute(path));
                        ^
/home/rijan/work_in_progress/interactive_job_submission/build.zig:12:51: 0x2c0c92 in build (build)
    exe.addLibraryPath(std.Build.LazyPath.relative("/nix/store/lhfi31nbyv62rw5szbfrh3pdnvcfgxmc-ncurses-6.4/lib"));
                                                  ^
/nix/store/19sirdxr263wp244wgp51vb291br0f9k-zig-0.11.0/lib/zig/std/Build.zig:1638:33: 0x2afe03 in runBuild__anon_7125 (build)
        .Void => build_zig.build(b),
                                ^
/nix/store/19sirdxr263wp244wgp51vb291br0f9k-zig-0.11.0/lib/zig/build_runner.zig:297:29: 0x2abbd2 in main (build)
        try builder.runBuild(root);
                            ^
/nix/store/19sirdxr263wp244wgp51vb291br0f9k-zig-0.11.0/lib/zig/std/start.zig:574:37: 0x2974de in posixCallMainAndExit (build)
            const result = root.main() catch |err| {
                                    ^
/nix/store/19sirdxr263wp244wgp51vb291br0f9k-zig-0.11.0/lib/zig/std/start.zig:243:5: 0x296fc1 in _start (build)
    asm volatile (switch (native_arch) {
    ^
???:?:?: 0x4 in ??? (???)
Unwind information for `???:0x4` was not available, trace may be incomplete

Try it without the relative call:

obj.addLibraryPath(.{ .path = "Your Library Path" });

It’s calling an assert in the “relative” path function that’s saying “this cannot be absolute” but in your case we are using an absolute path.

that was it!

I changed it to

const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = std.zig.CrossTarget{ .os_tag = .linux, .cpu_arch = .x86_64 };

    const exe = b.addExecutable(.{
        .name = "ncurses_interaction",
        .root_source_file = .{ .path = "ncurses_interaction.zig" },
        .target = target,
    });
    exe.addLibraryPath(.{ .path = "/nix/store/lhfi31nbyv62rw5szbfrh3pdnvcfgxmc-ncurses-6.4/lib" });
    exe.linkLibC();
    exe.linkSystemLibrary("ncursesw");

    b.installArtifact(exe);
}

I now have a zig-out!

Thank you so much!

1 Like