Skip to content

Commit ffef5d2

Browse files
committed
significantly increase test coverage
* add zig build option `-Dskip-libc` to skip tests that build libc (e.g. if you don't want to wait for musl to build) * add `-Denable-wine` option which uses wine to run cross compiled windows tests on non-windows hosts * add `-Denable-qemu` option which uses qemu to run cross compiled foreign architecture tests * add `-Denable-foreign-glibc=path` option which combined with `-Denable-qemu` enables running cross compiled tests that link against glibc. See https://github.com/ziglang/zig/wiki/Updating-libc#glibc for how to produce this directory. * the test matrix is done manually. release test builds are only enabled by default for the native target. this should save us some CI time, while still providing decent coverage of release builds. - add test coverage for `x86_64-linux-musl -lc` (building musl libc) - add test coverage for `x86_64-linux-gnu -lc` (building glibc) - add test coverage for `aarch64v8_5a-linux-none` - add test coverage for `aarch64v8_5a-linux-musl -lc` (building musl libc) - add test coverage for `aarch64v8_5a-linux-gnu -lc` (building glibc) - add test coverage for `arm-linux-none` - test coverage for `arm-linux-musleabihf -lc` (building musl libc) is disabled due to #3286 - test coverage for `arm-linux-gnueabihf -lc` (building glibc) is disabled due to #3287 - test coverage for `x86_64-windows-gnu -lc` (building mingw-w64) is disabled due to #3285 * enable qemu testing on the Linux CI job. There's not really a good reason to enable wine, since we have a Windows CI job as well. * remove the no longer needed `--build-file ../build.zig` from CI scripts * fix bug in glibc compilation where it wasn't properly reading the abi list txt files, resulting in "key not found" error. * std.build.Target gains: - isNetBSD - isLinux - osRequiresLibC - getArchPtrBitWidth - getExternalExecutor * zig build system gains support for enabling wine and enabling qemu. `artifact.enable_wine = true;`, `artifact.enable_qemu = true;`. This communicates that the system has these tools installed and the build system will use them to run tests. * zig build system gains support for overriding the dynamic linker of an executable artifact. * fix std.c.lseek prototype. makes behavior tests for arm-linux-musleabihf pass. * disable std lib tests that are failing on ARM. See #3288, #3289 * provide `std.os.off_t`. * disable some of the compiler_rt symbols for arm 32 bit. Fixes compiler_rt tests for arm 32 bit * add __stack_chk_guard when linking against glibc. Fixes std lib tests for aarch64-linux-gnu * workaround for "unable to inline function" using `@inlineCall`. Fixes compiler_rt tests for arm 32 bit.
1 parent c571671 commit ffef5d2

22 files changed

+479
-89
lines changed

build.zig

+8-6
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub fn build(b: *Builder) !void {
7070
const skip_release_fast = b.option(bool, "skip-release-fast", "Main test suite skips release-fast builds") orelse skip_release;
7171
const skip_release_safe = b.option(bool, "skip-release-safe", "Main test suite skips release-safe builds") orelse skip_release;
7272
const skip_non_native = b.option(bool, "skip-non-native", "Main test suite skips non-native builds") orelse false;
73+
const skip_libc = b.option(bool, "skip-libc", "Main test suite skips tests that link libc") orelse false;
7374
const skip_self_hosted = b.option(bool, "skip-self-hosted", "Main test suite skips building self hosted compiler") orelse false;
7475
if (!skip_self_hosted) {
7576
// TODO re-enable this after https://github.com/ziglang/zig/issues/2377
@@ -96,6 +97,10 @@ pub fn build(b: *Builder) !void {
9697

9798
const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter");
9899

100+
const is_wine_enabled = b.option(bool, "enable-wine", "Use Wine to run cross compiled Windows tests") orelse false;
101+
const is_qemu_enabled = b.option(bool, "enable-qemu", "Use QEMU to run cross compiled foreign architecture tests") orelse false;
102+
const glibc_multi_dir = b.option([]const u8, "enable-foreign-glibc", "Provide directory with glibc installations to run cross compiled tests that link glibc");
103+
99104
const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests");
100105
test_stage2_step.dependOn(&test_stage2.step);
101106

@@ -122,19 +127,16 @@ pub fn build(b: *Builder) !void {
122127
}
123128
const modes = chosen_modes[0..chosen_mode_index];
124129

125-
const multi_and_single = [_]bool{ false, true };
126-
const just_multi = [_]bool{false};
127-
128130
// run stage1 `zig fmt` on this build.zig file just to make sure it works
129131
test_step.dependOn(&fmt_build_zig.step);
130132
const fmt_step = b.step("test-fmt", "Run zig fmt against build.zig to make sure it works");
131133
fmt_step.dependOn(&fmt_build_zig.step);
132134

133-
test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes, multi_and_single, skip_non_native));
135+
test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes, false, skip_non_native, skip_libc, is_wine_enabled, is_qemu_enabled, glibc_multi_dir));
134136

135-
test_step.dependOn(tests.addPkgTests(b, test_filter, "std/std.zig", "std", "Run the standard library tests", modes, multi_and_single, skip_non_native));
137+
test_step.dependOn(tests.addPkgTests(b, test_filter, "std/std.zig", "std", "Run the standard library tests", modes, false, skip_non_native, skip_libc, is_wine_enabled, is_qemu_enabled, glibc_multi_dir));
136138

137-
test_step.dependOn(tests.addPkgTests(b, test_filter, "std/special/compiler_rt.zig", "compiler-rt", "Run the compiler_rt tests", modes, just_multi, skip_non_native));
139+
test_step.dependOn(tests.addPkgTests(b, test_filter, "std/special/compiler_rt.zig", "compiler-rt", "Run the compiler_rt tests", modes, true, skip_non_native, true, is_wine_enabled, is_qemu_enabled, glibc_multi_dir));
138140

139141
test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes));
140142
test_step.dependOn(tests.addStandaloneTests(b, test_filter, modes));

ci/azure/linux_script

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ sudo apt-get update -q
1212

1313
sudo apt-get remove -y llvm-*
1414
sudo rm -rf /usr/local/*
15-
sudo apt-get install -y libxml2-dev libclang-9-dev llvm-9 llvm-9-dev cmake s3cmd gcc-7 g++-7
15+
sudo apt-get install -y libxml2-dev libclang-9-dev llvm-9 llvm-9-dev cmake s3cmd gcc-7 g++-7 qemu
1616

1717
export CC=gcc-7
1818
export CXX=g++-7
1919
mkdir build
2020
cd build
2121
cmake .. -DCMAKE_BUILD_TYPE=Release
2222
make -j2 install
23-
./zig build --build-file ../build.zig test
23+
./zig build test -Denable-qemu
2424

2525
if [ "${BUILD_REASON}" != "PullRequest" ]; then
2626
ARTIFACTSDIR="$BUILDDIR/artifacts"

ci/azure/macos_script

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ mkdir build
7070
cd build
7171
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$PREFIX -DCMAKE_INSTALL_PREFIX=$(pwd)/release -DZIG_STATIC=ON
7272
make $JOBS install
73-
release/bin/zig build --build-file ../build.zig test
73+
release/bin/zig build test
7474

7575
if [ "${BUILD_REASON}" != "PullRequest" ]; then
7676
mv ../LICENSE release/

ci/azure/windows_script.bat

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ cd %ZIGBUILDDIR%
2020
cmake.exe .. -Thost=x64 -G"Visual Studio 15 2017 Win64" "-DCMAKE_INSTALL_PREFIX=%ZIGINSTALLDIR%" "-DCMAKE_PREFIX_PATH=%ZIGPREFIXPATH%" -DCMAKE_BUILD_TYPE=Release || exit /b
2121
msbuild /p:Configuration=Release INSTALL.vcxproj || exit /b
2222

23-
"%ZIGINSTALLDIR%\bin\zig.exe" build --build-file ..\build.zig test || exit /b
23+
"%ZIGINSTALLDIR%\bin\zig.exe" build test || exit /b
2424

2525
set "PATH=%CD:~0,2%\msys64\usr\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem"
2626
SET "MSYSTEM=MINGW64"

src/glibc.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbo
9999
if (!opt_line.is_some) break;
100100

101101
ver_list_base = allocate<ZigGLibCVerList>(glibc_abi->all_functions.length);
102-
ZigTarget *target = allocate<ZigTarget>(1);
103102
SplitIterator line_it = memSplit(opt_line.value, str(" "));
104103
for (;;) {
104+
ZigTarget *target = allocate<ZigTarget>(1);
105105
Optional<Slice<uint8_t>> opt_target = SplitIterator_next(&line_it);
106106
if (!opt_target.is_some) break;
107107

std/build.zig

+174-1
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,13 @@ pub const Target = union(enum) {
11751175
};
11761176
}
11771177

1178+
pub fn isLinux(self: Target) bool {
1179+
return switch (self.getOs()) {
1180+
.linux => true,
1181+
else => false,
1182+
};
1183+
}
1184+
11781185
pub fn isUefi(self: Target) bool {
11791186
return switch (self.getOs()) {
11801187
.uefi => true,
@@ -1196,9 +1203,125 @@ pub const Target = union(enum) {
11961203
};
11971204
}
11981205

1206+
pub fn isNetBSD(self: Target) bool {
1207+
return switch (self.getOs()) {
1208+
.netbsd => true,
1209+
else => false,
1210+
};
1211+
}
1212+
11991213
pub fn wantSharedLibSymLinks(self: Target) bool {
12001214
return !self.isWindows();
12011215
}
1216+
1217+
pub fn osRequiresLibC(self: Target) bool {
1218+
return self.isDarwin() or self.isFreeBSD() or self.isNetBSD();
1219+
}
1220+
1221+
pub fn getArchPtrBitWidth(self: Target) u32 {
1222+
switch (self.getArch()) {
1223+
.avr,
1224+
.msp430,
1225+
=> return 16,
1226+
1227+
.arc,
1228+
.arm,
1229+
.armeb,
1230+
.hexagon,
1231+
.le32,
1232+
.mips,
1233+
.mipsel,
1234+
.powerpc,
1235+
.r600,
1236+
.riscv32,
1237+
.sparc,
1238+
.sparcel,
1239+
.tce,
1240+
.tcele,
1241+
.thumb,
1242+
.thumbeb,
1243+
.i386,
1244+
.xcore,
1245+
.nvptx,
1246+
.amdil,
1247+
.hsail,
1248+
.spir,
1249+
.kalimba,
1250+
.shave,
1251+
.lanai,
1252+
.wasm32,
1253+
.renderscript32,
1254+
.aarch64_32,
1255+
=> return 32,
1256+
1257+
.aarch64,
1258+
.aarch64_be,
1259+
.mips64,
1260+
.mips64el,
1261+
.powerpc64,
1262+
.powerpc64le,
1263+
.riscv64,
1264+
.x86_64,
1265+
.nvptx64,
1266+
.le64,
1267+
.amdil64,
1268+
.hsail64,
1269+
.spir64,
1270+
.wasm64,
1271+
.renderscript64,
1272+
.amdgcn,
1273+
.bpfel,
1274+
.bpfeb,
1275+
.sparcv9,
1276+
.s390x,
1277+
=> return 64,
1278+
}
1279+
}
1280+
1281+
pub const Executor = union(enum) {
1282+
native,
1283+
qemu: []const u8,
1284+
wine: []const u8,
1285+
unavailable,
1286+
};
1287+
1288+
pub fn getExternalExecutor(self: Target) Executor {
1289+
if (@TagType(Target)(self) == .Native) return .native;
1290+
1291+
// If the target OS matches the host OS, we can use QEMU to emulate a foreign architecture.
1292+
if (self.getOs() == builtin.os) {
1293+
return switch (self.getArch()) {
1294+
.aarch64 => Executor{ .qemu = "qemu-aarch64" },
1295+
.aarch64_be => Executor{ .qemu = "qemu-aarch64_be" },
1296+
.arm => Executor{ .qemu = "qemu-arm" },
1297+
.armeb => Executor{ .qemu = "qemu-armeb" },
1298+
.i386 => Executor{ .qemu = "qemu-i386" },
1299+
.mips => Executor{ .qemu = "qemu-mips" },
1300+
.mipsel => Executor{ .qemu = "qemu-mipsel" },
1301+
.mips64 => Executor{ .qemu = "qemu-mips64" },
1302+
.mips64el => Executor{ .qemu = "qemu-mips64el" },
1303+
.powerpc => Executor{ .qemu = "qemu-ppc" },
1304+
.powerpc64 => Executor{ .qemu = "qemu-ppc64" },
1305+
.powerpc64le => Executor{ .qemu = "qemu-ppc64le" },
1306+
.riscv32 => Executor{ .qemu = "qemu-riscv32" },
1307+
.riscv64 => Executor{ .qemu = "qemu-riscv64" },
1308+
.s390x => Executor{ .qemu = "qemu-s390x" },
1309+
.sparc => Executor{ .qemu = "qemu-sparc" },
1310+
.x86_64 => Executor{ .qemu = "qemu-x86_64" },
1311+
else => return .unavailable,
1312+
};
1313+
}
1314+
1315+
if (self.isWindows()) {
1316+
switch (self.getArchPtrBitWidth()) {
1317+
32 => return Executor{ .wine = "wine" },
1318+
64 => return Executor{ .wine = "wine64" },
1319+
else => return .unavailable,
1320+
}
1321+
}
1322+
1323+
return .unavailable;
1324+
}
12021325
};
12031326

12041327
const Pkg = struct {
@@ -1266,6 +1389,7 @@ pub const LibExeObjStep = struct {
12661389
include_dirs: ArrayList(IncludeDir),
12671390
output_dir: ?[]const u8,
12681391
need_system_paths: bool,
1392+
is_linking_libc: bool = false,
12691393

12701394
installed_path: ?[]const u8,
12711395
install_step: ?*InstallArtifactStep,
@@ -1275,6 +1399,20 @@ pub const LibExeObjStep = struct {
12751399

12761400
valgrind_support: ?bool = null,
12771401

1402+
/// Uses system Wine installation to run cross compiled Windows build artifacts.
1403+
enable_wine: bool = false,
1404+
1405+
/// Uses system QEMU installation to run cross compiled foreign architecture build artifacts.
1406+
enable_qemu: bool = false,
1407+
1408+
/// After following the steps in https://github.com/ziglang/zig/wiki/Updating-libc#glibc,
1409+
/// this will be the directory $glibc-build-dir/install/glibcs
1410+
/// Given the example of the aarch64 target, this is the directory
1411+
/// that contains the path `aarch64-linux-gnu/lib/ld-linux-aarch64.so.1`.
1412+
glibc_multi_install_dir: ?[]const u8 = null,
1413+
1414+
dynamic_linker: ?[]const u8 = null,
1415+
12781416
const LinkObject = union(enum) {
12791417
StaticPath: []const u8,
12801418
OtherStep: *LibExeObjStep,
@@ -1504,7 +1642,9 @@ pub const LibExeObjStep = struct {
15041642

15051643
pub fn linkSystemLibrary(self: *LibExeObjStep, name: []const u8) void {
15061644
self.link_objects.append(LinkObject{ .SystemLib = self.builder.dupe(name) }) catch unreachable;
1507-
if (!isLibCLibrary(name)) {
1645+
if (isLibCLibrary(name)) {
1646+
self.is_linking_libc = true;
1647+
} else {
15081648
self.need_system_paths = true;
15091649
}
15101650
}
@@ -1840,6 +1980,11 @@ pub const LibExeObjStep = struct {
18401980
zig_args.append(builder.pathFromRoot(linker_script)) catch unreachable;
18411981
}
18421982

1983+
if (self.dynamic_linker) |dynamic_linker| {
1984+
try zig_args.append("--dynamic-linker");
1985+
try zig_args.append(dynamic_linker);
1986+
}
1987+
18431988
if (self.version_script) |version_script| {
18441989
try zig_args.append("--version-script");
18451990
try zig_args.append(builder.pathFromRoot(version_script));
@@ -1854,6 +1999,34 @@ pub const LibExeObjStep = struct {
18541999
try zig_args.append("--test-cmd-bin");
18552000
}
18562001
}
2002+
} else switch (self.target.getExternalExecutor()) {
2003+
.native, .unavailable => {},
2004+
.qemu => |bin_name| if (self.enable_qemu) qemu: {
2005+
const need_cross_glibc = self.target.isGnu() and self.target.isLinux() and self.is_linking_libc;
2006+
const glibc_dir_arg = if (need_cross_glibc)
2007+
self.glibc_multi_install_dir orelse break :qemu
2008+
else
2009+
null;
2010+
try zig_args.append("--test-cmd");
2011+
try zig_args.append(bin_name);
2012+
if (glibc_dir_arg) |dir| {
2013+
const full_dir = try fs.path.join(builder.allocator, [_][]const u8{
2014+
dir,
2015+
try self.target.linuxTriple(builder.allocator),
2016+
});
2017+
2018+
try zig_args.append("--test-cmd");
2019+
try zig_args.append("-L");
2020+
try zig_args.append("--test-cmd");
2021+
try zig_args.append(full_dir);
2022+
}
2023+
try zig_args.append("--test-cmd-bin");
2024+
},
2025+
.wine => |bin_name| if (self.enable_wine) {
2026+
try zig_args.append("--test-cmd");
2027+
try zig_args.append(bin_name);
2028+
try zig_args.append("--test-cmd-bin");
2029+
},
18572030
}
18582031
for (self.packages.toSliceConst()) |pkg| {
18592032
zig_args.append("--pkg-begin") catch unreachable;

std/c.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ pub extern "c" fn close(fd: fd_t) c_int;
6363
pub extern "c" fn @"close$NOCANCEL"(fd: fd_t) c_int;
6464
pub extern "c" fn fstat(fd: fd_t, buf: *Stat) c_int;
6565
pub extern "c" fn @"fstat$INODE64"(fd: fd_t, buf: *Stat) c_int;
66-
pub extern "c" fn lseek(fd: fd_t, offset: isize, whence: c_int) isize;
66+
pub extern "c" fn lseek(fd: fd_t, offset: off_t, whence: c_int) off_t;
6767
pub extern "c" fn open(path: [*]const u8, oflag: c_uint, ...) c_int;
6868
pub extern "c" fn openat(fd: c_int, path: [*]const u8, oflag: c_uint, ...) c_int;
6969
pub extern "c" fn raise(sig: c_int) c_int;

std/fmt/parse_float.zig

+4
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,10 @@ pub fn parseFloat(comptime T: type, s: []const u8) !T {
382382
}
383383

384384
test "fmt.parseFloat" {
385+
if (@import("builtin").arch == .arm) {
386+
// TODO https://github.com/ziglang/zig/issues/3289
387+
return error.SkipZigTest;
388+
}
385389
const testing = std.testing;
386390
const expect = testing.expect;
387391
const expectEqual = testing.expectEqual;

std/fs/path.zig

+8
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,10 @@ test "resolve" {
646646
}
647647

648648
test "resolveWindows" {
649+
if (@import("builtin").arch == .aarch64) {
650+
// TODO https://github.com/ziglang/zig/issues/3288
651+
return error.SkipZigTest;
652+
}
649653
if (windows.is_the_target) {
650654
const cwd = try process.getCwdAlloc(debug.global_allocator);
651655
const parsed_cwd = windowsParsePath(cwd);
@@ -1086,6 +1090,10 @@ pub fn relativePosix(allocator: *Allocator, from: []const u8, to: []const u8) ![
10861090
}
10871091

10881092
test "relative" {
1093+
if (@import("builtin").arch == .aarch64) {
1094+
// TODO https://github.com/ziglang/zig/issues/3288
1095+
return error.SkipZigTest;
1096+
}
10891097
testRelativeWindows("c:/blah\\blah", "d:/games", "D:\\games");
10901098
testRelativeWindows("c:/aaaa/bbbb", "c:/aaaa", "..");
10911099
testRelativeWindows("c:/aaaa/bbbb", "c:/cccc", "..\\..\\cccc");

std/io/test.zig

+4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ const fs = std.fs;
1111
const File = std.fs.File;
1212

1313
test "write a file, read it, then delete it" {
14+
if (builtin.arch == .aarch64 and builtin.glibc_version != null) {
15+
// TODO https://github.com/ziglang/zig/issues/3288
16+
return error.SkipZigTest;
17+
}
1418
var raw_bytes: [200 * 1024]u8 = undefined;
1519
var allocator = &std.heap.FixedBufferAllocator.init(raw_bytes[0..]).allocator;
1620

std/os/bits/darwin.zig

+3-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ pub const mach_timebase_info_data = extern struct {
4343
denom: u32,
4444
};
4545

46+
pub const off_t = i64;
47+
4648
/// Renamed to Stat to not conflict with the stat function.
4749
/// atime, mtime, and ctime have functions to return `timespec`,
4850
/// because although this is a POSIX API, the layout and names of
@@ -65,7 +67,7 @@ pub const Stat = extern struct {
6567
ctimensec: isize,
6668
birthtimesec: isize,
6769
birthtimensec: isize,
68-
size: i64,
70+
size: off_t,
6971
blocks: i64,
7072
blksize: i32,
7173
flags: u32,

0 commit comments

Comments
 (0)