CI: more C backend test coverage

The CI now runs C backend tests in addition to compiling them. It uses
-std=c99 -pedantic -Werror in order to catch non-conformant C code.

This necessitated disabling a test case that caused a C compile error,
in addition to disabling a handful of warnings that are already being
triggered by Zig's C backend output for the behavior tests.

The upshot is that I was able to, very cleanly, integrate the C backend
tests into the build system, so that it communicates via the test runner
protocol along with all the other behavior tests.
This commit is contained in:
Andrew Kelley 2023-04-13 17:22:53 -07:00
parent 3c93c1664a
commit 4a233d1871
5 changed files with 62 additions and 15 deletions

View File

@ -679,8 +679,7 @@ pub fn addRunArtifact(b: *Build, exe: *CompileStep) *RunStep {
run_step.addArtifactArg(exe);
if (exe.kind == .@"test") {
run_step.stdio = .zig_test;
run_step.addArgs(&.{"--listen=-"});
run_step.enableTestRunnerMode();
}
if (exe.vcpkg_bin_path) |path| {

View File

@ -140,6 +140,11 @@ pub fn setName(self: *RunStep, name: []const u8) void {
self.rename_step_with_output_arg = false;
}
pub fn enableTestRunnerMode(rs: *RunStep) void {
rs.stdio = .zig_test;
rs.addArgs(&.{"--listen=-"});
}
pub fn addArtifactArg(self: *RunStep, artifact: *CompileStep) void {
self.argv.append(Arg{ .artifact = artifact }) catch @panic("OOM");
self.step.dependOn(&artifact.step);

View File

@ -104,11 +104,9 @@ pub fn receiveMessage(s: *Server) !InMessage.Header {
const buf = fifo.readableSlice(0);
assert(fifo.readableLength() == buf.len);
if (buf.len >= @sizeOf(Header)) {
const header = @ptrCast(*align(1) const Header, buf[0..@sizeOf(Header)]);
// workaround for https://github.com/ziglang/zig/issues/14904
const bytes_len = bswap_and_workaround_u32(&header.bytes_len);
// workaround for https://github.com/ziglang/zig/issues/14904
const tag = bswap_and_workaround_tag(&header.tag);
const bytes_len = bswap_and_workaround_u32(buf[4..][0..4]);
const tag = bswap_and_workaround_tag(buf[0..][0..4]);
if (buf.len - @sizeOf(Header) >= bytes_len) {
fifo.discard(@sizeOf(Header));
@ -281,14 +279,12 @@ fn bswap_u32_array(slice: []u32) void {
}
/// workaround for https://github.com/ziglang/zig/issues/14904
fn bswap_and_workaround_u32(x: *align(1) const u32) u32 {
const bytes_ptr = @ptrCast(*const [4]u8, x);
fn bswap_and_workaround_u32(bytes_ptr: *const [4]u8) u32 {
return std.mem.readIntLittle(u32, bytes_ptr);
}
/// workaround for https://github.com/ziglang/zig/issues/14904
fn bswap_and_workaround_tag(x: *align(1) const InMessage.Tag) InMessage.Tag {
const bytes_ptr = @ptrCast(*const [4]u8, x);
fn bswap_and_workaround_tag(bytes_ptr: *const [4]u8) InMessage.Tag {
const int = std.mem.readIntLittle(u32, bytes_ptr);
return @intToEnum(InMessage.Tag, int);
}

View File

@ -209,6 +209,12 @@ test "atomicrmw with floats" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) {
// TODO: test.c:34929:7: error: address argument to atomic operation must be a pointer to integer or pointer ('zig_f32 *' (aka 'float *') invalid
// when compiling with -std=c99 -pedantic
return error.SkipZigTest;
}
if ((builtin.zig_backend == .stage2_llvm or builtin.zig_backend == .stage2_c) and
builtin.cpu.arch == .aarch64)
{

View File

@ -988,18 +988,59 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
these_tests.overrideZigLibDir("lib");
these_tests.addIncludePath("test");
const run = b.addRunArtifact(these_tests);
run.skip_foreign_checks = true;
run.setName(b.fmt("run test {s}-{s}-{s}{s}{s}{s}", .{
const qualified_name = b.fmt("{s}-{s}-{s}{s}{s}{s}", .{
options.name,
triple_txt,
@tagName(test_target.optimize_mode),
libc_suffix,
single_threaded_suffix,
backend_suffix,
}));
});
step.dependOn(&run.step);
if (test_target.target.ofmt == std.Target.ObjectFormat.c) {
var altered_target = test_target.target;
altered_target.ofmt = null;
const compile_c = b.addExecutable(.{
.name = qualified_name,
.link_libc = test_target.link_libc,
.target = altered_target,
});
compile_c.overrideZigLibDir("lib");
compile_c.addCSourceFileSource(.{
.source = these_tests.getOutputSource(),
.args = &.{
// TODO output -std=c89 compatible C code
"-std=c99",
"-pedantic",
"-Werror",
// TODO stop violating these pedantic errors
"-Wno-address-of-packed-member",
"-Wno-gnu-folding-constant",
"-Wno-incompatible-pointer-types",
"-Wno-overlength-strings",
},
});
compile_c.addIncludePath("lib"); // for zig.h
if (test_target.link_libc == false and test_target.target.getOsTag() == .windows) {
compile_c.subsystem = .Console;
compile_c.linkSystemLibrary("kernel32");
compile_c.linkSystemLibrary("ntdll");
}
const run = b.addRunArtifact(compile_c);
run.skip_foreign_checks = true;
run.enableTestRunnerMode();
run.setName(b.fmt("run test {s}", .{qualified_name}));
step.dependOn(&run.step);
} else {
const run = b.addRunArtifact(these_tests);
run.skip_foreign_checks = true;
run.setName(b.fmt("run test {s}", .{qualified_name}));
step.dependOn(&run.step);
}
}
return step;
}