authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-09-24 21:36:36+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-09-26 18:21:22+01:00
log44fa23e26967e9d583e34f13de7d949973ee12d6
treee821cbec1adf5ed6087a0e5f14d790f85106a31d
parentc744875fd59cbe1fd4b1d89f51218a2e4e778b7b
signature Commit is signed but in an unrecognized format.

link.MachO: work around non-deterministic link input order

This commit should be reverted when https://codeberg.org/ziglang/zig/issues/36946 is fixed.

1 files changed, 24 insertions(+), 0 deletions(-)

src/link/MachO.zig+24
......@@ -354,6 +354,30 @@ pub fn flush(
354354 const sub_prog_node = prog_node.start("MachO Flush", 0);
355355 defer sub_prog_node.end();
356356
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
357381 // --verbose-link
358382 if (comp.verbose_link) try self.dumpArgv(comp);
359383