commit c698e55754748fa9e97fed4fe279c604d3b381cd (tree)
parent f60fe4dcb667cc638f4f8ea8fb20d11de3440671
Author: Matthew Lugg <mlugg@mlugg.co.uk>
Date: Wed, 27 May 2026 16:28:52 +0100
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.
Diffstat:
2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/src/Compilation.zig b/src/Compilation.zig
@@ -3008,10 +3008,19 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
// For compiling C objects, we rely on the cache hash system to avoid duplicating work.
// Add a Job for each C object.
- try comp.c_object_work_queue.ensureUnusedCapacity(gpa, comp.c_object_table.count());
- for (comp.c_object_table.keys()) |c_object| {
- comp.c_object_work_queue.pushBackAssumeCapacity(c_object);
- try comp.appendFileSystemInput(try .fromUnresolved(arena, comp.dirs, &.{c_object.src.src_path}));
+ if (comp.bin_file != null and comp.bin_file.?.post_prelink) {
+ assert(comp.config.incremental);
+ // TODO: this indicates that we are using incremental compilation and this is not the first
+ // incremental update. The incremental linkers do not (currently?) support updating C inputs
+ // incrementally. The frontend needs to learn to trigger a full rebuild if a C link input
+ // changes. For now, to avoid crashing the linker in this case, don't kick off C object
+ // updates if we've done prelink already. https://codeberg.org/ziglang/zig/issues/32081
+ } else {
+ try comp.c_object_work_queue.ensureUnusedCapacity(gpa, comp.c_object_table.count());
+ for (comp.c_object_table.keys()) |c_object| {
+ comp.c_object_work_queue.pushBackAssumeCapacity(c_object);
+ try comp.appendFileSystemInput(try .fromUnresolved(arena, comp.dirs, &.{c_object.src.src_path}));
+ }
}
for (comp.link_inputs) |input| if (input.path()) |path| {
@@ -7595,6 +7604,9 @@ pub fn queuePrelinkTaskMode(comp: *Compilation, path: Cache.Path, must_link: boo
/// Only valid to call during `update`.
pub fn queuePrelinkTasks(comp: *Compilation, tasks: []const link.PrelinkTask) Io.Cancelable!void {
+ if (tasks.len > 0) {
+ if (comp.bin_file) |lf| assert(!lf.post_prelink);
+ }
comp.link_prog_node.increaseEstimatedTotalItems(tasks.len);
try comp.link_queue.enqueuePrelink(comp, tasks);
}
diff --git a/src/link.zig b/src/link.zig
@@ -1205,6 +1205,7 @@ pub const File = struct {
pub fn loadInput(base: *File, input: Input) anyerror!void {
if (base.tag == .lld) return;
+ assert(!base.post_prelink);
switch (base.tag) {
inline .elf, .elf2, .wasm => |tag| {
dev.check(tag.devFeature());
@@ -1424,6 +1425,8 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
return;
};
+ assert(!base.post_prelink);
+
var timer = comp.startTimer();
defer if (timer.finish(io)) |ns| {
comp.mutex.lockUncancelable(io);