Problem building C library: NoZigModuleForCHeader

High level: I’m building an executable that compiles in code from a library that itself requires a static library that lives in a Git repository. I’ve structured this as a top-level project (my executable + the proximal library code) that has a depedency on a local subproject, which has a dependency on the Git repository.

The subproject’s build.zig looks something like this:

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const upstream = b.dependency("subproject", .{});
    const lib = b.addStaticLibrary(.{
        .name = "subproject",
        .target = target,
        .optimize = optimize,
        .pic = true,
        .strip = true,
        .link_libc = true,
    });

    lib.addIncludePath(upstream.path("include"));
    lib.installHeadersDirectory(upstream.path("include/subproject"), "subproject", .{});
    lib.installHeader(upstream.path("include/platform.h"), "subproject/platform.h");
    lib.addCSourceFiles(.{ .root = upstream.path(""), .files = sources });

    b.installArtifact(lib);
}

I’ve trimmed the main project’s build.zig down to about this:

pub fn build(b: *std.Build) !void {
    var target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const subproject = b.dependency("subproject", .{});
    const library = b.addStaticLibrary(.{
        .name = "library",
        .target = target,
        .optimize = optimize,
        .link_libc = true,
        .pic = true,
    });
    library.linker_allow_shlib_undefined = true;
    library.addIncludePath(subproject.artifact("subproject").getEmittedH().dirname());

    library.addIncludePath(b.path("vendor/library/include"));
    library.linkSystemLibrary("c++");
    library.linkLibrary(subproject.artifact("subproject"));
    library.root_module.addCSourceFiles(.{ .files = sources });

    b.installArtifact(library);
}

Running the subproject build successfully completes, but trying to run the “main” project’s build yields error: error: unable to create compilation: NoZigModuleForCHeader.

I feel like I’m missing something that would be obvious if I had more experience with Zig (or even with C development), but I’m blind to it…

Version: 0.14.0-dev.2435

The message is generated when compiling a module and both of the following holds:

  • there are header files to generate (options.emit_h != null) from zig files
  • there are no zig files in the module (!options.config.have_zcu).

getEmittedH() sets the emit_h flag.

That makes great sense. Is there a recommended way to add the subproject’s header directory that doesn’t involve getEmittedH()?

I am not sure how to get it from the dependency artifact.
Try this:

library.addIncludePath(b.pathJoin(&.{ b.install_path, "include", "subproject" }));

Looks like library.addIncludePath(subproject.artifact("subproject").getEmittedIncludeTree()) is what I was looking for.

1 Like