zcmd.zig
is a small lib I have been working on (while try to compile C/CPP legacy libs with zig)
liyu1981 / zcmd.zig
zcmd is a single file lib to replace zig's std.childProcess.run with the ability of running pipeline like bash..
zcmd.zig
zcmd
is a single file lib (zcmd.zig
) to replace zig's std.childProcess.run
. It has almost identical API like std.childProcess.run
, but with the ability of running pipeline like bash
.
Example like execution of single command (replacement of zig's std.childProcess.run
)
const result = try Zcmd.run(.{
.allocator = allocator,
.commands = &[_][]const []const u8{
&.{ "uname", "-a" },
},
});
the differences to std.childProcess.run
is it will take commands
instead of single command
.
It can run a bash
like pipeline like follows (to recursively find and list the latest modified files in a directory with subdirectories and times)
const result = try Zcmd.run(.{
.allocator = allocator
.commands = &[_][]const []const u8{
&.{ "find", ".", "-type", "f", "-exec"
…what it is?
Simply to say, it is a std.childProcess.run
replacement, but with the ability of running bash
pipeline.
Below is a good example from one of my other project how this can be used
const pod_version = brk: {
cwd.access(".git", .{}) catch {
const result = try zcmd.run(.{ // mark 1
.allocator = allocator,
.commands = &[_][]const []const u8{
&.{ "head", "-n", "1", "Changelog" },
&.{ "cut", "-d", "(", "-f", "2" },
&.{ "cut", "-d", ")", "-f", "1" },
},
});
std.debug.print("\n{any}\n", .{result});
result.assertSucceededPanic(.{});
break :brk result.trimedStdout();
};
// do not try to download git as originam CMakeList does. Do you guys have git?
const result = try zcmd.run(.{ // mark 2
.allocator = allocator,
.commands = &[_][]const []const u8{&.{ "git", "--git-dir=./.git", "describe", "--abbrev=4", "HEAD" }},
});
result.assertSucceededPanic(.{});
break :brk result.trimedStdout();
};
The above code is running pipelines like in bash
to generate a version string. In mark 1
case, it will run head -n 1 Changelog | cut -d ( -f 2 | cut -d ) -f 1
, and in mark 2
case it will run git --git-dir=./git describe -- abbrev=4 HEAD
.
The motivation for this lib is that I found std.childProcess.run
can only run one command, so assemble a pipeline will be tedious (and not efficient actually), and on the otherside, std.Build.addSystemCommand
supports only one command too.
usage
Use it like typical zig
pkg
zig fetch --save https://github.com/liyu1981/zcmd.zig/archive/refs/tags/v0.2.1.tar.gz
More frequently you will want to use it in build.zig
, which zcmd.zig
supports well. After added it to build.zig.zon
,
// when import in build.zig, the zcmd is exposed in nested const zcmd
const zcmd = @import("zcmd").zcmd;
// then next can use zcmd.run as above
or browse this example.
The API provided by zcmd.zig
is almost identical to std.childProcess.run
(besides it will accept commands instead of command). There are also other convenient help functions like those you may already see to assert results.
how it is implemented
zcmd.zig
is implemented with the same algorithm used by bash
. Essentially, the pipeline is started from first command to last command; each command will be run in the current process; and a child process is forked for executing possible next one; all commands will have unix pipes connected them together.
And because of the algorithm, it is currently only supporting linux/macos, windows is left out because I do not really know whether there are pipes and how they work there. If you want to help me to get this done, feel free to send a pull request, or point me to how to do it. Thanks.
examples and docs
Examples can be found in the repo.
Docs can be found here.
Top comments (1)
Cool project, thanks for sharing!