struct Fmt [src]

Alias for std.Build.Step.Fmt

This step has two modes: Modify mode: directly modify source files, formatting them in place. Check mode: fail the step if a non-conforming file is found.

Fields

step: Step
paths: []const []const u8
exclude_paths: []const []const u8
check: bool

Members

Source

//! This step has two modes: //! * Modify mode: directly modify source files, formatting them in place. //! * Check mode: fail the step if a non-conforming file is found. const std = @import("std"); const Step = std.Build.Step; const Fmt = @This(); step: Step, paths: []const []const u8, exclude_paths: []const []const u8, check: bool, pub const base_id: Step.Id = .fmt; pub const Options = struct { paths: []const []const u8 = &.{}, exclude_paths: []const []const u8 = &.{}, /// If true, fails the build step when any non-conforming files are encountered. check: bool = false, }; pub fn create(owner: *std.Build, options: Options) *Fmt { const fmt = owner.allocator.create(Fmt) catch @panic("OOM"); const name = if (options.check) "zig fmt --check" else "zig fmt"; fmt.* = .{ .step = Step.init(.{ .id = base_id, .name = name, .owner = owner, .makeFn = make, }), .paths = owner.dupeStrings(options.paths), .exclude_paths = owner.dupeStrings(options.exclude_paths), .check = options.check, }; return fmt; } fn make(step: *Step, options: Step.MakeOptions) !void { const prog_node = options.progress_node; // TODO: if check=false, this means we are modifying source files in place, which // is an operation that could race against other operations also modifying source files // in place. In this case, this step should obtain a write lock while making those // modifications. const b = step.owner; const arena = b.allocator; const fmt: *Fmt = @fieldParentPtr("step", step); var argv: std.ArrayListUnmanaged([]const u8) = .empty; try argv.ensureUnusedCapacity(arena, 2 + 1 + fmt.paths.len + 2 * fmt.exclude_paths.len); argv.appendAssumeCapacity(b.graph.zig_exe); argv.appendAssumeCapacity("fmt"); if (fmt.check) { argv.appendAssumeCapacity("--check"); } for (fmt.paths) |p| { argv.appendAssumeCapacity(b.pathFromRoot(p)); } for (fmt.exclude_paths) |p| { argv.appendAssumeCapacity("--exclude"); argv.appendAssumeCapacity(b.pathFromRoot(p)); } const run_result = try step.captureChildProcess(prog_node, argv.items); if (fmt.check) switch (run_result.term) { .Exited => |code| if (code != 0 and run_result.stdout.len != 0) { var it = std.mem.tokenizeScalar(u8, run_result.stdout, '\n'); while (it.next()) |bad_file_name| { try step.addError("{s}: non-conforming formatting", .{bad_file_name}); } }, else => {}, }; try step.handleChildProcessTerm(run_result.term, null, argv.items); }