diff --git a/lib/compiler/Maker/PkgConfig.zig b/lib/compiler/Maker/PkgConfig.zig index 567bad7061e92d1237f06f292e48b3965c01cc01..cafcf7c492e3be5986beb62e4b00759a6b01aa83 100644 --- a/lib/compiler/Maker/PkgConfig.zig +++ b/lib/compiler/Maker/PkgConfig.zig @@ -1,6 +1,7 @@ const std = @import("std"); const Io = std.Io; const mem = std.mem; +const assert = std.debug.assert; const Maker = @import("../Maker.zig"); const Step = @import("Step.zig"); @@ -92,14 +93,15 @@ pub fn run( }; const pkg_config_exe = getExe(graph); - const captured = try step.captureChildProcess(maker, progress_node, &.{ - pkg_config_exe, pkg_name, "--cflags", "--libs", + const stdout = try captureChildProcess(maker, step, .{ + .argv = &.{ pkg_config_exe, pkg_name, "--cflags", "--libs" }, + .progress_node = progress_node, + .allow_failure = !force, }); - try step.handleChildProcessTerm(maker, captured.term); var zig_cflags: std.ArrayList([]const u8) = .empty; var zig_libs: std.ArrayList([]const u8) = .empty; - var arg_it = mem.tokenizeAny(u8, captured.stdout, " \r\n\t"); + var arg_it = mem.tokenizeAny(u8, stdout, " \r\n\t"); while (arg_it.next()) |arg| { if (mem.eql(u8, arg, "-I")) { @@ -168,19 +170,14 @@ fn getList(maker: *Maker, step: *Step, progress_node: std.Progress.Node, force: if (pc.list) |list| return list; const pkg_config_exe = getExe(graph); - const captured = try step.captureChildProcess(maker, progress_node, &.{ pkg_config_exe, "--list-all" }); - if (force) { - try step.handleChildProcessTerm(maker, captured.term); - } else switch (captured.term) { - .exited => |code| if (code != 0) return error.PkgConfigUnavailable, - else => { - try step.handleChildProcessTerm(maker, captured.term); - unreachable; - }, - } + const stdout = try captureChildProcess(maker, step, .{ + .argv = &.{ pkg_config_exe, "--list-all" }, + .progress_node = progress_node, + .allow_failure = !force, + }); var list: std.ArrayList(Pkg) = .empty; - var line_it = mem.tokenizeAny(u8, captured.stdout, "\r\n"); + var line_it = mem.tokenizeAny(u8, stdout, "\r\n"); while (line_it.next()) |line| { if (mem.trim(u8, line, " \t").len == 0) continue; var tok_it = mem.tokenizeAny(u8, line, " \t"); @@ -200,3 +197,14 @@ fn getList(maker: *Maker, step: *Step, progress_node: std.Progress.Node, force: pc.list = result; return result; } + +fn captureChildProcess(maker: *Maker, step: *Step, options: Step.CaptureChildProcessOptions) ![]const u8 { + const captured = step.captureChildProcess(maker, options) catch |err| switch (err) { + error.FileNotFound => return error.PkgConfigUnavailable, + else => |e| return e, + }; + assert(step.result_failed_command != null); + if (captured.term.success()) return captured.stdout; + if (!options.allow_failure) return step.fail(maker, "{s} {f}", .{ options.argv[0], captured.term }); + return error.PkgConfigUnavailable; +} diff --git a/lib/compiler/Maker/Step.zig b/lib/compiler/Maker/Step.zig index 59fdabcfaa90ee2b5f78bc9118cdf4a980468df9..ddf60275d2c5c8cbc127d9f1a7c86c416d1b27af 100644 --- a/lib/compiler/Maker/Step.zig +++ b/lib/compiler/Maker/Step.zig @@ -329,13 +329,19 @@ pub fn reset(step: *Step, maker: *Maker) void { step.result_error_bundle = std.zig.ErrorBundle.empty; } -/// Populates `s.result_failed_command`. -pub fn captureChildProcess( - s: *Step, - maker: *Maker, - progress_node: std.Progress.Node, +pub const CaptureChildProcessError = error{ + FileNotFound, +} || ExtendedMakeError; + +pub const CaptureChildProcessOptions = struct { argv: []const []const u8, -) !std.process.RunResult { + progress_node: std.Progress.Node = .none, + environ_map: ?*const std.process.Environ.Map = null, + allow_failure: bool = false, +}; + +/// Populates `s.result_failed_command`. +pub fn captureChildProcess(s: *Step, maker: *Maker, options: CaptureChildProcessOptions) !std.process.RunResult { const gpa = maker.gpa; const graph = maker.graph; const arena = graph.arena; // TODO stop leaking into process arena @@ -343,20 +349,25 @@ pub fn captureChildProcess( // If an error occurs, it's happened in this command: assert(s.result_failed_command == null); - s.result_failed_command = try std.zig.allocPrintCmd(gpa, argv, .{}); + s.result_failed_command = try std.zig.allocPrintCmd(gpa, options.argv, .{}); try handleChildProcUnsupported(s, maker); - try graph.handleVerbose(.inherit, null, argv); + try graph.handleVerbose(.inherit, null, options.argv); const result = std.process.run(arena, io, .{ - .argv = argv, - .environ_map = &graph.environ_map, - .progress_node = progress_node, - }) catch |err| return s.fail(maker, "failed to run {s}: {t}", .{ argv[0], err }); + .argv = options.argv, + .environ_map = options.environ_map orelse &graph.environ_map, + .progress_node = options.progress_node, + }) catch |err| { + switch (err) { + error.OutOfMemory, error.Canceled => |e| return e, + error.FileNotFound => |e| if (options.allow_failure) return e, + else => {}, + } + return s.fail(maker, "failed to run {s}: {t}", .{ options.argv[0], err }); + }; - if (result.stderr.len > 0) { - try s.result_error_msgs.append(arena, result.stderr); - } + if (result.stderr.len > 0) try s.result_error_msgs.append(arena, result.stderr); return result; } @@ -679,12 +690,7 @@ pub inline fn handleChildProcUnsupported(s: *Step, maker: *Maker) FailError!void /// Asserts that the caller has already populated `s.result_failed_command`. pub fn handleChildProcessTerm(s: *Step, maker: *Maker, term: std.process.Child.Term) FailError!void { assert(s.result_failed_command != null); - return switch (term) { - .exited => |code| if (code != 0) s.fail(maker, "process exited with error code {d}", .{code}), - .signal => |sig| s.fail(maker, "process terminated with signal {t}", .{sig}), - .stopped => |sig| s.fail(maker, "process stopped with signal {t}", .{sig}), - .unknown => s.fail(maker, "process terminated unexpectedly", .{}), - }; + if (!term.success()) return s.fail(maker, "process {f}", .{term}); } /// Prefer `cacheHitAndWatch` unless you already added watch inputs diff --git a/lib/compiler/Maker/Step/Fmt.zig b/lib/compiler/Maker/Step/Fmt.zig index addd39a969491bf74c51b0db20235cfa26b18196..281686bed57d488d5db088d9f1c2593edf4f6371 100644 --- a/lib/compiler/Maker/Step/Fmt.zig +++ b/lib/compiler/Maker/Step/Fmt.zig @@ -43,7 +43,15 @@ pub fn make( argv.appendAssumeCapacity(try maker.resolveLazyPathIndexAbs(arena, lp, step_index)); } - const run_result = try step.captureChildProcess(maker, progress_node, argv.items); + const run_result = step.captureChildProcess(maker, .{ + .progress_node = progress_node, + .argv = argv.items, + .allow_failure = false, + }) catch |err| switch (err) { + error.FileNotFound => unreachable, + else => |e| return e, + }; + if (conf_fmt.flags.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');