zig/lib/std/Build/Step/Fmt.zig
Andrew Kelley 105db13536 std.Build: implement --host-target, --host-cpu, --host-dynamic-linker
This also makes a long-overdue change of extracting common state from
Build into a shared Graph object.

Getting the semantics right for these flags turned out to be quite
tricky. In the end it works like this:
* The override only happens when the target is fully native, with no
  additional query parameters, such as versions or CPU features added.
* The override affects the resolved Target but leaves the original Query
  unmodified.
* The "is native?" detection logic operates on the original, unmodified
  query. This makes it possible to provide invalid host target
  information, causing confusing errors to occur. Don't do that.

There are some minor breaking changes to std.Build API such as the fact
that `b.zig_exe` is now moved to `b.graph.zig_exe`, as well as a handful
of other similar flags.
2024-02-02 20:43:01 -07:00

72 lines
2.2 KiB
Zig

//! 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 = .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 self = owner.allocator.create(Fmt) catch @panic("OOM");
const name = if (options.check) "zig fmt --check" else "zig fmt";
self.* = .{
.step = Step.init(.{
.id = base_id,
.name = name,
.owner = owner,
.makeFn = make,
}),
.paths = options.paths,
.exclude_paths = options.exclude_paths,
.check = options.check,
};
return self;
}
fn make(step: *Step, prog_node: *std.Progress.Node) !void {
// zig fmt is fast enough that no progress is needed.
_ = prog_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 self = @fieldParentPtr(Fmt, "step", step);
var argv: std.ArrayListUnmanaged([]const u8) = .{};
try argv.ensureUnusedCapacity(arena, 2 + 1 + self.paths.len + 2 * self.exclude_paths.len);
argv.appendAssumeCapacity(b.graph.zig_exe);
argv.appendAssumeCapacity("fmt");
if (self.check) {
argv.appendAssumeCapacity("--check");
}
for (self.paths) |p| {
argv.appendAssumeCapacity(b.pathFromRoot(p));
}
for (self.exclude_paths) |p| {
argv.appendAssumeCapacity("--exclude");
argv.appendAssumeCapacity(b.pathFromRoot(p));
}
return step.evalChildProcess(argv.items);
}