| author | |
| committer | |
| log | 9d38e82b5c0f28ea6a2d8d31ebd73b6e2a8aad26 |
| tree | ba3290d61fd4c856f73a14b6346c674a1a178ffb |
| parent | 583e698256a2a26f26738c983e319d76926ef048 |
| parent | 445bd7a06fc34c9a59c6458774769bfaa2757a2f |
| signature |
make zig compiler processes live across rebuilds27 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 their | 410 | // 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 | } |
| 442 | 446 | ||
| 447 | fn 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 | |||
| 443 | const Run = struct { | 455 | const 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(); |
| 1033 | 1045 | ||
| 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 | }); | ||
| 1035 | 1051 | ||
| 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 and | 1053 | 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 tree | 1228 | \\ --fetch Exit after fetching dependency tree |
| 1213 | \\ --watch Continuously rebuild when source files are modified | 1229 | \\ --watch Continuously rebuild when source files are modified |
| 1214 | \\ --debounce <ms> Delay before rebuilding after changed file detected | 1230 | \\ --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 | }; |
| 124 | 125 | ||
| 125 | const AvailableDeps = []const struct { []const u8, []const u8 }; | 126 | const 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 | } |
| 1080 | 1081 | ||
| 1081 | fn makeUninstall(uninstall_step: *Step, prog_node: std.Progress.Node) anyerror!void { | 1082 | fn 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); |
| 1085 | 1086 |
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 | }; |
| 70 | 70 | ||
| 71 | pub const MakeFn = *const fn (step: *Step, prog_node: std.Progress.Node) anyerror!void; | 71 | pub const MakeOptions = struct { |
| 72 | progress_node: std.Progress.Node, | ||
| 73 | thread_pool: *std.Thread.Pool, | ||
| 74 | watch: bool, | ||
| 75 | }; | ||
| 76 | |||
| 77 | pub const MakeFn = *const fn (step: *Step, options: MakeOptions) anyerror!void; | ||
| 72 | 78 | ||
| 73 | pub const State = enum { | 79 | pub 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 they | 225 | /// If the Step's `make` function reports `error.MakeFailed`, it indicates they |
| 220 | /// have already reported the error. Otherwise, we add a simple error report | 226 | /// have already reported the error. Otherwise, we add a simple error report |
| 221 | /// here. | 227 | /// here. |
| 222 | pub fn make(s: *Step, prog_node: std.Progress.Node) error{ MakeFailed, MakeSkipped }!void { | 228 | pub fn make(s: *Step, options: MakeOptions) error{ MakeFailed, MakeSkipped }!void { |
| 223 | const arena = s.owner.allocator; | 229 | const arena = s.owner.allocator; |
| 224 | 230 | ||
| 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 | } |
| 262 | 268 | ||
| 263 | fn makeNoOp(step: *Step, prog_node: std.Progress.Node) anyerror!void { | 269 | fn makeNoOp(step: *Step, options: MakeOptions) anyerror!void { |
| 264 | _ = prog_node; | 270 | _ = options; |
| 265 | 271 | ||
| 266 | var all_cached = true; | 272 | var all_cached = true; |
| 267 | 273 | ||
| ... | @@ -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 | } |
| 354 | 360 | ||
| 361 | pub 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 spawned | 369 | /// 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. |
| 357 | pub fn evalZigProcess( | 371 | pub 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(); | ||
| 382 | 428 | ||
| 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 | } | ||
| 388 | 476 | ||
| 389 | try sendMessage(child.stdin.?, .update); | 477 | return result; |
| 390 | try sendMessage(child.stdin.?, .exit); | 478 | } |
| 479 | |||
| 480 | fn 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); | ||
| 391 | 488 | ||
| 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; |
| 394 | 491 | ||
| 395 | const stdout = poller.fifo(.stdout); | 492 | const stdout = zp.poller.fifo(.stdout); |
| 396 | 493 | ||
| 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); |
| 406 | 503 | ||
| ... | @@ -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 | } |
| 481 | 595 | ||
| 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 | } |
| 486 | 602 | ||
| 487 | // Send EOF to stdin. | 603 | return result; |
| 488 | child.stdin.?.close(); | 604 | } |
| 489 | child.stdin = null; | ||
| 490 | 605 | ||
| 491 | const term = child.wait() catch |err| { | 606 | pub 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 | } | ||
| 508 | 612 | ||
| 509 | try handleChildProcessTerm(s, term, null, argv); | 613 | fn setZigProcess(s: *Step, zp: *ZigProcess) void { |
| 510 | 614 | 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 | } | ||
| 517 | 619 | ||
| 518 | return result; | 620 | fn 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 | } |
| 520 | 633 | ||
| 521 | fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void { | 634 | fn 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 | } |
| 48 | 48 | ||
| 49 | fn make(step: *Step, prog_node: std.Progress.Node) !void { | 49 | fn 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 | } |
| 552 | 552 | ||
| 553 | fn make(step: *Step, prog_node: std.Progress.Node) !void { | 553 | fn 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, |
| 213 | 213 | ||
| 214 | no_builtin: bool = false, | 214 | no_builtin: bool = false, |
| 215 | 215 | ||
| 216 | /// Populated during the make phase when there is a long-lived compiler process. | ||
| 217 | /// Managed by the build runner, not user build script. | ||
| 218 | zig_process: ?*Step.ZigProcess, | ||
| 219 | |||
| 216 | pub const ExpectedCompileErrors = union(enum) { | 220 | pub 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 { |
| 398 | 402 | ||
| 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 | }; |
| 402 | 408 | ||
| 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 | }); |
| 1675 | 1681 | ||
| 1682 | try addFlag(&zig_args, "incremental", b.graph.incremental); | ||
| 1683 | |||
| 1676 | try zig_args.append("--listen=-"); | 1684 | try zig_args.append("--listen=-"); |
| 1677 | 1685 | ||
| 1678 | // Windows has an argument length limit of 32,766 characters, macOS 262,144 and Linux | 1686 | // 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 | } |
| 1737 | 1745 | ||
| 1738 | fn make(step: *Step, prog_node: std.Progress.Node) !void { | 1746 | fn 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); |
| 1741 | 1749 | ||
| 1742 | const zig_args = try getZigArgs(compile); | 1750 | const zig_args = try getZigArgs(compile); |
| 1743 | 1751 | ||
| 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 | } |
| 166 | 166 | ||
| 167 | fn make(step: *Step, prog_node: std.Progress.Node) !void { | 167 | fn 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 | } |
| 26 | 26 | ||
| 27 | fn make(step: *Step, prog_node: std.Progress.Node) !void { | 27 | fn make(step: *Step, options: Step.MakeOptions) !void { |
| 28 | _ = prog_node; // No progress to report. | 28 | _ = options; // No progress to report. |
| 29 | 29 | ||
| 30 | const fail: *Fail = @fieldParentPtr("step", step); | 30 | const fail: *Fail = @fieldParentPtr("step", step); |
| 31 | 31 |
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 | } |
| 38 | 38 | ||
| 39 | fn make(step: *Step, prog_node: std.Progress.Node) !void { | 39 | fn 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, which | 42 | // 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 files | 43 | // 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 those | 44 | // 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 | } |
| 117 | 117 | ||
| 118 | fn make(step: *Step, prog_node: std.Progress.Node) !void { | 118 | fn 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 | } |
| 57 | 57 | ||
| 58 | fn make(step: *Step, prog_node: std.Progress.Node) !void { | 58 | fn 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 | } |
| 37 | 37 | ||
| 38 | fn make(step: *Step, prog_node: std.Progress.Node) !void { | 38 | fn 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 | } |
| 92 | 92 | ||
| 93 | fn make(step: *Step, prog_node: std.Progress.Node) !void { | 93 | fn 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 }); |
| 159 | 160 | ||
| 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); |
| 162 | 163 | ||
| 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 | } |
| 412 | 412 | ||
| 413 | fn make(step: *Step, prog_node: std.Progress.Node) !void { | 413 | fn 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; |
| 416 | 416 | ||
| 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 | } |
| 25 | 25 | ||
| 26 | fn make(step: *Step, prog_node: std.Progress.Node) !void { | 26 | fn 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; | ||
| 30 | 28 | ||
| 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 | }; |
| 598 | fn make(step: *Step, prog_node: std.Progress.Node) !void { | 598 | fn 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 | } |
| 118 | 118 | ||
| 119 | fn make(step: *Step, prog_node: std.Progress.Node) !void { | 119 | fn 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); |
| 122 | 123 | ||
| ... | @@ -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 { |
| 154 | 155 | ||
| 155 | try argv_list.append(translate_c.source.getPath2(b, step)); | 156 | try argv_list.append(translate_c.source.getPath2(b, step)); |
| 156 | 157 | ||
| 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); |
| 158 | 159 | ||
| 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 | } |
| 69 | 69 | ||
| 70 | fn make(step: *Step, prog_node: std.Progress.Node) !void { | 70 | fn 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); |
| 74 | 74 |
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 | } |
| 173 | 173 | ||
| 174 | fn make(step: *Step, prog_node: std.Progress.Node) !void { | 174 | fn 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 | } |
| 271 | 271 | ||
| 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; |
| 329 | 342 | ||
| 330 | var debug_start_trace = std.debug.Trace.init; | 343 | var debug_start_trace = std.debug.Trace.init; |
| 331 | 344 | ||
| 345 | pub const have_ipc = switch (builtin.os.tag) { | ||
| 346 | .wasi, .freestanding, .windows => false, | ||
| 347 | else => true, | ||
| 348 | }; | ||
| 349 | |||
| 332 | const noop_impl = builtin.single_threaded or switch (builtin.os.tag) { | 350 | const 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 | }; |
| 40 | 41 | ||
| 41 | /// Trailing: | 42 | /// Trailing: |
src/Compilation.zig+5-4| ... | @@ -169,7 +169,7 @@ time_report: bool, | ... | @@ -169,7 +169,7 @@ time_report: bool, |
| 169 | stack_report: bool, | 169 | stack_report: bool, |
| 170 | debug_compiler_runtime_libs: bool, | 170 | debug_compiler_runtime_libs: bool, |
| 171 | debug_compile_errors: bool, | 171 | debug_compile_errors: bool, |
| 172 | debug_incremental: bool, | 172 | incremental: bool, |
| 173 | job_queued_compiler_rt_lib: bool = false, | 173 | job_queued_compiler_rt_lib: bool = false, |
| 174 | job_queued_compiler_rt_obj: bool = false, | 174 | job_queued_compiler_rt_obj: bool = false, |
| 175 | job_queued_update_builtin_zig: bool, | 175 | job_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 build | 1138 | /// Normally when you create a `Compilation`, Zig will automatically build |
| 1139 | /// and link in required dependencies, such as compiler-rt and libc. When | 1139 | /// and link in required dependencies, such as compiler-rt and libc. When |
| 1140 | /// building such dependencies themselves, this flag must be set to avoid | 1140 | /// 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(); |
| 1367 | 1368 | ||
| 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 | } |
| 2360 | 2361 | ||
| 2361 | fn appendFileSystemInput( | 2362 | pub 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; |
| 2728 | 2728 | ||
| 2729 | if (!zcu.comp.debug_incremental) return false; | 2729 | if (!zcu.comp.incremental) return false; |
| 2730 | 2730 | ||
| 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); |
| 2828 | 2828 | ||
| 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); |
| 3066 | 3066 | ||
| 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); |
| 3333 | 3333 | ||
| 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); |
| 3423 | 3423 | ||
| 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 |
| 38104 | 38104 | ||
| 38105 | pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void { | 38105 | pub 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; |
| 38108 | 38108 | ||
| 38109 | // Avoid creating dependencies on ourselves. This situation can arise when we analyze the fields | 38109 | // 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 would | 38110 | // 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 | } |
| 2680 | 2680 | ||
| 2681 | pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { | 2681 | pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { |
| 2682 | if (!zcu.comp.debug_incremental) return null; | 2682 | if (!zcu.comp.incremental) return null; |
| 2683 | 2683 | ||
| 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); |
| 890 | 890 | ||
| 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); |
| 1420 | 1420 | ||
| 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); |
| 1423 | 1427 | ||
| ... | @@ -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 | }); |
| 1529 | 1533 | ||
| 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 exit | 404 | \\ -h, --help Print this help and exit |
| 405 | \\ --color [auto|off|on] Enable or disable colored error messages | 405 | \\ --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 code | 409 | \\ -femit-bin[=path] (default) Output machine code |
| 408 | \\ -fno-emit-bin Do not output machine code | 410 | \\ -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 scope | 644 | \\ --debug-log [scope] Enable printing debug/info log messages for scope |
| 643 | \\ --debug-compile-errors Crash with helpful diagnostics at the first compile error | 645 | \\ --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 format | 646 | \\ --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 | ; |
| 648 | 649 | ||
| ... | @@ -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 | }; |
| 3227 | 3230 | ||
| 3231 | const incremental = opt_incremental orelse false; | ||
| 3232 | |||
| 3228 | process.raiseFileDescriptorLimit(); | 3233 | process.raiseFileDescriptorLimit(); |
| 3229 | 3234 | ||
| 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); |
| 3455 | 3460 | ||
| 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 | } |
| 4034 | 4039 | ||
| 4035 | fn saveState(comp: *Compilation, debug_incremental: bool) void { | 4040 | fn 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 | } |
| 82 | 82 | ||
| 83 | fn compare_headers(step: *std.Build.Step, prog_node: std.Progress.Node) !void { | 83 | fn 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}"; |
| 87 | 87 |