| ... | @@ -24,6 +24,21 @@ cwd: ?Build.LazyPath, | ... | @@ -24,6 +24,21 @@ cwd: ?Build.LazyPath, |
| 24 | /// Override this field to modify the environment, or use setEnvironmentVariable | 24 | /// Override this field to modify the environment, or use setEnvironmentVariable |
| 25 | env_map: ?*EnvMap, | 25 | env_map: ?*EnvMap, |
| 26 | | 26 | |
| | 27 | /// Controls the `NO_COLOR` and `CLICOLOR_FORCE` environment variables. |
| | 28 | color: enum { |
| | 29 | /// `CLICOLOR_FORCE` is set, and `NO_COLOR` is unset. |
| | 30 | enable, |
| | 31 | /// `NO_COLOR` is set, and `CLICOLOR_FORCE` is unset. |
| | 32 | disable, |
| | 33 | /// If the build runner is using color, equivalent to `.enable`. Otherwise, equivalent to `.disable`. |
| | 34 | inherit, |
| | 35 | /// If stderr is captured or checked, equivalent to `.disable`. Otherwise, equivalent to `.inherit`. |
| | 36 | auto, |
| | 37 | /// The build runner does not modify the `CLICOLOR_FORCE` or `NO_COLOR` environment variables. |
| | 38 | /// They are treated like normal variables, so can be controlled through `setEnvironmentVariable`. |
| | 39 | manual, |
| | 40 | } = .auto, |
| | 41 | |
| 27 | /// When `true` prevents `ZIG_PROGRESS` environment variable from being passed | 42 | /// When `true` prevents `ZIG_PROGRESS` environment variable from being passed |
| 28 | /// to the child process, which otherwise would be used for the child to send | 43 | /// to the child process, which otherwise would be used for the child to send |
| 29 | /// progress updates to the parent. | 44 | /// progress updates to the parent. |
| ... | @@ -525,7 +540,7 @@ pub fn setCwd(run: *Run, cwd: Build.LazyPath) void { | ... | @@ -525,7 +540,7 @@ pub fn setCwd(run: *Run, cwd: Build.LazyPath) void { |
| 525 | pub fn clearEnvironment(run: *Run) void { | 540 | pub fn clearEnvironment(run: *Run) void { |
| 526 | const b = run.step.owner; | 541 | const b = run.step.owner; |
| 527 | const new_env_map = b.allocator.create(EnvMap) catch @panic("OOM"); | 542 | const new_env_map = b.allocator.create(EnvMap) catch @panic("OOM"); |
| 528 | new_env_map.* = EnvMap.init(b.allocator); | 543 | new_env_map.* = .init(b.allocator); |
| 529 | run.env_map = new_env_map; | 544 | run.env_map = new_env_map; |
| 530 | } | 545 | } |
| 531 | | 546 | |
| ... | @@ -806,6 +821,9 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -806,6 +821,9 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 806 | } | 821 | } |
| 807 | } | 822 | } |
| 808 | | 823 | |
| | 824 | man.hash.add(run.color); |
| | 825 | man.hash.add(run.disable_zig_progress); |
| | 826 | |
| 809 | for (run.argv.items) |arg| { | 827 | for (run.argv.items) |arg| { |
| 810 | switch (arg) { | 828 | switch (arg) { |
| 811 | .bytes => |bytes| { | 829 | .bytes => |bytes| { |
| ... | @@ -1130,6 +1148,7 @@ pub fn rerunInFuzzMode( | ... | @@ -1130,6 +1148,7 @@ pub fn rerunInFuzzMode( |
| 1130 | .thread_pool = undefined, // not used by `runCommand` | 1148 | .thread_pool = undefined, // not used by `runCommand` |
| 1131 | .watch = undefined, // not used by `runCommand` | 1149 | .watch = undefined, // not used by `runCommand` |
| 1132 | .web_server = null, // only needed for time reports | 1150 | .web_server = null, // only needed for time reports |
| | 1151 | .ttyconf = fuzz.ttyconf, |
| 1133 | .unit_test_timeout_ns = null, // don't time out fuzz tests for now | 1152 | .unit_test_timeout_ns = null, // don't time out fuzz tests for now |
| 1134 | .gpa = undefined, // not used by `runCommand` | 1153 | .gpa = undefined, // not used by `runCommand` |
| 1135 | }, .{ | 1154 | }, .{ |
| ... | @@ -1234,9 +1253,40 @@ fn runCommand( | ... | @@ -1234,9 +1253,40 @@ fn runCommand( |
| 1234 | var interp_argv = std.array_list.Managed([]const u8).init(b.allocator); | 1253 | var interp_argv = std.array_list.Managed([]const u8).init(b.allocator); |
| 1235 | defer interp_argv.deinit(); | 1254 | defer interp_argv.deinit(); |
| 1236 | | 1255 | |
| 1237 | var env_map = run.env_map orelse &b.graph.env_map; | 1256 | var env_map: EnvMap = env: { |
| | 1257 | const orig = run.env_map orelse &b.graph.env_map; |
| | 1258 | break :env try orig.clone(gpa); |
| | 1259 | }; |
| | 1260 | defer env_map.deinit(); |
| | 1261 | |
| | 1262 | color: switch (run.color) { |
| | 1263 | .manual => {}, |
| | 1264 | .enable => { |
| | 1265 | try env_map.put("CLICOLOR_FORCE", "1"); |
| | 1266 | env_map.remove("NO_COLOR"); |
| | 1267 | }, |
| | 1268 | .disable => { |
| | 1269 | try env_map.put("NO_COLOR", "1"); |
| | 1270 | env_map.remove("CLICOLOR_FORCE"); |
| | 1271 | }, |
| | 1272 | .inherit => switch (options.ttyconf) { |
| | 1273 | .no_color, .windows_api => continue :color .disable, |
| | 1274 | .escape_codes => continue :color .enable, |
| | 1275 | }, |
| | 1276 | .auto => { |
| | 1277 | const capture_stderr = run.captured_stderr != null or switch (run.stdio) { |
| | 1278 | .check => |checks| checksContainStderr(checks.items), |
| | 1279 | .infer_from_args, .inherit, .zig_test => false, |
| | 1280 | }; |
| | 1281 | if (capture_stderr) { |
| | 1282 | continue :color .disable; |
| | 1283 | } else { |
| | 1284 | continue :color .inherit; |
| | 1285 | } |
| | 1286 | }, |
| | 1287 | } |
| 1238 | | 1288 | |
| 1239 | const opt_generic_result = spawnChildAndCollect(run, argv, env_map, has_side_effects, options, fuzz_context) catch |err| term: { | 1289 | const opt_generic_result = spawnChildAndCollect(run, argv, &env_map, has_side_effects, options, fuzz_context) catch |err| term: { |
| 1240 | // InvalidExe: cpu arch mismatch | 1290 | // InvalidExe: cpu arch mismatch |
| 1241 | // FileNotFound: can happen with a wrong dynamic linker path | 1291 | // FileNotFound: can happen with a wrong dynamic linker path |
| 1242 | if (err == error.InvalidExe or err == error.FileNotFound) interpret: { | 1292 | if (err == error.InvalidExe or err == error.FileNotFound) interpret: { |
| ... | @@ -1273,12 +1323,7 @@ fn runCommand( | ... | @@ -1273,12 +1323,7 @@ fn runCommand( |
| 1273 | // Wine's excessive stderr logging is only situationally helpful. Disable it by default, but | 1323 | // Wine's excessive stderr logging is only situationally helpful. Disable it by default, but |
| 1274 | // allow the user to override it (e.g. with `WINEDEBUG=err+all`) if desired. | 1324 | // allow the user to override it (e.g. with `WINEDEBUG=err+all`) if desired. |
| 1275 | if (env_map.get("WINEDEBUG") == null) { | 1325 | if (env_map.get("WINEDEBUG") == null) { |
| 1276 | // We don't own `env_map` at this point, so create a copy in order to modify it. | 1326 | try env_map.put("WINEDEBUG", "-all"); |
| 1277 | const new_env_map = arena.create(EnvMap) catch @panic("OOM"); | | |
| 1278 | new_env_map.hash_map = try env_map.hash_map.cloneWithAllocator(arena); | | |
| 1279 | try new_env_map.put("WINEDEBUG", "-all"); | | |
| 1280 | | | |
| 1281 | env_map = new_env_map; | | |
| 1282 | } | 1327 | } |
| 1283 | } else { | 1328 | } else { |
| 1284 | return failForeign(run, "-fwine", argv[0], exe); | 1329 | return failForeign(run, "-fwine", argv[0], exe); |
| ... | @@ -1377,7 +1422,7 @@ fn runCommand( | ... | @@ -1377,7 +1422,7 @@ fn runCommand( |
| 1377 | step.result_failed_command = null; | 1422 | step.result_failed_command = null; |
| 1378 | try Step.handleVerbose2(step.owner, cwd, run.env_map, interp_argv.items); | 1423 | try Step.handleVerbose2(step.owner, cwd, run.env_map, interp_argv.items); |
| 1379 | | 1424 | |
| 1380 | break :term spawnChildAndCollect(run, interp_argv.items, env_map, has_side_effects, options, fuzz_context) catch |e| { | 1425 | break :term spawnChildAndCollect(run, interp_argv.items, &env_map, has_side_effects, options, fuzz_context) catch |e| { |
| 1381 | if (!run.failing_to_execute_foreign_is_an_error) return error.MakeSkipped; | 1426 | if (!run.failing_to_execute_foreign_is_an_error) return error.MakeSkipped; |
| 1382 | if (e == error.MakeFailed) return error.MakeFailed; // error already reported | 1427 | if (e == error.MakeFailed) return error.MakeFailed; // error already reported |
| 1383 | return step.fail("unable to spawn interpreter {s}: {s}", .{ | 1428 | return step.fail("unable to spawn interpreter {s}: {s}", .{ |