diff --git a/.gitattributes b/.gitattributes index 355918890be1..8f894eb5690f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,5 @@ *.zig text eol=lf +*.txt text eol=lf langref.html.in text eol=lf deps/* linguist-vendored diff --git a/build.zig b/build.zig index 457314b42a6d..b38fb87cb706 100644 --- a/build.zig +++ b/build.zig @@ -70,6 +70,7 @@ pub fn build(b: *Builder) !void { const skip_release_fast = b.option(bool, "skip-release-fast", "Main test suite skips release-fast builds") orelse skip_release; const skip_release_safe = b.option(bool, "skip-release-safe", "Main test suite skips release-safe builds") orelse skip_release; const skip_non_native = b.option(bool, "skip-non-native", "Main test suite skips non-native builds") orelse false; + const skip_libc = b.option(bool, "skip-libc", "Main test suite skips tests that link libc") orelse false; const skip_self_hosted = b.option(bool, "skip-self-hosted", "Main test suite skips building self hosted compiler") orelse false; if (!skip_self_hosted) { // TODO re-enable this after https://github.com/ziglang/zig/issues/2377 @@ -96,6 +97,10 @@ pub fn build(b: *Builder) !void { const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter"); + const is_wine_enabled = b.option(bool, "enable-wine", "Use Wine to run cross compiled Windows tests") orelse false; + const is_qemu_enabled = b.option(bool, "enable-qemu", "Use QEMU to run cross compiled foreign architecture tests") orelse false; + const glibc_multi_dir = b.option([]const u8, "enable-foreign-glibc", "Provide directory with glibc installations to run cross compiled tests that link glibc"); + const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests"); test_stage2_step.dependOn(&test_stage2.step); @@ -122,19 +127,16 @@ pub fn build(b: *Builder) !void { } const modes = chosen_modes[0..chosen_mode_index]; - const multi_and_single = [_]bool{ false, true }; - const just_multi = [_]bool{false}; - // run stage1 `zig fmt` on this build.zig file just to make sure it works test_step.dependOn(&fmt_build_zig.step); const fmt_step = b.step("test-fmt", "Run zig fmt against build.zig to make sure it works"); fmt_step.dependOn(&fmt_build_zig.step); - test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes, multi_and_single, skip_non_native)); + 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)); - test_step.dependOn(tests.addPkgTests(b, test_filter, "std/std.zig", "std", "Run the standard library tests", modes, multi_and_single, skip_non_native)); + 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)); - 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)); + 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)); test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes)); test_step.dependOn(tests.addStandaloneTests(b, test_filter, modes)); diff --git a/ci/azure/linux_script b/ci/azure/linux_script index 65724e782709..e12f16f15f47 100755 --- a/ci/azure/linux_script +++ b/ci/azure/linux_script @@ -12,7 +12,7 @@ sudo apt-get update -q sudo apt-get remove -y llvm-* sudo rm -rf /usr/local/* -sudo apt-get install -y libxml2-dev libclang-9-dev llvm-9 llvm-9-dev cmake s3cmd gcc-7 g++-7 +sudo apt-get install -y libxml2-dev libclang-9-dev llvm-9 llvm-9-dev cmake s3cmd gcc-7 g++-7 qemu export CC=gcc-7 export CXX=g++-7 @@ -20,7 +20,7 @@ mkdir build cd build cmake .. -DCMAKE_BUILD_TYPE=Release make -j2 install -./zig build --build-file ../build.zig test +./zig build test -Denable-qemu if [ "${BUILD_REASON}" != "PullRequest" ]; then ARTIFACTSDIR="$BUILDDIR/artifacts" diff --git a/ci/azure/macos_script b/ci/azure/macos_script index 1253f78b875a..adfe3c7178c6 100755 --- a/ci/azure/macos_script +++ b/ci/azure/macos_script @@ -70,7 +70,7 @@ mkdir build cd build cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$PREFIX -DCMAKE_INSTALL_PREFIX=$(pwd)/release -DZIG_STATIC=ON make $JOBS install -release/bin/zig build --build-file ../build.zig test +release/bin/zig build test if [ "${BUILD_REASON}" != "PullRequest" ]; then mv ../LICENSE release/ diff --git a/ci/azure/pipelines.yml b/ci/azure/pipelines.yml index 8e6fcde6365b..bcc2f119456b 100644 --- a/ci/azure/pipelines.yml +++ b/ci/azure/pipelines.yml @@ -27,7 +27,7 @@ jobs: displayName: 'Build and test' - job: BuildWindows pool: - vmImage: 'vs2017-win2016' + vmImage: 'windows-2019' timeoutInMinutes: 360 diff --git a/ci/azure/windows_script.bat b/ci/azure/windows_script.bat index 9d1dbfb7c44a..5c44abcbe108 100644 --- a/ci/azure/windows_script.bat +++ b/ci/azure/windows_script.bat @@ -10,17 +10,18 @@ SET "PATH=%PREVPATH%" SET "MSYSTEM=%PREVMSYSTEM%" SET "ZIGBUILDDIR=%SRCROOT%\build" -SET "ZIGINSTALLDIR=%ZIGBUILDDIR%\release" +SET "ZIGINSTALLDIR=%ZIGBUILDDIR%\dist" SET "ZIGPREFIXPATH=%SRCROOT%\llvm+clang-9.0.0-win64-msvc-release" -call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 +call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 mkdir %ZIGBUILDDIR% cd %ZIGBUILDDIR% -cmake.exe .. -Thost=x64 -G"Visual Studio 15 2017 Win64" "-DCMAKE_INSTALL_PREFIX=%ZIGINSTALLDIR%" "-DCMAKE_PREFIX_PATH=%ZIGPREFIXPATH%" -DCMAKE_BUILD_TYPE=Release || exit /b -msbuild /p:Configuration=Release INSTALL.vcxproj || exit /b +REM Here we use MinSizeRel instead of Release to work around https://github.com/ziglang/zig/issues/3024 +cmake.exe .. -Thost=x64 -G"Visual Studio 16 2019" -A x64 "-DCMAKE_INSTALL_PREFIX=%ZIGINSTALLDIR%" "-DCMAKE_PREFIX_PATH=%ZIGPREFIXPATH%" -DCMAKE_BUILD_TYPE=MinSizeRel || exit /b +msbuild /p:Configuration=MinSizeRel INSTALL.vcxproj || exit /b -"%ZIGINSTALLDIR%\bin\zig.exe" build --build-file ..\build.zig test || exit /b +"%ZIGINSTALLDIR%\bin\zig.exe" build test || exit /b set "PATH=%CD:~0,2%\msys64\usr\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem" SET "MSYSTEM=MINGW64" diff --git a/ci/azure/windows_upload b/ci/azure/windows_upload index 266d1b57ddba..d5527fa13aeb 100755 --- a/ci/azure/windows_upload +++ b/ci/azure/windows_upload @@ -6,16 +6,15 @@ set -e if [ "${BUILD_REASON}" != "PullRequest" ]; then cd "$ZIGBUILDDIR" - rm release/*.exe - mv ../LICENSE release/ - mv ../zig-cache/langref.html release/ - mv release/bin/zig.exe release/ - rmdir release/bin + mv ../LICENSE dist/ + mv ../zig-cache/langref.html dist/ + mv dist/bin/zig.exe dist/ + rmdir dist/bin - VERSION=$(release/zig.exe version) + VERSION=$(dist/zig.exe version) DIRNAME="zig-windows-x86_64-$VERSION" TARBALL="$DIRNAME.zip" - mv release "$DIRNAME" + mv dist "$DIRNAME" 7z a "$TARBALL" "$DIRNAME" mv "$DOWNLOADSECUREFILE_SECUREFILEPATH" "$HOME/.s3cfg" diff --git a/lib/libc/include/any-windows-any/psdk_inc/intrin-impl.h b/lib/libc/include/any-windows-any/psdk_inc/intrin-impl.h index 4c6d8fd02942..591d9994bab2 100644 --- a/lib/libc/include/any-windows-any/psdk_inc/intrin-impl.h +++ b/lib/libc/include/any-windows-any/psdk_inc/intrin-impl.h @@ -1938,32 +1938,6 @@ __buildmov(__movsd, unsigned __LONG32, "d") #define __INTRINSIC_DEFINED___movsd #endif /* __INTRINSIC_PROLOG */ -#if !defined(__GNUC__) || __GNUC__ < 8 /* GCC 8 has already defined _xgetbv */ -/* NOTE: This should be in immintrin.h */ -#if __INTRINSIC_PROLOG(_xgetbv) -unsigned __int64 _xgetbv(unsigned int); -#if !__has_builtin(_xgetbv) -__INTRINSICS_USEINLINE -unsigned __int64 _xgetbv(unsigned int index) -{ -#if defined(__x86_64__) || defined(_AMD64_) - unsigned __int64 val1, val2; -#else - unsigned __LONG32 val1, val2; -#endif /* defined(__x86_64__) || defined(_AMD64_) */ - - __asm__ __volatile__( - "xgetbv" - : "=a" (val1), "=d" (val2) - : "c" (index)); - - return (((unsigned __int64)val2) << 32) | val1; -} -#endif -#define __INTRINSIC_DEFINED__xgetbv -#endif /* __INTRINSIC_PROLOG */ -#endif /* __GNUC__ < 8 */ - #endif /* defined(__x86_64__) || defined(_AMD64_) || defined(__i386__) || defined(_X86_) */ /* ***************************************************** */ diff --git a/src/buffer.cpp b/src/buffer.cpp index 3564481b8423..86435e0f1496 100644 --- a/src/buffer.cpp +++ b/src/buffer.cpp @@ -61,7 +61,6 @@ void buf_appendf(Buf *buf, const char *format, ...) { // these functions are not static inline so they can be better used as template parameters bool buf_eql_buf(Buf *buf, Buf *other) { - assert(buf->list.length); return buf_eql_mem(buf, buf_ptr(other), buf_len(other)); } diff --git a/src/glibc.cpp b/src/glibc.cpp index d7ae47ed7197..50ccf20efe87 100644 --- a/src/glibc.cpp +++ b/src/glibc.cpp @@ -50,7 +50,7 @@ Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbo } { - SplitIterator it = memSplit(buf_to_slice(vers_txt_contents), str("\n")); + SplitIterator it = memSplit(buf_to_slice(vers_txt_contents), str("\r\n")); for (;;) { Optional> opt_component = SplitIterator_next(&it); if (!opt_component.is_some) break; @@ -65,7 +65,7 @@ Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbo } } { - SplitIterator it = memSplit(buf_to_slice(fns_txt_contents), str("\n")); + SplitIterator it = memSplit(buf_to_slice(fns_txt_contents), str("\r\n")); for (;;) { Optional> opt_component = SplitIterator_next(&it); if (!opt_component.is_some) break; @@ -91,17 +91,19 @@ Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbo } } { - SplitIterator it = memSplit(buf_to_slice(abi_txt_contents), str("\n")); + SplitIterator it = memSplit(buf_to_slice(abi_txt_contents), str("\r\n")); ZigGLibCVerList *ver_list_base = nullptr; + int line_num = 0; for (;;) { if (ver_list_base == nullptr) { + line_num += 1; Optional> opt_line = SplitIterator_next_separate(&it); if (!opt_line.is_some) break; ver_list_base = allocate(glibc_abi->all_functions.length); - ZigTarget *target = allocate(1); SplitIterator line_it = memSplit(opt_line.value, str(" ")); for (;;) { + ZigTarget *target = allocate(1); Optional> opt_target = SplitIterator_next(&line_it); if (!opt_target.is_some) break; @@ -122,7 +124,19 @@ Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbo target->os = OsLinux; err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len); - assert(err == ErrorNone); + if (err != ErrorNone) { + fprintf(stderr, "Error parsing %s:%d: %s\n", buf_ptr(glibc_abi->abi_txt_path), + line_num, err_str(err)); + fprintf(stderr, "arch: '%.*s', os: '%.*s', abi: '%.*s'\n", + (int)opt_arch.value.len, (const char*)opt_arch.value.ptr, + (int)opt_os.value.len, (const char*)opt_os.value.ptr, + (int)opt_abi.value.len, (const char*)opt_abi.value.ptr); + fprintf(stderr, "parsed from target: '%.*s'\n", + (int)opt_target.value.len, (const char*)opt_target.value.ptr); + fprintf(stderr, "parsed from line:\n%.*s\n", (int)opt_line.value.len, opt_line.value.ptr); + fprintf(stderr, "Zig installation appears to be corrupted.\n"); + exit(1); + } glibc_abi->version_table.put(target, ver_list_base); } @@ -130,6 +144,7 @@ Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbo } for (size_t fn_i = 0; fn_i < glibc_abi->all_functions.length; fn_i += 1) { ZigGLibCVerList *ver_list = &ver_list_base[fn_i]; + line_num += 1; Optional> opt_line = SplitIterator_next_separate(&it); assert(opt_line.is_some); @@ -266,7 +281,7 @@ Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, con // - If there are no versions, don't emit it // - Take the greatest one <= than the target one // - If none of them is <= than the - // specified one don't pick any default version + // specified one don't pick any default version if (ver_list->len == 0) continue; uint8_t chosen_def_ver_index = 255; for (uint8_t ver_i = 0; ver_i < ver_list->len; ver_i += 1) { @@ -322,7 +337,7 @@ Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, con codegen_set_lib_version(child_gen, lib->sover, 0, 0); child_gen->is_dynamic = true; child_gen->is_dummy_so = true; - child_gen->version_script_path = map_file_path; + child_gen->version_script_path = map_file_path; child_gen->enable_cache = false; child_gen->output_dir = dummy_dir; codegen_build_and_link(child_gen); diff --git a/src/link.cpp b/src/link.cpp index d595580f9ab4..0d51188bb343 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -1295,6 +1295,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { c_file->args.append("-include"); c_file->args.append(path_from_libc(parent, "glibc" OS_SEP "include" OS_SEP "libc-modules.h")); c_file->args.append("-DMODULE_NAME=libc"); + c_file->args.append("-Wno-nonportable-include-path"); c_file->args.append("-include"); c_file->args.append(path_from_libc(parent, "glibc" OS_SEP "include" OS_SEP "libc-symbols.h")); c_file->args.append("-DTOP_NAMESPACE=glibc"); @@ -1321,6 +1322,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { c_file->args.append("-include"); c_file->args.append(path_from_libc(parent, "glibc" OS_SEP "include" OS_SEP "libc-modules.h")); c_file->args.append("-DMODULE_NAME=libc"); + c_file->args.append("-Wno-nonportable-include-path"); c_file->args.append("-include"); c_file->args.append(path_from_libc(parent, "glibc" OS_SEP "include" OS_SEP "libc-symbols.h")); c_file->args.append("-DPIC"); @@ -1377,6 +1379,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { c_file->args.append("-include"); c_file->args.append(path_from_libc(parent, "glibc" OS_SEP "include" OS_SEP "libc-modules.h")); c_file->args.append("-DMODULE_NAME=libc"); + c_file->args.append("-Wno-nonportable-include-path"); c_file->args.append("-include"); c_file->args.append(path_from_libc(parent, "glibc" OS_SEP "include" OS_SEP "libc-symbols.h")); c_file->args.append("-DPIC"); @@ -1420,6 +1423,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { c_file->args.append("-include"); c_file->args.append(path_from_libc(parent, "glibc" OS_SEP "include" OS_SEP "libc-modules.h")); c_file->args.append("-DMODULE_NAME=libc"); + c_file->args.append("-Wno-nonportable-include-path"); c_file->args.append("-include"); c_file->args.append(path_from_libc(parent, "glibc" OS_SEP "include" OS_SEP "libc-symbols.h")); c_file->args.append("-DPIC"); diff --git a/src/os.cpp b/src/os.cpp index 3a6ed2c286f4..6dc3777f8c40 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -116,7 +116,7 @@ static void os_spawn_process_posix(ZigList &args, Termination *ter pid_t pid; int rc = posix_spawnp(&pid, args.at(0), nullptr, nullptr, const_cast(argv), environ); if (rc != 0) { - zig_panic("posix_spawn failed: %s", strerror(rc)); + zig_panic("unable to spawn %s: %s", args.at(0), strerror(rc)); } int status; diff --git a/src/util.cpp b/src/util.cpp index 65b1fe308231..13bfbbcd4715 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -18,17 +18,10 @@ void zig_panic(const char *format, ...) { vfprintf(stderr, format, ap); fflush(stderr); va_end(ap); - stage2_panic(nullptr, 0); + stage2_panic("", 0); abort(); } -void assert(bool ok) { - if (!ok) { - const char *msg = "Assertion failed. This is a bug in the Zig compiler."; - stage2_panic(msg, strlen(msg)); - } -} - uint32_t int_hash(int i) { return (uint32_t)(i % UINT32_MAX); } diff --git a/src/util.hpp b/src/util.hpp index 1248635de9c8..8abcef32ceec 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -43,15 +43,21 @@ ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF(1, 2) void zig_panic(const char *format, ...); +static inline void zig_assert(bool ok, const char *file, int line, const char *func) { + if (!ok) { + zig_panic("Assertion failed at %s:%d in %s. This is a bug in the Zig compiler.", file, line, func); + } +} + #ifdef _WIN32 #define __func__ __FUNCTION__ #endif -#define zig_unreachable() zig_panic("unreachable: %s:%s:%d", __FILE__, __func__, __LINE__) +#define zig_unreachable() zig_panic("Unreachable at %s:%d in %s. This is a bug in the Zig compiler.", __FILE__, __LINE__, __func__) // Assertions in stage1 are always on, and they call zig @panic. #undef assert -void assert(bool ok); +#define assert(ok) zig_assert(ok, __FILE__, __LINE__, __func__) #if defined(_MSC_VER) static inline int clzll(unsigned long long mask) { diff --git a/std/build.zig b/std/build.zig index 54a49e9d58e5..915b2558570b 100644 --- a/std/build.zig +++ b/std/build.zig @@ -1015,6 +1015,7 @@ pub const Target = union(enum) { => return .msvc, .linux, .wasi, + .emscripten, => return .musl, } } @@ -1175,6 +1176,13 @@ pub const Target = union(enum) { }; } + pub fn isLinux(self: Target) bool { + return switch (self.getOs()) { + .linux => true, + else => false, + }; + } + pub fn isUefi(self: Target) bool { return switch (self.getOs()) { .uefi => true, @@ -1196,9 +1204,125 @@ pub const Target = union(enum) { }; } + pub fn isNetBSD(self: Target) bool { + return switch (self.getOs()) { + .netbsd => true, + else => false, + }; + } + pub fn wantSharedLibSymLinks(self: Target) bool { return !self.isWindows(); } + + pub fn osRequiresLibC(self: Target) bool { + return self.isDarwin() or self.isFreeBSD() or self.isNetBSD(); + } + + pub fn getArchPtrBitWidth(self: Target) u32 { + switch (self.getArch()) { + .avr, + .msp430, + => return 16, + + .arc, + .arm, + .armeb, + .hexagon, + .le32, + .mips, + .mipsel, + .powerpc, + .r600, + .riscv32, + .sparc, + .sparcel, + .tce, + .tcele, + .thumb, + .thumbeb, + .i386, + .xcore, + .nvptx, + .amdil, + .hsail, + .spir, + .kalimba, + .shave, + .lanai, + .wasm32, + .renderscript32, + .aarch64_32, + => return 32, + + .aarch64, + .aarch64_be, + .mips64, + .mips64el, + .powerpc64, + .powerpc64le, + .riscv64, + .x86_64, + .nvptx64, + .le64, + .amdil64, + .hsail64, + .spir64, + .wasm64, + .renderscript64, + .amdgcn, + .bpfel, + .bpfeb, + .sparcv9, + .s390x, + => return 64, + } + } + + pub const Executor = union(enum) { + native, + qemu: []const u8, + wine: []const u8, + unavailable, + }; + + pub fn getExternalExecutor(self: Target) Executor { + if (@TagType(Target)(self) == .Native) return .native; + + // If the target OS matches the host OS, we can use QEMU to emulate a foreign architecture. + if (self.getOs() == builtin.os) { + return switch (self.getArch()) { + .aarch64 => Executor{ .qemu = "qemu-aarch64" }, + .aarch64_be => Executor{ .qemu = "qemu-aarch64_be" }, + .arm => Executor{ .qemu = "qemu-arm" }, + .armeb => Executor{ .qemu = "qemu-armeb" }, + .i386 => Executor{ .qemu = "qemu-i386" }, + .mips => Executor{ .qemu = "qemu-mips" }, + .mipsel => Executor{ .qemu = "qemu-mipsel" }, + .mips64 => Executor{ .qemu = "qemu-mips64" }, + .mips64el => Executor{ .qemu = "qemu-mips64el" }, + .powerpc => Executor{ .qemu = "qemu-ppc" }, + .powerpc64 => Executor{ .qemu = "qemu-ppc64" }, + .powerpc64le => Executor{ .qemu = "qemu-ppc64le" }, + .riscv32 => Executor{ .qemu = "qemu-riscv32" }, + .riscv64 => Executor{ .qemu = "qemu-riscv64" }, + .s390x => Executor{ .qemu = "qemu-s390x" }, + .sparc => Executor{ .qemu = "qemu-sparc" }, + .x86_64 => Executor{ .qemu = "qemu-x86_64" }, + else => return .unavailable, + }; + } + + if (self.isWindows()) { + switch (self.getArchPtrBitWidth()) { + 32 => return Executor{ .wine = "wine" }, + 64 => return Executor{ .wine = "wine64" }, + else => return .unavailable, + } + } + + return .unavailable; + } }; const Pkg = struct { @@ -1266,6 +1390,7 @@ pub const LibExeObjStep = struct { include_dirs: ArrayList(IncludeDir), output_dir: ?[]const u8, need_system_paths: bool, + is_linking_libc: bool = false, installed_path: ?[]const u8, install_step: ?*InstallArtifactStep, @@ -1275,6 +1400,20 @@ pub const LibExeObjStep = struct { valgrind_support: ?bool = null, + /// Uses system Wine installation to run cross compiled Windows build artifacts. + enable_wine: bool = false, + + /// Uses system QEMU installation to run cross compiled foreign architecture build artifacts. + enable_qemu: bool = false, + + /// After following the steps in https://github.com/ziglang/zig/wiki/Updating-libc#glibc, + /// this will be the directory $glibc-build-dir/install/glibcs + /// Given the example of the aarch64 target, this is the directory + /// that contains the path `aarch64-linux-gnu/lib/ld-linux-aarch64.so.1`. + glibc_multi_install_dir: ?[]const u8 = null, + + dynamic_linker: ?[]const u8 = null, + const LinkObject = union(enum) { StaticPath: []const u8, OtherStep: *LibExeObjStep, @@ -1504,7 +1643,9 @@ pub const LibExeObjStep = struct { pub fn linkSystemLibrary(self: *LibExeObjStep, name: []const u8) void { self.link_objects.append(LinkObject{ .SystemLib = self.builder.dupe(name) }) catch unreachable; - if (!isLibCLibrary(name)) { + if (isLibCLibrary(name)) { + self.is_linking_libc = true; + } else { self.need_system_paths = true; } } @@ -1840,6 +1981,11 @@ pub const LibExeObjStep = struct { zig_args.append(builder.pathFromRoot(linker_script)) catch unreachable; } + if (self.dynamic_linker) |dynamic_linker| { + try zig_args.append("--dynamic-linker"); + try zig_args.append(dynamic_linker); + } + if (self.version_script) |version_script| { try zig_args.append("--version-script"); try zig_args.append(builder.pathFromRoot(version_script)); @@ -1854,6 +2000,34 @@ pub const LibExeObjStep = struct { try zig_args.append("--test-cmd-bin"); } } + } else switch (self.target.getExternalExecutor()) { + .native, .unavailable => {}, + .qemu => |bin_name| if (self.enable_qemu) qemu: { + const need_cross_glibc = self.target.isGnu() and self.target.isLinux() and self.is_linking_libc; + const glibc_dir_arg = if (need_cross_glibc) + self.glibc_multi_install_dir orelse break :qemu + else + null; + try zig_args.append("--test-cmd"); + try zig_args.append(bin_name); + if (glibc_dir_arg) |dir| { + const full_dir = try fs.path.join(builder.allocator, [_][]const u8{ + dir, + try self.target.linuxTriple(builder.allocator), + }); + + try zig_args.append("--test-cmd"); + try zig_args.append("-L"); + try zig_args.append("--test-cmd"); + try zig_args.append(full_dir); + } + try zig_args.append("--test-cmd-bin"); + }, + .wine => |bin_name| if (self.enable_wine) { + try zig_args.append("--test-cmd"); + try zig_args.append(bin_name); + try zig_args.append("--test-cmd-bin"); + }, } for (self.packages.toSliceConst()) |pkg| { zig_args.append("--pkg-begin") catch unreachable; diff --git a/std/c.zig b/std/c.zig index 45d93bfd9f63..5c280ac551de 100644 --- a/std/c.zig +++ b/std/c.zig @@ -63,7 +63,7 @@ pub extern "c" fn close(fd: fd_t) c_int; pub extern "c" fn @"close$NOCANCEL"(fd: fd_t) c_int; pub extern "c" fn fstat(fd: fd_t, buf: *Stat) c_int; pub extern "c" fn @"fstat$INODE64"(fd: fd_t, buf: *Stat) c_int; -pub extern "c" fn lseek(fd: fd_t, offset: isize, whence: c_int) isize; +pub extern "c" fn lseek(fd: fd_t, offset: off_t, whence: c_int) off_t; pub extern "c" fn open(path: [*]const u8, oflag: c_uint, ...) c_int; pub extern "c" fn openat(fd: c_int, path: [*]const u8, oflag: c_uint, ...) c_int; pub extern "c" fn raise(sig: c_int) c_int; diff --git a/std/fmt/parse_float.zig b/std/fmt/parse_float.zig index d0a826a55ef6..9a35e27c2190 100644 --- a/std/fmt/parse_float.zig +++ b/std/fmt/parse_float.zig @@ -382,6 +382,10 @@ pub fn parseFloat(comptime T: type, s: []const u8) !T { } test "fmt.parseFloat" { + if (@import("builtin").arch == .arm) { + // TODO https://github.com/ziglang/zig/issues/3289 + return error.SkipZigTest; + } const testing = std.testing; const expect = testing.expect; const expectEqual = testing.expectEqual; diff --git a/std/fs/path.zig b/std/fs/path.zig index 0181e949ddc5..2bb23f04cedd 100644 --- a/std/fs/path.zig +++ b/std/fs/path.zig @@ -646,6 +646,10 @@ test "resolve" { } test "resolveWindows" { + if (@import("builtin").arch == .aarch64) { + // TODO https://github.com/ziglang/zig/issues/3288 + return error.SkipZigTest; + } if (windows.is_the_target) { const cwd = try process.getCwdAlloc(debug.global_allocator); const parsed_cwd = windowsParsePath(cwd); @@ -1086,6 +1090,10 @@ pub fn relativePosix(allocator: *Allocator, from: []const u8, to: []const u8) ![ } test "relative" { + if (@import("builtin").arch == .aarch64) { + // TODO https://github.com/ziglang/zig/issues/3288 + return error.SkipZigTest; + } testRelativeWindows("c:/blah\\blah", "d:/games", "D:\\games"); testRelativeWindows("c:/aaaa/bbbb", "c:/aaaa", ".."); testRelativeWindows("c:/aaaa/bbbb", "c:/cccc", "..\\..\\cccc"); diff --git a/std/io/test.zig b/std/io/test.zig index 40258eab5f2e..e624733ba8e4 100644 --- a/std/io/test.zig +++ b/std/io/test.zig @@ -11,6 +11,10 @@ const fs = std.fs; const File = std.fs.File; test "write a file, read it, then delete it" { + if (builtin.arch == .aarch64 and builtin.glibc_version != null) { + // TODO https://github.com/ziglang/zig/issues/3288 + return error.SkipZigTest; + } var raw_bytes: [200 * 1024]u8 = undefined; var allocator = &std.heap.FixedBufferAllocator.init(raw_bytes[0..]).allocator; diff --git a/std/os/bits/darwin.zig b/std/os/bits/darwin.zig index 483d4cda908f..69dcdf06cc6f 100644 --- a/std/os/bits/darwin.zig +++ b/std/os/bits/darwin.zig @@ -43,6 +43,8 @@ pub const mach_timebase_info_data = extern struct { denom: u32, }; +pub const off_t = i64; + /// Renamed to Stat to not conflict with the stat function. /// atime, mtime, and ctime have functions to return `timespec`, /// because although this is a POSIX API, the layout and names of @@ -65,7 +67,7 @@ pub const Stat = extern struct { ctimensec: isize, birthtimesec: isize, birthtimensec: isize, - size: i64, + size: off_t, blocks: i64, blksize: i32, flags: u32, diff --git a/std/os/bits/freebsd.zig b/std/os/bits/freebsd.zig index 45432a6c076d..4be95b05658a 100644 --- a/std/os/bits/freebsd.zig +++ b/std/os/bits/freebsd.zig @@ -73,6 +73,8 @@ pub const msghdr_const = extern struct { msg_flags: i32, }; +pub const off_t = i64; + /// Renamed to Stat to not conflict with the stat function. /// atime, mtime, and ctime have functions to return `timespec`, /// because although this is a POSIX API, the layout and names of @@ -96,7 +98,7 @@ pub const Stat = extern struct { ctim: timespec, birthtim: timespec, - size: i64, + size: off_t, blocks: i64, blksize: isize, flags: u32, diff --git a/std/os/bits/linux/arm-eabi.zig b/std/os/bits/linux/arm-eabi.zig index fef63110eea2..4b3e1094da3e 100644 --- a/std/os/bits/linux/arm-eabi.zig +++ b/std/os/bits/linux/arm-eabi.zig @@ -511,6 +511,8 @@ pub const msghdr_const = extern struct { msg_flags: i32, }; +pub const off_t = i64; + /// Renamed to Stat to not conflict with the stat function. /// atime, mtime, and ctime have functions to return `timespec`, /// because although this is a POSIX API, the layout and names of @@ -527,7 +529,7 @@ pub const Stat = extern struct { gid: u32, rdev: u64, __rdev_padding: u32, - size: i64, + size: off_t, blksize: i32, blocks: u64, atim: timespec, diff --git a/std/os/bits/linux/arm64.zig b/std/os/bits/linux/arm64.zig index 2b1b5d07eee0..692efc0eb3be 100644 --- a/std/os/bits/linux/arm64.zig +++ b/std/os/bits/linux/arm64.zig @@ -1,11 +1,13 @@ // arm64-specific declarations that are intended to be imported into the POSIX namespace. // This does include Linux-only APIs. -const std = @import("../../std.zig"); +const std = @import("../../../std.zig"); const linux = std.os.linux; const socklen_t = linux.socklen_t; const iovec = linux.iovec; const iovec_const = linux.iovec_const; +const uid_t = linux.uid_t; +const gid_t = linux.gid_t; pub const SYS_io_setup = 0; pub const SYS_io_destroy = 1; @@ -382,6 +384,15 @@ pub const msghdr_const = extern struct { msg_flags: i32, }; +pub const blksize_t = i32; +pub const nlink_t = u32; +pub const time_t = isize; +pub const mode_t = u32; +pub const off_t = isize; +pub const ino_t = usize; +pub const dev_t = usize; +pub const blkcnt_t = isize; + /// Renamed to Stat to not conflict with the stat function. /// atime, mtime, and ctime have functions to return `timespec`, /// because although this is a POSIX API, the layout and names of @@ -389,23 +400,22 @@ pub const msghdr_const = extern struct { /// in C, macros are used to hide the differences. Here we use /// methods to accomplish this. pub const Stat = extern struct { - dev: u64, - ino: u64, - nlink: usize, - - mode: u32, - uid: u32, - gid: u32, - __pad0: u32, - rdev: u64, - size: i64, - blksize: isize, - blocks: i64, - + dev: dev_t, + ino: ino_t, + mode: mode_t, + nlink: nlink_t, + uid: uid_t, + gid: gid_t, + rdev: dev_t, + __pad: usize, + size: off_t, + blksize: blksize_t, + __pad2: i32, + blocks: blkcnt_t, atim: timespec, mtim: timespec, ctim: timespec, - __unused: [3]isize, + __unused: [2]u32, pub fn atime(self: Stat) timespec { return self.atim; @@ -421,7 +431,7 @@ pub const Stat = extern struct { }; pub const timespec = extern struct { - tv_sec: isize, + tv_sec: time_t, tv_nsec: isize, }; diff --git a/std/os/bits/linux/x86_64.zig b/std/os/bits/linux/x86_64.zig index 9548e0803a9b..626acd00d617 100644 --- a/std/os/bits/linux/x86_64.zig +++ b/std/os/bits/linux/x86_64.zig @@ -479,6 +479,8 @@ pub const msghdr_const = extern struct { msg_flags: i32, }; +pub const off_t = i64; + /// Renamed to Stat to not conflict with the stat function. /// atime, mtime, and ctime have functions to return `timespec`, /// because although this is a POSIX API, the layout and names of @@ -495,7 +497,7 @@ pub const Stat = extern struct { gid: u32, __pad0: u32, rdev: u64, - size: i64, + size: off_t, blksize: isize, blocks: i64, diff --git a/std/os/bits/netbsd.zig b/std/os/bits/netbsd.zig index ff19d090af71..1408b60ab0a0 100644 --- a/std/os/bits/netbsd.zig +++ b/std/os/bits/netbsd.zig @@ -73,6 +73,8 @@ pub const msghdr_const = extern struct { msg_flags: i32, }; +pub const off_t = i64; + /// Renamed to Stat to not conflict with the stat function. /// atime, mtime, and ctime have functions to return `timespec`, /// because although this is a POSIX API, the layout and names of @@ -94,7 +96,7 @@ pub const Stat = extern struct { ctim: timespec, birthtim: timespec, - size: i64, + size: off_t, blocks: i64, blksize: isize, flags: u32, diff --git a/std/os/test.zig b/std/os/test.zig index a821c5dd9fe2..a0bb74052903 100644 --- a/std/os/test.zig +++ b/std/os/test.zig @@ -95,6 +95,10 @@ test "cpu count" { } test "AtomicFile" { + if (builtin.arch == .aarch64 and builtin.glibc_version != null) { + // TODO https://github.com/ziglang/zig/issues/3288 + return error.SkipZigTest; + } var buffer: [1024]u8 = undefined; const allocator = &std.heap.FixedBufferAllocator.init(buffer[0..]).allocator; const test_out_file = "tmp_atomic_file_test_dest.txt"; diff --git a/std/rb.zig b/std/rb.zig index 3f2a2d5bb09c..4180c7459c3c 100644 --- a/std/rb.zig +++ b/std/rb.zig @@ -511,6 +511,11 @@ fn testCompare(l: *Node, r: *Node) mem.Compare { } test "rb" { + if (@import("builtin").arch == .aarch64) { + // TODO https://github.com/ziglang/zig/issues/3288 + return error.SkipZigTest; + } + var tree: Tree = undefined; var ns: [10]testNumber = undefined; ns[0].value = 42; @@ -571,6 +576,10 @@ test "inserting and looking up" { } test "multiple inserts, followed by calling first and last" { + if (@import("builtin").arch == .aarch64) { + // TODO https://github.com/ziglang/zig/issues/3288 + return error.SkipZigTest; + } var tree: Tree = undefined; tree.init(testCompare); var zeroth: testNumber = undefined; diff --git a/std/special/compiler_rt.zig b/std/special/compiler_rt.zig index a5bbefa1db80..638a9bb60c8b 100644 --- a/std/special/compiler_rt.zig +++ b/std/special/compiler_rt.zig @@ -143,7 +143,7 @@ comptime { @export("__negsf2", @import("compiler_rt/negXf2.zig").__negsf2, linkage); @export("__negdf2", @import("compiler_rt/negXf2.zig").__negdf2, linkage); - if (is_arm_arch and !is_arm_64) { + if (is_arm_arch and !is_arm_64 and !is_test) { @export("__aeabi_unwind_cpp_pr0", __aeabi_unwind_cpp_pr0, strong_linkage); @export("__aeabi_unwind_cpp_pr1", __aeabi_unwind_cpp_pr1, linkage); @export("__aeabi_unwind_cpp_pr2", __aeabi_unwind_cpp_pr2, linkage); @@ -233,7 +233,7 @@ comptime { @export("__aeabi_dcmpgt", @import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmpgt, linkage); @export("__aeabi_dcmpun", @import("compiler_rt/comparedf2.zig").__unorddf2, linkage); } - if (builtin.os == builtin.Os.windows) { + if (builtin.os == .windows) { if (!builtin.link_libc) { @export("_chkstk", @import("compiler_rt/stack_probe.zig")._chkstk, strong_linkage); @export("__chkstk", @import("compiler_rt/stack_probe.zig").__chkstk, strong_linkage); @@ -247,11 +247,11 @@ comptime { } switch (builtin.arch) { - builtin.Arch.i386 => { + .i386 => { @export("_aulldiv", @import("compiler_rt/aulldiv.zig")._aulldiv, strong_linkage); @export("_aullrem", @import("compiler_rt/aullrem.zig")._aullrem, strong_linkage); }, - builtin.Arch.x86_64 => { + .x86_64 => { // The "ti" functions must use @Vector(2, u64) parameter types to adhere to the ABI // that LLVM expects compiler-rt to have. @export("__divti3", @import("compiler_rt/divti3.zig").__divti3_windows_x86_64, linkage); @@ -264,6 +264,9 @@ comptime { else => {}, } } else { + if (builtin.glibc_version != null) { + @export("__stack_chk_guard", __stack_chk_guard, linkage); + } @export("__divti3", @import("compiler_rt/divti3.zig").__divti3, linkage); @export("__modti3", @import("compiler_rt/modti3.zig").__modti3, linkage); @export("__multi3", @import("compiler_rt/multi3.zig").__multi3, linkage); diff --git a/std/special/compiler_rt/arm/aeabi_dcmp.zig b/std/special/compiler_rt/arm/aeabi_dcmp.zig index a51d9854cea0..33bfdabcfbac 100644 --- a/std/special/compiler_rt/arm/aeabi_dcmp.zig +++ b/std/special/compiler_rt/arm/aeabi_dcmp.zig @@ -14,31 +14,31 @@ const ConditionalOperator = enum { pub nakedcc fn __aeabi_dcmpeq() noreturn { @setRuntimeSafety(false); - aeabi_dcmp(.Eq); + @inlineCall(aeabi_dcmp, .Eq); unreachable; } pub nakedcc fn __aeabi_dcmplt() noreturn { @setRuntimeSafety(false); - aeabi_dcmp(.Lt); + @inlineCall(aeabi_dcmp, .Lt); unreachable; } pub nakedcc fn __aeabi_dcmple() noreturn { @setRuntimeSafety(false); - aeabi_dcmp(.Le); + @inlineCall(aeabi_dcmp, .Le); unreachable; } pub nakedcc fn __aeabi_dcmpge() noreturn { @setRuntimeSafety(false); - aeabi_dcmp(.Ge); + @inlineCall(aeabi_dcmp, .Ge); unreachable; } pub nakedcc fn __aeabi_dcmpgt() noreturn { @setRuntimeSafety(false); - aeabi_dcmp(.Gt); + @inlineCall(aeabi_dcmp, .Gt); unreachable; } @@ -49,7 +49,7 @@ inline fn convert_dcmp_args_to_df2_args() void { ); } -inline fn aeabi_dcmp(comptime cond: ConditionalOperator) void { +fn aeabi_dcmp(comptime cond: ConditionalOperator) void { @setRuntimeSafety(false); asm volatile ( \\ push { r4, lr } diff --git a/std/special/compiler_rt/arm/aeabi_fcmp.zig b/std/special/compiler_rt/arm/aeabi_fcmp.zig index f82dd25270cf..cc5efc64fc00 100644 --- a/std/special/compiler_rt/arm/aeabi_fcmp.zig +++ b/std/special/compiler_rt/arm/aeabi_fcmp.zig @@ -14,31 +14,31 @@ const ConditionalOperator = enum { pub nakedcc fn __aeabi_fcmpeq() noreturn { @setRuntimeSafety(false); - aeabi_fcmp(.Eq); + @inlineCall(aeabi_fcmp, .Eq); unreachable; } pub nakedcc fn __aeabi_fcmplt() noreturn { @setRuntimeSafety(false); - aeabi_fcmp(.Lt); + @inlineCall(aeabi_fcmp, .Lt); unreachable; } pub nakedcc fn __aeabi_fcmple() noreturn { @setRuntimeSafety(false); - aeabi_fcmp(.Le); + @inlineCall(aeabi_fcmp, .Le); unreachable; } pub nakedcc fn __aeabi_fcmpge() noreturn { @setRuntimeSafety(false); - aeabi_fcmp(.Ge); + @inlineCall(aeabi_fcmp, .Ge); unreachable; } pub nakedcc fn __aeabi_fcmpgt() noreturn { @setRuntimeSafety(false); - aeabi_fcmp(.Gt); + @inlineCall(aeabi_fcmp, .Gt); unreachable; } @@ -49,7 +49,7 @@ inline fn convert_fcmp_args_to_sf2_args() void { ); } -inline fn aeabi_fcmp(comptime cond: ConditionalOperator) void { +fn aeabi_fcmp(comptime cond: ConditionalOperator) void { @setRuntimeSafety(false); asm volatile ( \\ push { r4, lr } diff --git a/test/tests.zig b/test/tests.zig index bbaf62ac94df..7dc1d1f620ea 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -23,21 +23,183 @@ const runtime_safety = @import("runtime_safety.zig"); const translate_c = @import("translate_c.zig"); const gen_h = @import("gen_h.zig"); -const cross_targets = [_]CrossTarget{ - CrossTarget{ - .os = .linux, - .arch = .x86_64, - .abi = .gnu, +const TestTarget = struct { + target: Target = .Native, + mode: builtin.Mode = .Debug, + link_libc: bool = false, + single_threaded: bool = false, + disable_native: bool = false, +}; + +const test_targets = [_]TestTarget{ + TestTarget{}, + TestTarget{ + .link_libc = true, + }, + TestTarget{ + .single_threaded = true, + }, + + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = .x86_64, + .abi = .none, + }, + }, + }, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = .x86_64, + .abi = .gnu, + }, + }, + .link_libc = true, + }, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = .x86_64, + .abi = .musl, + }, + }, + .link_libc = true, + }, + + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = builtin.Arch{ .aarch64 = builtin.Arch.Arm64.v8_5a }, + .abi = .none, + }, + }, + }, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = builtin.Arch{ .aarch64 = builtin.Arch.Arm64.v8_5a }, + .abi = .musl, + }, + }, + .link_libc = true, + }, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = builtin.Arch{ .aarch64 = builtin.Arch.Arm64.v8_5a }, + .abi = .gnu, + }, + }, + .link_libc = true, + }, + + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = builtin.Arch{ .arm = builtin.Arch.Arm32.v8_5a }, + .abi = .none, + }, + }, + }, + // TODO https://github.com/ziglang/zig/issues/3286 + //TestTarget{ + // .target = Target{ + // .Cross = CrossTarget{ + // .os = .linux, + // .arch = builtin.Arch{ .arm = builtin.Arch.Arm32.v8_5a }, + // .abi = .musleabihf, + // }, + // }, + // .link_libc = true, + //}, + // TODO https://github.com/ziglang/zig/issues/3287 + //TestTarget{ + // .target = Target{ + // .Cross = CrossTarget{ + // .os = .linux, + // .arch = builtin.Arch{ .arm = builtin.Arch.Arm32.v8_5a }, + // .abi = .gnueabihf, + // }, + // }, + // .link_libc = true, + //}, + + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .macosx, + .arch = .x86_64, + .abi = .gnu, + }, + }, + // TODO https://github.com/ziglang/zig/issues/3295 + .disable_native = true, + }, + + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .windows, + .arch = .x86_64, + .abi = .msvc, + }, + }, + }, + + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .windows, + .arch = .x86_64, + .abi = .gnu, + }, + }, + .link_libc = true, }, - CrossTarget{ - .os = .macosx, - .arch = .x86_64, - .abi = .gnu, + + // Do the release tests last because they take a long time + TestTarget{ + .mode = .ReleaseFast, + }, + TestTarget{ + .link_libc = true, + .mode = .ReleaseFast, + }, + TestTarget{ + .mode = .ReleaseFast, + .single_threaded = true, + }, + + TestTarget{ + .mode = .ReleaseSafe, + }, + TestTarget{ + .link_libc = true, + .mode = .ReleaseSafe, + }, + TestTarget{ + .mode = .ReleaseSafe, + .single_threaded = true, }, - CrossTarget{ - .os = .windows, - .arch = .x86_64, - .abi = .msvc, + + TestTarget{ + .mode = .ReleaseSmall, + }, + TestTarget{ + .link_libc = true, + .mode = .ReleaseSmall, + }, + TestTarget{ + .mode = .ReleaseSmall, + .single_threaded = true, }, }; @@ -182,57 +344,77 @@ pub fn addPkgTests( name: []const u8, desc: []const u8, modes: []const Mode, - single_threaded_list: []const bool, + skip_single_threaded: bool, skip_non_native: bool, + skip_libc: bool, + is_wine_enabled: bool, + is_qemu_enabled: bool, + glibc_dir: ?[]const u8, ) *build.Step { const step = b.step(b.fmt("test-{}", name), desc); - var targets = std.ArrayList(*const CrossTarget).init(b.allocator); - defer targets.deinit(); - const host = CrossTarget{ .os = builtin.os, .arch = builtin.arch, .abi = builtin.abi }; - targets.append(&host) catch unreachable; - for (cross_targets) |*t| { - if (t.os == builtin.os and t.arch == builtin.arch and t.abi == builtin.abi) continue; - targets.append(t) catch unreachable; - } + for (test_targets) |test_target| { + if (skip_non_native and test_target.target != .Native) + continue; - for (targets.toSliceConst()) |test_target| { - const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch); - if (skip_non_native and !is_native) + if (skip_libc and test_target.link_libc) + continue; + + if (test_target.link_libc and test_target.target.osRequiresLibC()) { + // This would be a redundant test. + continue; + } + + if (skip_single_threaded and test_target.single_threaded) + continue; + + const ArchTag = @TagType(builtin.Arch); + if (test_target.disable_native and + test_target.target.getOs() == builtin.os and + ArchTag(test_target.target.getArch()) == ArchTag(builtin.arch)) + { continue; - for (modes) |mode| { - for ([_]bool{ false, true }) |link_libc| { - for (single_threaded_list) |single_threaded| { - if (link_libc and !is_native) { - // don't assume we have a cross-compiling libc set up - continue; - } - const these_tests = b.addTest(root_src); - these_tests.setNamePrefix(b.fmt( - "{}-{}-{}-{}-{}-{} ", - name, - @tagName(test_target.os), - @tagName(test_target.arch), - @tagName(mode), - if (link_libc) "c" else "bare", - if (single_threaded) "single" else "multi", - )); - these_tests.single_threaded = single_threaded; - these_tests.setFilter(test_filter); - these_tests.setBuildMode(mode); - if (!is_native) { - these_tests.setTarget(test_target.arch, test_target.os, test_target.abi); - } - if (link_libc) { - these_tests.linkSystemLibrary("c"); - } - if (mem.eql(u8, name, "std")) { - these_tests.overrideStdDir("std"); - } - step.dependOn(&these_tests.step); - } - } } + + const want_this_mode = for (modes) |m| { + if (m == test_target.mode) break true; + } else false; + if (!want_this_mode) continue; + + const libc_prefix = if (test_target.target.osRequiresLibC()) + "" + else if (test_target.link_libc) + "c" + else + "bare"; + + const triple_prefix = if (test_target.target == .Native) + ([]const u8)("native") + else + test_target.target.zigTripleNoSubArch(b.allocator) catch unreachable; + + const these_tests = b.addTest(root_src); + these_tests.setNamePrefix(b.fmt( + "{}-{}-{}-{}-{} ", + name, + triple_prefix, + @tagName(test_target.mode), + libc_prefix, + if (test_target.single_threaded) "single" else "multi", + )); + these_tests.single_threaded = test_target.single_threaded; + these_tests.setFilter(test_filter); + these_tests.setBuildMode(test_target.mode); + these_tests.setTheTarget(test_target.target); + if (test_target.link_libc) { + these_tests.linkSystemLibrary("c"); + } + these_tests.overrideStdDir("std"); + these_tests.enable_wine = is_wine_enabled; + these_tests.enable_qemu = is_qemu_enabled; + these_tests.glibc_multi_install_dir = glibc_dir; + + step.dependOn(&these_tests.step); } return step; }