Files
zig/test/incremental/change_exports
T
Matthew Lugg 291addadf8 tests: move incremental target matrix out of manifests
Having the matrix of test targets for incremental compilation in the
individual test manifests has turned out to be inconvenient for a few
reasons: the tests are almost certain to accidentally get out of sync,
disabling targets entirely is annoying to do, and incr-check needs to
take care to print the target in all error messages (which currently
does not always happen).

If I recall correctly, I originally designed it this way because it
allows targets to be disabled at the granularity of individual tests,
but there's an easier approach to that: just let a test manifest that it
should be *skipped* on a certain target! As skipping is the rare case,
and also the case you want readers to notice, it makes sense for *it* to
be explicitly specified, like how unit tests use `error.SkipZigTest`.

So, `incr-check` no longer runs through a list of targets specified in
the manifest. Instead, it accepts (and, in fact, requires) a single
target on the command line, and runs the test for that specific target.
If the file contains a `#skip_target` directive for that target, then
`incr-check` exits immediately, so we can still disable targets at
individual test granularity, but you can also disable a target for all
tests by just commenting it out of the matrix in `test/tests.zig`.

As a nice bonus, this also allows the build system to run different
incremental test targets in parallel, because the targets are now
different steps.

This definitely seems like a better way to split the work between the
build system and incr-check---sorry for getting this wrong initially!
2026-04-15 00:06:18 +02:00

170 lines
4.5 KiB
Plaintext

#update=initial version
#file=main.zig
export fn foo() void {}
const bar: u32 = 123;
const other: u32 = 456;
comptime {
@export(&bar, .{ .name = "bar" });
}
pub fn main() !void {
const S = struct {
extern fn foo() void;
extern const bar: u32;
};
S.foo();
var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
try stdout_writer.interface.print("{}\n", .{S.bar});
}
const std = @import("std");
const io = std.Io.Threaded.global_single_threaded.io();
#expect_stdout="123\n"
#update=add conflict
#file=main.zig
export fn foo() void {}
const bar: u32 = 123;
const other: u32 = 456;
comptime {
@export(&bar, .{ .name = "bar" });
@export(&other, .{ .name = "foo" });
}
pub fn main() !void {
const S = struct {
extern fn foo() void;
extern const bar: u32;
extern const other: u32;
};
S.foo();
var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other });
}
const std = @import("std");
const io = std.Io.Threaded.global_single_threaded.io();
#expect_error=main.zig:6:5: error: exported symbol collision: foo
#expect_error=main.zig:1:1: note: other symbol here
#update=resolve conflict
#file=main.zig
export fn foo() void {}
const bar: u32 = 123;
const other: u32 = 456;
comptime {
@export(&bar, .{ .name = "bar" });
@export(&other, .{ .name = "other" });
}
pub fn main() !void {
const S = struct {
extern fn foo() void;
extern const bar: u32;
extern const other: u32;
};
S.foo();
var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other });
}
const std = @import("std");
const io = std.Io.Threaded.global_single_threaded.io();
#expect_stdout="123 456\n"
#update=put exports in decl
#file=main.zig
export fn foo() void {}
const bar: u32 = 123;
const other: u32 = 456;
const does_exports = {
@export(&bar, .{ .name = "bar" });
@export(&other, .{ .name = "other" });
};
comptime {
_ = does_exports;
}
pub fn main() !void {
const S = struct {
extern fn foo() void;
extern const bar: u32;
extern const other: u32;
};
S.foo();
var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other });
}
const std = @import("std");
const io = std.Io.Threaded.global_single_threaded.io();
#expect_stdout="123 456\n"
#update=remove reference to exporting decl
#file=main.zig
export fn foo() void {}
const bar: u32 = 123;
const other: u32 = 456;
const does_exports = {
@export(&bar, .{ .name = "bar" });
@export(&other, .{ .name = "other" });
};
comptime {
//_ = does_exports;
}
pub fn main() !void {
const S = struct {
extern fn foo() void;
};
S.foo();
}
const std = @import("std");
#expect_stdout=""
#update=mark consts as export
#file=main.zig
export fn foo() void {}
export const bar: u32 = 123;
export const other: u32 = 456;
const does_exports = {
@export(&bar, .{ .name = "bar" });
@export(&other, .{ .name = "other" });
};
comptime {
//_ = does_exports;
}
pub fn main() !void {
const S = struct {
extern fn foo() void;
extern const bar: u32;
extern const other: u32;
};
S.foo();
var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other });
}
const std = @import("std");
const io = std.Io.Threaded.global_single_threaded.io();
#expect_stdout="123 456\n"
#update=reintroduce reference to exporting decl, introducing conflict
#file=main.zig
export fn foo() void {}
export const bar: u32 = 123;
export const other: u32 = 456;
const does_exports = {
@export(&bar, .{ .name = "bar" });
@export(&other, .{ .name = "other" });
};
comptime {
_ = does_exports;
}
pub fn main() !void {
const S = struct {
extern fn foo() void;
extern const bar: u32;
extern const other: u32;
};
S.foo();
var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other });
}
const std = @import("std");
const io = std.Io.Threaded.global_single_threaded.io();
#expect_error=main.zig:5:5: error: exported symbol collision: bar
#expect_error=main.zig:2:1: note: other symbol here
#expect_error=main.zig:6:5: error: exported symbol collision: other
#expect_error=main.zig:3:1: note: other symbol here