-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make contents of zig env
available in build.zig
#19932
Comments
If you want to do it in pure Zig today: //! Step for determining the zig lib dir and various subdirectories via `zig env`
const std = @import("std");
const Step = std.Build.Step;
const ZigLibDir = @This();
const LazyPath = std.Build.LazyPath;
step: Step,
/// path to zig's lib directory
lib_dir: std.Build.GeneratedFile,
/// path to compiler-rt directory
compiler_rt: std.Build.GeneratedFile,
/// path to directory which has zig.h
include: std.Build.GeneratedFile,
pub fn create(owner: *std.Build) !*ZigLibDir {
const self = try owner.allocator.create(ZigLibDir);
const name = "zig lib dir";
self.* = .{
.step = Step.init(.{
.id = .custom,
.name = name,
.owner = owner,
.makeFn = make,
}),
.lib_dir = .{ .step = &self.step },
.compiler_rt = .{ .step = &self.step },
.include = .{ .step = &self.step },
};
return self;
}
const ZigEnv = struct {
lib_dir: []const u8,
};
fn make(step: *Step, prog_node: *std.Progress.Node) !void {
_ = prog_node;
const b = step.owner;
const self = @fieldParentPtr(ZigLibDir, "step", step);
const zig_env_args: [2][]const u8 = .{ b.graph.zig_exe, "env" };
var out_code: u8 = undefined;
const zig_env = try b.runAllowFail(&zig_env_args, &out_code, .Ignore);
const parsed_str = try std.json.parseFromSlice(ZigEnv, b.allocator, zig_env, .{ .ignore_unknown_fields = true });
defer parsed_str.deinit();
self.lib_dir.path = parsed_str.value.lib_dir;
self.compiler_rt.path = try std.fs.path.join(b.allocator, &[_][]const u8{ parsed_str.value.lib_dir, "compiler_rt.zig" });
self.include.path = try std.fs.path.join(b.allocator, &[_][]const u8{ parsed_str.value.lib_dir, "include" });
}
pub fn getLibPath(self: *ZigLibDir) std.Build.LazyPath {
return .{ .generated = &self.lib_dir };
}
pub fn getCompilerRTPath(self: *ZigLibDir) std.Build.LazyPath {
return .{ .generated = &self.compiler_rt };
}
pub fn getIncludePath(self: *ZigLibDir) std.Build.LazyPath {
return .{ .generated = &self.include };
} For a full example - clone this repo: https://github.com/Vexu/arocc and check out commit |
Thanks for the code, I might refer back here if I do ever want to customize the build system more deeply. But I hope it's also clear from that example why I think it'll be convenient to have this information built-in. |
My use case is automatically compiling C-backend-generated code from build.zig. In order to do this, you need to pass the directory containing
zig.h
with-I
. This directory is available inzig env
with the keylib_dir
, but the information inzig env
isn't directly available in build.zig.The workaround I've found is to create a system command step that pipes
zig env
intojq
, capture its stdout, and include acat
of the file its stdout goes to in my C compiler command: https://github.com/190n/zip8/blob/6443612ddd4e897c64ee51d9ca61ba3b854f30f5/build.zig#L126-L153. But this is inconvenient and it adds system dependencies. It'd be possible to parse this info with std.json, but since capturing the stdout of the command gives me a LazyPath I think I would have to write a custom build step to receive that filename, open it, and parse its contents. I imagine enough of the other info inzig env
is also useful that this justifies having it immediately available in the build system.The text was updated successfully, but these errors were encountered: