Hi … another question for you Zig experts… Thanks for all the help!
I’m attempting to write some software that uses shared library plugins.
I want to have plugins that come with the software and I want build and install them all into a single dist directory.
I would like to run zig build and have it build the executable and all of the individual shared library plugins. Then have it put them all together into a dist folder.
The issue is keeping the builds separate. My first thought was to launch zig build again within each plugin folder and copy the shared library. It seems like I need to use addSystemCommand to do this.
There doesn’t appear to be a way to specify a directory to compile outside of the CWD for zig build but I’m not sure about zig build-lib
So, I will need to change directory, run the system command and change back and package all that into a custom build step? Or use CMake or a Shell script.
Any ideas on the best process to use? Also, do I need to search for the zig executable or is there an easy way to get the current running path?
Thanks!
You can have as many build.addExecutable and build.addSharedLibrary as you want, just remember to install them all and set the proper dependencies. You probably want the main install step to depend on the executable and all the plugins. If you have a separate build.zig for each plugin, it’s slightly more complicated, but nothing huge.
The zig init example shows how to output an executable and a static library simultaneously.
1 Like
The idea is that each plugin will also be an example of how others can create their own plugins and build them independently of my code. They will be dynamically loaded later. They shouldn’t have to depend on the main build.zig to build. Plus, each of them will have maybe wildly different dependencies.
How do you specify a separate build.zig file?
I’ve supporsed following project directories.
/
main_executable
build.zig
build.zig.zon
src/
lib
plugin_a
build.zig
src/
...
plugin_a
build.zig
src/
...
If main_executable is used plugin_a and plugin_a
- Add depencencies to
build.zig.zon of main_executable
(main_executable/build.zig.zon)
.{
// (snip)
.dependencies = .{
.plugin_a = .{ .path = "../lib/plugin_a" },
.plugin_b = .{ .path = "../lib/plugin_b" },
},
}
- Add artifacts to
build.zig of main_executable
(main_executable/build.zig)
const std = @import("std");
pub fn build(b: *std.Build) !void {
// Please add options for `std.Build.dependency` method as necessary
const dep_plugin_a = b.dependency("plugin_a", .{});
const dep_plugin_b = b.dependency("plugin_b", .{});
// main executable artifact
const exe = b.addExecutable(.{
// (snip) options
});
b.installArtifact(exe);
// plugin artifacts
const plugin_a = dep_plugin_a.artifact("plugin_a");
b.installArtifact(plugin_a);
const plugin_b = dep_plugin_a.artifact("plugin_b");
b.installArtifact(plugin_b);
}
It notes that plugin_a and plugin_b projects are built as executable or static/dynamic library respectively.
5 Likes
That works great! Thanks @ktz_alias
1 Like
Just for reference in case anyone is searching …
You can run zig build from build.zig or indeed any command.
const something_path = "plugins/something/";
var something = b.addSystemCommand(&.{ "zig", "build" });
// sets directory to plugin path when running command
something.setCwd(b.path(something_path));
// checks exit code and will stop compiling if not ok
something.addCheck(.{ .expect_term = .{ .Exited = 0 } });
// makes sure that is run every time build is run
something.has_side_effects = true;
// installs library from plugin into base zig-out/lib
b.installLibFile(something_path ++ "zig-out/lib/libsomething.so", "libsomething.so");
// makes sure it is run before main exe
exe.step.dependOn(&something.step);
1 Like