| ... | ... | @@ -36,8 +36,10 @@ env_map: ?*EnvMap, |
| 36 | 36 | /// be skipped if all output files are up-to-date and input files are |
| 37 | 37 | /// unchanged. |
| 38 | 38 | stdio: StdIo = .infer_from_args, |
| 39 | | /// This field must be `null` if stdio is `inherit`. |
| 40 | | stdin: ?[]const u8 = null, |
| 39 | |
| 40 | /// This field must be `.none` if stdio is `inherit`. |
| 41 | /// It should be only set using `setStdIn`. |
| 42 | stdin: StdIn = .none, |
| 41 | 43 | |
| 42 | 44 | /// Additional file paths relative to build.zig that, when modified, indicate |
| 43 | 45 | /// that the Run step should be re-executed. |
| ... | ... | @@ -77,6 +79,12 @@ captured_stderr: ?*Output = null, |
| 77 | 79 | |
| 78 | 80 | has_side_effects: bool = false, |
| 79 | 81 | |
| 82 | pub const StdIn = union(enum) { |
| 83 | none, |
| 84 | bytes: []const u8, |
| 85 | file_source: std.Build.FileSource, |
| 86 | }; |
| 87 | |
| 80 | 88 | pub const StdIo = union(enum) { |
| 81 | 89 | /// Whether the Run step has side-effects will be determined by whether or not one |
| 82 | 90 | /// of the args is an output file (added with `addOutputFileArg`). |
| ... | ... | @@ -229,6 +237,14 @@ pub fn addArgs(self: *Run, args: []const []const u8) void { |
| 229 | 237 | } |
| 230 | 238 | } |
| 231 | 239 | |
| 240 | pub fn setStdIn(self: *Run, stdin: StdIn) void { |
| 241 | switch (stdin) { |
| 242 | .file_source => |file_source| file_source.addStepDependencies(&self.step), |
| 243 | .bytes, .none => {}, |
| 244 | } |
| 245 | self.stdin = stdin; |
| 246 | } |
| 247 | |
| 232 | 248 | pub fn clearEnvironment(self: *Run) void { |
| 233 | 249 | const b = self.step.owner; |
| 234 | 250 | const new_env_map = b.allocator.create(EnvMap) catch @panic("OOM"); |
| ... | ... | @@ -454,8 +470,15 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 454 | 470 | } |
| 455 | 471 | } |
| 456 | 472 | |
| 457 | | if (self.stdin) |bytes| { |
| 458 | | man.hash.addBytes(bytes); |
| 473 | switch (self.stdin) { |
| 474 | .bytes => |bytes| { |
| 475 | man.hash.addBytes(bytes); |
| 476 | }, |
| 477 | .file_source => |file_source| { |
| 478 | const file_path = file_source.getPath(b); |
| 479 | _ = try man.addFile(file_path, null); |
| 480 | }, |
| 481 | .none => {}, |
| 459 | 482 | } |
| 460 | 483 | |
| 461 | 484 | if (self.captured_stdout) |output| { |
| ... | ... | @@ -934,7 +957,7 @@ fn spawnChildAndCollect( |
| 934 | 957 | }; |
| 935 | 958 | if (self.captured_stdout != null) child.stdout_behavior = .Pipe; |
| 936 | 959 | if (self.captured_stderr != null) child.stderr_behavior = .Pipe; |
| 937 | | if (self.stdin != null) { |
| 960 | if (self.stdin != .none) { |
| 938 | 961 | assert(child.stdin_behavior != .Inherit); |
| 939 | 962 | child.stdin_behavior = .Pipe; |
| 940 | 963 | } |
| ... | ... | @@ -1158,12 +1181,27 @@ fn sendRunTestMessage(file: std.fs.File, index: u32) !void { |
| 1158 | 1181 | fn evalGeneric(self: *Run, child: *std.process.Child) !StdIoResult { |
| 1159 | 1182 | const arena = self.step.owner.allocator; |
| 1160 | 1183 | |
| 1161 | | if (self.stdin) |stdin| { |
| 1162 | | child.stdin.?.writeAll(stdin) catch |err| { |
| 1163 | | return self.step.fail("unable to write stdin: {s}", .{@errorName(err)}); |
| 1164 | | }; |
| 1165 | | child.stdin.?.close(); |
| 1166 | | child.stdin = null; |
| 1184 | switch (self.stdin) { |
| 1185 | .bytes => |bytes| { |
| 1186 | child.stdin.?.writeAll(bytes) catch |err| { |
| 1187 | return self.step.fail("unable to write stdin: {s}", .{@errorName(err)}); |
| 1188 | }; |
| 1189 | child.stdin.?.close(); |
| 1190 | child.stdin = null; |
| 1191 | }, |
| 1192 | .file_source => |file_source| { |
| 1193 | const path = file_source.getPath(self.step.owner); |
| 1194 | const file = self.step.owner.build_root.handle.openFile(path, .{}) catch |err| { |
| 1195 | return self.step.fail("unable to open stdin file: {s}", .{@errorName(err)}); |
| 1196 | }; |
| 1197 | defer file.close(); |
| 1198 | child.stdin.?.writeFileAll(file, .{}) catch |err| { |
| 1199 | return self.step.fail("unable to write file to stdin: {s}", .{@errorName(err)}); |
| 1200 | }; |
| 1201 | child.stdin.?.close(); |
| 1202 | child.stdin = null; |
| 1203 | }, |
| 1204 | .none => {}, |
| 1167 | 1205 | } |
| 1168 | 1206 | |
| 1169 | 1207 | // These are not optionals, as a workaround for |