| ... | @@ -1133,17 +1133,24 @@ pub fn spawnChild(self: *Build, argv: []const []const u8) !void { | ... | @@ -1133,17 +1133,24 @@ pub fn spawnChild(self: *Build, argv: []const []const u8) !void { |
| 1133 | return self.spawnChildEnvMap(null, self.env_map, argv); | 1133 | return self.spawnChildEnvMap(null, self.env_map, argv); |
| 1134 | } | 1134 | } |
| 1135 | | 1135 | |
| 1136 | fn printCmd(cwd: ?[]const u8, argv: []const []const u8) void { | 1136 | fn allocPrintCmd(ally: Allocator, opt_cwd: ?[]const u8, argv: []const []const u8) ![]u8 { |
| 1137 | if (cwd) |yes_cwd| std.debug.print("cd {s} && ", .{yes_cwd}); | 1137 | var buf = ArrayList(u8).init(ally); |
| | 1138 | if (opt_cwd) |cwd| try buf.writer().print("cd {s} && ", .{cwd}); |
| 1138 | for (argv) |arg| { | 1139 | for (argv) |arg| { |
| 1139 | std.debug.print("{s} ", .{arg}); | 1140 | try buf.writer().print("{s} ", .{arg}); |
| 1140 | } | 1141 | } |
| 1141 | std.debug.print("\n", .{}); | 1142 | try buf.append('\n'); |
| | 1143 | return buf.toOwnedSlice(); |
| | 1144 | } |
| | 1145 | |
| | 1146 | fn printCmd(ally: Allocator, cwd: ?[]const u8, argv: []const []const u8) void { |
| | 1147 | const text = allocPrintCmd(ally, cwd, argv) catch @panic("OOM"); |
| | 1148 | std.debug.print("{s}", .{text}); |
| 1142 | } | 1149 | } |
| 1143 | | 1150 | |
| 1144 | pub fn spawnChildEnvMap(self: *Build, cwd: ?[]const u8, env_map: *const EnvMap, argv: []const []const u8) !void { | 1151 | pub fn spawnChildEnvMap(self: *Build, cwd: ?[]const u8, env_map: *const EnvMap, argv: []const []const u8) !void { |
| 1145 | if (self.verbose) { | 1152 | if (self.verbose) { |
| 1146 | printCmd(cwd, argv); | 1153 | printCmd(self.allocator, cwd, argv); |
| 1147 | } | 1154 | } |
| 1148 | | 1155 | |
| 1149 | if (!std.process.can_spawn) | 1156 | if (!std.process.can_spawn) |
| ... | @@ -1162,13 +1169,13 @@ pub fn spawnChildEnvMap(self: *Build, cwd: ?[]const u8, env_map: *const EnvMap, | ... | @@ -1162,13 +1169,13 @@ pub fn spawnChildEnvMap(self: *Build, cwd: ?[]const u8, env_map: *const EnvMap, |
| 1162 | .Exited => |code| { | 1169 | .Exited => |code| { |
| 1163 | if (code != 0) { | 1170 | if (code != 0) { |
| 1164 | log.err("The following command exited with error code {}:", .{code}); | 1171 | log.err("The following command exited with error code {}:", .{code}); |
| 1165 | printCmd(cwd, argv); | 1172 | printCmd(self.allocator, cwd, argv); |
| 1166 | return error.UncleanExit; | 1173 | return error.UncleanExit; |
| 1167 | } | 1174 | } |
| 1168 | }, | 1175 | }, |
| 1169 | else => { | 1176 | else => { |
| 1170 | log.err("The following command terminated unexpectedly:", .{}); | 1177 | log.err("The following command terminated unexpectedly:", .{}); |
| 1171 | printCmd(cwd, argv); | 1178 | printCmd(self.allocator, cwd, argv); |
| 1172 | | 1179 | |
| 1173 | return error.UncleanExit; | 1180 | return error.UncleanExit; |
| 1174 | }, | 1181 | }, |
| ... | @@ -1381,57 +1388,91 @@ pub fn execAllowFail( | ... | @@ -1381,57 +1388,91 @@ pub fn execAllowFail( |
| 1381 | } | 1388 | } |
| 1382 | } | 1389 | } |
| 1383 | | 1390 | |
| 1384 | pub fn execFromStep(self: *Build, argv: []const []const u8, src_step: ?*Step) ![]u8 { | 1391 | pub fn execFromStep(b: *Build, argv: []const []const u8, s: *Step) ![]u8 { |
| 1385 | assert(argv.len != 0); | 1392 | assert(argv.len != 0); |
| 1386 | | 1393 | |
| 1387 | if (self.verbose) { | 1394 | if (b.verbose) { |
| 1388 | printCmd(null, argv); | 1395 | printCmd(b.allocator, null, argv); |
| 1389 | } | 1396 | } |
| 1390 | | 1397 | |
| 1391 | if (!std.process.can_spawn) { | 1398 | if (!std.process.can_spawn) { |
| 1392 | if (src_step) |s| log.err("{s}...", .{s.name}); | 1399 | s.result.stderr = b.fmt("Unable to spawn the following command: cannot spawn child processes\n{s}", .{ |
| 1393 | log.err("Unable to spawn the following command: cannot spawn child process", .{}); | 1400 | try allocPrintCmd(b.allocator, null, argv), |
| 1394 | printCmd(null, argv); | 1401 | }); |
| 1395 | std.os.abort(); | 1402 | return error.CannotSpawnProcesses; |
| 1396 | } | 1403 | } |
| 1397 | | 1404 | |
| 1398 | var code: u8 = undefined; | 1405 | var code: u8 = undefined; |
| 1399 | return self.execAllowFail(argv, &code, .Inherit) catch |err| switch (err) { | 1406 | const result = unwrapExecResult(&code, std.ChildProcess.exec(.{ |
| 1400 | error.ExecNotSupported => { | 1407 | .allocator = b.allocator, |
| 1401 | if (src_step) |s| log.err("{s}...", .{s.name}); | 1408 | .argv = argv, |
| 1402 | log.err("Unable to spawn the following command: cannot spawn child process", .{}); | 1409 | .env_map = b.env_map, |
| 1403 | printCmd(null, argv); | 1410 | .max_output_bytes = 10 * 1024 * 1024, |
| 1404 | std.os.abort(); | 1411 | })) catch |err| switch (err) { |
| 1405 | }, | | |
| 1406 | error.FileNotFound => { | 1412 | error.FileNotFound => { |
| 1407 | if (src_step) |s| log.err("{s}...", .{s.name}); | 1413 | s.result.stderr = b.fmt("unable to spawn the following command: file not found\n{s}", .{ |
| 1408 | log.err("Unable to spawn the following command: file not found", .{}); | 1414 | try allocPrintCmd(b.allocator, null, argv), |
| 1409 | printCmd(null, argv); | 1415 | }); |
| 1410 | std.os.exit(@truncate(u8, code)); | 1416 | return error.ExecFailed; |
| 1411 | }, | 1417 | }, |
| 1412 | error.ExitCodeFailure => { | 1418 | error.ExitCodeFailure => { |
| 1413 | if (src_step) |s| log.err("{s}...", .{s.name}); | 1419 | s.result.stderr = b.fmt("the following command exited with error code {d}:\n{s}", .{ |
| 1414 | if (self.prominent_compile_errors) { | 1420 | code, try allocPrintCmd(b.allocator, null, argv), |
| 1415 | log.err("The step exited with error code {d}", .{code}); | 1421 | }); |
| 1416 | } else { | 1422 | return error.ExecFailed; |
| 1417 | log.err("The following command exited with error code {d}:", .{code}); | | |
| 1418 | printCmd(null, argv); | | |
| 1419 | } | | |
| 1420 | | | |
| 1421 | std.os.exit(@truncate(u8, code)); | | |
| 1422 | }, | 1423 | }, |
| 1423 | error.ProcessTerminated => { | 1424 | error.ProcessTerminated => { |
| 1424 | if (src_step) |s| log.err("{s}...", .{s.name}); | 1425 | s.result.stderr = b.fmt("the following command terminated unexpectedly:\n{s}", .{ |
| 1425 | log.err("The following command terminated unexpectedly:", .{}); | 1426 | try allocPrintCmd(b.allocator, null, argv), |
| 1426 | printCmd(null, argv); | 1427 | }); |
| 1427 | std.os.exit(@truncate(u8, code)); | 1428 | return error.ExecFailed; |
| 1428 | }, | 1429 | }, |
| 1429 | else => |e| return e, | 1430 | else => |e| return e, |
| 1430 | }; | 1431 | }; |
| | 1432 | |
| | 1433 | s.result.stderr = result.stderr; |
| | 1434 | return result.stdout; |
| 1431 | } | 1435 | } |
| 1432 | | 1436 | |
| 1433 | pub fn exec(self: *Build, argv: []const []const u8) ![]u8 { | 1437 | fn unwrapExecResult( |
| 1434 | return self.execFromStep(argv, null); | 1438 | code_ptr: *u8, |
| | 1439 | wrapped: std.ChildProcess.ExecError!std.ChildProcess.ExecResult, |
| | 1440 | ) !std.ChildProcess.ExecResult { |
| | 1441 | const result = try wrapped; |
| | 1442 | switch (result.term) { |
| | 1443 | .Exited => |code| { |
| | 1444 | code_ptr.* = code; |
| | 1445 | if (code != 0) { |
| | 1446 | return error.ExitCodeFailure; |
| | 1447 | } |
| | 1448 | return result; |
| | 1449 | }, |
| | 1450 | .Signal, .Stopped, .Unknown => |code| { |
| | 1451 | _ = code; |
| | 1452 | return error.ProcessTerminated; |
| | 1453 | }, |
| | 1454 | } |
| | 1455 | } |
| | 1456 | |
| | 1457 | /// This is a helper function to be called from build.zig scripts, *not* from |
| | 1458 | /// inside step make() functions. If any errors occur, it fails the build with |
| | 1459 | /// a helpful message. |
| | 1460 | pub fn exec(b: *Build, argv: []const []const u8) []u8 { |
| | 1461 | if (!std.process.can_spawn) { |
| | 1462 | std.debug.print("unable to spawn the following command: cannot spawn child process\n{s}", .{ |
| | 1463 | try allocPrintCmd(b.allocator, null, argv), |
| | 1464 | }); |
| | 1465 | process.exit(1); |
| | 1466 | } |
| | 1467 | |
| | 1468 | var code: u8 = undefined; |
| | 1469 | return b.execAllowFail(argv, &code, .Inherit) catch |err| { |
| | 1470 | const printed_cmd = allocPrintCmd(b.allocator, null, argv) catch @panic("OOM"); |
| | 1471 | std.debug.print("unable to spawn the following command: {s}\n{s}", .{ |
| | 1472 | @errorName(err), printed_cmd, |
| | 1473 | }); |
| | 1474 | process.exit(1); |
| | 1475 | }; |
| 1435 | } | 1476 | } |
| 1436 | | 1477 | |
| 1437 | pub fn addSearchPrefix(self: *Build, search_prefix: []const u8) void { | 1478 | pub fn addSearchPrefix(self: *Build, search_prefix: []const u8) void { |