@@ -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
79
pub const State = enum {
74
80
precheck_unstarted ,
@@ -219,10 +225,10 @@ pub fn init(options: StepOptions) Step {
219
225
/// If the Step's `make` function reports `error.MakeFailed`, it indicates they
220
226
/// have already reported the error. Otherwise, we add a simple error report
221
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
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
232
error .MakeFailed = > return error .MakeFailed ,
227
233
error .MakeSkipped = > return error .MakeSkipped ,
228
234
else = > {
@@ -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 {
264
- _ = prog_node ;
269
+ fn makeNoOp (step : * Step , options : MakeOptions ) anyerror ! void {
270
+ _ = options ;
265
271
266
272
var all_cached = true ;
267
273
@@ -352,13 +358,25 @@ pub fn addError(step: *Step, comptime fmt: []const u8, args: anytype) error{OutO
352
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
+
365
+ pub const StreamEnum = enum { stdout , stderr };
366
+ };
367
+
355
368
/// Assumes that argv contains `--listen=-` and that the process being spawned
356
369
/// is the zig compiler - the same version that compiled the build runner.
357
370
pub fn evalZigProcess (
358
371
s : * Step ,
359
372
argv : []const []const u8 ,
360
373
prog_node : std.Progress.Node ,
374
+ watch : bool ,
361
375
) ! ? []const u8 {
376
+ if (s .getZigProcess ()) | zp | {
377
+ assert (watch );
378
+ return zigProcessUpdate (s , zp , watch );
379
+ }
362
380
assert (argv .len != 0 );
363
381
const b = s .owner ;
364
382
const arena = b .allocator ;
@@ -378,29 +396,76 @@ pub fn evalZigProcess(
378
396
child .spawn () catch | err | return s .fail ("unable to spawn {s}: {s}" , .{
379
397
argv [0 ], @errorName (err ),
380
398
});
381
- var timer = try std .time .Timer .start ();
382
399
383
- var poller = std .io .poll (gpa , enum { stdout , stderr }, .{
384
- .stdout = child .stdout .? ,
385
- .stderr = child .stderr .? ,
386
- });
387
- defer poller .deinit ();
400
+ const zp = try arena .create (ZigProcess );
401
+ zp .* = .{
402
+ .child = child ,
403
+ .poller = std .io .poll (gpa , ZigProcess .StreamEnum , .{
404
+ .stdout = child .stdout .? ,
405
+ .stderr = child .stderr .? ,
406
+ }),
407
+ };
408
+ if (watch ) s .setZigProcess (zp );
409
+ defer if (! watch ) zp .poller .deinit ();
410
+
411
+ const result = try zigProcessUpdate (s , zp , watch );
412
+
413
+ if (! watch ) {
414
+ // Send EOF to stdin.
415
+ zp .child .stdin .? .close ();
416
+ zp .child .stdin = null ;
417
+
418
+ const term = zp .child .wait () catch | err | {
419
+ return s .fail ("unable to wait for {s}: {s}" , .{ argv [0 ], @errorName (err ) });
420
+ };
421
+ s .result_peak_rss = zp .child .resource_usage_statistics .getMaxRss () orelse 0 ;
422
+
423
+ // Special handling for Compile step that is expecting compile errors.
424
+ if (s .cast (Compile )) | compile | switch (term ) {
425
+ .Exited = > {
426
+ // Note that the exit code may be 0 in this case due to the
427
+ // compiler server protocol.
428
+ if (compile .expect_errors != null ) {
429
+ return error .NeedCompileErrorCheck ;
430
+ }
431
+ },
432
+ else = > {},
433
+ };
434
+
435
+ try handleChildProcessTerm (s , term , null , argv );
436
+ }
437
+
438
+ if (s .result_error_bundle .errorMessageCount () > 0 ) {
439
+ return s .fail ("the following command failed with {d} compilation errors:\n {s}" , .{
440
+ s .result_error_bundle .errorMessageCount (),
441
+ try allocPrintCmd (arena , null , argv ),
442
+ });
443
+ }
444
+
445
+ return result ;
446
+ }
388
447
389
- try sendMessage (child .stdin .? , .update );
390
- try sendMessage (child .stdin .? , .exit );
448
+ fn zigProcessUpdate (s : * Step , zp : * ZigProcess , watch : bool ) ! ? []const u8 {
449
+ const b = s .owner ;
450
+ const arena = b .allocator ;
451
+
452
+ var timer = try std .time .Timer .start ();
453
+
454
+ try sendMessage (zp .child .stdin .? , .update );
455
+ if (! watch ) try sendMessage (zp .child .stdin .? , .exit );
391
456
392
457
const Header = std .zig .Server .Message .Header ;
393
458
var result : ? []const u8 = null ;
394
459
395
- const stdout = poller .fifo (.stdout );
460
+ const stdout = zp . poller .fifo (.stdout );
396
461
397
462
poll : while (true ) {
398
463
while (stdout .readableLength () < @sizeOf (Header )) {
399
- if (! (try poller .poll ())) break :poll ;
464
+ if (! (try zp . poller .poll ())) break :poll ;
400
465
}
401
466
const header = stdout .reader ().readStruct (Header ) catch unreachable ;
402
467
while (stdout .readableLength () < header .bytes_len ) {
403
- if (! (try poller .poll ())) break :poll ;
468
+ if (! (try zp . poller .poll ())) break :poll ;
404
469
}
405
470
const body = stdout .readableSliceOfLen (header .bytes_len );
406
471
@@ -428,12 +493,22 @@ pub fn evalZigProcess(
428
493
.string_bytes = try arena .dupe (u8 , string_bytes ),
429
494
.extra = extra_array ,
430
495
};
496
+ if (watch ) {
497
+ // This message indicates the end of the update.
498
+ stdout .discard (body .len );
499
+ break ;
500
+ }
431
501
},
432
502
.emit_bin_path = > {
433
503
const EbpHdr = std .zig .Server .Message .EmitBinPath ;
434
504
const ebp_hdr = @as (* align (1 ) const EbpHdr , @ptrCast (body ));
435
505
s .result_cached = ebp_hdr .flags .cache_hit ;
436
506
result = try arena .dupe (u8 , body [@sizeOf (EbpHdr ).. ]);
507
+ if (watch ) {
508
+ // This message indicates the end of the update.
509
+ stdout .discard (body .len );
510
+ break ;
511
+ }
437
512
},
438
513
.file_system_inputs = > {
439
514
s .clearWatchInputs ();
@@ -470,6 +545,13 @@ pub fn evalZigProcess(
470
545
};
471
546
try addWatchInputFromPath (s , path , std .fs .path .basename (sub_path ));
472
547
},
548
+ .global_cache = > {
549
+ const path : Build.Cache.Path = .{
550
+ .root_dir = s .owner .graph .global_cache_root ,
551
+ .sub_path = sub_path_dirname ,
552
+ };
553
+ try addWatchInputFromPath (s , path , std .fs .path .basename (sub_path ));
554
+ },
473
555
}
474
556
}
475
557
},
@@ -479,43 +561,28 @@ pub fn evalZigProcess(
479
561
stdout .discard (body .len );
480
562
}
481
563
482
- const stderr = poller .fifo (.stderr );
564
+ s .result_duration_ns = timer .read ();
565
+
566
+ const stderr = zp .poller .fifo (.stderr );
483
567
if (stderr .readableLength () > 0 ) {
484
568
try s .result_error_msgs .append (arena , try stderr .toOwnedSlice ());
485
569
}
486
570
487
- // Send EOF to stdin.
488
- child .stdin .? .close ();
489
- child .stdin = null ;
571
+ return result ;
572
+ }
490
573
491
- const term = child .wait () catch | err | {
492
- return s .fail ("unable to wait for {s}: {s}" , .{ argv [0 ], @errorName (err ) });
574
+ fn getZigProcess (s : * Step ) ? * ZigProcess {
575
+ return switch (s .id ) {
576
+ .compile = > s .cast (Compile ).? .zig_process ,
577
+ else = > null ,
493
578
};
494
- s .result_duration_ns = timer .read ();
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
- };
508
-
509
- try handleChildProcessTerm (s , term , null , argv );
579
+ }
510
580
511
- if (s .result_error_bundle .errorMessageCount () > 0 ) {
512
- return s .fail ("the following command failed with {d} compilation errors:\n {s}" , .{
513
- s .result_error_bundle .errorMessageCount (),
514
- try allocPrintCmd (arena , null , argv ),
515
- });
581
+ fn setZigProcess (s : * Step , zp : * ZigProcess ) void {
582
+ switch (s .id ) {
583
+ .compile = > s .cast (Compile ).? .zig_process = zp ,
584
+ else = > unreachable ,
516
585
}
517
-
518
- return result ;
519
586
}
520
587
521
588
fn sendMessage (file : std.fs.File , tag : std.zig.Client.Message.Tag ) ! void {
0 commit comments