I am building a cross-platform app and want to be able to retain a build for every platform. To that end I am trying to impose the following structure on the output directory:
Instead of compiling the binary to zig-out/bin
, I want to compile to e.g. bin/macos_aarch64
.
The first part is taken care of by invoking the compiler via zig build -p bin
.
The second part is partially taken care of by the Step.InstallArtifact.Options
:
const target = b.standardTargetOptions(.{});
const artifact = b.addInstallArtifact(exe, .{
.dest_dir = .{
.override = .{
.custom = try std.fmt.allocPrint(b.allocator, "{s}_{s}", .{
@tagName(target.result.os.tag),
@tagName(target.result.cpu.arch),
}),
},
},
});
b.getInstallStep().dependOn(&artifact.step);
I have a problem in my custom build step however. Calling step.owner.standardTargetOptions(.{})
in the makeFn yields a panic:
var make_symlink = b.step("link-data", "Create symlink to data folder");
make_symlink.makeFn = struct {
fn make(step: *std.Build.Step, _: std.Build.Step.MakeOptions) !void {
const output_target = step.owner.standardTargetOptions(.{});
const output_dir = try std.fmt.allocPrint(
step.owner.allocator, "bin/{s}_{s}", .{
@tagName(output_target.result.os.tag),
@tagName(output_target.result.cpu.arch),
}
);
const exe_dir = try std.fs.cwd().openDir(output_dir, .{});
exe_dir.deleteFile("data") catch |err| switch (err) {
error.FileNotFound => {},
else => return err,
};
try exe_dir.symLink("../../data", "data", .{ .is_directory = true });
}
}.make;
make_symlink.dependOn(b.getInstallStep());
thread 136342 panic: Option 'target' declared twice
[...]
[...]/build.zig:45:67: 0x101054313 in make (build)
const output_target = step.owner.standardTargetOptions(.{});
What am I doing wrong here? Is it illegal to call standardTargetOptions
twice? How else do I get access to those in the make
function?
And how do I access the build prefix – bin/
in my case?
A hint in the right direction would be greatly appreciated!