authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-15 01:27:23-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-07-15 01:27:23-07:00
log9d38e82b5c0f28ea6a2d8d31ebd73b6e2a8aad26
treeba3290d61fd4c856f73a14b6346c674a1a178ffb
parent583e698256a2a26f26738c983e319d76926ef048
parent445bd7a06fc34c9a59c6458774769bfaa2757a2f
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #20633 from ziglang/long-live-zig

make zig compiler processes live across rebuilds

27 files changed, 285 insertions(+), 105 deletions(-)

lib/compiler/build_runner.zig+21-3
...@@ -235,6 +235,10 @@ pub fn main() !void {...@@ -235,6 +235,10 @@ pub fn main() !void {
235 prominent_compile_errors = true;235 prominent_compile_errors = true;
236 } else if (mem.eql(u8, arg, "--watch")) {236 } else if (mem.eql(u8, arg, "--watch")) {
237 watch = true;237 watch = true;
238 } else if (mem.eql(u8, arg, "-fincremental")) {
239 graph.incremental = true;
240 } else if (mem.eql(u8, arg, "-fno-incremental")) {
241 graph.incremental = false;
238 } else if (mem.eql(u8, arg, "-fwine")) {242 } else if (mem.eql(u8, arg, "-fwine")) {
239 builder.enable_wine = true;243 builder.enable_wine = true;
240 } else if (mem.eql(u8, arg, "-fno-wine")) {244 } else if (mem.eql(u8, arg, "-fno-wine")) {
...@@ -406,8 +410,8 @@ pub fn main() !void {...@@ -406,8 +410,8 @@ pub fn main() !void {
406 // trigger a rebuild on all steps with modified inputs, as well as their410 // trigger a rebuild on all steps with modified inputs, as well as their
407 // recursive dependants.411 // recursive dependants.
408 var caption_buf: [std.Progress.Node.max_name_len]u8 = undefined;412 var caption_buf: [std.Progress.Node.max_name_len]u8 = undefined;
409 const caption = std.fmt.bufPrint(&caption_buf, "Watching {d} Directories", .{413 const caption = std.fmt.bufPrint(&caption_buf, "watching {d} directories, {d} processes", .{
410 w.dir_table.entries.len,414 w.dir_table.entries.len, countSubProcesses(run.step_stack.keys()),
411 }) catch &caption_buf;415 }) catch &caption_buf;
412 var debouncing_node = main_progress_node.start(caption, 0);416 var debouncing_node = main_progress_node.start(caption, 0);
413 var debounce_timeout: Watch.Timeout = .none;417 var debounce_timeout: Watch.Timeout = .none;
...@@ -440,6 +444,14 @@ fn markFailedStepsDirty(gpa: Allocator, all_steps: []const *Step) void {...@@ -440,6 +444,14 @@ fn markFailedStepsDirty(gpa: Allocator, all_steps: []const *Step) void {
440 };444 };
441}445}
442446
447fn countSubProcesses(all_steps: []const *Step) usize {
448 var count: usize = 0;
449 for (all_steps) |s| {
450 count += @intFromBool(s.getZigProcess() != null);
451 }
452 return count;
453}
454
443const Run = struct {455const Run = struct {
444 max_rss: u64,456 max_rss: u64,
445 max_rss_is_default: bool,457 max_rss_is_default: bool,
...@@ -1031,7 +1043,11 @@ fn workerMakeOneStep(...@@ -1031,7 +1043,11 @@ fn workerMakeOneStep(
1031 const sub_prog_node = prog_node.start(s.name, 0);1043 const sub_prog_node = prog_node.start(s.name, 0);
1032 defer sub_prog_node.end();1044 defer sub_prog_node.end();
10331045
1034 const make_result = s.make(sub_prog_node);1046 const make_result = s.make(.{
1047 .progress_node = sub_prog_node,
1048 .thread_pool = thread_pool,
1049 .watch = run.watch,
1050 });
10351051
1036 // No matter the result, we want to display error/warning messages.1052 // No matter the result, we want to display error/warning messages.
1037 const show_compile_errors = !run.prominent_compile_errors and1053 const show_compile_errors = !run.prominent_compile_errors and
...@@ -1212,6 +1228,8 @@ fn usage(b: *std.Build, out_stream: anytype) !void {...@@ -1212,6 +1228,8 @@ fn usage(b: *std.Build, out_stream: anytype) !void {
1212 \\ --fetch Exit after fetching dependency tree1228 \\ --fetch Exit after fetching dependency tree
1213 \\ --watch Continuously rebuild when source files are modified1229 \\ --watch Continuously rebuild when source files are modified
1214 \\ --debounce <ms> Delay before rebuilding after changed file detected1230 \\ --debounce <ms> Delay before rebuilding after changed file detected
1231 \\ -fincremental Enable incremental compilation
1232 \\ -fno-incremental Disable incremental compilation
1215 \\1233 \\
1216 \\Project-Specific Options:1234 \\Project-Specific Options:
1217 \\1235 \\
lib/std/Build.zig+3-2
...@@ -120,6 +120,7 @@ pub const Graph = struct {...@@ -120,6 +120,7 @@ pub const Graph = struct {
120 needed_lazy_dependencies: std.StringArrayHashMapUnmanaged(void) = .{},120 needed_lazy_dependencies: std.StringArrayHashMapUnmanaged(void) = .{},
121 /// Information about the native target. Computed before build() is invoked.121 /// Information about the native target. Computed before build() is invoked.
122 host: ResolvedTarget,122 host: ResolvedTarget,
123 incremental: ?bool = null,
123};124};
124125
125const AvailableDeps = []const struct { []const u8, []const u8 };126const AvailableDeps = []const struct { []const u8, []const u8 };
...@@ -1078,8 +1079,8 @@ pub fn getUninstallStep(b: *Build) *Step {...@@ -1078,8 +1079,8 @@ pub fn getUninstallStep(b: *Build) *Step {
1078 return &b.uninstall_tls.step;1079 return &b.uninstall_tls.step;
1079}1080}
10801081
1081fn makeUninstall(uninstall_step: *Step, prog_node: std.Progress.Node) anyerror!void {1082fn makeUninstall(uninstall_step: *Step, options: Step.MakeOptions) anyerror!void {
1082 _ = prog_node;1083 _ = options;
1083 const uninstall_tls: *TopLevelStep = @fieldParentPtr("step", uninstall_step);1084 const uninstall_tls: *TopLevelStep = @fieldParentPtr("step", uninstall_step);
1084 const b: *Build = @fieldParentPtr("uninstall_tls", uninstall_tls);1085 const b: *Build = @fieldParentPtr("uninstall_tls", uninstall_tls);
10851086
lib/std/Build/Step.zig+157-44
...@@ -68,7 +68,13 @@ pub const TestResults = struct {...@@ -68,7 +68,13 @@ pub const TestResults = struct {
68 }68 }
69};69};
7070
71pub const MakeFn = *const fn (step: *Step, prog_node: std.Progress.Node) anyerror!void;71pub const MakeOptions = struct {
72 progress_node: std.Progress.Node,
73 thread_pool: *std.Thread.Pool,
74 watch: bool,
75};
76
77pub const MakeFn = *const fn (step: *Step, options: MakeOptions) anyerror!void;
7278
73pub const State = enum {79pub const State = enum {
74 precheck_unstarted,80 precheck_unstarted,
...@@ -219,10 +225,10 @@ pub fn init(options: StepOptions) Step {...@@ -219,10 +225,10 @@ pub fn init(options: StepOptions) Step {
219/// If the Step's `make` function reports `error.MakeFailed`, it indicates they225/// If the Step's `make` function reports `error.MakeFailed`, it indicates they
220/// have already reported the error. Otherwise, we add a simple error report226/// have already reported the error. Otherwise, we add a simple error report
221/// here.227/// here.
222pub fn make(s: *Step, prog_node: std.Progress.Node) error{ MakeFailed, MakeSkipped }!void {228pub fn make(s: *Step, options: MakeOptions) error{ MakeFailed, MakeSkipped }!void {
223 const arena = s.owner.allocator;229 const arena = s.owner.allocator;
224230
225 s.makeFn(s, prog_node) catch |err| switch (err) {231 s.makeFn(s, options) catch |err| switch (err) {
226 error.MakeFailed => return error.MakeFailed,232 error.MakeFailed => return error.MakeFailed,
227 error.MakeSkipped => return error.MakeSkipped,233 error.MakeSkipped => return error.MakeSkipped,
228 else => {234 else => {
...@@ -260,8 +266,8 @@ pub fn getStackTrace(s: *Step) ?std.builtin.StackTrace {...@@ -260,8 +266,8 @@ pub fn getStackTrace(s: *Step) ?std.builtin.StackTrace {
260 };266 };
261}267}
262268
263fn makeNoOp(step: *Step, prog_node: std.Progress.Node) anyerror!void {269fn makeNoOp(step: *Step, options: MakeOptions) anyerror!void {
264 _ = prog_node;270 _ = options;
265271
266 var all_cached = true;272 var all_cached = true;
267273
...@@ -352,13 +358,54 @@ pub fn addError(step: *Step, comptime fmt: []const u8, args: anytype) error{OutO...@@ -352,13 +358,54 @@ pub fn addError(step: *Step, comptime fmt: []const u8, args: anytype) error{OutO
352 try step.result_error_msgs.append(arena, msg);358 try step.result_error_msgs.append(arena, msg);
353}359}
354360
361pub const ZigProcess = struct {
362 child: std.process.Child,
363 poller: std.io.Poller(StreamEnum),
364 progress_ipc_fd: if (std.Progress.have_ipc) ?std.posix.fd_t else void,
365
366 pub const StreamEnum = enum { stdout, stderr };
367};
368
355/// Assumes that argv contains `--listen=-` and that the process being spawned369/// Assumes that argv contains `--listen=-` and that the process being spawned
356/// is the zig compiler - the same version that compiled the build runner.370/// is the zig compiler - the same version that compiled the build runner.
357pub fn evalZigProcess(371pub fn evalZigProcess(
358 s: *Step,372 s: *Step,
359 argv: []const []const u8,373 argv: []const []const u8,
360 prog_node: std.Progress.Node,374 prog_node: std.Progress.Node,
375 watch: bool,
361) !?[]const u8 {376) !?[]const u8 {
377 if (s.getZigProcess()) |zp| update: {
378 assert(watch);
379 if (std.Progress.have_ipc) if (zp.progress_ipc_fd) |fd| prog_node.setIpcFd(fd);
380 const result = zigProcessUpdate(s, zp, watch) catch |err| switch (err) {
381 error.BrokenPipe => {
382 // Process restart required.
383 const term = zp.child.wait() catch |e| {
384 return s.fail("unable to wait for {s}: {s}", .{ argv[0], @errorName(e) });
385 };
386 _ = term;
387 s.clearZigProcess();
388 break :update;
389 },
390 else => |e| return e,
391 };
392
393 if (s.result_error_bundle.errorMessageCount() > 0)
394 return s.fail("{d} compilation errors", .{s.result_error_bundle.errorMessageCount()});
395
396 if (s.result_error_msgs.items.len > 0 and result == null) {
397 // Crash detected.
398 const term = zp.child.wait() catch |e| {
399 return s.fail("unable to wait for {s}: {s}", .{ argv[0], @errorName(e) });
400 };
401 s.result_peak_rss = zp.child.resource_usage_statistics.getMaxRss() orelse 0;
402 s.clearZigProcess();
403 try handleChildProcessTerm(s, term, null, argv);
404 return error.MakeFailed;
405 }
406
407 return result;
408 }
362 assert(argv.len != 0);409 assert(argv.len != 0);
363 const b = s.owner;410 const b = s.owner;
364 const arena = b.allocator;411 const arena = b.allocator;
...@@ -378,29 +425,79 @@ pub fn evalZigProcess(...@@ -378,29 +425,79 @@ pub fn evalZigProcess(
378 child.spawn() catch |err| return s.fail("unable to spawn {s}: {s}", .{425 child.spawn() catch |err| return s.fail("unable to spawn {s}: {s}", .{
379 argv[0], @errorName(err),426 argv[0], @errorName(err),
380 });427 });
381 var timer = try std.time.Timer.start();
382428
383 var poller = std.io.poll(gpa, enum { stdout, stderr }, .{429 const zp = try gpa.create(ZigProcess);
384 .stdout = child.stdout.?,430 zp.* = .{
385 .stderr = child.stderr.?,431 .child = child,
386 });432 .poller = std.io.poll(gpa, ZigProcess.StreamEnum, .{
387 defer poller.deinit();433 .stdout = child.stdout.?,
434 .stderr = child.stderr.?,
435 }),
436 .progress_ipc_fd = if (std.Progress.have_ipc) child.progress_node.getIpcFd() else {},
437 };
438 if (watch) s.setZigProcess(zp);
439 defer if (!watch) zp.poller.deinit();
440
441 const result = try zigProcessUpdate(s, zp, watch);
442
443 if (!watch) {
444 // Send EOF to stdin.
445 zp.child.stdin.?.close();
446 zp.child.stdin = null;
447
448 const term = zp.child.wait() catch |err| {
449 return s.fail("unable to wait for {s}: {s}", .{ argv[0], @errorName(err) });
450 };
451 s.result_peak_rss = zp.child.resource_usage_statistics.getMaxRss() orelse 0;
452
453 // Special handling for Compile step that is expecting compile errors.
454 if (s.cast(Compile)) |compile| switch (term) {
455 .Exited => {
456 // Note that the exit code may be 0 in this case due to the
457 // compiler server protocol.
458 if (compile.expect_errors != null) {
459 return error.NeedCompileErrorCheck;
460 }
461 },
462 else => {},
463 };
464
465 try handleChildProcessTerm(s, term, null, argv);
466 }
467
468 // This is intentionally printed for failure on the first build but not for
469 // subsequent rebuilds.
470 if (s.result_error_bundle.errorMessageCount() > 0) {
471 return s.fail("the following command failed with {d} compilation errors:\n{s}", .{
472 s.result_error_bundle.errorMessageCount(),
473 try allocPrintCmd(arena, null, argv),
474 });
475 }
388476
389 try sendMessage(child.stdin.?, .update);477 return result;
390 try sendMessage(child.stdin.?, .exit);478}
479
480fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?[]const u8 {
481 const b = s.owner;
482 const arena = b.allocator;
483
484 var timer = try std.time.Timer.start();
485
486 try sendMessage(zp.child.stdin.?, .update);
487 if (!watch) try sendMessage(zp.child.stdin.?, .exit);
391488
392 const Header = std.zig.Server.Message.Header;489 const Header = std.zig.Server.Message.Header;
393 var result: ?[]const u8 = null;490 var result: ?[]const u8 = null;
394491
395 const stdout = poller.fifo(.stdout);492 const stdout = zp.poller.fifo(.stdout);
396493
397 poll: while (true) {494 poll: while (true) {
398 while (stdout.readableLength() < @sizeOf(Header)) {495 while (stdout.readableLength() < @sizeOf(Header)) {
399 if (!(try poller.poll())) break :poll;496 if (!(try zp.poller.poll())) break :poll;
400 }497 }
401 const header = stdout.reader().readStruct(Header) catch unreachable;498 const header = stdout.reader().readStruct(Header) catch unreachable;
402 while (stdout.readableLength() < header.bytes_len) {499 while (stdout.readableLength() < header.bytes_len) {
403 if (!(try poller.poll())) break :poll;500 if (!(try zp.poller.poll())) break :poll;
404 }501 }
405 const body = stdout.readableSliceOfLen(header.bytes_len);502 const body = stdout.readableSliceOfLen(header.bytes_len);
406503
...@@ -428,12 +525,22 @@ pub fn evalZigProcess(...@@ -428,12 +525,22 @@ pub fn evalZigProcess(
428 .string_bytes = try arena.dupe(u8, string_bytes),525 .string_bytes = try arena.dupe(u8, string_bytes),
429 .extra = extra_array,526 .extra = extra_array,
430 };527 };
528 if (watch) {
529 // This message indicates the end of the update.
530 stdout.discard(body.len);
531 break;
532 }
431 },533 },
432 .emit_bin_path => {534 .emit_bin_path => {
433 const EbpHdr = std.zig.Server.Message.EmitBinPath;535 const EbpHdr = std.zig.Server.Message.EmitBinPath;
434 const ebp_hdr = @as(*align(1) const EbpHdr, @ptrCast(body));536 const ebp_hdr = @as(*align(1) const EbpHdr, @ptrCast(body));
435 s.result_cached = ebp_hdr.flags.cache_hit;537 s.result_cached = ebp_hdr.flags.cache_hit;
436 result = try arena.dupe(u8, body[@sizeOf(EbpHdr)..]);538 result = try arena.dupe(u8, body[@sizeOf(EbpHdr)..]);
539 if (watch) {
540 // This message indicates the end of the update.
541 stdout.discard(body.len);
542 break;
543 }
437 },544 },
438 .file_system_inputs => {545 .file_system_inputs => {
439 s.clearWatchInputs();546 s.clearWatchInputs();
...@@ -470,6 +577,13 @@ pub fn evalZigProcess(...@@ -470,6 +577,13 @@ pub fn evalZigProcess(
470 };577 };
471 try addWatchInputFromPath(s, path, std.fs.path.basename(sub_path));578 try addWatchInputFromPath(s, path, std.fs.path.basename(sub_path));
472 },579 },
580 .global_cache => {
581 const path: Build.Cache.Path = .{
582 .root_dir = s.owner.graph.global_cache_root,
583 .sub_path = sub_path_dirname,
584 };
585 try addWatchInputFromPath(s, path, std.fs.path.basename(sub_path));
586 },
473 }587 }
474 }588 }
475 },589 },
...@@ -479,43 +593,42 @@ pub fn evalZigProcess(...@@ -479,43 +593,42 @@ pub fn evalZigProcess(
479 stdout.discard(body.len);593 stdout.discard(body.len);
480 }594 }
481595
482 const stderr = poller.fifo(.stderr);596 s.result_duration_ns = timer.read();
597
598 const stderr = zp.poller.fifo(.stderr);
483 if (stderr.readableLength() > 0) {599 if (stderr.readableLength() > 0) {
484 try s.result_error_msgs.append(arena, try stderr.toOwnedSlice());600 try s.result_error_msgs.append(arena, try stderr.toOwnedSlice());
485 }601 }
486602
487 // Send EOF to stdin.603 return result;
488 child.stdin.?.close();604}
489 child.stdin = null;
490605
491 const term = child.wait() catch |err| {606pub fn getZigProcess(s: *Step) ?*ZigProcess {
492 return s.fail("unable to wait for {s}: {s}", .{ argv[0], @errorName(err) });607 return switch (s.id) {
493 };608 .compile => s.cast(Compile).?.zig_process,
494 s.result_duration_ns = timer.read();609 else => null,
495 s.result_peak_rss = child.resource_usage_statistics.getMaxRss() orelse 0;
496
497 // Special handling for Compile step that is expecting compile errors.
498 if (s.cast(Compile)) |compile| switch (term) {
499 .Exited => {
500 // Note that the exit code may be 0 in this case due to the
501 // compiler server protocol.
502 if (compile.expect_errors != null) {
503 return error.NeedCompileErrorCheck;
504 }
505 },
506 else => {},
507 };610 };
611}
508612
509 try handleChildProcessTerm(s, term, null, argv);613fn setZigProcess(s: *Step, zp: *ZigProcess) void {
510614 switch (s.id) {
511 if (s.result_error_bundle.errorMessageCount() > 0) {615 .compile => s.cast(Compile).?.zig_process = zp,
512 return s.fail("the following command failed with {d} compilation errors:\n{s}", .{616 else => unreachable,
513 s.result_error_bundle.errorMessageCount(),
514 try allocPrintCmd(arena, null, argv),
515 });
516 }617 }
618}
517619
518 return result;620fn clearZigProcess(s: *Step) void {
621 const gpa = s.owner.allocator;
622 switch (s.id) {
623 .compile => {
624 const compile = s.cast(Compile).?;
625 if (compile.zig_process) |zp| {
626 gpa.destroy(zp);
627 compile.zig_process = null;
628 }
629 },
630 else => unreachable,
631 }
519}632}
520633
521fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void {634fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void {
lib/std/Build/Step/CheckFile.zig+2-2
...@@ -46,8 +46,8 @@ pub fn setName(check_file: *CheckFile, name: []const u8) void {...@@ -46,8 +46,8 @@ pub fn setName(check_file: *CheckFile, name: []const u8) void {
46 check_file.step.name = name;46 check_file.step.name = name;
47}47}
4848
49fn make(step: *Step, prog_node: std.Progress.Node) !void {49fn make(step: *Step, options: Step.MakeOptions) !void {
50 _ = prog_node;50 _ = options;
51 const b = step.owner;51 const b = step.owner;
52 const check_file: *CheckFile = @fieldParentPtr("step", step);52 const check_file: *CheckFile = @fieldParentPtr("step", step);
53 try step.singleUnchangingWatchInput(check_file.source);53 try step.singleUnchangingWatchInput(check_file.source);
lib/std/Build/Step/CheckObject.zig+2-2
...@@ -550,8 +550,8 @@ pub fn checkComputeCompare(...@@ -550,8 +550,8 @@ pub fn checkComputeCompare(
550 check_object.checks.append(check) catch @panic("OOM");550 check_object.checks.append(check) catch @panic("OOM");
551}551}
552552
553fn make(step: *Step, prog_node: std.Progress.Node) !void {553fn make(step: *Step, make_options: Step.MakeOptions) !void {
554 _ = prog_node;554 _ = make_options;
555 const b = step.owner;555 const b = step.owner;
556 const gpa = b.allocator;556 const gpa = b.allocator;
557 const check_object: *CheckObject = @fieldParentPtr("step", step);557 const check_object: *CheckObject = @fieldParentPtr("step", step);
lib/std/Build/Step/Compile.zig+14-2
...@@ -213,6 +213,10 @@ is_linking_libcpp: bool = false,...@@ -213,6 +213,10 @@ is_linking_libcpp: bool = false,
213213
214no_builtin: bool = false,214no_builtin: bool = false,
215215
216/// Populated during the make phase when there is a long-lived compiler process.
217/// Managed by the build runner, not user build script.
218zig_process: ?*Step.ZigProcess,
219
216pub const ExpectedCompileErrors = union(enum) {220pub const ExpectedCompileErrors = union(enum) {
217 contains: []const u8,221 contains: []const u8,
218 exact: []const []const u8,222 exact: []const []const u8,
...@@ -398,6 +402,8 @@ pub fn create(owner: *std.Build, options: Options) *Compile {...@@ -398,6 +402,8 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
398402
399 .use_llvm = options.use_llvm,403 .use_llvm = options.use_llvm,
400 .use_lld = options.use_lld,404 .use_lld = options.use_lld,
405
406 .zig_process = null,
401 };407 };
402408
403 compile.root_module.init(owner, options.root_module, compile);409 compile.root_module.init(owner, options.root_module, compile);
...@@ -1673,6 +1679,8 @@ fn getZigArgs(compile: *Compile) ![][]const u8 {...@@ -1673,6 +1679,8 @@ fn getZigArgs(compile: *Compile) ![][]const u8 {
1673 b.fmt("{}", .{err_limit}),1679 b.fmt("{}", .{err_limit}),
1674 });1680 });
16751681
1682 try addFlag(&zig_args, "incremental", b.graph.incremental);
1683
1676 try zig_args.append("--listen=-");1684 try zig_args.append("--listen=-");
16771685
1678 // Windows has an argument length limit of 32,766 characters, macOS 262,144 and Linux1686 // Windows has an argument length limit of 32,766 characters, macOS 262,144 and Linux
...@@ -1735,13 +1743,17 @@ fn getZigArgs(compile: *Compile) ![][]const u8 {...@@ -1735,13 +1743,17 @@ fn getZigArgs(compile: *Compile) ![][]const u8 {
1735 return try zig_args.toOwnedSlice();1743 return try zig_args.toOwnedSlice();
1736}1744}
17371745
1738fn make(step: *Step, prog_node: std.Progress.Node) !void {1746fn make(step: *Step, options: Step.MakeOptions) !void {
1739 const b = step.owner;1747 const b = step.owner;
1740 const compile: *Compile = @fieldParentPtr("step", step);1748 const compile: *Compile = @fieldParentPtr("step", step);
17411749
1742 const zig_args = try getZigArgs(compile);1750 const zig_args = try getZigArgs(compile);
17431751
1744 const maybe_output_bin_path = step.evalZigProcess(zig_args, prog_node) catch |err| switch (err) {1752 const maybe_output_bin_path = step.evalZigProcess(
1753 zig_args,
1754 options.progress_node,
1755 (b.graph.incremental == true) and options.watch,
1756 ) catch |err| switch (err) {
1745 error.NeedCompileErrorCheck => {1757 error.NeedCompileErrorCheck => {
1746 assert(compile.expect_errors != null);1758 assert(compile.expect_errors != null);
1747 try checkCompileErrors(compile);1759 try checkCompileErrors(compile);
lib/std/Build/Step/ConfigHeader.zig+2-2
...@@ -164,8 +164,8 @@ fn putValue(config_header: *ConfigHeader, field_name: []const u8, comptime T: ty...@@ -164,8 +164,8 @@ fn putValue(config_header: *ConfigHeader, field_name: []const u8, comptime T: ty
164 }164 }
165}165}
166166
167fn make(step: *Step, prog_node: std.Progress.Node) !void {167fn make(step: *Step, options: Step.MakeOptions) !void {
168 _ = prog_node;168 _ = options;
169 const b = step.owner;169 const b = step.owner;
170 const config_header: *ConfigHeader = @fieldParentPtr("step", step);170 const config_header: *ConfigHeader = @fieldParentPtr("step", step);
171 if (config_header.style.getPath()) |lp| try step.singleUnchangingWatchInput(lp);171 if (config_header.style.getPath()) |lp| try step.singleUnchangingWatchInput(lp);
lib/std/Build/Step/Fail.zig+2-2
...@@ -24,8 +24,8 @@ pub fn create(owner: *std.Build, error_msg: []const u8) *Fail {...@@ -24,8 +24,8 @@ pub fn create(owner: *std.Build, error_msg: []const u8) *Fail {
24 return fail;24 return fail;
25}25}
2626
27fn make(step: *Step, prog_node: std.Progress.Node) !void {27fn make(step: *Step, options: Step.MakeOptions) !void {
28 _ = prog_node; // No progress to report.28 _ = options; // No progress to report.
2929
30 const fail: *Fail = @fieldParentPtr("step", step);30 const fail: *Fail = @fieldParentPtr("step", step);
3131
lib/std/Build/Step/Fmt.zig+3-1
...@@ -36,7 +36,9 @@ pub fn create(owner: *std.Build, options: Options) *Fmt {...@@ -36,7 +36,9 @@ pub fn create(owner: *std.Build, options: Options) *Fmt {
36 return fmt;36 return fmt;
37}37}
3838
39fn make(step: *Step, prog_node: std.Progress.Node) !void {39fn make(step: *Step, options: Step.MakeOptions) !void {
40 const prog_node = options.progress_node;
41
40 // TODO: if check=false, this means we are modifying source files in place, which42 // TODO: if check=false, this means we are modifying source files in place, which
41 // is an operation that could race against other operations also modifying source files43 // is an operation that could race against other operations also modifying source files
42 // in place. In this case, this step should obtain a write lock while making those44 // in place. In this case, this step should obtain a write lock while making those
lib/std/Build/Step/InstallArtifact.zig+2-2
...@@ -115,8 +115,8 @@ pub fn create(owner: *std.Build, artifact: *Step.Compile, options: Options) *Ins...@@ -115,8 +115,8 @@ pub fn create(owner: *std.Build, artifact: *Step.Compile, options: Options) *Ins
115 return install_artifact;115 return install_artifact;
116}116}
117117
118fn make(step: *Step, prog_node: std.Progress.Node) !void {118fn make(step: *Step, options: Step.MakeOptions) !void {
119 _ = prog_node;119 _ = options;
120 const install_artifact: *InstallArtifact = @fieldParentPtr("step", step);120 const install_artifact: *InstallArtifact = @fieldParentPtr("step", step);
121 const b = step.owner;121 const b = step.owner;
122 const cwd = fs.cwd();122 const cwd = fs.cwd();
lib/std/Build/Step/InstallDir.zig+2-2
...@@ -55,8 +55,8 @@ pub fn create(owner: *std.Build, options: Options) *InstallDir {...@@ -55,8 +55,8 @@ pub fn create(owner: *std.Build, options: Options) *InstallDir {
55 return install_dir;55 return install_dir;
56}56}
5757
58fn make(step: *Step, prog_node: std.Progress.Node) !void {58fn make(step: *Step, options: Step.MakeOptions) !void {
59 _ = prog_node;59 _ = options;
60 const b = step.owner;60 const b = step.owner;
61 const install_dir: *InstallDir = @fieldParentPtr("step", step);61 const install_dir: *InstallDir = @fieldParentPtr("step", step);
62 step.clearWatchInputs();62 step.clearWatchInputs();
lib/std/Build/Step/InstallFile.zig+2-2
...@@ -35,8 +35,8 @@ pub fn create(...@@ -35,8 +35,8 @@ pub fn create(
35 return install_file;35 return install_file;
36}36}
3737
38fn make(step: *Step, prog_node: std.Progress.Node) !void {38fn make(step: *Step, options: Step.MakeOptions) !void {
39 _ = prog_node;39 _ = options;
40 const b = step.owner;40 const b = step.owner;
41 const install_file: *InstallFile = @fieldParentPtr("step", step);41 const install_file: *InstallFile = @fieldParentPtr("step", step);
42 try step.singleUnchangingWatchInput(install_file.source);42 try step.singleUnchangingWatchInput(install_file.source);
lib/std/Build/Step/ObjCopy.zig+3-2
...@@ -90,7 +90,8 @@ pub fn getOutputSeparatedDebug(objcopy: *const ObjCopy) ?std.Build.LazyPath {...@@ -90,7 +90,8 @@ pub fn getOutputSeparatedDebug(objcopy: *const ObjCopy) ?std.Build.LazyPath {
90 return if (objcopy.output_file_debug) |*file| .{ .generated = .{ .file = file } } else null;90 return if (objcopy.output_file_debug) |*file| .{ .generated = .{ .file = file } } else null;
91}91}
9292
93fn make(step: *Step, prog_node: std.Progress.Node) !void {93fn make(step: *Step, options: Step.MakeOptions) !void {
94 const prog_node = options.progress_node;
94 const b = step.owner;95 const b = step.owner;
95 const objcopy: *ObjCopy = @fieldParentPtr("step", step);96 const objcopy: *ObjCopy = @fieldParentPtr("step", step);
96 try step.singleUnchangingWatchInput(objcopy.input_file);97 try step.singleUnchangingWatchInput(objcopy.input_file);
...@@ -158,7 +159,7 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {...@@ -158,7 +159,7 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {
158 try argv.appendSlice(&.{ full_src_path, full_dest_path });159 try argv.appendSlice(&.{ full_src_path, full_dest_path });
159160
160 try argv.append("--listen=-");161 try argv.append("--listen=-");
161 _ = try step.evalZigProcess(argv.items, prog_node);162 _ = try step.evalZigProcess(argv.items, prog_node, false);
162163
163 objcopy.output_file.path = full_dest_path;164 objcopy.output_file.path = full_dest_path;
164 if (objcopy.output_file_debug) |*file| file.path = full_dest_path_debug;165 if (objcopy.output_file_debug) |*file| file.path = full_dest_path_debug;
lib/std/Build/Step/Options.zig+3-3
...@@ -410,9 +410,9 @@ pub fn getOutput(options: *Options) LazyPath {...@@ -410,9 +410,9 @@ pub fn getOutput(options: *Options) LazyPath {
410 return .{ .generated = .{ .file = &options.generated_file } };410 return .{ .generated = .{ .file = &options.generated_file } };
411}411}
412412
413fn make(step: *Step, prog_node: std.Progress.Node) !void {413fn make(step: *Step, make_options: Step.MakeOptions) !void {
414 // This step completes so quickly that no progress is necessary.414 // This step completes so quickly that no progress reporting is necessary.
415 _ = prog_node;415 _ = make_options;
416416
417 const b = step.owner;417 const b = step.owner;
418 const options: *Options = @fieldParentPtr("step", step);418 const options: *Options = @fieldParentPtr("step", step);
lib/std/Build/Step/RemoveDir.zig+2-4
...@@ -23,10 +23,8 @@ pub fn create(owner: *std.Build, doomed_path: LazyPath) *RemoveDir {...@@ -23,10 +23,8 @@ pub fn create(owner: *std.Build, doomed_path: LazyPath) *RemoveDir {
23 return remove_dir;23 return remove_dir;
24}24}
2525
26fn make(step: *Step, prog_node: std.Progress.Node) !void {26fn make(step: *Step, options: Step.MakeOptions) !void {
27 // TODO update progress node while walking file system.27 _ = options;
28 // Should the standard library support this use case??
29 _ = prog_node;
3028
31 const b = step.owner;29 const b = step.owner;
32 const remove_dir: *RemoveDir = @fieldParentPtr("step", step);30 const remove_dir: *RemoveDir = @fieldParentPtr("step", step);
lib/std/Build/Step/Run.zig+2-1
...@@ -595,7 +595,8 @@ const IndexedOutput = struct {...@@ -595,7 +595,8 @@ const IndexedOutput = struct {
595 tag: @typeInfo(Arg).Union.tag_type.?,595 tag: @typeInfo(Arg).Union.tag_type.?,
596 output: *Output,596 output: *Output,
597};597};
598fn make(step: *Step, prog_node: std.Progress.Node) !void {598fn make(step: *Step, options: Step.MakeOptions) !void {
599 const prog_node = options.progress_node;
599 const b = step.owner;600 const b = step.owner;
600 const arena = b.allocator;601 const arena = b.allocator;
601 const run: *Run = @fieldParentPtr("step", step);602 const run: *Run = @fieldParentPtr("step", step);
lib/std/Build/Step/TranslateC.zig+3-2
...@@ -116,7 +116,8 @@ pub fn defineCMacroRaw(translate_c: *TranslateC, name_and_value: []const u8) voi...@@ -116,7 +116,8 @@ pub fn defineCMacroRaw(translate_c: *TranslateC, name_and_value: []const u8) voi
116 translate_c.c_macros.append(translate_c.step.owner.dupe(name_and_value)) catch @panic("OOM");116 translate_c.c_macros.append(translate_c.step.owner.dupe(name_and_value)) catch @panic("OOM");
117}117}
118118
119fn make(step: *Step, prog_node: std.Progress.Node) !void {119fn make(step: *Step, options: Step.MakeOptions) !void {
120 const prog_node = options.progress_node;
120 const b = step.owner;121 const b = step.owner;
121 const translate_c: *TranslateC = @fieldParentPtr("step", step);122 const translate_c: *TranslateC = @fieldParentPtr("step", step);
122123
...@@ -154,7 +155,7 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {...@@ -154,7 +155,7 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {
154155
155 try argv_list.append(translate_c.source.getPath2(b, step));156 try argv_list.append(translate_c.source.getPath2(b, step));
156157
157 const output_path = try step.evalZigProcess(argv_list.items, prog_node);158 const output_path = try step.evalZigProcess(argv_list.items, prog_node, false);
158159
159 translate_c.out_basename = fs.path.basename(output_path.?);160 translate_c.out_basename = fs.path.basename(output_path.?);
160 const output_dir = fs.path.dirname(output_path.?).?;161 const output_dir = fs.path.dirname(output_path.?).?;
lib/std/Build/Step/UpdateSourceFiles.zig+2-2
...@@ -67,8 +67,8 @@ pub fn addBytesToSource(usf: *UpdateSourceFiles, bytes: []const u8, sub_path: []...@@ -67,8 +67,8 @@ pub fn addBytesToSource(usf: *UpdateSourceFiles, bytes: []const u8, sub_path: []
67 }) catch @panic("OOM");67 }) catch @panic("OOM");
68}68}
6969
70fn make(step: *Step, prog_node: std.Progress.Node) !void {70fn make(step: *Step, options: Step.MakeOptions) !void {
71 _ = prog_node;71 _ = options;
72 const b = step.owner;72 const b = step.owner;
73 const usf: *UpdateSourceFiles = @fieldParentPtr("step", step);73 const usf: *UpdateSourceFiles = @fieldParentPtr("step", step);
7474
lib/std/Build/Step/WriteFile.zig+2-2
...@@ -171,8 +171,8 @@ fn maybeUpdateName(write_file: *WriteFile) void {...@@ -171,8 +171,8 @@ fn maybeUpdateName(write_file: *WriteFile) void {
171 }171 }
172}172}
173173
174fn make(step: *Step, prog_node: std.Progress.Node) !void {174fn make(step: *Step, options: Step.MakeOptions) !void {
175 _ = prog_node;175 _ = options;
176 const b = step.owner;176 const b = step.owner;
177 const arena = b.allocator;177 const arena = b.allocator;
178 const gpa = arena;178 const gpa = arena;
lib/std/Progress.zig+18
...@@ -269,6 +269,19 @@ pub const Node = struct {...@@ -269,6 +269,19 @@ pub const Node = struct {
269 storageByIndex(index).setIpcFd(fd);269 storageByIndex(index).setIpcFd(fd);
270 }270 }
271271
272 /// Posix-only. Thread-safe. Assumes the node is storing an IPC file
273 /// descriptor.
274 pub fn getIpcFd(node: Node) ?posix.fd_t {
275 const index = node.index.unwrap() orelse return null;
276 const storage = storageByIndex(index);
277 const int = @atomicLoad(u32, &storage.completed_count, .monotonic);
278 return switch (@typeInfo(posix.fd_t)) {
279 .Int => @bitCast(int),
280 .Pointer => @ptrFromInt(int),
281 else => @compileError("unsupported fd_t of " ++ @typeName(posix.fd_t)),
282 };
283 }
284
272 fn storageByIndex(index: Node.Index) *Node.Storage {285 fn storageByIndex(index: Node.Index) *Node.Storage {
273 return &global_progress.node_storage[@intFromEnum(index)];286 return &global_progress.node_storage[@intFromEnum(index)];
274 }287 }
...@@ -329,6 +342,11 @@ var default_draw_buffer: [4096]u8 = undefined;...@@ -329,6 +342,11 @@ var default_draw_buffer: [4096]u8 = undefined;
329342
330var debug_start_trace = std.debug.Trace.init;343var debug_start_trace = std.debug.Trace.init;
331344
345pub const have_ipc = switch (builtin.os.tag) {
346 .wasi, .freestanding, .windows => false,
347 else => true,
348};
349
332const noop_impl = builtin.single_threaded or switch (builtin.os.tag) {350const noop_impl = builtin.single_threaded or switch (builtin.os.tag) {
333 .wasi, .freestanding => true,351 .wasi, .freestanding => true,
334 else => false,352 else => false,
lib/std/zig/Server.zig+1
...@@ -36,6 +36,7 @@ pub const Message = struct {...@@ -36,6 +36,7 @@ pub const Message = struct {
36 cwd,36 cwd,
37 zig_lib,37 zig_lib,
38 local_cache,38 local_cache,
39 global_cache,
39 };40 };
4041
41 /// Trailing:42 /// Trailing:
src/Compilation.zig+5-4
...@@ -169,7 +169,7 @@ time_report: bool,...@@ -169,7 +169,7 @@ time_report: bool,
169stack_report: bool,169stack_report: bool,
170debug_compiler_runtime_libs: bool,170debug_compiler_runtime_libs: bool,
171debug_compile_errors: bool,171debug_compile_errors: bool,
172debug_incremental: bool,172incremental: bool,
173job_queued_compiler_rt_lib: bool = false,173job_queued_compiler_rt_lib: bool = false,
174job_queued_compiler_rt_obj: bool = false,174job_queued_compiler_rt_obj: bool = false,
175job_queued_update_builtin_zig: bool,175job_queued_update_builtin_zig: bool,
...@@ -1134,7 +1134,7 @@ pub const CreateOptions = struct {...@@ -1134,7 +1134,7 @@ pub const CreateOptions = struct {
1134 verbose_llvm_cpu_features: bool = false,1134 verbose_llvm_cpu_features: bool = false,
1135 debug_compiler_runtime_libs: bool = false,1135 debug_compiler_runtime_libs: bool = false,
1136 debug_compile_errors: bool = false,1136 debug_compile_errors: bool = false,
1137 debug_incremental: bool = false,1137 incremental: bool = false,
1138 /// Normally when you create a `Compilation`, Zig will automatically build1138 /// Normally when you create a `Compilation`, Zig will automatically build
1139 /// and link in required dependencies, such as compiler-rt and libc. When1139 /// and link in required dependencies, such as compiler-rt and libc. When
1140 /// building such dependencies themselves, this flag must be set to avoid1140 /// building such dependencies themselves, this flag must be set to avoid
...@@ -1363,6 +1363,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1363,6 +1363,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1363 cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() });1363 cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() });
1364 cache.addPrefix(options.zig_lib_directory);1364 cache.addPrefix(options.zig_lib_directory);
1365 cache.addPrefix(options.local_cache_directory);1365 cache.addPrefix(options.local_cache_directory);
1366 cache.addPrefix(options.global_cache_directory);
1366 errdefer cache.manifest_dir.close();1367 errdefer cache.manifest_dir.close();
13671368
1368 // This is shared hasher state common to zig source and all C source files.1369 // This is shared hasher state common to zig source and all C source files.
...@@ -1515,7 +1516,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1515,7 +1516,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1515 .test_name_prefix = options.test_name_prefix,1516 .test_name_prefix = options.test_name_prefix,
1516 .debug_compiler_runtime_libs = options.debug_compiler_runtime_libs,1517 .debug_compiler_runtime_libs = options.debug_compiler_runtime_libs,
1517 .debug_compile_errors = options.debug_compile_errors,1518 .debug_compile_errors = options.debug_compile_errors,
1518 .debug_incremental = options.debug_incremental,1519 .incremental = options.incremental,
1519 .libcxx_abi_version = options.libcxx_abi_version,1520 .libcxx_abi_version = options.libcxx_abi_version,
1520 .root_name = root_name,1521 .root_name = root_name,
1521 .sysroot = sysroot,1522 .sysroot = sysroot,
...@@ -2358,7 +2359,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2358,7 +2359,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2358 }2359 }
2359}2360}
23602361
2361fn appendFileSystemInput(2362pub fn appendFileSystemInput(
2362 comp: *Compilation,2363 comp: *Compilation,
2363 file_system_inputs: *std.ArrayListUnmanaged(u8),2364 file_system_inputs: *std.ArrayListUnmanaged(u8),
2364 root: Cache.Path,2365 root: Cache.Path,
src/Sema.zig+6-6
...@@ -2726,7 +2726,7 @@ fn maybeRemoveOutdatedType(sema: *Sema, ty: InternPool.Index) !bool {...@@ -2726,7 +2726,7 @@ fn maybeRemoveOutdatedType(sema: *Sema, ty: InternPool.Index) !bool {
2726 const pt = sema.pt;2726 const pt = sema.pt;
2727 const zcu = pt.zcu;2727 const zcu = pt.zcu;
27282728
2729 if (!zcu.comp.debug_incremental) return false;2729 if (!zcu.comp.incremental) return false;
27302730
2731 const decl_index = Type.fromInterned(ty).getOwnerDecl(zcu);2731 const decl_index = Type.fromInterned(ty).getOwnerDecl(zcu);
2732 const decl_as_depender = AnalUnit.wrap(.{ .decl = decl_index });2732 const decl_as_depender = AnalUnit.wrap(.{ .decl = decl_index });
...@@ -2826,7 +2826,7 @@ fn zirStructDecl(...@@ -2826,7 +2826,7 @@ fn zirStructDecl(
2826 mod.declPtr(new_decl_index).owns_tv = true;2826 mod.declPtr(new_decl_index).owns_tv = true;
2827 errdefer pt.abortAnonDecl(new_decl_index);2827 errdefer pt.abortAnonDecl(new_decl_index);
28282828
2829 if (pt.zcu.comp.debug_incremental) {2829 if (pt.zcu.comp.incremental) {
2830 try ip.addDependency(2830 try ip.addDependency(
2831 sema.gpa,2831 sema.gpa,
2832 AnalUnit.wrap(.{ .decl = new_decl_index }),2832 AnalUnit.wrap(.{ .decl = new_decl_index }),
...@@ -3064,7 +3064,7 @@ fn zirEnumDecl(...@@ -3064,7 +3064,7 @@ fn zirEnumDecl(
3064 new_decl.owns_tv = true;3064 new_decl.owns_tv = true;
3065 errdefer if (!done) pt.abortAnonDecl(new_decl_index);3065 errdefer if (!done) pt.abortAnonDecl(new_decl_index);
30663066
3067 if (pt.zcu.comp.debug_incremental) {3067 if (pt.zcu.comp.incremental) {
3068 try mod.intern_pool.addDependency(3068 try mod.intern_pool.addDependency(
3069 gpa,3069 gpa,
3070 AnalUnit.wrap(.{ .decl = new_decl_index }),3070 AnalUnit.wrap(.{ .decl = new_decl_index }),
...@@ -3331,7 +3331,7 @@ fn zirUnionDecl(...@@ -3331,7 +3331,7 @@ fn zirUnionDecl(
3331 mod.declPtr(new_decl_index).owns_tv = true;3331 mod.declPtr(new_decl_index).owns_tv = true;
3332 errdefer pt.abortAnonDecl(new_decl_index);3332 errdefer pt.abortAnonDecl(new_decl_index);
33333333
3334 if (pt.zcu.comp.debug_incremental) {3334 if (pt.zcu.comp.incremental) {
3335 try mod.intern_pool.addDependency(3335 try mod.intern_pool.addDependency(
3336 gpa,3336 gpa,
3337 AnalUnit.wrap(.{ .decl = new_decl_index }),3337 AnalUnit.wrap(.{ .decl = new_decl_index }),
...@@ -3421,7 +3421,7 @@ fn zirOpaqueDecl(...@@ -3421,7 +3421,7 @@ fn zirOpaqueDecl(
3421 mod.declPtr(new_decl_index).owns_tv = true;3421 mod.declPtr(new_decl_index).owns_tv = true;
3422 errdefer pt.abortAnonDecl(new_decl_index);3422 errdefer pt.abortAnonDecl(new_decl_index);
34233423
3424 if (pt.zcu.comp.debug_incremental) {3424 if (pt.zcu.comp.incremental) {
3425 try ip.addDependency(3425 try ip.addDependency(
3426 gpa,3426 gpa,
3427 AnalUnit.wrap(.{ .decl = new_decl_index }),3427 AnalUnit.wrap(.{ .decl = new_decl_index }),
...@@ -38104,7 +38104,7 @@ fn isKnownZigType(sema: *Sema, ref: Air.Inst.Ref, tag: std.builtin.TypeId) bool...@@ -38104,7 +38104,7 @@ fn isKnownZigType(sema: *Sema, ref: Air.Inst.Ref, tag: std.builtin.TypeId) bool
3810438104
38105pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void {38105pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void {
38106 const zcu = sema.pt.zcu;38106 const zcu = sema.pt.zcu;
38107 if (!zcu.comp.debug_incremental) return;38107 if (!zcu.comp.incremental) return;
3810838108
38109 // Avoid creating dependencies on ourselves. This situation can arise when we analyze the fields38109 // Avoid creating dependencies on ourselves. This situation can arise when we analyze the fields
38110 // of a type and they use `@This()`. This dependency would be unnecessary, and in fact would38110 // of a type and they use `@This()`. This dependency would be unnecessary, and in fact would
src/Zcu.zig+1-1
...@@ -2679,7 +2679,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni...@@ -2679,7 +2679,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni
2679}2679}
26802680
2681pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {2681pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
2682 if (!zcu.comp.debug_incremental) return null;2682 if (!zcu.comp.incremental) return null;
26832683
2684 if (zcu.outdated.count() == 0 and zcu.potentially_outdated.count() == 0) {2684 if (zcu.outdated.count() == 0 and zcu.potentially_outdated.count() == 0) {
2685 log.debug("findOutdatedToAnalyze: no outdated depender", .{});2685 log.debug("findOutdatedToAnalyze: no outdated depender", .{});
src/Zcu/PerThread.zig+9-1
...@@ -888,7 +888,7 @@ fn getFileRootStruct(...@@ -888,7 +888,7 @@ fn getFileRootStruct(
888 };888 };
889 errdefer wip_ty.cancel(ip, pt.tid);889 errdefer wip_ty.cancel(ip, pt.tid);
890890
891 if (zcu.comp.debug_incremental) {891 if (zcu.comp.incremental) {
892 try ip.addDependency(892 try ip.addDependency(
893 gpa,893 gpa,
894 InternPool.AnalUnit.wrap(.{ .decl = decl_index }),894 InternPool.AnalUnit.wrap(.{ .decl = decl_index }),
...@@ -1418,6 +1418,10 @@ pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult {...@@ -1418,6 +1418,10 @@ pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult {
1418 const sub_file_path = try gpa.dupe(u8, mod.root_src_path);1418 const sub_file_path = try gpa.dupe(u8, mod.root_src_path);
1419 errdefer gpa.free(sub_file_path);1419 errdefer gpa.free(sub_file_path);
14201420
1421 const comp = zcu.comp;
1422 if (comp.file_system_inputs) |fsi|
1423 try comp.appendFileSystemInput(fsi, mod.root, sub_file_path);
1424
1421 const new_file = try gpa.create(Zcu.File);1425 const new_file = try gpa.create(Zcu.File);
1422 errdefer gpa.destroy(new_file);1426 errdefer gpa.destroy(new_file);
14231427
...@@ -1527,6 +1531,10 @@ pub fn importFile(...@@ -1527,6 +1531,10 @@ pub fn importFile(
1527 resolved_root_path, resolved_path, sub_file_path, import_string,1531 resolved_root_path, resolved_path, sub_file_path, import_string,
1528 });1532 });
15291533
1534 const comp = zcu.comp;
1535 if (comp.file_system_inputs) |fsi|
1536 try comp.appendFileSystemInput(fsi, mod.root, sub_file_path);
1537
1530 const path_digest = zcu.computePathDigest(mod, sub_file_path);1538 const path_digest = zcu.computePathDigest(mod, sub_file_path);
1531 const new_file_index = try ip.createFile(gpa, pt.tid, .{1539 const new_file_index = try ip.createFile(gpa, pt.tid, .{
1532 .bin_digest = path_digest,1540 .bin_digest = path_digest,
src/main.zig+14-9
...@@ -404,6 +404,8 @@ const usage_build_generic =...@@ -404,6 +404,8 @@ const usage_build_generic =
404 \\ -h, --help Print this help and exit404 \\ -h, --help Print this help and exit
405 \\ --color [auto|off|on] Enable or disable colored error messages405 \\ --color [auto|off|on] Enable or disable colored error messages
406 \\ -j<N> Limit concurrent jobs (default is to use all CPU cores)406 \\ -j<N> Limit concurrent jobs (default is to use all CPU cores)
407 \\ -fincremental Enable incremental compilation
408 \\ -fno-incremental Disable incremental compilation
407 \\ -femit-bin[=path] (default) Output machine code409 \\ -femit-bin[=path] (default) Output machine code
408 \\ -fno-emit-bin Do not output machine code410 \\ -fno-emit-bin Do not output machine code
409 \\ -femit-asm[=path] Output .s (assembly code)411 \\ -femit-asm[=path] Output .s (assembly code)
...@@ -642,7 +644,6 @@ const usage_build_generic =...@@ -642,7 +644,6 @@ const usage_build_generic =
642 \\ --debug-log [scope] Enable printing debug/info log messages for scope644 \\ --debug-log [scope] Enable printing debug/info log messages for scope
643 \\ --debug-compile-errors Crash with helpful diagnostics at the first compile error645 \\ --debug-compile-errors Crash with helpful diagnostics at the first compile error
644 \\ --debug-link-snapshot Enable dumping of the linker's state in JSON format646 \\ --debug-link-snapshot Enable dumping of the linker's state in JSON format
645 \\ --debug-incremental Enable experimental feature: incremental compilation
646 \\647 \\
647;648;
648649
...@@ -904,7 +905,7 @@ fn buildOutputType(...@@ -904,7 +905,7 @@ fn buildOutputType(
904 var minor_subsystem_version: ?u16 = null;905 var minor_subsystem_version: ?u16 = null;
905 var mingw_unicode_entry_point: bool = false;906 var mingw_unicode_entry_point: bool = false;
906 var enable_link_snapshots: bool = false;907 var enable_link_snapshots: bool = false;
907 var debug_incremental: bool = false;908 var opt_incremental: ?bool = null;
908 var install_name: ?[]const u8 = null;909 var install_name: ?[]const u8 = null;
909 var hash_style: link.File.Elf.HashStyle = .both;910 var hash_style: link.File.Elf.HashStyle = .both;
910 var entitlements: ?[]const u8 = null;911 var entitlements: ?[]const u8 = null;
...@@ -1357,8 +1358,10 @@ fn buildOutputType(...@@ -1357,8 +1358,10 @@ fn buildOutputType(
1357 } else {1358 } else {
1358 enable_link_snapshots = true;1359 enable_link_snapshots = true;
1359 }1360 }
1360 } else if (mem.eql(u8, arg, "--debug-incremental")) {1361 } else if (mem.eql(u8, arg, "-fincremental")) {
1361 debug_incremental = true;1362 opt_incremental = true;
1363 } else if (mem.eql(u8, arg, "-fno-incremental")) {
1364 opt_incremental = false;
1362 } else if (mem.eql(u8, arg, "--entitlements")) {1365 } else if (mem.eql(u8, arg, "--entitlements")) {
1363 entitlements = args_iter.nextOrFatal();1366 entitlements = args_iter.nextOrFatal();
1364 } else if (mem.eql(u8, arg, "-fcompiler-rt")) {1367 } else if (mem.eql(u8, arg, "-fcompiler-rt")) {
...@@ -3225,6 +3228,8 @@ fn buildOutputType(...@@ -3225,6 +3228,8 @@ fn buildOutputType(
3225 break :b .incremental;3228 break :b .incremental;
3226 };3229 };
32273230
3231 const incremental = opt_incremental orelse false;
3232
3228 process.raiseFileDescriptorLimit();3233 process.raiseFileDescriptorLimit();
32293234
3230 var file_system_inputs: std.ArrayListUnmanaged(u8) = .{};3235 var file_system_inputs: std.ArrayListUnmanaged(u8) = .{};
...@@ -3336,7 +3341,7 @@ fn buildOutputType(...@@ -3336,7 +3341,7 @@ fn buildOutputType(
3336 .cache_mode = cache_mode,3341 .cache_mode = cache_mode,
3337 .subsystem = subsystem,3342 .subsystem = subsystem,
3338 .debug_compile_errors = debug_compile_errors,3343 .debug_compile_errors = debug_compile_errors,
3339 .debug_incremental = debug_incremental,3344 .incremental = incremental,
3340 .enable_link_snapshots = enable_link_snapshots,3345 .enable_link_snapshots = enable_link_snapshots,
3341 .install_name = install_name,3346 .install_name = install_name,
3342 .entitlements = entitlements,3347 .entitlements = entitlements,
...@@ -3443,7 +3448,7 @@ fn buildOutputType(...@@ -3443,7 +3448,7 @@ fn buildOutputType(
3443 updateModule(comp, color, root_prog_node) catch |err| switch (err) {3448 updateModule(comp, color, root_prog_node) catch |err| switch (err) {
3444 error.SemanticAnalyzeFail => {3449 error.SemanticAnalyzeFail => {
3445 assert(listen == .none);3450 assert(listen == .none);
3446 saveState(comp, debug_incremental);3451 saveState(comp, incremental);
3447 process.exit(1);3452 process.exit(1);
3448 },3453 },
3449 else => |e| return e,3454 else => |e| return e,
...@@ -3451,7 +3456,7 @@ fn buildOutputType(...@@ -3451,7 +3456,7 @@ fn buildOutputType(
3451 }3456 }
3452 if (build_options.only_c) return cleanExit();3457 if (build_options.only_c) return cleanExit();
3453 try comp.makeBinFileExecutable();3458 try comp.makeBinFileExecutable();
3454 saveState(comp, debug_incremental);3459 saveState(comp, incremental);
34553460
3456 if (test_exec_args.items.len == 0 and target.ofmt == .c) default_exec_args: {3461 if (test_exec_args.items.len == 0 and target.ofmt == .c) default_exec_args: {
3457 // Default to using `zig run` to execute the produced .c code from `zig test`.3462 // Default to using `zig run` to execute the produced .c code from `zig test`.
...@@ -4032,8 +4037,8 @@ fn createModule(...@@ -4032,8 +4037,8 @@ fn createModule(
4032 return mod;4037 return mod;
4033}4038}
40344039
4035fn saveState(comp: *Compilation, debug_incremental: bool) void {4040fn saveState(comp: *Compilation, incremental: bool) void {
4036 if (debug_incremental) {4041 if (incremental) {
4037 comp.saveState() catch |err| {4042 comp.saveState() catch |err| {
4038 warn("unable to save incremental compilation state: {s}", .{@errorName(err)});4043 warn("unable to save incremental compilation state: {s}", .{@errorName(err)});
4039 };4044 };
test/standalone/cmakedefine/build.zig+2-2
...@@ -80,8 +80,8 @@ pub fn build(b: *std.Build) void {...@@ -80,8 +80,8 @@ pub fn build(b: *std.Build) void {
80 test_step.dependOn(&wrapper_header.step);80 test_step.dependOn(&wrapper_header.step);
81}81}
8282
83fn compare_headers(step: *std.Build.Step, prog_node: std.Progress.Node) !void {83fn compare_headers(step: *std.Build.Step, options: std.Build.Step.MakeOptions) !void {
84 _ = prog_node;84 _ = options;
85 const allocator = step.owner.allocator;85 const allocator = step.owner.allocator;
86 const expected_fmt = "expected_{s}";86 const expected_fmt = "expected_{s}";
8787