Skip to content

Commit d7c59fd

Browse files
committed
std.Build.Step.Run: integrate with --watch
1 parent e7d198e commit d7c59fd

File tree

2 files changed

+44
-4
lines changed

2 files changed

+44
-4
lines changed

lib/std/Build/Step.zig

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,18 +582,35 @@ pub fn allocPrintCmd2(
582582
return buf.toOwnedSlice(arena);
583583
}
584584

585+
/// Prefer `cacheHitAndWatch` unless you already added watch inputs
586+
/// separately from using the cache system.
585587
pub fn cacheHit(s: *Step, man: *Build.Cache.Manifest) !bool {
586588
s.result_cached = man.hit() catch |err| return failWithCacheError(s, man, err);
587589
return s.result_cached;
588590
}
589591

592+
/// Clears previous watch inputs, if any, and then populates watch inputs from
593+
/// the full set of files picked up by the cache manifest.
594+
///
595+
/// Must be accompanied with `writeManifestAndWatch`.
596+
pub fn cacheHitAndWatch(s: *Step, man: *Build.Cache.Manifest) !bool {
597+
const is_hit = man.hit() catch |err| return failWithCacheError(s, man, err);
598+
s.result_cached = is_hit;
599+
// The above call to hit() populates the manifest with files, so in case of
600+
// a hit, we need to populate watch inputs.
601+
if (is_hit) try setWatchInputsFromManifest(s, man);
602+
return is_hit;
603+
}
604+
590605
fn failWithCacheError(s: *Step, man: *const Build.Cache.Manifest, err: anyerror) anyerror {
591606
const i = man.failed_file_index orelse return err;
592607
const pp = man.files.keys()[i].prefixed_path;
593608
const prefix = man.cache.prefixes()[pp.prefix].path orelse "";
594609
return s.fail("{s}: {s}/{s}", .{ @errorName(err), prefix, pp.sub_path });
595610
}
596611

612+
/// Prefer `writeManifestAndWatch` unless you already added watch inputs
613+
/// separately from using the cache system.
597614
pub fn writeManifest(s: *Step, man: *Build.Cache.Manifest) !void {
598615
if (s.test_results.isSuccess()) {
599616
man.writeManifest() catch |err| {
@@ -602,6 +619,29 @@ pub fn writeManifest(s: *Step, man: *Build.Cache.Manifest) !void {
602619
}
603620
}
604621

622+
/// Clears previous watch inputs, if any, and then populates watch inputs from
623+
/// the full set of files picked up by the cache manifest.
624+
///
625+
/// Must be accompanied with `cacheHitAndWatch`.
626+
pub fn writeManifestAndWatch(s: *Step, man: *Build.Cache.Manifest) !void {
627+
try writeManifest(s, man);
628+
try setWatchInputsFromManifest(s, man);
629+
}
630+
631+
fn setWatchInputsFromManifest(s: *Step, man: *Build.Cache.Manifest) !void {
632+
const arena = s.owner.allocator;
633+
const prefixes = man.cache.prefixes();
634+
clearWatchInputs(s);
635+
for (man.files.keys()) |file| {
636+
// The file path data is freed when the cache manifest is cleaned up at the end of `make`.
637+
const sub_path = try arena.dupe(u8, file.prefixed_path.sub_path);
638+
try addWatchInputFromPath(s, .{
639+
.root_dir = prefixes[file.prefixed_path.prefix],
640+
.sub_path = std.fs.path.dirname(sub_path) orelse "",
641+
}, std.fs.path.basename(sub_path));
642+
}
643+
}
644+
605645
/// For steps that have a single input that never changes when re-running `make`.
606646
pub fn singleUnchangingWatchInput(step: *Step, lazy_path: Build.LazyPath) Allocator.Error!void {
607647
if (!step.inputs.populated()) try step.addWatchInput(lazy_path);

lib/std/Build/Step/Run.zig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {
615615
// On Windows we don't have rpaths so we have to add .dll search paths to PATH
616616
run.addPathForDynLibs(artifact);
617617
}
618-
const file_path = artifact.installed_path orelse artifact.generated_bin.?.path.?; // the path is guaranteed to be set
618+
const file_path = artifact.installed_path orelse artifact.generated_bin.?.path.?;
619619

620620
try argv_list.append(file_path);
621621

@@ -665,7 +665,7 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {
665665
_ = try man.addFile(lazy_path.getPath2(b, step), null);
666666
}
667667

668-
if (!has_side_effects and try step.cacheHit(&man)) {
668+
if (!has_side_effects and try step.cacheHitAndWatch(&man)) {
669669
// cache hit, skip running command
670670
const digest = man.final();
671671

@@ -719,7 +719,7 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {
719719
}
720720

721721
try runCommand(run, argv_list.items, has_side_effects, output_dir_path, prog_node);
722-
if (!has_side_effects) try step.writeManifest(&man);
722+
if (!has_side_effects) try step.writeManifestAndWatch(&man);
723723
return;
724724
};
725725

@@ -795,7 +795,7 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {
795795
};
796796
}
797797

798-
if (!has_side_effects) try step.writeManifest(&man);
798+
if (!has_side_effects) try step.writeManifestAndWatch(&man);
799799

800800
try populateGeneratedPaths(
801801
arena,

0 commit comments

Comments
 (0)