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