| ... | @@ -55,531 +55,564 @@ pub fn make( | ... | @@ -55,531 +55,564 @@ pub fn make( |
| 55 | var man = graph.cache.obtain(); | 55 | var man = graph.cache.obtain(); |
| 56 | defer man.deinit(); | 56 | defer man.deinit(); |
| 57 | | 57 | |
| 58 | if (conf_run.environ_map.value) |environ_map_index| { | 58 | var tmp_dir_path: ["tmp".len + Dir.path.sep_str.len + std.fmt.hex(@as(u64, 0)).len]u8 = undefined; |
| 59 | const environ_map = environ_map_index.get(conf); | 59 | |
| 60 | for (environ_map.keys.slice(conf), environ_map.values.slice(conf)) |key, value| { | 60 | const has_side_effects = has_side_effects: { |
| 61 | man.hash.addBytesZ(key.slice(conf)); | 61 | if (conf_run.environ_map.value) |environ_map_index| { |
| 62 | man.hash.addBytesZ(value.slice(conf)); | 62 | const environ_map = environ_map_index.get(conf); |
| | 63 | for (environ_map.keys.slice(conf), environ_map.values.slice(conf)) |key, value| { |
| | 64 | man.hash.addBytesZ(key.slice(conf)); |
| | 65 | man.hash.addBytesZ(value.slice(conf)); |
| | 66 | } |
| 63 | } | 67 | } |
| 64 | } | | |
| 65 | | 68 | |
| 66 | for (conf_run.preopens.slice) |preopen| { | 69 | for (conf_run.preopens.slice) |preopen| { |
| 67 | man.hash.addBytesZ(preopen.name.slice(conf)); | 70 | man.hash.addBytesZ(preopen.name.slice(conf)); |
| 68 | const cwd_path = try maker.resolveLazyPathIndex(arena, preopen.path, run_index); | 71 | const cwd_path = try maker.resolveLazyPathIndex(arena, preopen.path, run_index); |
| 69 | man.hash.addBytes(try cwd_path.toString(arena)); | 72 | man.hash.addBytes(try cwd_path.toString(arena)); |
| 70 | } | 73 | } |
| 71 | | 74 | |
| 72 | man.hash.add(graph.fuzzing); | 75 | man.hash.add(graph.fuzzing); |
| 73 | man.hash.add(conf_run.flags.color); | 76 | man.hash.add(conf_run.flags.color); |
| 74 | man.hash.add(conf_run.flags.disable_zig_progress); | 77 | man.hash.add(conf_run.flags.disable_zig_progress); |
| 75 | | 78 | |
| 76 | var any_discovered_inputs = switch (conf_run.flags.stdio) { | 79 | var any_discovered_inputs = switch (conf_run.flags.stdio) { |
| 77 | .infer_from_args, .inherit, .check, .zig_test => false, | 80 | .infer_from_args, .inherit, .check, .zig_test => false, |
| 78 | .protocol => true, | 81 | .protocol => true, |
| 79 | }; | 82 | }; |
| 80 | var any_output_args = false; | 83 | var any_output_args = false; |
| 81 | var any_cli_positionals = false; | 84 | var any_cli_positionals = false; |
| | 85 | |
| | 86 | for (switch (conf_run.flags.stdio) { |
| | 87 | .infer_from_args, .inherit, .check, .zig_test => conf_run.args.slice, |
| | 88 | .protocol => conf_run.args.slice[0..1], // arguments communicated over protocol |
| | 89 | }) |arg_index| { |
| | 90 | const arg = arg_index.get(conf); |
| | 91 | try argv_list.ensureUnusedCapacity(gpa, 1); |
| | 92 | switch (arg.flags.tag) { |
| | 93 | .string => { |
| | 94 | const string = arg.prefix.value.?.slice(conf); |
| | 95 | argv_list.appendAssumeCapacity(string); |
| | 96 | man.hash.addBytesZ(string); |
| | 97 | }, |
| | 98 | .path_file => { |
| | 99 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; |
| | 100 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; |
| | 101 | const file_path = try maker.resolveLazyPathIndex(arena, arg.path.value.?, run_index); |
| | 102 | argv_list.appendAssumeCapacity(try mem.concat(arena, u8, &.{ |
| | 103 | prefix, try convertPathArg(arena, run_index, maker, file_path, arg.flags.make_absolute), suffix, |
| | 104 | })); |
| | 105 | man.hash.add(arg.flags.make_absolute); |
| | 106 | man.hash.addBytesZ(prefix); |
| | 107 | man.hash.addBytesZ(suffix); |
| | 108 | _ = try man.addInputPath(file_path, .{}); |
| | 109 | }, |
| | 110 | .path_directory => { |
| | 111 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; |
| | 112 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; |
| | 113 | const file_path = try maker.resolveLazyPathIndex(arena, arg.path.value.?, run_index); |
| | 114 | const resolved_arg = try mem.concat(arena, u8, &.{ |
| | 115 | prefix, try convertPathArg(arena, run_index, maker, file_path, arg.flags.make_absolute), suffix, |
| | 116 | }); |
| | 117 | argv_list.appendAssumeCapacity(resolved_arg); |
| | 118 | man.hash.add(arg.flags.make_absolute); |
| | 119 | man.hash.addBytes(resolved_arg); |
| | 120 | }, |
| | 121 | .file_content => { |
| | 122 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; |
| | 123 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; |
| | 124 | const file_path = try maker.resolveLazyPathIndex(arena, arg.path.value.?, run_index); |
| | 125 | |
| | 126 | var result: std.Io.Writer.Allocating = .init(arena); |
| | 127 | result.writer.writeAll(prefix) catch return error.OutOfMemory; |
| | 128 | |
| | 129 | const file = file_path.root_dir.handle.openFile(io, file_path.sub_path, .{}) catch |err| |
| | 130 | return step.fail(maker, "unable to open input file {qf}: {t}", .{ file_path, err }); |
| | 131 | defer file.close(io); |
| | 132 | |
| | 133 | var file_reader = file.reader(io, &.{}); |
| | 134 | _ = file_reader.interface.streamRemaining(&result.writer) catch |err| switch (err) { |
| | 135 | error.ReadFailed => switch (file_reader.err.?) { |
| | 136 | error.Canceled => |e| return e, |
| | 137 | else => |e| return step.fail(maker, "failed to read from {qf}: {t}", .{ file_path, e }), |
| | 138 | }, |
| | 139 | error.WriteFailed => return error.OutOfMemory, |
| | 140 | }; |
| | 141 | result.writer.writeAll(suffix) catch return error.OutOfMemory; |
| 82 | | 142 | |
| 83 | for (switch (conf_run.flags.stdio) { | 143 | argv_list.appendAssumeCapacity(result.written()); |
| 84 | .infer_from_args, .inherit, .check, .zig_test => conf_run.args.slice, | 144 | man.hash.addBytesZ(prefix); |
| 85 | .protocol => conf_run.args.slice[0..1], // arguments communicated over protocol | 145 | _ = try man.addInputPath(file_path, .{}); |
| 86 | }) |arg_index| { | 146 | man.hash.addBytesZ(suffix); |
| 87 | const arg = arg_index.get(conf); | 147 | }, |
| 88 | try argv_list.ensureUnusedCapacity(gpa, 1); | 148 | .artifact => { |
| 89 | switch (arg.flags.tag) { | 149 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; |
| 90 | .string => { | 150 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; |
| 91 | const string = arg.prefix.value.?.slice(conf); | 151 | const producer_index = arg.producer.value.?; |
| 92 | argv_list.appendAssumeCapacity(string); | 152 | const producer_step = producer_index.ptr(conf); |
| 93 | man.hash.addBytesZ(string); | 153 | const producer = producer_step.extended.get(conf.extra).compile; |
| 94 | }, | 154 | const producer_make_comp_step = maker.stepByIndex(producer_index); |
| 95 | .path_file => { | 155 | const producer_make_comp = &producer_make_comp_step.extended.compile; |
| 96 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; | 156 | |
| 97 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; | 157 | const file_path = producer_make_comp.installed_path orelse |
| 98 | const file_path = try maker.resolveLazyPathIndex(arena, arg.path.value.?, run_index); | 158 | maker.generatedPath(producer.generated_bin.value.?); |
| 99 | argv_list.appendAssumeCapacity(try mem.concat(arena, u8, &.{ | 159 | |
| 100 | prefix, try convertPathArg(arena, run_index, maker, file_path, arg.flags.make_absolute), suffix, | 160 | argv_list.appendAssumeCapacity(try mem.concat(arena, u8, &.{ |
| 101 | })); | 161 | prefix, try convertPathArg(arena, run_index, maker, file_path, arg.flags.make_absolute), suffix, |
| 102 | man.hash.add(arg.flags.make_absolute); | 162 | })); |
| 103 | man.hash.addBytesZ(prefix); | 163 | |
| 104 | man.hash.addBytesZ(suffix); | 164 | man.hash.add(arg.flags.make_absolute); |
| 105 | _ = try man.addInputPath(file_path, .{}); | 165 | man.hash.addBytesZ(prefix); |
| 106 | }, | 166 | man.hash.addBytesZ(suffix); |
| 107 | .path_directory => { | 167 | _ = try man.addInputPath(file_path, .{}); |
| 108 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; | 168 | }, |
| 109 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; | 169 | .output_file, .output_directory => { |
| 110 | const file_path = try maker.resolveLazyPathIndex(arena, arg.path.value.?, run_index); | 170 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; |
| 111 | const resolved_arg = try mem.concat(arena, u8, &.{ | 171 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; |
| 112 | prefix, try convertPathArg(arena, run_index, maker, file_path, arg.flags.make_absolute), suffix, | 172 | const basename = arg.basename.value.?.slice(conf); |
| 113 | }); | 173 | |
| 114 | argv_list.appendAssumeCapacity(resolved_arg); | 174 | man.hash.add(arg.flags.make_absolute); |
| 115 | man.hash.add(arg.flags.make_absolute); | 175 | man.hash.addBytesZ(prefix); |
| 116 | man.hash.addBytes(resolved_arg); | 176 | man.hash.addBytesZ(basename); |
| | 177 | man.hash.addBytesZ(suffix); |
| | 178 | man.hash.add(arg.flags.dep_file); |
| | 179 | |
| | 180 | if (arg.flags.dep_file) any_discovered_inputs = true; |
| | 181 | any_output_args = true; |
| | 182 | |
| | 183 | // Add a placeholder into the argument list because we need the |
| | 184 | // manifest hash to be updated with all arguments before the |
| | 185 | // object directory is computed. |
| | 186 | try output_placeholders.append(gpa, .{ |
| | 187 | .index = @intCast(argv_list.items.len), |
| | 188 | .offset = 0, |
| | 189 | .arg_index = arg_index, |
| | 190 | }); |
| | 191 | _ = argv_list.addOneAssumeCapacity(); |
| | 192 | }, |
| | 193 | .passthru => { |
| | 194 | any_cli_positionals = true; |
| | 195 | if (maker.run_args) |run_args| { |
| | 196 | try argv_list.appendSlice(gpa, run_args); |
| | 197 | man.hash.addListOfBytes(run_args); |
| | 198 | } |
| | 199 | }, |
| | 200 | .enable_darling => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_darling, arg.prefix.value, arg.suffix.value), |
| | 201 | .enable_qemu => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_qemu, arg.prefix.value, arg.suffix.value), |
| | 202 | .enable_rosetta => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_rosetta, arg.prefix.value, arg.suffix.value), |
| | 203 | .enable_wasmtime => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_wasmtime, arg.prefix.value, arg.suffix.value), |
| | 204 | .enable_wine => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_wine, arg.prefix.value, arg.suffix.value), |
| | 205 | } |
| | 206 | } |
| | 207 | |
| | 208 | var owned_dirs: std.bit_set.Dynamic = .{}; |
| | 209 | var inherit_dirs: std.ArrayList(Io.Dir) = .empty; |
| | 210 | var owned_files: std.bit_set.Dynamic = .{}; |
| | 211 | var inherit_files: std.ArrayList(Io.File) = .empty; |
| | 212 | var protocol_args: std.ArrayList(u8) = .empty; |
| | 213 | var input_dirs: std.ArrayList(Cache.Path) = .empty; |
| | 214 | defer { |
| | 215 | for (inherit_dirs.items, 0..) |inherit_dir, inherit_dir_index| |
| | 216 | if (owned_dirs.isSet(inherit_dir_index)) inherit_dir.close(io); |
| | 217 | for (inherit_files.items, 0..) |inherit_file, inherit_file_index| |
| | 218 | if (owned_files.isSet(inherit_file_index)) inherit_file.close(io); |
| | 219 | owned_dirs.deinit(gpa); |
| | 220 | inherit_dirs.deinit(gpa); |
| | 221 | owned_files.deinit(gpa); |
| | 222 | inherit_files.deinit(gpa); |
| | 223 | protocol_args.deinit(gpa); |
| | 224 | input_dirs.deinit(gpa); |
| | 225 | } |
| | 226 | switch (conf_run.flags.stdio) { |
| | 227 | .infer_from_args, .inherit, .check => {}, |
| | 228 | .zig_test => { |
| | 229 | const cache_dir_string = try convertPathArg(arena, run_index, maker, .{ .root_dir = cache_root }, false); |
| | 230 | |
| | 231 | try argv_list.ensureUnusedCapacity(gpa, 3); |
| | 232 | argv_list.appendAssumeCapacity(try arena.print("--cache-dir={s}", .{cache_dir_string})); |
| | 233 | argv_list.appendAssumeCapacity(try arena.print("--seed=0x{x}", .{graph.random_seed})); |
| | 234 | argv_list.appendAssumeCapacity("--listen=-"); |
| 117 | }, | 235 | }, |
| 118 | .file_content => { | 236 | .protocol => { |
| 119 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; | 237 | argv_list.appendAssumeCapacity("--listen=-"); |
| 120 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; | 238 | try input_dirs.append(gpa, if (conf_run.cwd.value) |lazy_cwd| |
| 121 | const file_path = try maker.resolveLazyPathIndex(arena, arg.path.value.?, run_index); | 239 | try maker.resolveLazyPathIndex(arena, lazy_cwd, run_index) |
| | 240 | else |
| | 241 | .cwd()); |
| | 242 | for (conf_run.args.slice[1..]) |arg_index| { |
| | 243 | const arg = arg_index.get(conf); |
| | 244 | switch (arg.flags.tag) { |
| | 245 | .string => { |
| | 246 | const string = arg.prefix.value.?.slice(conf); |
| 122 | | 247 | |
| 123 | var result: std.Io.Writer.Allocating = .init(arena); | 248 | man.hash.addBytesZ(string); |
| 124 | result.writer.writeAll(prefix) catch return error.OutOfMemory; | | |
| 125 | | 249 | |
| 126 | const file = file_path.root_dir.handle.openFile(io, file_path.sub_path, .{}) catch |err| | 250 | try protocol_args.ensureUnusedCapacity(gpa, 1 + string.len + 1); |
| 127 | return step.fail(maker, "unable to open input file {qf}: {t}", .{ file_path, err }); | 251 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.string)); |
| 128 | defer file.close(io); | 252 | protocol_args.appendSliceAssumeCapacity(string); |
| | 253 | protocol_args.appendAssumeCapacity(0); |
| | 254 | }, |
| | 255 | .path_file => { |
| | 256 | const lazy_path = arg.path.value.?.get(conf); |
| | 257 | switch (lazy_path) { |
| | 258 | else => {}, |
| | 259 | .relative => |relative| switch (relative.flags.base) { |
| | 260 | else => {}, |
| | 261 | .libc_runtimes => if (graph.libc_runtimes_dir == null) continue, |
| | 262 | }, |
| | 263 | } |
| 129 | | 264 | |
| 130 | var file_reader = file.reader(io, &.{}); | 265 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; |
| 131 | _ = file_reader.interface.streamRemaining(&result.writer) catch |err| switch (err) { | 266 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; |
| 132 | error.ReadFailed => switch (file_reader.err.?) { | 267 | const file_path = try maker.resolveLazyPath(arena, lazy_path, run_index); |
| 133 | error.Canceled => |e| return e, | 268 | |
| 134 | else => |e| return step.fail(maker, "failed to read from {qf}: {t}", .{ file_path, e }), | 269 | try owned_files.resize(gpa, owned_files.bit_length + 1, true); |
| 135 | }, | 270 | try inherit_files.ensureUnusedCapacity(gpa, 1); |
| 136 | error.WriteFailed => return error.OutOfMemory, | 271 | const file = file_path.root_dir.handle.openFile(io, file_path.sub_path, .{}) catch |err| |
| 137 | }; | 272 | return step.fail(maker, "unable to open input file {qf}: {t}", .{ file_path, err }); |
| 138 | result.writer.writeAll(suffix) catch return error.OutOfMemory; | 273 | inherit_files.appendAssumeCapacity(file); |
| | 274 | |
| | 275 | man.hash.addBytesZ(prefix); |
| | 276 | _ = try man.addInputPath(file_path, .{}); |
| | 277 | man.hash.addBytesZ(suffix); |
| | 278 | |
| | 279 | try protocol_args.ensureUnusedCapacity(gpa, 1 + prefix.len + 1 + |
| | 280 | 1 + @sizeOf(Io.File.Handle) + |
| | 281 | 1 + suffix.len + 1); |
| | 282 | if (prefix.len > 0) { |
| | 283 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.prefix)); |
| | 284 | protocol_args.appendSliceAssumeCapacity(prefix); |
| | 285 | protocol_args.appendAssumeCapacity(0); |
| | 286 | } |
| | 287 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.input_file)); |
| | 288 | const file_handle: *align(1) Io.File.Handle = |
| | 289 | @ptrCast(protocol_args.addManyAsArrayAssumeCapacity(@sizeOf(Io.File.Handle))); |
| | 290 | file_handle.* = file.handle; |
| | 291 | if (suffix.len > 0) { |
| | 292 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.suffix)); |
| | 293 | protocol_args.appendSliceAssumeCapacity(prefix); |
| | 294 | protocol_args.appendAssumeCapacity(0); |
| | 295 | } |
| | 296 | }, |
| | 297 | .path_directory => { |
| | 298 | const lazy_path = arg.path.value.?.get(conf); |
| | 299 | switch (lazy_path) { |
| | 300 | else => {}, |
| | 301 | .relative => |relative| switch (relative.flags.base) { |
| | 302 | else => {}, |
| | 303 | .libc_runtimes => if (graph.libc_runtimes_dir == null) continue, |
| | 304 | }, |
| | 305 | } |
| 139 | | 306 | |
| 140 | argv_list.appendAssumeCapacity(result.written()); | 307 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; |
| 141 | man.hash.addBytesZ(prefix); | 308 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; |
| 142 | _ = try man.addInputPath(file_path, .{}); | 309 | const dir_path = try maker.resolveLazyPath(arena, lazy_path, run_index); |
| 143 | man.hash.addBytesZ(suffix); | 310 | try input_dirs.append(gpa, dir_path); |
| | 311 | |
| | 312 | const has_sub_path = dir_path.sub_path.len > 0; |
| | 313 | try owned_dirs.resize(gpa, owned_dirs.bit_length + 1, has_sub_path); |
| | 314 | try inherit_dirs.ensureUnusedCapacity(gpa, 1); |
| | 315 | const dir = if (has_sub_path) |
| | 316 | dir_path.root_dir.handle.openDir(io, dir_path.sub_path, .{ |
| | 317 | .iterate = true, |
| | 318 | }) catch |err| return step.fail(maker, "unable to open input dir {qf}: {t}", .{ dir_path, err }) |
| | 319 | else |
| | 320 | dir_path.root_dir.handle; |
| | 321 | inherit_dirs.appendAssumeCapacity(dir); |
| | 322 | |
| | 323 | man.hash.addBytesZ(prefix); |
| | 324 | man.hash.addOptionalBytes(dir_path.root_dir.path); |
| | 325 | man.hash.addBytes(dir_path.sub_path); |
| | 326 | man.hash.addBytesZ(suffix); |
| | 327 | |
| | 328 | try protocol_args.ensureUnusedCapacity(gpa, 1 + prefix.len + 1 + |
| | 329 | 1 + @sizeOf(Io.Dir.Handle) + |
| | 330 | 1 + suffix.len + 1); |
| | 331 | if (prefix.len > 0) { |
| | 332 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.prefix)); |
| | 333 | protocol_args.appendSliceAssumeCapacity(prefix); |
| | 334 | protocol_args.appendAssumeCapacity(0); |
| | 335 | } |
| | 336 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.input_dir)); |
| | 337 | const dir_handle: *align(1) Io.Dir.Handle = |
| | 338 | @ptrCast(protocol_args.addManyAsArrayAssumeCapacity(@sizeOf(Io.Dir.Handle))); |
| | 339 | dir_handle.* = dir.handle; |
| | 340 | if (suffix.len > 0) { |
| | 341 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.suffix)); |
| | 342 | protocol_args.appendSliceAssumeCapacity(prefix); |
| | 343 | protocol_args.appendAssumeCapacity(0); |
| | 344 | } |
| | 345 | }, |
| | 346 | .file_content => { |
| | 347 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; |
| | 348 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; |
| | 349 | const file_path = try maker.resolveLazyPathIndex(arena, arg.path.value.?, run_index); |
| | 350 | |
| | 351 | try owned_files.resize(gpa, owned_files.bit_length + 1, true); |
| | 352 | try inherit_files.ensureUnusedCapacity(gpa, 1); |
| | 353 | const file = file_path.root_dir.handle.openFile(io, file_path.sub_path, .{}) catch |err| |
| | 354 | return step.fail(maker, "unable to open input file {qf}: {t}", .{ file_path, err }); |
| | 355 | inherit_files.appendAssumeCapacity(file); |
| | 356 | |
| | 357 | man.hash.addBytesZ(prefix); |
| | 358 | _ = try man.addInputPath(file_path, .{}); |
| | 359 | man.hash.addBytesZ(suffix); |
| | 360 | |
| | 361 | try protocol_args.ensureUnusedCapacity(gpa, 1 + prefix.len + 1 + |
| | 362 | 1 + @sizeOf(Io.File.Handle) + |
| | 363 | 1 + suffix.len + 1); |
| | 364 | if (prefix.len > 0) { |
| | 365 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.prefix)); |
| | 366 | protocol_args.appendSliceAssumeCapacity(prefix); |
| | 367 | protocol_args.appendAssumeCapacity(0); |
| | 368 | } |
| | 369 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.input_file_content)); |
| | 370 | const file_handle: *align(1) Io.File.Handle = |
| | 371 | @ptrCast(protocol_args.addManyAsArrayAssumeCapacity(@sizeOf(Io.File.Handle))); |
| | 372 | file_handle.* = file.handle; |
| | 373 | if (suffix.len > 0) { |
| | 374 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.suffix)); |
| | 375 | protocol_args.appendSliceAssumeCapacity(prefix); |
| | 376 | protocol_args.appendAssumeCapacity(0); |
| | 377 | } |
| | 378 | }, |
| | 379 | .artifact => { |
| | 380 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; |
| | 381 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; |
| | 382 | const producer_index = arg.producer.value.?; |
| | 383 | const producer_step = producer_index.ptr(conf); |
| | 384 | const producer = producer_step.extended.get(conf.extra).compile; |
| | 385 | const producer_make_comp_step = maker.stepByIndex(producer_index); |
| | 386 | const producer_make_comp = &producer_make_comp_step.extended.compile; |
| | 387 | |
| | 388 | const file_path = producer_make_comp.installed_path orelse |
| | 389 | maker.generatedPath(producer.generated_bin.value.?); |
| | 390 | |
| | 391 | try owned_files.resize(gpa, owned_files.bit_length + 1, true); |
| | 392 | try inherit_files.ensureUnusedCapacity(gpa, 1); |
| | 393 | const file = file_path.root_dir.handle.openFile(io, file_path.sub_path, .{}) catch |err| |
| | 394 | return step.fail(maker, "unable to open input artifact {qf}: {t}", .{ file_path, err }); |
| | 395 | inherit_files.appendAssumeCapacity(file); |
| | 396 | |
| | 397 | man.hash.addBytesZ(prefix); |
| | 398 | _ = try man.addInputPath(file_path, .{}); |
| | 399 | man.hash.addBytesZ(suffix); |
| | 400 | |
| | 401 | try protocol_args.ensureUnusedCapacity(gpa, 1 + prefix.len + 1 + |
| | 402 | 1 + @sizeOf(Io.File.Handle) + |
| | 403 | 1 + suffix.len + 1); |
| | 404 | if (prefix.len > 0) { |
| | 405 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.prefix)); |
| | 406 | protocol_args.appendSliceAssumeCapacity(prefix); |
| | 407 | protocol_args.appendAssumeCapacity(0); |
| | 408 | } |
| | 409 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.input_file)); |
| | 410 | const file_handle: *align(1) Io.File.Handle = |
| | 411 | @ptrCast(protocol_args.addManyAsArrayAssumeCapacity(@sizeOf(Io.File.Handle))); |
| | 412 | file_handle.* = file.handle; |
| | 413 | if (suffix.len > 0) { |
| | 414 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.suffix)); |
| | 415 | protocol_args.appendSliceAssumeCapacity(prefix); |
| | 416 | protocol_args.appendAssumeCapacity(0); |
| | 417 | } |
| | 418 | }, |
| | 419 | .output_file => { |
| | 420 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; |
| | 421 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; |
| | 422 | const basename = arg.basename.value.?.slice(conf); |
| | 423 | |
| | 424 | man.hash.addBytesZ(prefix); |
| | 425 | man.hash.addBytesZ(basename); |
| | 426 | man.hash.addBytesZ(suffix); |
| | 427 | assert(!arg.flags.dep_file); |
| | 428 | |
| | 429 | try protocol_args.ensureUnusedCapacity(gpa, 1 + prefix.len + 1 + |
| | 430 | 1 + @sizeOf(Io.File.Handle) + |
| | 431 | 1 + suffix.len + 1); |
| | 432 | if (prefix.len > 0) { |
| | 433 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.prefix)); |
| | 434 | protocol_args.appendSliceAssumeCapacity(prefix); |
| | 435 | protocol_args.appendAssumeCapacity(0); |
| | 436 | } |
| | 437 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.output_file)); |
| | 438 | |
| | 439 | // Add a placeholder into the argument list because we need the |
| | 440 | // manifest hash to be updated with all arguments before the |
| | 441 | // object directory is computed. |
| | 442 | try owned_files.resize(gpa, owned_files.bit_length + 1, false); |
| | 443 | try inherit_files.ensureUnusedCapacity(gpa, 1); |
| | 444 | try output_placeholders.append(gpa, .{ |
| | 445 | .index = @intCast(inherit_files.items.len), |
| | 446 | .offset = @intCast(protocol_args.items.len), |
| | 447 | .arg_index = arg_index, |
| | 448 | }); |
| | 449 | _ = inherit_files.addOneAssumeCapacity(); |
| | 450 | |
| | 451 | _ = protocol_args.addManyAsArrayAssumeCapacity(@sizeOf(Io.File.Handle)); |
| | 452 | if (suffix.len > 0) { |
| | 453 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.suffix)); |
| | 454 | protocol_args.appendSliceAssumeCapacity(prefix); |
| | 455 | protocol_args.appendAssumeCapacity(0); |
| | 456 | } |
| | 457 | }, |
| | 458 | .output_directory => { |
| | 459 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; |
| | 460 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; |
| | 461 | const basename = arg.basename.value.?.slice(conf); |
| | 462 | |
| | 463 | man.hash.addBytesZ(prefix); |
| | 464 | man.hash.addBytesZ(basename); |
| | 465 | man.hash.addBytesZ(suffix); |
| | 466 | assert(!arg.flags.dep_file); |
| | 467 | |
| | 468 | try protocol_args.ensureUnusedCapacity(gpa, 1 + prefix.len + 1 + |
| | 469 | 1 + @sizeOf(Io.Dir.Handle) + |
| | 470 | 1 + suffix.len + 1); |
| | 471 | if (prefix.len > 0) { |
| | 472 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.prefix)); |
| | 473 | protocol_args.appendSliceAssumeCapacity(prefix); |
| | 474 | protocol_args.appendAssumeCapacity(0); |
| | 475 | } |
| | 476 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.output_dir)); |
| | 477 | |
| | 478 | // Add a placeholder into the argument list because we need the |
| | 479 | // manifest hash to be updated with all arguments before the |
| | 480 | // object directory is computed. |
| | 481 | try owned_dirs.resize(gpa, owned_dirs.bit_length + 1, false); |
| | 482 | try inherit_dirs.ensureUnusedCapacity(gpa, 1); |
| | 483 | try output_placeholders.append(gpa, .{ |
| | 484 | .index = @intCast(inherit_dirs.items.len), |
| | 485 | .offset = @intCast(protocol_args.items.len), |
| | 486 | .arg_index = arg_index, |
| | 487 | }); |
| | 488 | _ = inherit_dirs.addOneAssumeCapacity(); |
| | 489 | |
| | 490 | _ = protocol_args.addManyAsArrayAssumeCapacity(@sizeOf(Io.Dir.Handle)); |
| | 491 | if (suffix.len > 0) { |
| | 492 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.suffix)); |
| | 493 | protocol_args.appendSliceAssumeCapacity(prefix); |
| | 494 | protocol_args.appendAssumeCapacity(0); |
| | 495 | } |
| | 496 | }, |
| | 497 | .passthru => if (maker.run_args) |run_args| { |
| | 498 | man.hash.addListOfBytes(run_args); |
| | 499 | |
| | 500 | for (run_args) |run_arg| { |
| | 501 | try protocol_args.ensureUnusedCapacity(gpa, 1 + run_arg.len + 1); |
| | 502 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.string)); |
| | 503 | protocol_args.appendSliceAssumeCapacity(run_arg); |
| | 504 | protocol_args.appendAssumeCapacity(0); |
| | 505 | } |
| | 506 | }, |
| | 507 | .enable_darling => try thirdPartyToggleProtocol(gpa, &man.hash, &protocol_args, conf, graph.enable_darling, arg.prefix.value, arg.suffix.value), |
| | 508 | .enable_qemu => try thirdPartyToggleProtocol(gpa, &man.hash, &protocol_args, conf, graph.enable_qemu, arg.prefix.value, arg.suffix.value), |
| | 509 | .enable_rosetta => try thirdPartyToggleProtocol(gpa, &man.hash, &protocol_args, conf, graph.enable_rosetta, arg.prefix.value, arg.suffix.value), |
| | 510 | .enable_wasmtime => try thirdPartyToggleProtocol(gpa, &man.hash, &protocol_args, conf, graph.enable_wasmtime, arg.prefix.value, arg.suffix.value), |
| | 511 | .enable_wine => try thirdPartyToggleProtocol(gpa, &man.hash, &protocol_args, conf, graph.enable_wine, arg.prefix.value, arg.suffix.value), |
| | 512 | } |
| | 513 | } |
| 144 | }, | 514 | }, |
| 145 | .artifact => { | 515 | } |
| 146 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; | | |
| 147 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; | | |
| 148 | const producer_index = arg.producer.value.?; | | |
| 149 | const producer_step = producer_index.ptr(conf); | | |
| 150 | const producer = producer_step.extended.get(conf.extra).compile; | | |
| 151 | const producer_make_comp_step = maker.stepByIndex(producer_index); | | |
| 152 | const producer_make_comp = &producer_make_comp_step.extended.compile; | | |
| 153 | | | |
| 154 | const file_path = producer_make_comp.installed_path orelse | | |
| 155 | maker.generatedPath(producer.generated_bin.value.?); | | |
| 156 | | | |
| 157 | argv_list.appendAssumeCapacity(try mem.concat(arena, u8, &.{ | | |
| 158 | prefix, try convertPathArg(arena, run_index, maker, file_path, arg.flags.make_absolute), suffix, | | |
| 159 | })); | | |
| 160 | | 516 | |
| 161 | man.hash.add(arg.flags.make_absolute); | 517 | switch (conf_run.stdin.u) { |
| 162 | man.hash.addBytesZ(prefix); | 518 | .bytes => |bytes| { |
| 163 | man.hash.addBytesZ(suffix); | 519 | man.hash.addBytes(bytes.slice(conf)); |
| 164 | _ = try man.addInputPath(file_path, .{}); | | |
| 165 | }, | | |
| 166 | .output_file, .output_directory => { | | |
| 167 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; | | |
| 168 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; | | |
| 169 | const basename = arg.basename.value.?.slice(conf); | | |
| 170 | | | |
| 171 | man.hash.add(arg.flags.make_absolute); | | |
| 172 | man.hash.addBytesZ(prefix); | | |
| 173 | man.hash.addBytesZ(basename); | | |
| 174 | man.hash.addBytesZ(suffix); | | |
| 175 | man.hash.add(arg.flags.dep_file); | | |
| 176 | | | |
| 177 | if (arg.flags.dep_file) any_discovered_inputs = true; | | |
| 178 | any_output_args = true; | | |
| 179 | | | |
| 180 | // Add a placeholder into the argument list because we need the | | |
| 181 | // manifest hash to be updated with all arguments before the | | |
| 182 | // object directory is computed. | | |
| 183 | try output_placeholders.append(gpa, .{ | | |
| 184 | .index = @intCast(argv_list.items.len), | | |
| 185 | .offset = 0, | | |
| 186 | .arg_index = arg_index, | | |
| 187 | }); | | |
| 188 | _ = argv_list.addOneAssumeCapacity(); | | |
| 189 | }, | 520 | }, |
| 190 | .passthru => { | 521 | .lazy_path => |lazy_path| { |
| 191 | any_cli_positionals = true; | 522 | const file_path = try maker.resolveLazyPathIndex(arena, lazy_path, run_index); |
| 192 | if (maker.run_args) |run_args| { | 523 | _ = try man.addInputPath(file_path, .{}); |
| 193 | try argv_list.appendSlice(gpa, run_args); | | |
| 194 | man.hash.addListOfBytes(run_args); | | |
| 195 | } | | |
| 196 | }, | 524 | }, |
| 197 | .enable_darling => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_darling, arg.prefix.value, arg.suffix.value), | 525 | .none => {}, |
| 198 | .enable_qemu => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_qemu, arg.prefix.value, arg.suffix.value), | | |
| 199 | .enable_rosetta => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_rosetta, arg.prefix.value, arg.suffix.value), | | |
| 200 | .enable_wasmtime => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_wasmtime, arg.prefix.value, arg.suffix.value), | | |
| 201 | .enable_wine => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_wine, arg.prefix.value, arg.suffix.value), | | |
| 202 | } | 526 | } |
| 203 | } | | |
| 204 | | | |
| 205 | var owned_dirs: std.bit_set.Dynamic = .{}; | | |
| 206 | var inherit_dirs: std.ArrayList(Io.Dir) = .empty; | | |
| 207 | var owned_files: std.bit_set.Dynamic = .{}; | | |
| 208 | var inherit_files: std.ArrayList(Io.File) = .empty; | | |
| 209 | var protocol_args: std.ArrayList(u8) = .empty; | | |
| 210 | var input_dirs: std.ArrayList(Cache.Path) = .empty; | | |
| 211 | defer { | | |
| 212 | for (inherit_dirs.items, 0..) |inherit_dir, inherit_dir_index| | | |
| 213 | if (owned_dirs.isSet(inherit_dir_index)) inherit_dir.close(io); | | |
| 214 | for (inherit_files.items, 0..) |inherit_file, inherit_file_index| | | |
| 215 | if (owned_files.isSet(inherit_file_index)) inherit_file.close(io); | | |
| 216 | owned_dirs.deinit(gpa); | | |
| 217 | inherit_dirs.deinit(gpa); | | |
| 218 | owned_files.deinit(gpa); | | |
| 219 | inherit_files.deinit(gpa); | | |
| 220 | protocol_args.deinit(gpa); | | |
| 221 | input_dirs.deinit(gpa); | | |
| 222 | } | | |
| 223 | switch (conf_run.flags.stdio) { | | |
| 224 | .infer_from_args, .inherit, .check => {}, | | |
| 225 | .zig_test => { | | |
| 226 | const cache_dir_string = try convertPathArg(arena, run_index, maker, .{ .root_dir = cache_root }, false); | | |
| 227 | | 527 | |
| 228 | try argv_list.ensureUnusedCapacity(gpa, 3); | 528 | if (conf_run.captured_stdout.value) |captured| { |
| 229 | argv_list.appendAssumeCapacity(try arena.print("--cache-dir={s}", .{cache_dir_string})); | 529 | man.hash.addBytes(captured.basename.slice(conf)); |
| 230 | argv_list.appendAssumeCapacity(try arena.print("--seed=0x{x}", .{graph.random_seed})); | 530 | man.hash.add(conf_run.flags.stdout_trim_whitespace); |
| 231 | argv_list.appendAssumeCapacity("--listen=-"); | 531 | } |
| 232 | }, | | |
| 233 | .protocol => { | | |
| 234 | argv_list.appendAssumeCapacity("--listen=-"); | | |
| 235 | try input_dirs.append(gpa, if (conf_run.cwd.value) |lazy_cwd| | | |
| 236 | try maker.resolveLazyPathIndex(arena, lazy_cwd, run_index) | | |
| 237 | else | | |
| 238 | .cwd()); | | |
| 239 | for (conf_run.args.slice[1..]) |arg_index| { | | |
| 240 | const arg = arg_index.get(conf); | | |
| 241 | switch (arg.flags.tag) { | | |
| 242 | .string => { | | |
| 243 | const string = arg.prefix.value.?.slice(conf); | | |
| 244 | | | |
| 245 | man.hash.addBytesZ(string); | | |
| 246 | | | |
| 247 | try protocol_args.ensureUnusedCapacity(gpa, 1 + string.len + 1); | | |
| 248 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.string)); | | |
| 249 | protocol_args.appendSliceAssumeCapacity(string); | | |
| 250 | protocol_args.appendAssumeCapacity(0); | | |
| 251 | }, | | |
| 252 | .path_file => { | | |
| 253 | const lazy_path = arg.path.value.?.get(conf); | | |
| 254 | switch (lazy_path) { | | |
| 255 | else => {}, | | |
| 256 | .relative => |relative| switch (relative.flags.base) { | | |
| 257 | else => {}, | | |
| 258 | .libc_runtimes => if (graph.libc_runtimes_dir == null) continue, | | |
| 259 | }, | | |
| 260 | } | | |
| 261 | | | |
| 262 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; | | |
| 263 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; | | |
| 264 | const file_path = try maker.resolveLazyPath(arena, lazy_path, run_index); | | |
| 265 | | | |
| 266 | try owned_files.resize(gpa, owned_files.bit_length + 1, true); | | |
| 267 | try inherit_files.ensureUnusedCapacity(gpa, 1); | | |
| 268 | const file = file_path.root_dir.handle.openFile(io, file_path.sub_path, .{}) catch |err| | | |
| 269 | return step.fail(maker, "unable to open input file {qf}: {t}", .{ file_path, err }); | | |
| 270 | inherit_files.appendAssumeCapacity(file); | | |
| 271 | | | |
| 272 | man.hash.addBytesZ(prefix); | | |
| 273 | _ = try man.addInputPath(file_path, .{}); | | |
| 274 | man.hash.addBytesZ(suffix); | | |
| 275 | | | |
| 276 | try protocol_args.ensureUnusedCapacity(gpa, 1 + prefix.len + 1 + | | |
| 277 | 1 + @sizeOf(Io.File.Handle) + | | |
| 278 | 1 + suffix.len + 1); | | |
| 279 | if (prefix.len > 0) { | | |
| 280 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.prefix)); | | |
| 281 | protocol_args.appendSliceAssumeCapacity(prefix); | | |
| 282 | protocol_args.appendAssumeCapacity(0); | | |
| 283 | } | | |
| 284 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.input_file)); | | |
| 285 | const file_handle: *align(1) Io.File.Handle = | | |
| 286 | @ptrCast(protocol_args.addManyAsArrayAssumeCapacity(@sizeOf(Io.File.Handle))); | | |
| 287 | file_handle.* = file.handle; | | |
| 288 | if (suffix.len > 0) { | | |
| 289 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.suffix)); | | |
| 290 | protocol_args.appendSliceAssumeCapacity(prefix); | | |
| 291 | protocol_args.appendAssumeCapacity(0); | | |
| 292 | } | | |
| 293 | }, | | |
| 294 | .path_directory => { | | |
| 295 | const lazy_path = arg.path.value.?.get(conf); | | |
| 296 | switch (lazy_path) { | | |
| 297 | else => {}, | | |
| 298 | .relative => |relative| switch (relative.flags.base) { | | |
| 299 | else => {}, | | |
| 300 | .libc_runtimes => if (graph.libc_runtimes_dir == null) continue, | | |
| 301 | }, | | |
| 302 | } | | |
| 303 | | | |
| 304 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; | | |
| 305 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; | | |
| 306 | const dir_path = try maker.resolveLazyPath(arena, lazy_path, run_index); | | |
| 307 | try input_dirs.append(gpa, dir_path); | | |
| 308 | | | |
| 309 | const has_sub_path = dir_path.sub_path.len > 0; | | |
| 310 | try owned_dirs.resize(gpa, owned_dirs.bit_length + 1, has_sub_path); | | |
| 311 | try inherit_dirs.ensureUnusedCapacity(gpa, 1); | | |
| 312 | const dir = if (has_sub_path) | | |
| 313 | dir_path.root_dir.handle.openDir(io, dir_path.sub_path, .{ | | |
| 314 | .iterate = true, | | |
| 315 | }) catch |err| return step.fail(maker, "unable to open input dir {qf}: {t}", .{ dir_path, err }) | | |
| 316 | else | | |
| 317 | dir_path.root_dir.handle; | | |
| 318 | inherit_dirs.appendAssumeCapacity(dir); | | |
| 319 | | | |
| 320 | man.hash.addBytesZ(prefix); | | |
| 321 | man.hash.addOptionalBytes(dir_path.root_dir.path); | | |
| 322 | man.hash.addBytes(dir_path.sub_path); | | |
| 323 | man.hash.addBytesZ(suffix); | | |
| 324 | | | |
| 325 | try protocol_args.ensureUnusedCapacity(gpa, 1 + prefix.len + 1 + | | |
| 326 | 1 + @sizeOf(Io.Dir.Handle) + | | |
| 327 | 1 + suffix.len + 1); | | |
| 328 | if (prefix.len > 0) { | | |
| 329 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.prefix)); | | |
| 330 | protocol_args.appendSliceAssumeCapacity(prefix); | | |
| 331 | protocol_args.appendAssumeCapacity(0); | | |
| 332 | } | | |
| 333 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.input_dir)); | | |
| 334 | const dir_handle: *align(1) Io.Dir.Handle = | | |
| 335 | @ptrCast(protocol_args.addManyAsArrayAssumeCapacity(@sizeOf(Io.Dir.Handle))); | | |
| 336 | dir_handle.* = dir.handle; | | |
| 337 | if (suffix.len > 0) { | | |
| 338 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.suffix)); | | |
| 339 | protocol_args.appendSliceAssumeCapacity(prefix); | | |
| 340 | protocol_args.appendAssumeCapacity(0); | | |
| 341 | } | | |
| 342 | }, | | |
| 343 | .file_content => { | | |
| 344 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; | | |
| 345 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; | | |
| 346 | const file_path = try maker.resolveLazyPathIndex(arena, arg.path.value.?, run_index); | | |
| 347 | | | |
| 348 | try owned_files.resize(gpa, owned_files.bit_length + 1, true); | | |
| 349 | try inherit_files.ensureUnusedCapacity(gpa, 1); | | |
| 350 | const file = file_path.root_dir.handle.openFile(io, file_path.sub_path, .{}) catch |err| | | |
| 351 | return step.fail(maker, "unable to open input file {qf}: {t}", .{ file_path, err }); | | |
| 352 | inherit_files.appendAssumeCapacity(file); | | |
| 353 | | | |
| 354 | man.hash.addBytesZ(prefix); | | |
| 355 | _ = try man.addInputPath(file_path, .{}); | | |
| 356 | man.hash.addBytesZ(suffix); | | |
| 357 | | | |
| 358 | try protocol_args.ensureUnusedCapacity(gpa, 1 + prefix.len + 1 + | | |
| 359 | 1 + @sizeOf(Io.File.Handle) + | | |
| 360 | 1 + suffix.len + 1); | | |
| 361 | if (prefix.len > 0) { | | |
| 362 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.prefix)); | | |
| 363 | protocol_args.appendSliceAssumeCapacity(prefix); | | |
| 364 | protocol_args.appendAssumeCapacity(0); | | |
| 365 | } | | |
| 366 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.input_file_content)); | | |
| 367 | const file_handle: *align(1) Io.File.Handle = | | |
| 368 | @ptrCast(protocol_args.addManyAsArrayAssumeCapacity(@sizeOf(Io.File.Handle))); | | |
| 369 | file_handle.* = file.handle; | | |
| 370 | if (suffix.len > 0) { | | |
| 371 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.suffix)); | | |
| 372 | protocol_args.appendSliceAssumeCapacity(prefix); | | |
| 373 | protocol_args.appendAssumeCapacity(0); | | |
| 374 | } | | |
| 375 | }, | | |
| 376 | .artifact => { | | |
| 377 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; | | |
| 378 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; | | |
| 379 | const producer_index = arg.producer.value.?; | | |
| 380 | const producer_step = producer_index.ptr(conf); | | |
| 381 | const producer = producer_step.extended.get(conf.extra).compile; | | |
| 382 | const producer_make_comp_step = maker.stepByIndex(producer_index); | | |
| 383 | const producer_make_comp = &producer_make_comp_step.extended.compile; | | |
| 384 | | | |
| 385 | const file_path = producer_make_comp.installed_path orelse | | |
| 386 | maker.generatedPath(producer.generated_bin.value.?); | | |
| 387 | | | |
| 388 | try owned_files.resize(gpa, owned_files.bit_length + 1, true); | | |
| 389 | try inherit_files.ensureUnusedCapacity(gpa, 1); | | |
| 390 | const file = file_path.root_dir.handle.openFile(io, file_path.sub_path, .{}) catch |err| | | |
| 391 | return step.fail(maker, "unable to open input artifact {qf}: {t}", .{ file_path, err }); | | |
| 392 | inherit_files.appendAssumeCapacity(file); | | |
| 393 | | | |
| 394 | man.hash.addBytesZ(prefix); | | |
| 395 | _ = try man.addInputPath(file_path, .{}); | | |
| 396 | man.hash.addBytesZ(suffix); | | |
| 397 | | | |
| 398 | try protocol_args.ensureUnusedCapacity(gpa, 1 + prefix.len + 1 + | | |
| 399 | 1 + @sizeOf(Io.File.Handle) + | | |
| 400 | 1 + suffix.len + 1); | | |
| 401 | if (prefix.len > 0) { | | |
| 402 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.prefix)); | | |
| 403 | protocol_args.appendSliceAssumeCapacity(prefix); | | |
| 404 | protocol_args.appendAssumeCapacity(0); | | |
| 405 | } | | |
| 406 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.input_file)); | | |
| 407 | const file_handle: *align(1) Io.File.Handle = | | |
| 408 | @ptrCast(protocol_args.addManyAsArrayAssumeCapacity(@sizeOf(Io.File.Handle))); | | |
| 409 | file_handle.* = file.handle; | | |
| 410 | if (suffix.len > 0) { | | |
| 411 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.suffix)); | | |
| 412 | protocol_args.appendSliceAssumeCapacity(prefix); | | |
| 413 | protocol_args.appendAssumeCapacity(0); | | |
| 414 | } | | |
| 415 | }, | | |
| 416 | .output_file => { | | |
| 417 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; | | |
| 418 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; | | |
| 419 | const basename = arg.basename.value.?.slice(conf); | | |
| 420 | | | |
| 421 | man.hash.addBytesZ(prefix); | | |
| 422 | man.hash.addBytesZ(basename); | | |
| 423 | man.hash.addBytesZ(suffix); | | |
| 424 | assert(!arg.flags.dep_file); | | |
| 425 | | | |
| 426 | try protocol_args.ensureUnusedCapacity(gpa, 1 + prefix.len + 1 + | | |
| 427 | 1 + @sizeOf(Io.File.Handle) + | | |
| 428 | 1 + suffix.len + 1); | | |
| 429 | if (prefix.len > 0) { | | |
| 430 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.prefix)); | | |
| 431 | protocol_args.appendSliceAssumeCapacity(prefix); | | |
| 432 | protocol_args.appendAssumeCapacity(0); | | |
| 433 | } | | |
| 434 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.output_file)); | | |
| 435 | | | |
| 436 | // Add a placeholder into the argument list because we need the | | |
| 437 | // manifest hash to be updated with all arguments before the | | |
| 438 | // object directory is computed. | | |
| 439 | try owned_files.resize(gpa, owned_files.bit_length + 1, false); | | |
| 440 | try inherit_files.ensureUnusedCapacity(gpa, 1); | | |
| 441 | try output_placeholders.append(gpa, .{ | | |
| 442 | .index = @intCast(inherit_files.items.len), | | |
| 443 | .offset = @intCast(protocol_args.items.len), | | |
| 444 | .arg_index = arg_index, | | |
| 445 | }); | | |
| 446 | _ = inherit_files.addOneAssumeCapacity(); | | |
| 447 | | | |
| 448 | _ = protocol_args.addManyAsArrayAssumeCapacity(@sizeOf(Io.File.Handle)); | | |
| 449 | if (suffix.len > 0) { | | |
| 450 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.suffix)); | | |
| 451 | protocol_args.appendSliceAssumeCapacity(prefix); | | |
| 452 | protocol_args.appendAssumeCapacity(0); | | |
| 453 | } | | |
| 454 | }, | | |
| 455 | .output_directory => { | | |
| 456 | const prefix = if (arg.prefix.value) |p| p.slice(conf) else ""; | | |
| 457 | const suffix = if (arg.suffix.value) |p| p.slice(conf) else ""; | | |
| 458 | const basename = arg.basename.value.?.slice(conf); | | |
| 459 | | | |
| 460 | man.hash.addBytesZ(prefix); | | |
| 461 | man.hash.addBytesZ(basename); | | |
| 462 | man.hash.addBytesZ(suffix); | | |
| 463 | assert(!arg.flags.dep_file); | | |
| 464 | | | |
| 465 | try protocol_args.ensureUnusedCapacity(gpa, 1 + prefix.len + 1 + | | |
| 466 | 1 + @sizeOf(Io.Dir.Handle) + | | |
| 467 | 1 + suffix.len + 1); | | |
| 468 | if (prefix.len > 0) { | | |
| 469 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.prefix)); | | |
| 470 | protocol_args.appendSliceAssumeCapacity(prefix); | | |
| 471 | protocol_args.appendAssumeCapacity(0); | | |
| 472 | } | | |
| 473 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.output_dir)); | | |
| 474 | | | |
| 475 | // Add a placeholder into the argument list because we need the | | |
| 476 | // manifest hash to be updated with all arguments before the | | |
| 477 | // object directory is computed. | | |
| 478 | try owned_dirs.resize(gpa, owned_dirs.bit_length + 1, false); | | |
| 479 | try inherit_dirs.ensureUnusedCapacity(gpa, 1); | | |
| 480 | try output_placeholders.append(gpa, .{ | | |
| 481 | .index = @intCast(inherit_dirs.items.len), | | |
| 482 | .offset = @intCast(protocol_args.items.len), | | |
| 483 | .arg_index = arg_index, | | |
| 484 | }); | | |
| 485 | _ = inherit_dirs.addOneAssumeCapacity(); | | |
| 486 | | 532 | |
| 487 | _ = protocol_args.addManyAsArrayAssumeCapacity(@sizeOf(Io.Dir.Handle)); | 533 | if (conf_run.captured_stderr.value) |captured| { |
| 488 | if (suffix.len > 0) { | 534 | man.hash.addBytes(captured.basename.slice(conf)); |
| 489 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.suffix)); | 535 | man.hash.add(conf_run.flags.stderr_trim_whitespace); |
| 490 | protocol_args.appendSliceAssumeCapacity(prefix); | 536 | } |
| 491 | protocol_args.appendAssumeCapacity(0); | | |
| 492 | } | | |
| 493 | }, | | |
| 494 | .passthru => if (maker.run_args) |run_args| { | | |
| 495 | man.hash.addListOfBytes(run_args); | | |
| 496 | | 537 | |
| 497 | for (run_args) |run_arg| { | 538 | switch (conf_run.flags.stdio) { |
| 498 | try protocol_args.ensureUnusedCapacity(gpa, 1 + run_arg.len + 1); | 539 | .infer_from_args, .inherit, .zig_test, .protocol => {}, |
| 499 | protocol_args.appendAssumeCapacity(@backingInt(std.zig.Client.Message.Arg.string)); | 540 | .check => { |
| 500 | protocol_args.appendSliceAssumeCapacity(run_arg); | 541 | man.hash.addBytes(if (conf_run.expect_stderr_exact.value) |bytes| bytes.slice(conf) else ""); |
| 501 | protocol_args.appendAssumeCapacity(0); | 542 | man.hash.addBytes(if (conf_run.expect_stdout_exact.value) |bytes| bytes.slice(conf) else ""); |
| 502 | } | 543 | for (conf_run.expect_stderr_match.slice) |bytes| man.hash.addBytes(bytes.slice(conf)); |
| 503 | }, | 544 | for (conf_run.expect_stdout_match.slice) |bytes| man.hash.addBytes(bytes.slice(conf)); |
| 504 | .enable_darling => try thirdPartyToggleProtocol(gpa, &man.hash, &protocol_args, conf, graph.enable_darling, arg.prefix.value, arg.suffix.value), | 545 | man.hash.add(conf_run.flags2.expect_term_status); |
| 505 | .enable_qemu => try thirdPartyToggleProtocol(gpa, &man.hash, &protocol_args, conf, graph.enable_qemu, arg.prefix.value, arg.suffix.value), | 546 | man.hash.addOptional(conf_run.expect_term_value.value); |
| 506 | .enable_rosetta => try thirdPartyToggleProtocol(gpa, &man.hash, &protocol_args, conf, graph.enable_rosetta, arg.prefix.value, arg.suffix.value), | 547 | }, |
| 507 | .enable_wasmtime => try thirdPartyToggleProtocol(gpa, &man.hash, &protocol_args, conf, graph.enable_wasmtime, arg.prefix.value, arg.suffix.value), | 548 | } |
| 508 | .enable_wine => try thirdPartyToggleProtocol(gpa, &man.hash, &protocol_args, conf, graph.enable_wine, arg.prefix.value, arg.suffix.value), | | |
| 509 | } | | |
| 510 | } | | |
| 511 | }, | | |
| 512 | } | | |
| 513 | | 549 | |
| 514 | switch (conf_run.stdin.u) { | 550 | for (conf_run.file_inputs.slice) |lazy_path| { |
| 515 | .bytes => |bytes| { | | |
| 516 | man.hash.addBytes(bytes.slice(conf)); | | |
| 517 | }, | | |
| 518 | .lazy_path => |lazy_path| { | | |
| 519 | const file_path = try maker.resolveLazyPathIndex(arena, lazy_path, run_index); | 551 | const file_path = try maker.resolveLazyPathIndex(arena, lazy_path, run_index); |
| 520 | _ = try man.addInputPath(file_path, .{}); | 552 | _ = try man.addInputPath(file_path, .{}); |
| 521 | }, | 553 | } |
| 522 | .none => {}, | | |
| 523 | } | | |
| 524 | | | |
| 525 | if (conf_run.captured_stdout.value) |captured| { | | |
| 526 | man.hash.addBytes(captured.basename.slice(conf)); | | |
| 527 | man.hash.add(conf_run.flags.stdout_trim_whitespace); | | |
| 528 | } | | |
| 529 | | | |
| 530 | if (conf_run.captured_stderr.value) |captured| { | | |
| 531 | man.hash.addBytes(captured.basename.slice(conf)); | | |
| 532 | man.hash.add(conf_run.flags.stderr_trim_whitespace); | | |
| 533 | } | | |
| 534 | | 554 | |
| 535 | switch (conf_run.flags.stdio) { | 555 | if (conf_run.cwd.value) |lazy_path| { |
| 536 | .infer_from_args, .inherit, .zig_test, .protocol => {}, | 556 | const cwd_path = try maker.resolveLazyPathIndex(arena, lazy_path, run_index); |
| 537 | .check => { | 557 | _ = man.hash.addBytes(try cwd_path.toString(arena)); |
| 538 | man.hash.addBytes(if (conf_run.expect_stderr_exact.value) |bytes| bytes.slice(conf) else ""); | 558 | } |
| 539 | man.hash.addBytes(if (conf_run.expect_stdout_exact.value) |bytes| bytes.slice(conf) else ""); | | |
| 540 | for (conf_run.expect_stderr_match.slice) |bytes| man.hash.addBytes(bytes.slice(conf)); | | |
| 541 | for (conf_run.expect_stdout_match.slice) |bytes| man.hash.addBytes(bytes.slice(conf)); | | |
| 542 | man.hash.add(conf_run.flags2.expect_term_status); | | |
| 543 | man.hash.addOptional(conf_run.expect_term_value.value); | | |
| 544 | }, | | |
| 545 | } | | |
| 546 | | 559 | |
| 547 | for (conf_run.file_inputs.slice) |lazy_path| { | 560 | // Whether the Run step has side effects *other than* updating the output arguments. |
| 548 | const file_path = try maker.resolveLazyPathIndex(arena, lazy_path, run_index); | 561 | // When fuzzing we need to always run the test runner to populate fuzz_tests. |
| 549 | _ = try man.addInputPath(file_path, .{}); | 562 | const has_side_effects = graph.fuzzing or conf_run.flags.has_side_effects or any_cli_positionals or |
| 550 | } | 563 | switch (conf_run.flags.stdio) { |
| | 564 | .infer_from_args => !any_output_args and |
| | 565 | conf_run.captured_stdout.value == null and |
| | 566 | conf_run.captured_stderr.value == null, |
| | 567 | .inherit => true, |
| | 568 | .check, .zig_test, .protocol => false, |
| | 569 | }; |
| 551 | | 570 | |
| 552 | if (conf_run.cwd.value) |lazy_path| { | 571 | if (!has_side_effects and try step.cacheHitWatched(maker, &man, progress_node)) { |
| 553 | const cwd_path = try maker.resolveLazyPathIndex(arena, lazy_path, run_index); | 572 | // Cache hit; skip running command. |
| 554 | _ = man.hash.addBytes(try cwd_path.toString(arena)); | 573 | const digest = man.hitDigestHex(); |
| 555 | } | 574 | try populateGeneratedStdIo(maker, &conf_run, &digest); |
| | 575 | try populateGeneratedPaths(maker, output_placeholders.items, &digest); |
| | 576 | step.result_cached = true; |
| | 577 | return; |
| | 578 | } |
| 556 | | 579 | |
| 557 | // Whether the Run step has side effects *other than* updating the output arguments. | 580 | if (!any_discovered_inputs) { |
| 558 | // When fuzzing we need to always run the test runner to populate fuzz_tests. | 581 | // We already know the final output paths; use them directly. |
| 559 | const has_side_effects = graph.fuzzing or conf_run.flags.has_side_effects or any_cli_positionals or | 582 | const digest = if (has_side_effects) man.hash.final() else man.missDigestHex(); |
| 560 | switch (conf_run.flags.stdio) { | 583 | const output_dir_path = "o" ++ Dir.path.sep_str ++ &digest; |
| 561 | .infer_from_args => !any_output_args and | 584 | try populateGeneratedStdIo(maker, &conf_run, &digest); |
| 562 | conf_run.captured_stdout.value == null and | 585 | try populateGeneratedPathsCreateDirs(arena, run_index, maker, output_dir_path, output_placeholders.items, switch (conf_run.flags.stdio) { |
| 563 | conf_run.captured_stderr.value == null, | 586 | .infer_from_args, .inherit, .check, .zig_test => .{ .argv = argv_list.items }, |
| 564 | .inherit => true, | 587 | .protocol => .{ .protocol = .{ |
| 565 | .check, .zig_test, .protocol => false, | 588 | .owned_dirs = &owned_dirs, |
| 566 | }; | 589 | .inherit_dirs = inherit_dirs.items, |
| | 590 | .owned_files = &owned_files, |
| | 591 | .inherit_files = inherit_files.items, |
| | 592 | .args = protocol_args.items, |
| | 593 | } }, |
| | 594 | }); |
| | 595 | runCommand(arena, run, run_index, maker, progress_node, argv_list.items, &.{}, &.{}, &.{}, &.{}, null, has_side_effects, output_dir_path, null) catch |err| switch (err) { |
| | 596 | else => |e| return e, |
| | 597 | error.MakeFailed, error.MakeSkipped => |e| { |
| | 598 | try step.setWatchInputsFromManifest(maker, &man); |
| | 599 | return e; |
| | 600 | }, |
| | 601 | }; |
| | 602 | if (has_side_effects) { |
| | 603 | try step.setWatchInputsFromManifest(maker, &man); |
| | 604 | } else { |
| | 605 | try step.finalizeManifestAndWatch(maker, &man); |
| | 606 | } |
| | 607 | return; |
| | 608 | } |
| 567 | | 609 | |
| 568 | if (!has_side_effects and try step.cacheHitWatched(maker, &man, progress_node)) { | 610 | // We do not know the final output paths yet; use temporary directory to run the command. |
| 569 | // Cache hit; skip running command. | 611 | var rand_int: u64 = undefined; |
| 570 | const digest = man.hitDigestHex(); | 612 | io.random(@ptrCast(&rand_int)); |
| 571 | try populateGeneratedStdIo(maker, &conf_run, &digest); | 613 | tmp_dir_path = ("tmp" ++ Dir.path.sep_str ++ std.fmt.hex(rand_int)).*; |
| 572 | try populateGeneratedPaths(maker, output_placeholders.items, &digest); | | |
| 573 | step.result_cached = true; | | |
| 574 | return; | | |
| 575 | } | | |
| 576 | | 614 | |
| 577 | if (!any_discovered_inputs) { | 615 | try populateGeneratedPathsCreateDirs(arena, run_index, maker, &tmp_dir_path, output_placeholders.items, switch (conf_run.flags.stdio) { |
| 578 | // We already know the final output paths; use them directly. | | |
| 579 | const digest = if (has_side_effects) man.hash.final() else man.missDigestHex(); | | |
| 580 | const output_dir_path = "o" ++ Dir.path.sep_str ++ &digest; | | |
| 581 | try populateGeneratedStdIo(maker, &conf_run, &digest); | | |
| 582 | try populateGeneratedPathsCreateDirs(arena, run_index, maker, output_dir_path, output_placeholders.items, switch (conf_run.flags.stdio) { | | |
| 583 | .infer_from_args, .inherit, .check, .zig_test => .{ .argv = argv_list.items }, | 616 | .infer_from_args, .inherit, .check, .zig_test => .{ .argv = argv_list.items }, |
| 584 | .protocol => .{ .protocol = .{ | 617 | .protocol => .{ .protocol = .{ |
| 585 | .owned_dirs = &owned_dirs, | 618 | .owned_dirs = &owned_dirs, |
| ... | @@ -589,57 +622,30 @@ pub fn make( | ... | @@ -589,57 +622,30 @@ pub fn make( |
| 589 | .args = protocol_args.items, | 622 | .args = protocol_args.items, |
| 590 | } }, | 623 | } }, |
| 591 | }); | 624 | }); |
| 592 | runCommand(arena, run, run_index, maker, progress_node, argv_list.items, &.{}, &.{}, &.{}, &.{}, null, has_side_effects, output_dir_path, null) catch |err| switch (err) { | 625 | runCommand( |
| | 626 | arena, |
| | 627 | run, |
| | 628 | run_index, |
| | 629 | maker, |
| | 630 | progress_node, |
| | 631 | argv_list.items, |
| | 632 | inherit_dirs.items, |
| | 633 | inherit_files.items, |
| | 634 | protocol_args.items, |
| | 635 | input_dirs.items, |
| | 636 | &man, |
| | 637 | has_side_effects, |
| | 638 | &tmp_dir_path, |
| | 639 | null, |
| | 640 | ) catch |err| switch (err) { |
| 593 | else => |e| return e, | 641 | else => |e| return e, |
| 594 | error.MakeFailed, error.MakeSkipped => |e| { | 642 | error.MakeFailed, error.MakeSkipped => |e| { |
| 595 | try step.setWatchInputsFromManifest(maker, &man); | 643 | try step.setWatchInputsFromManifest(maker, &man); |
| 596 | return e; | 644 | return e; |
| 597 | }, | 645 | }, |
| 598 | }; | 646 | }; |
| 599 | if (has_side_effects) { | | |
| 600 | try step.setWatchInputsFromManifest(maker, &man); | | |
| 601 | } else { | | |
| 602 | try step.finalizeManifestAndWatch(maker, &man); | | |
| 603 | } | | |
| 604 | return; | | |
| 605 | } | | |
| 606 | | 647 | |
| 607 | // We do not know the final output paths yet; use temporary directory to run the command. | 648 | break :has_side_effects has_side_effects; |
| 608 | var rand_int: u64 = undefined; | | |
| 609 | io.random(@ptrCast(&rand_int)); | | |
| 610 | const tmp_dir_path = "tmp" ++ Dir.path.sep_str ++ std.fmt.hex(rand_int); | | |
| 611 | | | |
| 612 | try populateGeneratedPathsCreateDirs(arena, run_index, maker, tmp_dir_path, output_placeholders.items, switch (conf_run.flags.stdio) { | | |
| 613 | .infer_from_args, .inherit, .check, .zig_test => .{ .argv = argv_list.items }, | | |
| 614 | .protocol => .{ .protocol = .{ | | |
| 615 | .owned_dirs = &owned_dirs, | | |
| 616 | .inherit_dirs = inherit_dirs.items, | | |
| 617 | .owned_files = &owned_files, | | |
| 618 | .inherit_files = inherit_files.items, | | |
| 619 | .args = protocol_args.items, | | |
| 620 | } }, | | |
| 621 | }); | | |
| 622 | runCommand( | | |
| 623 | arena, | | |
| 624 | run, | | |
| 625 | run_index, | | |
| 626 | maker, | | |
| 627 | progress_node, | | |
| 628 | argv_list.items, | | |
| 629 | inherit_dirs.items, | | |
| 630 | inherit_files.items, | | |
| 631 | protocol_args.items, | | |
| 632 | input_dirs.items, | | |
| 633 | &man, | | |
| 634 | has_side_effects, | | |
| 635 | tmp_dir_path, | | |
| 636 | null, | | |
| 637 | ) catch |err| switch (err) { | | |
| 638 | else => |e| return e, | | |
| 639 | error.MakeFailed, error.MakeSkipped => |e| { | | |
| 640 | try step.setWatchInputsFromManifest(maker, &man); | | |
| 641 | return e; | | |
| 642 | }, | | |
| 643 | }; | 649 | }; |
| 644 | | 650 | |
| 645 | for (output_placeholders.items) |placeholder| { | 651 | for (output_placeholders.items) |placeholder| { |
| ... | @@ -686,7 +692,7 @@ pub fn make( | ... | @@ -686,7 +692,7 @@ pub fn make( |
| 686 | | 692 | |
| 687 | if (any_output) { | 693 | if (any_output) { |
| 688 | // Rename into place. | 694 | // Rename into place. |
| 689 | const tmp_path: Path = .{ .root_dir = cache_root, .sub_path = tmp_dir_path }; | 695 | const tmp_path: Path = .{ .root_dir = cache_root, .sub_path = &tmp_dir_path }; |
| 690 | const dst_path: Path = .{ .root_dir = cache_root, .sub_path = "o" ++ Dir.path.sep_str ++ &digest }; | 696 | const dst_path: Path = .{ .root_dir = cache_root, .sub_path = "o" ++ Dir.path.sep_str ++ &digest }; |
| 691 | Dir.rename( | 697 | Dir.rename( |
| 692 | tmp_path.root_dir.handle, | 698 | tmp_path.root_dir.handle, |