authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-04-27 20:58:30-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:34-07:00
logc8b583885d75524fc92cc02a9d00a49a76f2ea70
tree085230c5da972f023c5db37c3ceafd48611f9c7f
parent0d48cbb822551c07ac987c9c2e20d3251ee3a09c

maker: port Run step logic up to spawnChildAndCollect


8 files changed, 328 insertions(+), 262 deletions(-)

BRANCH_TODO+1
......@@ -18,6 +18,7 @@
1818* https://codeberg.org/ziglang/zig/pulls/30762
1919
2020## Followup Issues
21* reduce the size of Maker.Step.Extended (make Run smaller) probably by using an arena per make
2122* link_eh_frame_hdr should be DefaultingBool
2223* make --foo, --no-foo CLI args uniform (make them -f args instead)
2324* install steps should provide generated files for installed things, then delete the run step hack
lib/compiler/Maker.zig+12-22
......@@ -153,17 +153,6 @@ pub fn main(init: process.Init.Minimal) !void {
153153 var debounce_interval_ms: u16 = 50;
154154 var webui_listen: ?Io.net.IpAddress = null;
155155 var debug_pkg_config: bool = false;
156 // After following the steps in https://codeberg.org/ziglang/infra/src/branch/master/libc-update/glibc.md,
157 // this will be the directory $glibc-build-dir/install/glibcs
158 // Given the example of the aarch64 target, this is the directory
159 // that contains the path `aarch64-linux-gnu/lib/ld-linux-aarch64.so.1`.
160 // Also works for dynamic musl.
161 var libc_runtimes_dir: ?[]const u8 = null;
162 var enable_wine = false;
163 var enable_qemu = false;
164 var enable_wasmtime = false;
165 var enable_darling = false;
166 var enable_rosetta = false;
167156 var run_args: ?[]const []const u8 = null;
168157
169158 if (std.zig.EnvVar.ZIG_BUILD_ERROR_STYLE.get(&graph.environ_map)) |str| {
......@@ -314,7 +303,7 @@ pub fn main(init: process.Init.Minimal) !void {
314303 fatal("unrecognized optimization mode: {s}", .{rest});
315304 } else if (mem.eql(u8, arg, "--libc-runtimes") or mem.eql(u8, arg, "--glibc-runtimes")) {
316305 // --glibc-runtimes was the old name of the flag; kept for compatibility for now.
317 libc_runtimes_dir = nextArgOrFatal(args, &arg_idx);
306 graph.libc_runtimes_dir = nextArgOrFatal(args, &arg_idx);
318307 } else if (mem.eql(u8, arg, "--verbose")) {
319308 graph.verbose = true;
320309 } else if (mem.eql(u8, arg, "--verbose-air")) {
......@@ -370,25 +359,25 @@ pub fn main(init: process.Init.Minimal) !void {
370359 } else if (mem.eql(u8, arg, "-fno-incremental")) {
371360 graph.incremental = false;
372361 } else if (mem.eql(u8, arg, "-fwine")) {
373 enable_wine = true;
362 graph.enable_wine = true;
374363 } else if (mem.eql(u8, arg, "-fno-wine")) {
375 enable_wine = false;
364 graph.enable_wine = false;
376365 } else if (mem.eql(u8, arg, "-fqemu")) {
377 enable_qemu = true;
366 graph.enable_qemu = true;
378367 } else if (mem.eql(u8, arg, "-fno-qemu")) {
379 enable_qemu = false;
368 graph.enable_qemu = false;
380369 } else if (mem.eql(u8, arg, "-fwasmtime")) {
381 enable_wasmtime = true;
370 graph.enable_wasmtime = true;
382371 } else if (mem.eql(u8, arg, "-fno-wasmtime")) {
383 enable_wasmtime = false;
372 graph.enable_wasmtime = false;
384373 } else if (mem.eql(u8, arg, "-frosetta")) {
385 enable_rosetta = true;
374 graph.enable_rosetta = true;
386375 } else if (mem.eql(u8, arg, "-fno-rosetta")) {
387 enable_rosetta = false;
376 graph.enable_rosetta = false;
388377 } else if (mem.eql(u8, arg, "-fdarling")) {
389 enable_darling = true;
378 graph.enable_darling = true;
390379 } else if (mem.eql(u8, arg, "-fno-darling")) {
391 enable_darling = false;
380 graph.enable_darling = false;
392381 } else if (mem.eql(u8, arg, "-fallow-so-scripts")) {
393382 graph.allow_so_scripts = true;
394383 } else if (mem.eql(u8, arg, "-fno-allow-so-scripts")) {
......@@ -533,6 +522,7 @@ pub fn main(init: process.Init.Minimal) !void {
533522 .bin = install_bin_path,
534523 .include = install_include_path,
535524 },
525
536526 .steps = try arena.alloc(Step, scanned_config.configuration.steps.len),
537527 .generated_files = try arena.alloc(Path, scanned_config.configuration.generated_files_len),
538528 .run_args = run_args,
lib/compiler/Maker/Graph.zig+12
......@@ -52,6 +52,18 @@ error_limit: ?u32 = null,
5252/// a single step spawning a fixed number of processes this can be used.
5353max_jobs: ?u32 = null,
5454
55/// After following the steps in https://codeberg.org/ziglang/infra/src/branch/master/libc-update/glibc.md,
56/// this will be the directory $glibc-build-dir/install/glibcs
57/// Given the example of the aarch64 target, this is the directory
58/// that contains the path `aarch64-linux-gnu/lib/ld-linux-aarch64.so.1`.
59/// Also works for dynamic musl.
60libc_runtimes_dir: ?[]const u8 = null,
61enable_wine: bool = false,
62enable_qemu: bool = false,
63enable_wasmtime: bool = false,
64enable_darling: bool = false,
65enable_rosetta: bool = false,
66
5567/// Intention of verbose is to print all sub-process command lines to stderr
5668/// before spawning them.
5769pub fn handleVerbose(
lib/compiler/Maker/Step.zig+5-8
......@@ -62,12 +62,11 @@ comptime {
6262 // Common cache line size is 128. This check prevents accidentally crossing
6363 // an additional cache line. In the future it might be nice to try to fit
6464 // this struct in 128 bytes or less.
65 assert(@sizeOf(@This()) <= 128 * 3);
65 assert(@sizeOf(@This()) <= 128 * 4);
6666}
6767
6868pub const Extended = union(enum) {
6969 check_file: Todo,
70 check_object: Todo,
7170 compile: Compile,
7271 config_header: Todo,
7372 fail: Todo,
......@@ -87,7 +86,6 @@ pub const Extended = union(enum) {
8786 pub fn init(tag: Configuration.Step.Tag) Extended {
8887 return switch (tag) {
8988 .check_file => .{ .check_file = .{} },
90 .check_object => .{ .check_object = .{} },
9189 .compile => .{ .compile = .{} },
9290 .config_header => .{ .config_header = .{} },
9391 .fail => .{ .fail = .{} },
......@@ -645,9 +643,8 @@ fn sendMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag) !void {
645643/// Asserts that the caller has already populated `s.result_failed_command`.
646644pub inline fn handleChildProcUnsupported(s: *Step, maker: *Maker) FailError!void {
647645 assert(s.result_failed_command != null);
648 if (!std.process.can_spawn) {
646 if (!std.process.can_spawn)
649647 return s.fail(maker, "unable to spawn process: host cannot spawn child processes", .{});
650 }
651648}
652649
653650/// Asserts that the caller has already populated `s.result_failed_command`.
......@@ -708,10 +705,10 @@ fn failWithCacheError(
708705
709706/// Prefer `writeManifestAndWatch` unless you already added watch inputs
710707/// separately from using the cache system.
711pub fn writeManifest(s: *Step, man: *Cache.Manifest) !void {
708pub fn writeManifest(s: *Step, maker: *Maker, man: *Cache.Manifest) !void {
712709 if (s.test_results.isSuccess()) {
713710 man.writeManifest() catch |err| {
714 try s.addError("unable to write cache manifest: {t}", .{err});
711 try s.addError(maker, "unable to write cache manifest: {t}", .{err});
715712 };
716713 }
717714}
......@@ -721,7 +718,7 @@ pub fn writeManifest(s: *Step, man: *Cache.Manifest) !void {
721718///
722719/// Must be accompanied with `cacheHitAndWatch`.
723720pub fn writeManifestAndWatch(s: *Step, maker: *Maker, man: *Cache.Manifest) !void {
724 try writeManifest(s, man);
721 try writeManifest(s, maker, man);
725722 try setWatchInputsFromManifest(s, maker, man);
726723}
727724
lib/compiler/Maker/Step/Run.zig+293-209
......@@ -16,6 +16,7 @@ const allocPrint = std.fmt.allocPrint;
1616
1717const Step = @import("../Step.zig");
1818const Maker = @import("../../Maker.zig");
19const Fuzz = @import("../../Maker/Fuzz.zig");
1920
2021/// If this is a Zig unit test binary, this tracks the names of the unit
2122/// tests that are also fuzz tests. Indexes cannot be used as they may
......@@ -31,6 +32,8 @@ rebuilt_executable: ?Path = null,
3132argv: std.ArrayList([]const u8) = .empty,
3233/// Persisted to reuse memory on subsequent calls to `make`.
3334output_placeholders: std.ArrayList(IndexedOutput) = .empty,
35/// Persisted to reuse memory on subsequent calls to `make`.
36environ_map: std.process.Environ.Map = .{ .array_hash_map = .empty, .allocator = undefined },
3437
3538pub fn make(
3639 run: *Run,
......@@ -67,6 +70,8 @@ pub fn make(
6770 man.hash.add(conf_run.flags.color);
6871 man.hash.add(conf_run.flags.disable_zig_progress);
6972
73 var dep_file_count: usize = 0;
74
7075 for (conf_run.args.slice) |arg_index| {
7176 const arg = arg_index.get(conf);
7277 try argv_list.ensureUnusedCapacity(gpa, 1);
......@@ -157,6 +162,9 @@ pub fn make(
157162 man.hash.addBytesZ(basename);
158163 man.hash.addBytesZ(suffix);
159164
165 man.hash.add(arg.flags.dep_file);
166 dep_file_count += @intFromBool(arg.flags.dep_file);
167
160168 // Add a placeholder into the argument list because we need the
161169 // manifest hash to be updated with all arguments before the
162170 // object directory is computed.
......@@ -220,145 +228,95 @@ pub fn make(
220228
221229 const has_side_effects = conf_run.flags.has_side_effects;
222230
223 if (true) @panic("TODO");
224
225231 if (!has_side_effects and try step.cacheHitAndWatch(maker, &man)) {
226 // cache hit, skip running command
232 // Cache hit; skip running command.
227233 const digest = man.final();
228
229 try populateGeneratedPaths(
230 arena,
231 output_placeholders.items,
232 &conf_run,
233 cache_root,
234 &digest,
235 );
236
234 try populateGeneratedStdIo(maker, &conf_run, cache_root, &digest);
235 try populateGeneratedPaths(maker, output_placeholders.items, cache_root, &digest);
237236 step.result_cached = true;
238237 return;
239238 }
240239
241 const dep_output_file = conf_run.dep_output_file orelse {
242 // We already know the final output paths, use them directly.
243 const digest = if (has_side_effects)
244 man.hash.final()
245 else
246 man.final();
247
248 try populateGeneratedPaths(
249 arena,
250 output_placeholders.items,
251 &conf_run,
252 cache_root,
253 &digest,
254 );
255
240 if (dep_file_count == 0) {
241 // We already know the final output paths; use them directly.
242 const digest = if (has_side_effects) man.hash.final() else man.final();
256243 const output_dir_path = "o" ++ Dir.path.sep_str ++ &digest;
257 for (output_placeholders.items) |placeholder| {
258 const output_sub_path = graph.pathJoin(&.{ output_dir_path, placeholder.output.basename });
259 const output_sub_dir_path = switch (placeholder.tag) {
260 .output_file => Dir.path.dirname(output_sub_path).?,
261 .output_directory => output_sub_path,
262 else => unreachable,
263 };
264 cache_root.handle.createDirPath(io, output_sub_dir_path) catch |err| {
265 return step.fail(maker, "unable to make path '{f}{s}': {t}", .{
266 cache_root, output_sub_dir_path, err,
267 });
268 };
269 const arg_output_path = try convertPathArg(run_index, maker, .{
270 .root_dir = .cwd(),
271 .sub_path = placeholder.output.generated_file.getPath(),
272 });
273 argv_list.items[placeholder.index] = if (placeholder.output.prefix.len == 0)
274 arg_output_path
275 else
276 try allocPrint(arena, "{s}{s}", .{ placeholder.output.prefix, arg_output_path });
277 }
278
279 try runCommand(run, maker, progress_node, argv_list.items, has_side_effects, output_dir_path, null);
280 if (!has_side_effects) try step.writeManifestAndWatch(&man);
244 try populateGeneratedStdIo(maker, &conf_run, cache_root, &digest);
245 try populateGeneratedPathsCreateDirs(run, run_index, maker, output_dir_path);
246 try runCommand(run, run_index, maker, progress_node, argv_list.items, has_side_effects, output_dir_path, null);
247 if (!has_side_effects) try step.writeManifestAndWatch(maker, &man);
281248 return;
282 };
249 }
283250
284 // We do not know the final output paths yet, use temp paths to run the command.
251 // We do not know the final output paths yet; use temporary directory to run the command.
285252 var rand_int: u64 = undefined;
286253 io.random(@ptrCast(&rand_int));
287254 const tmp_dir_path = "tmp" ++ Dir.path.sep_str ++ std.fmt.hex(rand_int);
288255
256 try populateGeneratedPathsCreateDirs(run, run_index, maker, tmp_dir_path);
257 try runCommand(run, run_index, maker, progress_node, argv_list.items, has_side_effects, tmp_dir_path, null);
258
289259 for (output_placeholders.items) |placeholder| {
290 const output_components = .{ tmp_dir_path, placeholder.output.basename };
291 const output_sub_path = graph.pathJoin(&output_components);
292 const output_sub_dir_path = switch (placeholder.tag) {
293 .output_file => Dir.path.dirname(output_sub_path).?,
294 .output_directory => output_sub_path,
260 const arg = placeholder.arg_index.get(conf);
261 switch (arg.flags.tag) {
262 .output_file => if (arg.flags.dep_file) {
263 const generated_path = maker.generatedPath(arg.generated.value.?).*;
264 const result = if (has_side_effects)
265 man.addDepFile(generated_path.root_dir.handle, generated_path.sub_path)
266 else
267 man.addDepFilePost(generated_path.root_dir.handle, generated_path.sub_path);
268 result catch |err| switch (err) {
269 error.OutOfMemory, error.Canceled => |e| return e,
270 else => |e| return step.fail(maker, "failed adding to cache the file {f}: {t}", .{
271 generated_path, e,
272 }),
273 };
274 },
275 .output_directory => continue,
295276 else => unreachable,
296 };
297 cache_root.handle.createDirPath(io, output_sub_dir_path) catch |err| {
298 return step.fail(maker, "unable to make path '{f}{s}': {t}", .{
299 cache_root, output_sub_dir_path, err,
300 });
301 };
302 const raw_output_path: Path = .{
303 .root_dir = cache_root,
304 .sub_path = graph.pathJoin(&output_components),
305 };
306 placeholder.output.generated_file.path = raw_output_path.toString(arena) catch @panic("OOM");
307 argv_list.items[placeholder.index] = try mem.concat(arena, u8, .{
308 placeholder.output.prefix,
309 try convertPathArg(run_index, maker, raw_output_path),
310 });
277 }
311278 }
312279
313 try runCommand(run, maker, progress_node, argv_list.items, has_side_effects, tmp_dir_path, null);
314
315 const dep_file_dir = Dir.cwd();
316 const dep_file_basename = dep_output_file.generated_file.getPath2(graph, step);
317 if (has_side_effects)
318 try man.addDepFile(dep_file_dir, dep_file_basename)
319 else
320 try man.addDepFilePost(dep_file_dir, dep_file_basename);
321
322 const digest = if (has_side_effects)
323 man.hash.final()
324 else
325 man.final();
280 const digest = if (has_side_effects) man.hash.final() else man.final();
326281
327282 const any_output = output_placeholders.items.len > 0 or
328 conf_run.captured_stdout != null or conf_run.captured_stderr != null;
283 conf_run.captured_stdout.value != null or conf_run.captured_stderr.value != null;
329284
330 // Rename into place
331285 if (any_output) {
332 const o_sub_path = "o" ++ Dir.path.sep_str ++ &digest;
333
334 cache_root.handle.rename(tmp_dir_path, cache_root.handle, o_sub_path, io) catch |err| switch (err) {
335 Dir.RenameError.DirNotEmpty => {
336 cache_root.handle.deleteTree(io, o_sub_path) catch |del_err| {
337 return step.fail(maker, "unable to remove dir '{f}'{s}: {t}", .{
338 cache_root, tmp_dir_path, del_err,
339 });
340 };
341 cache_root.handle.rename(tmp_dir_path, cache_root.handle, o_sub_path, io) catch |retry_err| {
342 return step.fail(maker, "unable to rename dir '{f}{s}' to '{f}{s}': {t}", .{
343 cache_root, tmp_dir_path, cache_root, o_sub_path, retry_err,
344 });
345 };
286 // Rename into place.
287 const tmp_path: Path = .{ .root_dir = cache_root, .sub_path = tmp_dir_path };
288 const dst_path: Path = .{ .root_dir = cache_root, .sub_path = "o" ++ Dir.path.sep_str ++ &digest };
289 Dir.rename(
290 tmp_path.root_dir.handle,
291 tmp_path.sub_path,
292 dst_path.root_dir.handle,
293 dst_path.sub_path,
294 io,
295 ) catch |err| switch (err) {
296 error.DirNotEmpty => {
297 dst_path.root_dir.handle.deleteTree(io, dst_path.sub_path) catch |del_err|
298 return step.fail(maker, "failed to remove tree {f}: {t}", .{ dst_path, del_err });
299
300 Dir.rename(
301 tmp_path.root_dir.handle,
302 tmp_path.sub_path,
303 dst_path.root_dir.handle,
304 dst_path.sub_path,
305 io,
306 ) catch |retry_err| return step.fail(maker, "failed to rename directory {f} to {f}: {t}", .{
307 tmp_path, dst_path, retry_err,
308 });
346309 },
347 else => return step.fail(maker, "unable to rename dir '{f}{s}' to '{f}{s}': {t}", .{
348 cache_root, tmp_dir_path, cache_root, o_sub_path, err,
310 else => return step.fail(maker, "failed to rename directory {f} to {f}: {t}", .{
311 tmp_path, dst_path, err,
349312 }),
350313 };
351314 }
352315
353 if (!has_side_effects) try step.writeManifestAndWatch(&man);
316 if (!has_side_effects) try step.writeManifestAndWatch(maker, &man);
354317
355 try populateGeneratedPaths(
356 arena,
357 output_placeholders.items,
358 &conf_run,
359 cache_root,
360 &digest,
361 );
318 try populateGeneratedStdIo(maker, &conf_run, cache_root, &digest);
319 try populateGeneratedPaths(maker, output_placeholders.items, cache_root, &digest);
362320}
363321
364322/// Reads stdout of a Zig test process until a termination condition is reached:
......@@ -918,9 +876,12 @@ const FuzzTestRunner = struct {
918876 }
919877
920878 fn saveCrash(f: *FuzzTestRunner, id: u32, term: process.Child.Term) !void {
879 const fuzz = f.context.fuzz;
880 const maker = fuzz.maker;
921881 const step = &f.run.step;
922 const b = step.owner;
923 const io = b.graph.io;
882 const graph = maker.graph;
883 const io = graph.io;
884 const cache_root = graph.local_cache_root;
924885
925886 if (f.coverage_id == null) return;
926887
......@@ -938,7 +899,7 @@ const FuzzTestRunner = struct {
938899 }) {
939900 const name_prefix = "f" ++ Io.Dir.path.sep_str ++ "in";
940901 in_name = std.fmt.bufPrint(&in_name_buf, name_prefix ++ "{x}", .{i}) catch unreachable;
941 in_f = b.cache_root.handle.openFile(io, in_name, .{
902 in_f = cache_root.handle.openFile(io, in_name, .{
942903 .lock = .exclusive,
943904 .lock_nonblocking = true,
944905 }) catch |e| switch (e) {
......@@ -946,7 +907,7 @@ const FuzzTestRunner = struct {
946907 error.WouldBlock => continue, // Can not be from
947908 // the crashed instance since it is still locked.
948909 else => return step.fail("failed to open file '{f}{s}': {t}", .{
949 b.cache_root, in_name, e,
910 cache_root, in_name, e,
950911 }),
951912 };
952913
......@@ -955,7 +916,7 @@ const FuzzTestRunner = struct {
955916 in_f.close(io);
956917 switch (e) {
957918 error.ReadFailed => return step.fail("failed to read file '{f}{s}': {t}", .{
958 b.cache_root, in_name, in_r.err.?,
919 cache_root, in_name, in_r.err.?,
959920 }),
960921 error.EndOfStream => continue,
961922 }
......@@ -974,10 +935,10 @@ const FuzzTestRunner = struct {
974935
975936 // Save it to a seperate file
976937 const crash_name = "f" ++ Io.Dir.path.sep_str ++ "crash";
977 const out = b.cache_root.handle.createFile(io, crash_name, .{
938 const out = cache_root.handle.createFile(io, crash_name, .{
978939 .lock = .exclusive, // Multiple run steps could have found a crash at the same time
979940 }) catch |e| return step.fail("failed to create file '{f}{s}': {t}", .{
980 b.cache_root, crash_name, e,
941 cache_root, crash_name, e,
981942 });
982943 defer out.close(io);
983944
......@@ -985,17 +946,17 @@ const FuzzTestRunner = struct {
985946 var out_w = out.writerStreaming(io, &out_w_buf);
986947 _ = out_w.interface.sendFileAll(&in_r, .limited(header.len)) catch |e| switch (e) {
987948 error.ReadFailed => return step.fail("failed to read file '{f}{s}': {t}", .{
988 b.cache_root, in_name, in_r.err.?,
949 cache_root, in_name, in_r.err.?,
989950 }),
990951 error.WriteFailed => return step.fail("failed to write file '{f}{s}': {t}", .{
991 b.cache_root, crash_name, out_w.err.?,
952 cache_root, crash_name, out_w.err.?,
992953 }),
993954 };
994955
995956 return f.run.step.fail("test '{s}' {f}; input saved to '{f}{s}'", .{
996957 f.run.fuzz_tests.items[header.test_i],
997958 fmtTerm(term),
998 b.cache_root,
959 cache_root,
999960 crash_name,
1000961 });
1001962 }
......@@ -1492,54 +1453,85 @@ pub fn rerunInFuzzMode(
14921453 const maker = fuzz.maker;
14931454 const graph = maker.graph;
14941455 const step = &run.step;
1495 const b = step.owner;
14961456 const io = graph.io;
1497 const arena = b.allocator;
1498 var argv_list: std.ArrayList([]const u8) = .empty;
1499 for (run.argv.items) |arg| {
1500 switch (arg) {
1501 .bytes => |bytes| {
1502 try argv_list.append(arena, bytes);
1457 const arena = graph.arena; // TODO don't leak into the process arena
1458 const gpa = maker.gpa;
1459 const conf = &maker.scanned_config.configuration;
1460 const conf_step = run_index.ptr(conf);
1461 const conf_run = conf_step.extended.get(conf.extra).run;
1462 const argv_list = &run.argv;
1463
1464 argv_list.clearRetainingCapacity();
1465
1466 for (conf_run.args.slice) |arg_index| {
1467 const arg = arg_index.get(conf);
1468 try argv_list.ensureUnusedCapacity(gpa, 1);
1469 switch (arg.flags.tag) {
1470 .string => {
1471 const prefix = arg.prefix.value.?.slice(conf);
1472 argv_list.appendAssumeCapacity(prefix);
15031473 },
1504 .lazy_path => |file| {
1505 const file_path = file.lazy_path.getPath3(b, step);
1506 try argv_list.append(arena, b.fmt("{s}{s}", .{ file.prefix, convertPathArg(run_index, maker, file_path) }));
1474 .path_file => {
1475 const prefix = if (arg.prefix.value) |p| p.slice(conf) else "";
1476 const suffix = if (arg.suffix.value) |p| p.slice(conf) else "";
1477 const file_path = try maker.resolveLazyPathIndex(arena, arg.path.value.?, run_index);
1478 argv_list.appendAssumeCapacity(try mem.concat(arena, u8, &.{
1479 prefix, try convertPathArg(run_index, maker, file_path), suffix,
1480 }));
15071481 },
1508 .decorated_directory => |dd| {
1509 const file_path = dd.lazy_path.getPath3(b, step);
1510 try argv_list.append(arena, b.fmt("{s}{s}{s}", .{ dd.prefix, convertPathArg(run_index, maker, file_path), dd.suffix }));
1482 .path_directory => {
1483 const prefix = if (arg.prefix.value) |p| p.slice(conf) else "";
1484 const suffix = if (arg.suffix.value) |p| p.slice(conf) else "";
1485 const file_path = try maker.resolveLazyPathIndex(arena, arg.path.value.?, run_index);
1486 const resolved_arg = try mem.concat(arena, u8, &.{
1487 prefix, try convertPathArg(run_index, maker, file_path), suffix,
1488 });
1489 argv_list.appendAssumeCapacity(resolved_arg);
15111490 },
1512 .file_content => |file_plp| {
1513 const file_path = file_plp.lazy_path.getPath3(b, step);
1491 .file_content => {
1492 const prefix = if (arg.prefix.value) |p| p.slice(conf) else "";
1493 const suffix = if (arg.suffix.value) |p| p.slice(conf) else "";
1494 const file_path = try maker.resolveLazyPathIndex(arena, arg.path.value.?, run_index);
15141495
15151496 var result: std.Io.Writer.Allocating = .init(arena);
1516 errdefer result.deinit();
1517 result.writer.writeAll(file_plp.prefix) catch return error.OutOfMemory;
1497 result.writer.writeAll(prefix) catch return error.OutOfMemory;
15181498
1519 const file = try file_path.root_dir.handle.openFile(io, file_path.subPathOrDot(), .{});
1499 const file = file_path.root_dir.handle.openFile(io, file_path.sub_path, .{}) catch |err|
1500 return step.fail(maker, "unable to open input file {f}: {t}", .{ file_path, err });
15201501 defer file.close(io);
15211502
1522 var buf: [1024]u8 = undefined;
1523 var file_reader = file.reader(io, &buf);
1503 var file_reader = file.reader(io, &.{});
15241504 _ = file_reader.interface.streamRemaining(&result.writer) catch |err| switch (err) {
1525 error.ReadFailed => return file_reader.err.?,
1505 error.ReadFailed => switch (file_reader.err.?) {
1506 error.Canceled => |e| return e,
1507 else => |e| return step.fail(maker, "failed to read from {f}: {t}", .{ file_path, e }),
1508 },
15261509 error.WriteFailed => return error.OutOfMemory,
15271510 };
1511 result.writer.writeAll(suffix) catch return error.OutOfMemory;
15281512
1529 try argv_list.append(arena, result.written());
1513 argv_list.appendAssumeCapacity(result.written());
15301514 },
1531 .artifact => |pa| {
1532 const artifact = pa.artifact;
1533 const file_path: []const u8 = p: {
1534 if (artifact == run.producer.?) break :p b.fmt("{f}", .{run.rebuilt_executable.?});
1535 break :p artifact.installed_path orelse artifact.generated_bin.?.path.?;
1536 };
1537 try argv_list.append(arena, b.fmt("{s}{s}", .{
1538 pa.prefix,
1539 convertPathArg(run_index, maker, .{ .root_dir = .cwd(), .sub_path = file_path }),
1515 .artifact => {
1516 const prefix = if (arg.prefix.value) |p| p.slice(conf) else "";
1517 const suffix = if (arg.suffix.value) |p| p.slice(conf) else "";
1518 const producer_index = arg.producer.value.?;
1519 const producer_step = producer_index.ptr(conf);
1520 const producer = producer_step.extended.get(conf.extra).compile;
1521 const producer_make_comp_step = maker.stepByIndex(producer_index);
1522 const producer_make_comp = &producer_make_comp_step.extended.compile;
1523 const file_path: Path = if (producer_index == conf_run.producer.value.?)
1524 run.rebuilt_executable.?
1525 else
1526 producer_make_comp.installed_path orelse
1527 maker.generatedPath(producer.generated_bin.value.?).*;
1528 argv_list.appendAssumeCapacity(try mem.concat(arena, u8, &.{
1529 prefix, try convertPathArg(run_index, maker, file_path), suffix,
15401530 }));
15411531 },
1542 .output_file, .output_directory => unreachable,
1532 .output_file => unreachable,
1533 .output_directory => unreachable,
1534 .cli_rest_positionals => unreachable,
15431535 }
15441536 }
15451537
......@@ -1552,7 +1544,7 @@ pub fn rerunInFuzzMode(
15521544 var rand_int: u64 = undefined;
15531545 io.random(@ptrCast(&rand_int));
15541546 const tmp_dir_path = "tmp" ++ Dir.path.sep_str ++ std.fmt.hex(rand_int);
1555 try runCommand(run, maker, prog_node, argv_list.items, has_side_effects, tmp_dir_path, .{
1547 try runCommand(run, run_index, maker, prog_node, argv_list.items, has_side_effects, tmp_dir_path, .{
15561548 .fuzz = fuzz,
15571549 });
15581550}
......@@ -1560,28 +1552,94 @@ pub fn rerunInFuzzMode(
15601552const CapturedStdIo = void; // TODO get it from Configuration
15611553
15621554fn populateGeneratedPaths(
1563 arena: std.mem.Allocator,
1555 maker: *Maker,
15641556 output_placeholders: []const IndexedOutput,
1565 conf_run: *const Configuration.Step.Run,
15661557 cache_root: Cache.Directory,
15671558 digest: *const Cache.HexDigest,
15681559) !void {
1560 const conf = &maker.scanned_config.configuration;
1561 const graph = maker.graph;
1562 const arena = graph.arena; // TODO don't leak into the process arena
1563
15691564 for (output_placeholders) |placeholder| {
1570 placeholder.output.generated_file.path = try cache_root.join(arena, &.{
1571 "o", digest, placeholder.output.basename,
1572 });
1565 const arg = placeholder.arg_index.get(conf);
1566 maker.generatedPath(arg.generated.value.?).* = .{
1567 .root_dir = cache_root,
1568 .sub_path = try Dir.path.join(arena, &.{
1569 "o", digest, arg.basename.value.?.slice(conf),
1570 }),
1571 };
1572 }
1573}
1574
1575fn populateGeneratedPathsCreateDirs(
1576 run: *Run,
1577 run_index: Configuration.Step.Index,
1578 maker: *Maker,
1579 output_dir_path: []const u8,
1580) !void {
1581 const step = maker.stepByIndex(run_index);
1582 const conf = &maker.scanned_config.configuration;
1583 const graph = maker.graph;
1584 const io = graph.io;
1585 const arena = graph.arena; // TODO don't leak into the process arena
1586 const cache_root = graph.local_cache_root;
1587 const argv = run.argv.items;
1588
1589 for (run.output_placeholders.items) |placeholder| {
1590 const arg = placeholder.arg_index.get(conf);
1591 const prefix = if (arg.prefix.value) |p| p.slice(conf) else "";
1592 const suffix = if (arg.suffix.value) |p| p.slice(conf) else "";
1593 const basename = arg.basename.value.?.slice(conf);
1594
1595 const generated_path: Path = .{
1596 .root_dir = cache_root,
1597 .sub_path = try Dir.path.join(arena, &.{ output_dir_path, basename }),
1598 };
1599 const create_path: Path = .{
1600 .root_dir = cache_root,
1601 .sub_path = switch (arg.flags.tag) {
1602 .output_file => Dir.path.dirname(generated_path.sub_path).?,
1603 .output_directory => generated_path.sub_path,
1604 else => unreachable,
1605 },
1606 };
1607 create_path.root_dir.handle.createDirPath(io, create_path.sub_path) catch |err|
1608 return step.fail(maker, "unable to make path {f}: {t}", .{ create_path, err });
1609
1610 maker.generatedPath(arg.generated.value.?).* = generated_path;
1611
1612 const arg_output_path = try convertPathArg(run_index, maker, generated_path);
1613 argv[placeholder.index] = try mem.concat(arena, u8, &.{ prefix, arg_output_path, suffix });
15731614 }
1615}
1616
1617fn populateGeneratedStdIo(
1618 maker: *Maker,
1619 conf_run: *const Configuration.Step.Run,
1620 cache_root: Cache.Directory,
1621 digest: *const Cache.HexDigest,
1622) !void {
1623 const conf = &maker.scanned_config.configuration;
1624 const graph = maker.graph;
1625 const arena = graph.arena; // TODO don't leak into the process arena
15741626
15751627 if (conf_run.captured_stdout.value) |captured| {
1576 captured.output.generated_file.path = try cache_root.join(arena, &.{
1577 "o", digest, captured.output.basename,
1578 });
1628 maker.generatedPath(captured.generated_file).* = .{
1629 .root_dir = cache_root,
1630 .sub_path = try Dir.path.join(arena, &.{
1631 "o", digest, captured.basename.slice(conf),
1632 }),
1633 };
15791634 }
15801635
15811636 if (conf_run.captured_stderr.value) |captured| {
1582 captured.output.generated_file.path = try cache_root.join(arena, &.{
1583 "o", digest, captured.output.basename,
1584 });
1637 maker.generatedPath(captured.generated_file).* = .{
1638 .root_dir = cache_root,
1639 .sub_path = try Dir.path.join(arena, &.{
1640 "o", digest, captured.basename.slice(conf),
1641 }),
1642 };
15851643 }
15861644}
15871645
......@@ -1600,11 +1658,12 @@ fn fmtTerm(term: ?process.Child.Term) std.fmt.Alt(?process.Child.Term, formatTer
16001658}
16011659
16021660const FuzzContext = struct {
1603 fuzz: *std.Build.Fuzz,
1661 fuzz: *Fuzz,
16041662};
16051663
16061664fn runCommand(
16071665 run: *Run,
1666 run_index: Configuration.Step.Index,
16081667 maker: *Maker,
16091668 progress_node: std.Progress.Node,
16101669 argv: []const []const u8,
......@@ -1615,30 +1674,45 @@ fn runCommand(
16151674 const graph = maker.graph;
16161675 const arena = graph.arena; // TODO don't leak into process arena
16171676 const gpa = maker.gpa;
1618 const step = &run.step;
1619 const b = step.owner;
1677 const step = maker.stepByIndex(run_index);
16201678 const io = graph.io;
1679 const cache_root = graph.local_cache_root;
1680 const conf = &maker.scanned_config.configuration;
1681 const conf_step = run_index.ptr(conf);
1682 const conf_run = conf_step.extended.get(conf.extra).run;
1683 const environ_map = &run.environ_map;
16211684
1622 const cwd: process.Child.Cwd = if (run.cwd) |lazy_cwd| .{ .path = lazy_cwd.getPath2(b, step) } else .inherit;
1623
1624 try step.handleChildProcUnsupported();
1625 try Step.handleVerbose(step.owner, cwd, run.environ_map, argv);
1685 const cwd: process.Child.Cwd = if (conf_run.cwd.value) |lazy_cwd|
1686 .{ .path = try maker.resolveLazyPathIndexAbs(arena, lazy_cwd, run_index) }
1687 else
1688 .inherit;
16261689
1627 const allow_skip = switch (run.stdio) {
1628 .check, .zig_test => run.skip_foreign_checks,
1690 const allow_skip = switch (conf_run.flags.stdio) {
1691 .check, .zig_test => conf_run.flags.skip_foreign_checks,
16291692 else => false,
16301693 };
16311694
1632 var interp_argv = std.array_list.Managed([]const u8).init(b.allocator);
1633 defer interp_argv.deinit();
1695 var interp_argv: std.ArrayList([]const u8) = .empty;
1696
1697 // `environ_map` is initialized with an undefined `allocator` field; lazily
1698 // initialize it here.
1699 environ_map.allocator = gpa;
1700 // In either case we add to this mutatable data structure so that we can
1701 // tweak the environment below.
1702 environ_map.clearRetainingCapacity();
1703 if (conf_run.environ_map.value) |env_map_index| {
1704 const conf_env_map = env_map_index.get(conf);
1705 for (conf_env_map.keys.slice(conf), conf_env_map.values.slice(conf)) |k, v| {
1706 try environ_map.put(k.slice(conf), v.slice(conf));
1707 }
1708 } else {
1709 try environ_map.putAll(&graph.environ_map);
1710 }
1711 try graph.handleVerbose(cwd, environ_map, argv);
16341712
1635 var environ_map: EnvMap = env: {
1636 const orig = run.environ_map orelse &graph.environ_map;
1637 break :env try orig.clone(gpa);
1638 };
1639 defer environ_map.deinit();
1713 if (true) @panic("TODO");
16401714
1641 const opt_generic_result = spawnChildAndCollect(run, maker, progress_node, argv, &environ_map, has_side_effects, fuzz_context) catch |err| term: {
1715 const opt_generic_result = spawnChildAndCollect(run_index, run, maker, progress_node, argv, &environ_map, has_side_effects, fuzz_context) catch |err| term: {
16421716 // InvalidExe: cpu arch mismatch
16431717 // FileNotFound: can happen with a wrong dynamic linker path
16441718 if (err == error.InvalidExe or err == error.FileNotFound) interpret: {
......@@ -1660,7 +1734,7 @@ fn runCommand(
16601734 (root_target.isGnuLibC() or (root_target.isMuslLibC() and exe.linkage == .dynamic));
16611735 const other_target = exe.root_module.resolved_target.?.result;
16621736 switch (std.zig.system.getExternalExecutor(io, &graph.host.result, &other_target, .{
1663 .qemu_fixes_dl = need_cross_libc and b.libc_runtimes_dir != null,
1737 .qemu_fixes_dl = need_cross_libc and graph.libc_runtimes_dir != null,
16641738 .link_libc = exe.is_linking_libc,
16651739 })) {
16661740 .native, .rosetta => {
......@@ -1668,7 +1742,7 @@ fn runCommand(
16681742 break :interpret;
16691743 },
16701744 .wine => |bin_name| {
1671 if (b.enable_wine) {
1745 if (graph.enable_wine) {
16721746 try interp_argv.append(bin_name);
16731747 try interp_argv.appendSlice(argv);
16741748
......@@ -1682,21 +1756,21 @@ fn runCommand(
16821756 }
16831757 },
16841758 .qemu => |bin_name| {
1685 if (b.enable_qemu) {
1759 if (graph.enable_qemu) {
16861760 try interp_argv.append(bin_name);
16871761
16881762 if (need_cross_libc) {
1689 if (b.libc_runtimes_dir) |dir| {
1763 if (graph.libc_runtimes_dir) |dir| {
16901764 try interp_argv.append("-L");
1691 try interp_argv.append(b.pathJoin(&.{
1765 try interp_argv.append(try Dir.path.join(arena, &.{
16921766 dir,
16931767 try if (root_target.isGnuLibC()) std.zig.target.glibcRuntimeTriple(
1694 b.allocator,
1768 arena,
16951769 root_target.cpu.arch,
16961770 root_target.os.tag,
16971771 root_target.abi,
16981772 ) else if (root_target.isMuslLibC()) std.zig.target.muslRuntimeTriple(
1699 b.allocator,
1773 arena,
17001774 root_target.cpu.arch,
17011775 root_target.abi,
17021776 ) else unreachable,
......@@ -1708,7 +1782,7 @@ fn runCommand(
17081782 } else return failForeign(run, "-fqemu", argv[0], exe);
17091783 },
17101784 .darling => |bin_name| {
1711 if (b.enable_darling) {
1785 if (graph.enable_darling) {
17121786 try interp_argv.append(bin_name);
17131787 try interp_argv.appendSlice(argv);
17141788 } else {
......@@ -1716,7 +1790,7 @@ fn runCommand(
17161790 }
17171791 },
17181792 .wasmtime => |bin_name| {
1719 if (b.enable_wasmtime) {
1793 if (graph.enable_wasmtime) {
17201794 try interp_argv.append(bin_name);
17211795 try interp_argv.append("--dir=.");
17221796 // Wasmtime doeesn't inherit environment variables from the parent process
......@@ -1743,8 +1817,8 @@ fn runCommand(
17431817 .bad_os_or_cpu => {
17441818 if (allow_skip) return error.MakeSkipped;
17451819
1746 const host_name = try graph.host.result.zigTriple(b.allocator);
1747 const foreign_name = try root_target.zigTriple(b.allocator);
1820 const host_name = try graph.host.result.zigTriple(arena);
1821 const foreign_name = try root_target.zigTriple(arena);
17481822
17491823 return step.fail(maker, "the host system ({s}) is unable to execute binaries from the target ({s})", .{
17501824 host_name, foreign_name,
......@@ -1761,7 +1835,7 @@ fn runCommand(
17611835 step.result_failed_command = null;
17621836 try Step.handleVerbose(step.owner, cwd, run.environ_map, interp_argv.items);
17631837
1764 break :term spawnChildAndCollect(run, maker, progress_node, interp_argv.items, &environ_map, has_side_effects, fuzz_context) catch |e| {
1838 break :term spawnChildAndCollect(run_index, run, maker, progress_node, interp_argv.items, &environ_map, has_side_effects, fuzz_context) catch |e| {
17651839 if (!run.failing_to_execute_foreign_is_an_error) return error.MakeSkipped;
17661840 if (e == error.MakeFailed) return error.MakeFailed; // error already reported
17671841 return step.fail(maker, "unable to spawn interpreter {s}: {t}", .{ interp_argv.items[0], e });
......@@ -1800,14 +1874,14 @@ fn runCommand(
18001874 }) |stream| {
18011875 if (stream.captured) |captured| {
18021876 const output_components = .{ output_dir_path, captured.output.basename };
1803 const output_path = try b.cache_root.join(arena, &output_components);
1877 const output_path = try cache_root.join(arena, &output_components);
18041878 captured.output.generated_file.path = output_path;
18051879
1806 const sub_path = b.pathJoin(&output_components);
1880 const sub_path = try Dir.path.join(arena, &output_components);
18071881 const sub_path_dirname = Dir.path.dirname(sub_path).?;
1808 b.cache_root.handle.createDirPath(io, sub_path_dirname) catch |err| {
1809 return step.fail(maker, "unable to make path '{f}{s}': {s}", .{
1810 b.cache_root, sub_path_dirname, @errorName(err),
1882 cache_root.handle.createDirPath(io, sub_path_dirname) catch |err| {
1883 return step.fail(maker, "unable to make path '{f}{s}': {t}", .{
1884 cache_root, sub_path_dirname, err,
18111885 });
18121886 };
18131887 const data = switch (captured.trim_whitespace) {
......@@ -1816,9 +1890,9 @@ fn runCommand(
18161890 .leading => mem.trimStart(u8, stream.bytes.?, &std.ascii.whitespace),
18171891 .trailing => mem.trimEnd(u8, stream.bytes.?, &std.ascii.whitespace),
18181892 };
1819 b.cache_root.handle.writeFile(io, .{ .sub_path = sub_path, .data = data }) catch |err| {
1820 return step.fail(maker, "unable to write file '{f}{s}': {s}", .{
1821 b.cache_root, sub_path, @errorName(err),
1893 cache_root.handle.writeFile(io, .{ .sub_path = sub_path, .data = data }) catch |err| {
1894 return step.fail(maker, "unable to write file '{f}{s}': {t}", .{
1895 cache_root, sub_path, err,
18221896 });
18231897 };
18241898 }
......@@ -1912,6 +1986,7 @@ const EvalGenericResult = struct {
19121986};
19131987
19141988fn spawnChildAndCollect(
1989 run_index: Configuration.Step.Index,
19151990 run: *Run,
19161991 maker: *Maker,
19171992 progress_node: std.Progress.Node,
......@@ -1920,25 +1995,34 @@ fn spawnChildAndCollect(
19201995 has_side_effects: bool,
19211996 fuzz_context: ?FuzzContext,
19221997) !?EvalGenericResult {
1923 const b = run.step.owner;
1998 const step = run.step;
19241999 const graph = maker.graph;
19252000 const gpa = maker.gpa;
19262001 const io = graph.io;
2002 const arena = graph.arena; // TODO don't leak into process arena
2003 const conf = &maker.scanned_config.configuration;
2004 const conf_step = run_index.ptr(conf);
2005 const conf_run = conf_step.extended.get(conf.extra).run;
19272006
19282007 if (fuzz_context != null) {
19292008 assert(!has_side_effects);
19302009 assert(run.stdio == .zig_test);
19312010 }
19322011
1933 const child_cwd: process.Child.Cwd = if (run.cwd) |lazy_cwd| .{ .path = lazy_cwd.getPath2(b, &run.step) } else .inherit;
2012 const child_cwd: process.Child.Cwd = if (conf_run.cwd) |lazy_cwd|
2013 .{ .path = try maker.resolveLazyPathIndexAbs(arena, lazy_cwd, run_index) }
2014 else
2015 .inherit;
19342016
19352017 // If an error occurs, it's caused by this command:
1936 assert(run.step.result_failed_command == null);
1937 run.step.result_failed_command = try Step.allocPrintCmd(gpa, child_cwd, .{
2018 assert(step.result_failed_command == null);
2019 step.result_failed_command = try Step.allocPrintCmd(gpa, child_cwd, .{
19382020 .child = environ_map,
19392021 .parent = &graph.environ_map,
19402022 }, argv);
19412023
2024 try step.handleChildProcUnsupported(maker);
2025
19422026 var spawn_options: process.SpawnOptions = .{
19432027 .argv = argv,
19442028 .cwd = child_cwd,
......@@ -1973,7 +2057,7 @@ fn spawnChildAndCollect(
19732057 error.Canceled => |e| return e,
19742058 else => |e| e,
19752059 };
1976 run.step.result_duration_ns = @intCast(started.untilNow(io).raw.nanoseconds);
2060 step.result_duration_ns = @intCast(started.untilNow(io).raw.nanoseconds);
19772061 try result;
19782062 return null;
19792063 } else {
......@@ -1993,7 +2077,7 @@ fn spawnChildAndCollect(
19932077 error.Canceled => |e| return e,
19942078 else => |e| e,
19952079 };
1996 run.step.result_duration_ns = @intCast(started.untilNow(io).raw.nanoseconds);
2080 step.result_duration_ns = @intCast(started.untilNow(io).raw.nanoseconds);
19972081 return try result;
19982082 }
19992083}
lib/compiler/configurer.zig+2-3
......@@ -455,7 +455,7 @@ const Serialize = struct {
455455 .producer = .{ .value = null },
456456 .generated = .{ .value = null },
457457 },
458 .output_file => |a| .{
458 .output_file, .output_file_dep => |a, tag| .{
459459 .flags = .{
460460 .tag = .output_file,
461461 .prefix = a.prefix.len != 0,
......@@ -464,7 +464,7 @@ const Serialize = struct {
464464 .path = false,
465465 .producer = false,
466466 .generated = true,
467 .dep_file = false,
467 .dep_file = tag == .output_file_dep,
468468 },
469469 .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null },
470470 .suffix = .{ .value = null },
......@@ -1023,7 +1023,6 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
10231023 break :e @enumFromInt(extra_index);
10241024 },
10251025 .check_file => @panic("TODO"),
1026 .check_object => @panic("TODO"),
10271026 .config_header => @panic("TODO"),
10281027 .objcopy => @panic("TODO"),
10291028 .options => @panic("TODO"),
lib/std/Build/Configuration.zig-11
......@@ -427,7 +427,6 @@ pub const Step = extern struct {
427427 max_rss: MaxRss,
428428 extended: Storage.Extended(Flags, union(Tag) {
429429 check_file: CheckFile,
430 check_object: CheckObject,
431430 compile: Compile,
432431 config_header: ConfigHeader,
433432 fail: Fail,
......@@ -462,7 +461,6 @@ pub const Step = extern struct {
462461
463462 pub const Tag = enum(u5) {
464463 check_file,
465 check_object,
466464 compile,
467465 config_header,
468466 fail,
......@@ -997,15 +995,6 @@ pub const Step = extern struct {
997995 };
998996 };
999997
1000 pub const CheckObject = struct {
1001 flags: @This().Flags,
1002
1003 pub const Flags = packed struct(u32) {
1004 tag: Tag = .check_object,
1005 _: u27 = 0,
1006 };
1007 };
1008
1009998 pub const ConfigHeader = struct {
1010999 flags: @This().Flags,
10111000
lib/std/Build/Step/Run.zig+3-9
......@@ -85,8 +85,6 @@ stdio_limit: std.Io.Limit,
8585captured_stdout: ?*CapturedStdIo,
8686captured_stderr: ?*CapturedStdIo,
8787
88dep_output_file: ?*Output,
89
9088has_side_effects: bool,
9189test_runner_mode: bool = false,
9290
......@@ -141,6 +139,7 @@ pub const Arg = union(enum) {
141139 file_content: PrefixedLazyPath,
142140 bytes: []const u8,
143141 output_file: *Output,
142 output_file_dep: *Output,
144143 output_directory: *Output,
145144 /// The arguments passed after "--" on the "zig build" CLI.
146145 cli_rest_positionals,
......@@ -203,7 +202,6 @@ pub fn create(owner: *std.Build, name: []const u8) *Run {
203202 .stdio_limit = .unlimited,
204203 .captured_stdout = null,
205204 .captured_stderr = null,
206 .dep_output_file = null,
207205 .has_side_effects = false,
208206 .producer = null,
209207 };
......@@ -476,12 +474,10 @@ pub fn addDepFileOutputArg(run: *Run, basename: []const u8) std.Build.LazyPath {
476474
477475/// Add a prefixed path argument to a dep file (.d) for the child process to
478476/// write its discovered additional dependencies.
479/// Only one dep file argument is allowed by instance.
480477pub fn addPrefixedDepFileOutputArg(run: *Run, prefix: []const u8, basename: []const u8) std.Build.LazyPath {
481478 const b = run.step.owner;
482479 const graph = b.graph;
483480 const arena = graph.arena;
484 assert(run.dep_output_file == null);
485481
486482 const dep_file = arena.create(Output) catch @panic("OOM");
487483 dep_file.* = .{
......@@ -490,9 +486,7 @@ pub fn addPrefixedDepFileOutputArg(run: *Run, prefix: []const u8, basename: []co
490486 .generated_file = graph.addGeneratedFile(&run.step),
491487 };
492488
493 run.dep_output_file = dep_file;
494
495 run.argv.append(arena, .{ .output_file = dep_file }) catch @panic("OOM");
489 run.argv.append(arena, .{ .output_file_dep = dep_file }) catch @panic("OOM");
496490
497491 return .{ .generated = .{ .index = dep_file.generated_file } };
498492}
......@@ -544,7 +538,7 @@ pub fn addPathDir(run: *Run, search_path: []const u8) void {
544538 .decorated_directory => false,
545539 .file_content => unreachable, // not allowed as first arg
546540 .bytes => |bytes| std.mem.endsWith(u8, bytes, ".exe"),
547 .output_file, .output_directory => false,
541 .output_file, .output_file_dep, .output_directory => false,
548542 };
549543 const key = if (use_wine) "WINEPATH" else "PATH";
550544 const prev_path = environ_map.get(key);