authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-05-27 16:28:52+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-05-28 09:03:10+01:00
logc698e55754748fa9e97fed4fe279c604d3b381cd
tree0423dfd6599219ab25e1d4dd9bb5b3dff4c601ea
parentf60fe4dcb667cc638f4f8ea8fb20d11de3440671
signaturelock-open Commit is signed but in an unrecognized format.

Compilation: don't update C inputs on incremental updates

...at least, for now, so that the use case of performing incremental updates to the *Zig* source code works without crashing the linker. This works around https://codeberg.org/ziglang/zig/issues/32081.

2 files changed, 19 insertions(+), 4 deletions(-)

src/Compilation.zig+16-4
......@@ -3008,10 +3008,19 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
30083008
30093009 // For compiling C objects, we rely on the cache hash system to avoid duplicating work.
30103010 // Add a Job for each C object.
3011 try comp.c_object_work_queue.ensureUnusedCapacity(gpa, comp.c_object_table.count());
3012 for (comp.c_object_table.keys()) |c_object| {
3013 comp.c_object_work_queue.pushBackAssumeCapacity(c_object);
3014 try comp.appendFileSystemInput(try .fromUnresolved(arena, comp.dirs, &.{c_object.src.src_path}));
3011 if (comp.bin_file != null and comp.bin_file.?.post_prelink) {
3012 assert(comp.config.incremental);
3013 // TODO: this indicates that we are using incremental compilation and this is not the first
3014 // incremental update. The incremental linkers do not (currently?) support updating C inputs
3015 // incrementally. The frontend needs to learn to trigger a full rebuild if a C link input
3016 // changes. For now, to avoid crashing the linker in this case, don't kick off C object
3017 // updates if we've done prelink already. https://codeberg.org/ziglang/zig/issues/32081
3018 } else {
3019 try comp.c_object_work_queue.ensureUnusedCapacity(gpa, comp.c_object_table.count());
3020 for (comp.c_object_table.keys()) |c_object| {
3021 comp.c_object_work_queue.pushBackAssumeCapacity(c_object);
3022 try comp.appendFileSystemInput(try .fromUnresolved(arena, comp.dirs, &.{c_object.src.src_path}));
3023 }
30153024 }
30163025
30173026 for (comp.link_inputs) |input| if (input.path()) |path| {
......@@ -7595,6 +7604,9 @@ pub fn queuePrelinkTaskMode(comp: *Compilation, path: Cache.Path, must_link: boo
75957604
75967605/// Only valid to call during `update`.
75977606pub fn queuePrelinkTasks(comp: *Compilation, tasks: []const link.PrelinkTask) Io.Cancelable!void {
7607 if (tasks.len > 0) {
7608 if (comp.bin_file) |lf| assert(!lf.post_prelink);
7609 }
75987610 comp.link_prog_node.increaseEstimatedTotalItems(tasks.len);
75997611 try comp.link_queue.enqueuePrelink(comp, tasks);
76007612}
src/link.zig+3
......@@ -1205,6 +1205,7 @@ pub const File = struct {
12051205
12061206 pub fn loadInput(base: *File, input: Input) anyerror!void {
12071207 if (base.tag == .lld) return;
1208 assert(!base.post_prelink);
12081209 switch (base.tag) {
12091210 inline .elf, .elf2, .wasm => |tag| {
12101211 dev.check(tag.devFeature());
......@@ -1424,6 +1425,8 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
14241425 return;
14251426 };
14261427
1428 assert(!base.post_prelink);
1429
14271430 var timer = comp.startTimer();
14281431 defer if (timer.finish(io)) |ns| {
14291432 comp.mutex.lockUncancelable(io);