| ... | ... | @@ -1133,17 +1133,24 @@ pub fn spawnChild(self: *Build, argv: []const []const u8) !void { |
| 1133 | 1133 | return self.spawnChildEnvMap(null, self.env_map, argv); |
| 1134 | 1134 | } |
| 1135 | 1135 | |
| 1136 | | fn printCmd(cwd: ?[]const u8, argv: []const []const u8) void { |
| 1137 | | if (cwd) |yes_cwd| std.debug.print("cd {s} && ", .{yes_cwd}); |
| 1136 | fn allocPrintCmd(ally: Allocator, opt_cwd: ?[]const u8, argv: []const []const u8) ![]u8 { |
| 1137 | var buf = ArrayList(u8).init(ally); |
| 1138 | if (opt_cwd) |cwd| try buf.writer().print("cd {s} && ", .{cwd}); |
| 1138 | 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 | 1151 | pub fn spawnChildEnvMap(self: *Build, cwd: ?[]const u8, env_map: *const EnvMap, argv: []const []const u8) !void { |
| 1145 | 1152 | if (self.verbose) { |
| 1146 | | printCmd(cwd, argv); |
| 1153 | printCmd(self.allocator, cwd, argv); |
| 1147 | 1154 | } |
| 1148 | 1155 | |
| 1149 | 1156 | if (!std.process.can_spawn) |
| ... | ... | @@ -1162,13 +1169,13 @@ pub fn spawnChildEnvMap(self: *Build, cwd: ?[]const u8, env_map: *const EnvMap, |
| 1162 | 1169 | .Exited => |code| { |
| 1163 | 1170 | if (code != 0) { |
| 1164 | 1171 | log.err("The following command exited with error code {}:", .{code}); |
| 1165 | | printCmd(cwd, argv); |
| 1172 | printCmd(self.allocator, cwd, argv); |
| 1166 | 1173 | return error.UncleanExit; |
| 1167 | 1174 | } |
| 1168 | 1175 | }, |
| 1169 | 1176 | else => { |
| 1170 | 1177 | log.err("The following command terminated unexpectedly:", .{}); |
| 1171 | | printCmd(cwd, argv); |
| 1178 | printCmd(self.allocator, cwd, argv); |
| 1172 | 1179 | |
| 1173 | 1180 | return error.UncleanExit; |
| 1174 | 1181 | }, |
| ... | ... | @@ -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 | 1392 | assert(argv.len != 0); |
| 1386 | 1393 | |
| 1387 | | if (self.verbose) { |
| 1388 | | printCmd(null, argv); |
| 1394 | if (b.verbose) { |
| 1395 | printCmd(b.allocator, null, argv); |
| 1389 | 1396 | } |
| 1390 | 1397 | |
| 1391 | 1398 | if (!std.process.can_spawn) { |
| 1392 | | if (src_step) |s| log.err("{s}...", .{s.name}); |
| 1393 | | log.err("Unable to spawn the following command: cannot spawn child process", .{}); |
| 1394 | | printCmd(null, argv); |
| 1395 | | std.os.abort(); |
| 1399 | s.result.stderr = b.fmt("Unable to spawn the following command: cannot spawn child processes\n{s}", .{ |
| 1400 | try allocPrintCmd(b.allocator, null, argv), |
| 1401 | }); |
| 1402 | return error.CannotSpawnProcesses; |
| 1396 | 1403 | } |
| 1397 | 1404 | |
| 1398 | 1405 | var code: u8 = undefined; |
| 1399 | | return self.execAllowFail(argv, &code, .Inherit) catch |err| switch (err) { |
| 1400 | | error.ExecNotSupported => { |
| 1401 | | if (src_step) |s| log.err("{s}...", .{s.name}); |
| 1402 | | log.err("Unable to spawn the following command: cannot spawn child process", .{}); |
| 1403 | | printCmd(null, argv); |
| 1404 | | std.os.abort(); |
| 1405 | | }, |
| 1406 | const result = unwrapExecResult(&code, std.ChildProcess.exec(.{ |
| 1407 | .allocator = b.allocator, |
| 1408 | .argv = argv, |
| 1409 | .env_map = b.env_map, |
| 1410 | .max_output_bytes = 10 * 1024 * 1024, |
| 1411 | })) catch |err| switch (err) { |
| 1406 | 1412 | error.FileNotFound => { |
| 1407 | | if (src_step) |s| log.err("{s}...", .{s.name}); |
| 1408 | | log.err("Unable to spawn the following command: file not found", .{}); |
| 1409 | | printCmd(null, argv); |
| 1410 | | std.os.exit(@truncate(u8, code)); |
| 1413 | s.result.stderr = b.fmt("unable to spawn the following command: file not found\n{s}", .{ |
| 1414 | try allocPrintCmd(b.allocator, null, argv), |
| 1415 | }); |
| 1416 | return error.ExecFailed; |
| 1411 | 1417 | }, |
| 1412 | 1418 | error.ExitCodeFailure => { |
| 1413 | | if (src_step) |s| log.err("{s}...", .{s.name}); |
| 1414 | | if (self.prominent_compile_errors) { |
| 1415 | | log.err("The step exited with error code {d}", .{code}); |
| 1416 | | } else { |
| 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)); |
| 1419 | s.result.stderr = b.fmt("the following command exited with error code {d}:\n{s}", .{ |
| 1420 | code, try allocPrintCmd(b.allocator, null, argv), |
| 1421 | }); |
| 1422 | return error.ExecFailed; |
| 1422 | 1423 | }, |
| 1423 | 1424 | error.ProcessTerminated => { |
| 1424 | | if (src_step) |s| log.err("{s}...", .{s.name}); |
| 1425 | | log.err("The following command terminated unexpectedly:", .{}); |
| 1426 | | printCmd(null, argv); |
| 1427 | | std.os.exit(@truncate(u8, code)); |
| 1425 | s.result.stderr = b.fmt("the following command terminated unexpectedly:\n{s}", .{ |
| 1426 | try allocPrintCmd(b.allocator, null, argv), |
| 1427 | }); |
| 1428 | return error.ExecFailed; |
| 1428 | 1429 | }, |
| 1429 | 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 { |
| 1434 | | return self.execFromStep(argv, null); |
| 1437 | fn unwrapExecResult( |
| 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 | 1478 | pub fn addSearchPrefix(self: *Build, search_prefix: []const u8) void { |