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?
Thanks, that makes sense but how does the consuming package link to the installed library?
When using b.addLibrary(…) I’d do something like consuming_module.linkLibrary(wgpu_dep.artifact(“wgpu”))and it’d get the library linked and header search paths set up. I don’t quite understand how a downstream package access the installed files. I would have guessed something like: consuming_module.addIncludePath(wgpu_dep.path("include")); consuming_module.addObjectFile(wgpu_dep.path("lib/lib.a"));
but it seems I’m misunderstanding how things are passed along.
(Also, if doing it manually like is the way to do it just that I got some detail wrong, that won’t transitively pass down to packages downstream of that without the same addObjectFile issues?)
if its a zig project, it can just import the module you mentioned, module imports propagate linkage.
if its a c/cpp project, you dep.artifact("lib.a") and link that. @dimdin 's suggestion reminded me that you can export paths aswell, b.addNamedLazyPath("include", [path to headers]), then dep.namedLazyPath("include") on the other end.
Their suggestion of a top level include directory also works.
My original suggestion of installing the headers does not work, there isn’t any way to access installed headers of a dependency afaik.
Ok I think named lazy paths is what I’ll go with. I’ve now set it up so that my wgpu project exports a module with the translated C header, and adds the library to it with addObjectFile. In parallel it also adds two named paths, “lib” and “include” which my thorvg package uses when building thor. This can then be consume by my main gui project and everything seems happy.