How to wrap prebuilt libraries into Zig for use by other wrapped C libraries

Hi,

I have a situation where I want to a library which has prebuilt lib files (wgpu). The way I’ve seen it done and am trying is creating a translated module with build.addTranslateC and then “attaching” the library with something like translated_module.addObjectFile(wgpu_lib.path(“lib/libwgpu_native.a”));

This seems to work as long as another Zig project consumes by adding the module with e.g. addImport(…)

However, I’m also using a separate C++ library (ThorVG) which also uses wgpu, and since it’s a C++ project it needs to include the wgpu headers. The only way I’ve found to pass the headers along is creating a library with addLibrary and using installHeader, which makes sense although it creates an actual explicit library which might not be necessary since I have the binaries already. What makes matters worse is that since addObjectFileseems to be the way to link in an existing library as I understand things it packs the library into a new library rather than just transitively say “whatever links to this library needs to also link to this existing library” (which is how I guess it works with system libraries for example). Not only is this unnecessary, but also doesn’t seem to really work. Zig backend says “not an ELF file” about the resulting library and the LLVM backend says something similar but more complicated (can’t reproduce that error right this moment).

I can make things work for my local situation either by not setting up this multi package dependency thing and solve everything in my main project, or make two parallel paths from the wgpu package; one that exports Zig stuff (and includes the prebuilt binary with addObjectFile), and a separate one that exports the header file for inclusion by the intermediate C++ library (and whatever consumes that has to pinky promise it also adds the Zig module to get the linkage). But I’m not sure how I’d set this up in a case where I didn’t actually have the same control over all three parts locally.

Am I hitting Zig bugs with how it passes binaries, or am I just doing incredibly weird things?

Since you have existing lib and header files, you can just install those, without making an intermediate library.

b.installLibFile("path/to/lib.a", "lib.a");
and
b.getInstallStep().dependOn(&b.addInstallHeaderFile(b.path("path/to/header/lib.h"), "lib.h").step);

for some reason there is not a simple b.installHeaderFile, those are just wrappers for the verbosity of the latter snippet anyway.

When compiling ThorVG use addIncludePath to point to the path of the include files.

In the following example code wgpu is a downloaded dependency, and the directory include is added as include path when compiling the thorvg_lib:

const wgpu = b.dependency("thorvg", .{});
thorvg_lib.root_module.addIncludePath(wgpu.path("include"));
1 Like