Helllo,
I’m trying to build my project with a C dependency called blip-buf, this library has just two files (blip_buf.c and blip_buf.h). I’ve been trying to build it with this code:
const blip_buf_lib = b.addLibrary(
.{ .name = "blip_buf", .linkage = .static, .root_module = b.createModule(
.{
.target = target,
.optimize = optimize,
.link_libc = true,
},
) },
);
blip_buf_lib.addCSourceFile(.{ .file = b.path("third-party/blip_buf-1.1.0/blip_buf.c") });
blip_buf_lib.addIncludePath(b.path("third-party/blip_buf-1.1.0"));
b.installArtifact(blip_buf_lib);
mod.linkLibrary(blip_buf_lib);
But I’m getting this error
src/root.zig:18:15: error: C import failed
pub const c = @cImport({
^~~~~~~~
referenced by:
c: src/main.zig:4:15
main: src/main.zig:53:10
4 reference(s) hidden; use '-freference-trace=6' to see all references
.zig-cache/o/14771798dce5c649d8f7da9bebf86288/cimport.h:3:10: error: 'blip_buf.h' file not found
#include <blip_buf.h>
What am I missing here? You can see my full build.zig here.
You need to add the include path to the module as well.
blip_buf_lib.root_module.addIncludePath(b.path("third-party/blip_buf-1.1.0"));
1 Like
I’m still getting the same error.
const blip_buf_lib = b.addLibrary(
.{ .name = "blip_buf", .linkage = .static, .root_module = b.createModule(
.{
.target = target,
.optimize = optimize,
.link_libc = true,
},
) },
);
blip_buf_lib.addCSourceFile(.{ .file = b.path("third-party/blip_buf-1.1.0/blip_buf.c") });
blip_buf_lib.addIncludePath(b.path("third-party/blip_buf-1.1.0"));
blip_buf_lib.root_module.addIncludePath(b.path("third-party/blip_buf-1.1.0"));
b.installArtifact(blip_buf_lib);
mod.linkLibrary(blip_buf_lib);
My bad I failed to notice you haven’t provided a root_source_file for the module.
Create a file that @cImport your c header this acts as an importable module for the exe then add the import to the exe. some thing like this
// blip_buf.zig
pub const c = @cImport({
@cInclude("blip_buf.h");
});
const blip_buf_lib = b.addLibrary(
.{ .name = "blip_buf", .linkage = .static, .root_module = b.createModule(
.{
.root_source_file = b.path("blip_buf.zig"), // create this file
.target = target,
.optimize = optimize,
.link_libc = true,
},
) },
);
blip_buf_lib.addCSourceFile(.{ .file = b.path("third-party/blip_buf-1.1.0/blip_buf.c") });
blip_buf_lib.root_module.addIncludePath(b.path("third-party/blip_buf-1.1.0"));
blip_buf_lib.addIncludePath(b.path("third-party/blip_buf-1.1.0"));
b.installArtifact(blip_buf_lib);
mod.linkLibrary(blip_buf_lib);
Then
const exe = b.addExecutable(.{
.name = "8bit_emulator",
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
.imports = &.{
.{ .name = "blip_buf", .module = blip_buf_lib.root_module },
.{ .name = "8bit_emulator", .module = mod },
},
}),
});
1 Like
That worked, thanks!
I just have one more question, though. In my root.zig I have another @cImport, in the documentation it says that you should only have one @cImport in the entire application. So is this fine, having two @cImport, or is there a better way of handling this?
1 Like
If its a cimport that includes different headers you should be fine.
1 Like
Also for the sake of completeness instead of creating a wrapper you could call addIncludePath on the exe’s module instead and you should be able to import in the root module, works fine since you’re creating and linking to a library. But if you don’t need the compiler to output the library then creating a wrapper is needed but the library is not needed you could simplify things to
const blip_buf_mod = b.createModule(.{
.root_source_file = b.path("blip_buf.zig"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
blip_buf_mod.addCSourceFile(.{ .file = b.path("third-party/blip_buf-1.1.0/blip_buf.c") });
blip_buf_mod.addIncludePath(b.path("third-party/blip_buf-1.1.0"));
2 Likes
Hello, it’s me again. I’m getting the same error using this approach and the other approach as well. I guess it had worked before because the files that depended on blip_buf weren’t being used by others files of the project, so the compiler probably skipped compiling them.
Could you take a look at the code and check what I’m doing wrong?
Hello!
The addIncludePath should be called on the module that contains the file calling @cImport that would be the _8bit_emulator module
const mod = b.addModule("_8bit_emulator", .{
.root_source_file = b.path("src/root.zig"),
.target = target,
});
mod.addIncludePath(b.path("third-party/blip_buf-1.1.0"));
I had assumed the import was done by the src/main.zig and the exe sorry about that
1 Like
Hello, again!
I’m trying to run a test with --test-filter but it fails with this error
src/root.zig:19:15: error: C import failed
pub const c = @cImport({
^~~~~~~~
src/root.zig:19:15: note: libc headers not available; compilation does not link against libc
referenced by:
c: src/apu/buffer.zig:2:33
apu.buffer.SampleBuffer: src/apu/buffer.zig:11:13
14 reference(s) hidden; use '-freference-trace=16' to see all references
.zig-cache/o/ecb56e828e2cd32e919574aae0b45d08/cimport.h:1:10: error: 'SDL3/SDL.h' file not found
#include <SDL3/SDL.h>
I’ve tried using this code, but it didn’t work:
const mod_tests = b.addTest(.{
.root_module = mod,
});
const sdl_lib_tests = sdl_dep.artifact("SDL3_test");
mod_tests.linkLibrary(sdl_lib_tests);
// A run step that will run the test executable.
const run_mod_tests = b.addRunArtifact(mod_tests);
// Creates an executable that will run `test` blocks from the executable's
// root module. Note that test executables only test one module at a time,
// hence why we have to create two separate ones.
const exe_tests = b.addTest(.{
.root_module = exe.root_module,
});
exe_tests.linkLibrary(sdl_lib_tests);
// A run step that will run the second test executable.
const run_exe_tests = b.addRunArtifact(exe_tests);
I’m using this for the SDL dependency.
Hello again!
You’re not linking libc on a module that needs it. You can link it with .link_libc = true on module creation or later with module.link_libc = true;
Also this is a different issue than the original topic better creating a new topic for it.
I’ve already used .link_libc = true on the mod creation. Anyway, I’ve created a new topic here.