| ... | ... | @@ -354,6 +354,30 @@ pub fn flush( |
| 354 | 354 | const sub_prog_node = prog_node.start("MachO Flush", 0); |
| 355 | 355 | defer sub_prog_node.end(); |
| 356 | 356 | |
| 357 | // TODO: due to https://codeberg.org/ziglang/zig/issues/36946, we receive link inputs in a |
| 358 | // non-deterministic order. To ensure that this linker behaves deterministically, sort the |
| 359 | // inputs into a consistent order now. |
| 360 | { |
| 361 | const InputSortContext = struct { |
| 362 | fn lessThan(ctx: @This(), lhs: link.Input, rhs: link.Input) bool { |
| 363 | _ = ctx; |
| 364 | // We can't sort by full path because that could vary between runs where we still |
| 365 | // want reproducibility (e.g. the path is affected by cwd). So instead, let's sort |
| 366 | // by basename---that's good enough for our purposes since we never link two |
| 367 | // vendored libraries/objects with the same name. |
| 368 | const lhs_name = fs.path.basename(lhs.path().sub_path); |
| 369 | const rhs_name = fs.path.basename(rhs.path().sub_path); |
| 370 | return std.mem.order(u8, lhs_name, rhs_name).compare(.lt); |
| 371 | } |
| 372 | }; |
| 373 | std.mem.sort( |
| 374 | link.Input, |
| 375 | self.all_inputs.items, |
| 376 | @as(InputSortContext, .{}), |
| 377 | InputSortContext.lessThan, |
| 378 | ); |
| 379 | } |
| 380 | |
| 357 | 381 | // --verbose-link |
| 358 | 382 | if (comp.verbose_link) try self.dumpArgv(comp); |
| 359 | 383 | |