Skip to content
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

Build information dumping with --dump-build-info #14750

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions lib/build_runner.zig
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,16 @@ pub fn main() !void {
std.debug.print("Expected argument after --glibc-runtimes\n\n", .{});
return usageAndErr(builder, false, stderr_stream);
};
} else if (mem.eql(u8, arg, "--dump-build-info")) {
const mode = nextArg(args, &arg_idx) orelse {
std.debug.print("Expected argument after --dump-build-info\n\n", .{});
return usageAndErr(builder, false, stderr_stream);
};

builder.dump_build_info = std.meta.stringToEnum(@TypeOf(builder.dump_build_info), mode) orelse {
std.debug.print("invalid dump_build_info mode '{s}': must be 'off', 'dry', or 'wet'\n\n", .{mode});
process.exit(1);
};
} else if (mem.eql(u8, arg, "--verbose-link")) {
builder.verbose_link = true;
} else if (mem.eql(u8, arg, "--verbose-air")) {
Expand Down Expand Up @@ -363,6 +373,11 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi
\\ --global-cache-dir [path] Override path to global Zig cache directory
\\ --zig-lib-dir [arg] Override path to Zig lib directory
\\ --debug-log [scope] Enable debugging the compiler
\\ --dump-build-info [mode] Dump zon-formatted module and step information to stdout
\\ off: Does not dump any build info (default)
\\ dry: Only dumps build info, does not run any steps
\\ wet: Runs build steps and then dumps build info
\\
\\ --verbose-link Enable compiler debug output for linking
\\ --verbose-air Enable compiler debug output for Zig AIR
\\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
Expand Down
98 changes: 96 additions & 2 deletions lib/std/Build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ pkg_config_pkg_list: ?(PkgConfigError![]const PkgConfigPkg) = null,
args: ?[][]const u8 = null,
debug_log_scopes: []const []const u8 = &.{},
debug_compile_errors: bool = false,
/// Whether or not to dump build info in zon
/// upon construction of the build graph
dump_build_info: enum { off, dry, wet } = .off,

/// Experimental. Use system Darling installation to run cross compiled macOS build artifacts.
enable_darling: bool = false,
Expand All @@ -112,6 +115,7 @@ host: NativeTargetInfo,

dep_prefix: []const u8 = "",

dependencies: std.StringArrayHashMap(*Dependency),
modules: std.StringArrayHashMap(*Module),

pub const ExecError = error{
Expand Down Expand Up @@ -239,6 +243,7 @@ pub fn create(
.install_path = undefined,
.args = null,
.host = host,
.dependencies = std.StringArrayHashMap(*Dependency).init(allocator),
.modules = std.StringArrayHashMap(*Module).init(allocator),
};
try self.top_level_steps.append(&self.install_tls);
Expand Down Expand Up @@ -314,6 +319,7 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc
.glibc_runtimes_dir = parent.glibc_runtimes_dir,
.host = parent.host,
.dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),
.dependencies = std.StringArrayHashMap(*Dependency).init(allocator),
.modules = std.StringArrayHashMap(*Module).init(allocator),
};
try child.top_level_steps.append(&child.install_tls);
Expand Down Expand Up @@ -714,11 +720,95 @@ pub fn make(self: *Build, step_names: []const []const u8) !void {
}
}

for (wanted_steps.items) |s| {
try self.makeOneStep(s);
if (self.dump_build_info != .dry) {
for (wanted_steps.items) |s| {
try self.makeOneStep(s);
}
}

if (self.dump_build_info != .off) {
const stdout_writer = std.io.getStdOut().writer();
var buffered_writer = std.io.bufferedWriter(stdout_writer);
try self.dumpBuildInfo(buffered_writer.writer(), 0);
try buffered_writer.flush();
}
}

fn indent(writer: anytype, indentation: usize) !void {
try writer.writeByteNTimes(' ', 4 * indentation);
}

fn dumpModules(mods: std.StringArrayHashMap(*Module), writer: anytype, indentation: usize) !void {
if (mods.count() == 0) {
try writer.writeAll(
\\.{}
);
} else {
try writer.writeAll(".{\n");

var module_iterator = mods.iterator();
while (module_iterator.next()) |entry| {
try indent(writer, indentation + 1);
try writer.print(".{s} = .{{\n", .{std.zig.fmtId(entry.key_ptr.*)});

try indent(writer, indentation + 2);
try writer.print(".path = \"{}\",\n", .{
std.zig.fmtEscapes(
switch (entry.value_ptr.*.source_file) {
.generated => |gen| gen.path orelse "generated",
.path => |path| path,
},
),
});

try indent(writer, indentation + 2);
try writer.print(".dependencies = ", .{});
try dumpModules(entry.value_ptr.*.dependencies, writer, indentation + 2);
try writer.writeAll(",\n");

try indent(writer, indentation + 1);
try writer.writeAll("},\n");
}

try indent(writer, indentation);
try writer.writeAll("}");
}
}

pub fn dumpBuildInfo(self: *Build, writer: anytype, indentation: usize) !void {
try writer.writeAll(".{\n");

try indent(writer, indentation + 1);
try writer.print(".path = \"{}\",\n", .{std.zig.fmtEscapes(self.pathFromRoot("build.zig"))});

try indent(writer, indentation + 1);
try writer.writeAll(".dependencies = .{");

if (self.dependencies.count() == 0) {
try writer.writeAll("},\n");
} else {
try writer.writeAll("\n");

var dep_it = self.dependencies.iterator();
while (dep_it.next()) |entry| {
try indent(writer, indentation + 2);
try writer.print(".{s} = ", .{std.zig.fmtId(entry.key_ptr.*)});
try entry.value_ptr.*.builder.dumpBuildInfo(writer, indentation + 2);
}

try indent(writer, indentation + 1);
try writer.writeAll("},\n");
}

try indent(writer, indentation + 1);
try writer.writeAll(".modules = ");
try dumpModules(self.modules, writer, indentation + 1);
try writer.writeAll(",\n");

try indent(writer, indentation);
try writer.writeAll("}\n");
}

pub fn getInstallStep(self: *Build) *Step {
return &self.install_tls.step;
}
Expand Down Expand Up @@ -1537,6 +1627,9 @@ pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency {
const build_runner = @import("root");
const deps = build_runner.dependencies;

if (b.dependencies.get(name)) |dep|
return dep;

inline for (@typeInfo(deps.imports).Struct.decls) |decl| {
if (mem.startsWith(u8, decl.name, b.dep_prefix) and
mem.endsWith(u8, decl.name, name) and
Expand Down Expand Up @@ -1578,6 +1671,7 @@ fn dependencyInner(

const dep = b.allocator.create(Dependency) catch @panic("OOM");
dep.* = .{ .builder = sub_builder };
b.dependencies.put(name, dep) catch @panic("unhandled error");
return dep;
}

Expand Down