I’m still running into the issue of tests and executables needing to include the C headers and libraries that the library was built with. Does the library need to be built from a separate build.zig
file to make this work right?
Here is my build.zig
file I’m playing with to try to get this working:
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const module = b.addModule("platform", .{
.root_source_file = b.path("src/lib.zig"),
});
// Library
const lib = b.addStaticLibrary(.{
.name = "platform",
.root_source_file = b.path("src/lib.zig"),
.target = target,
.optimize = optimize,
});
lib.addIncludePath(b.path("src/egl"));
lib.addIncludePath(b.path("src/wayland"));
lib.addIncludePath(b.path("src/x11"));
lib.addCSourceFiles(.{
.files = &protocol_sources,
});
lib.linkLibC();
lib.linkSystemLibrary("wayland-client");
lib.linkSystemLibrary("wayland-egl");
lib.linkSystemLibrary("EGL");
lib.linkSystemLibrary("xkbcommon");
if (b.lazyDependency("zgl", .{
.target = target,
.optimize = optimize,
})) |dep| {
lib.root_module.addImport("zgl", dep.module("zgl"));
}
b.installArtifact(lib);
// Tests
{
const test_lib = b.addTest(.{
.root_source_file = b.path("src/lib.zig"),
.target = target,
.optimize = optimize,
});
test_lib.root_module.addImport("platform", module);
const test_step = b.step("test", "Run unit tests");
const test_step_run = b.addRunArtifact(test_lib);
test_step.dependOn(&test_step_run.step);
const testbin_step = b.step("test-bin", "Build unit tests into separate binary");
const testbin_step_run = b.addInstallArtifact(test_lib, .{});
testbin_step.dependOn(&testbin_step_run.step);
}
// Example
{
const example = b.addExecutable(.{
.name = "example",
.root_source_file = b.path("src/example.zig"),
.target = target,
.optimize = optimize,
});
example.root_module.addImport("platform", module);
if (b.lazyDependency("zgl", .{
.target = target,
.optimize = optimize,
})) |dep| {
example.root_module.addImport("zgl", dep.module("zgl"));
}
const example_step = b.step("example", "Build example");
const example_step_run = b.addInstallArtifact(example, .{});
example_step.dependOn(&example_step_run.step);
}
}
const protocol_sources = [_][]const u8{
"src/wayland/wayland-protocol.c",
"src/wayland/xdg-shell-protocol.c",
};
The library builds fine, but I get a compile error as soon as the test builds:
❯ zig build test-bin && ./zig-out/bin/test
test-bin
└─ install test
└─ zig test Debug native 2 errors
src/wayland.zig:10:15: error: C import failed
pub const c = @cImport({
^~~~~~~~
src/wayland.zig:10:15: note: libc headers not available; compilation does not link against libc
referenced by:
wayland__struct_2114: src/wayland.zig:22:15
remaining reference traces hidden; use '-freference-trace' to see all reference traces
/home/nairou/.persist/dev/projects/platform/.zig-cache/o/b48dcaa3d9447f6277086297ce68bdf5/cimport.h:1:10: error: 'wayland-client-core.h' file not found
#include <wayland-client-core.h>
^
error: the following command failed with 2 compilation errors:
/nix/store/a1iiismj2iw26m91l13kc3arr584ix44-zig-0.13.0/bin/zig test -ODebug --dep platform -Mroot=/home/nairou/.persist/dev/projects/platform/src/lib.zig -Mplatform=/home/nairou/.persist/dev/projects/platform/src/lib.zig --cache-dir /home/nairou/.persist/dev/projects/platform/.zig-cache --global-cache-dir /home/nairou/.cache/zig --name test --listen=-
Splitting the library into a separate build.zig
file just to hide these details from the other builds feels like a hack, but I’m not sure what else to try here.