zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

blob fdfd550d (54642B) - Raw


      1 const std = @import("std");
      2 const builtin = @import("builtin");
      3 const assert = std.debug.assert;
      4 const mem = std.mem;
      5 const OptimizeMode = std.builtin.OptimizeMode;
      6 const Step = std.Build.Step;
      7 
      8 // Cases
      9 const compare_output = @import("compare_output.zig");
     10 const stack_traces = @import("stack_traces.zig");
     11 const assemble_and_link = @import("assemble_and_link.zig");
     12 const translate_c = @import("translate_c.zig");
     13 const run_translated_c = @import("run_translated_c.zig");
     14 
     15 // Implementations
     16 pub const TranslateCContext = @import("src/TranslateC.zig");
     17 pub const RunTranslatedCContext = @import("src/RunTranslatedC.zig");
     18 pub const CompareOutputContext = @import("src/CompareOutput.zig");
     19 pub const StackTracesContext = @import("src/StackTrace.zig");
     20 pub const DebuggerContext = @import("src/Debugger.zig");
     21 
     22 const TestTarget = struct {
     23     target: std.Target.Query = .{},
     24     optimize_mode: std.builtin.OptimizeMode = .Debug,
     25     link_libc: ?bool = null,
     26     single_threaded: ?bool = null,
     27     use_llvm: ?bool = null,
     28     use_lld: ?bool = null,
     29     pic: ?bool = null,
     30     strip: ?bool = null,
     31     skip_modules: []const []const u8 = &.{},
     32 
     33     // This is intended for targets that are known to be slow to compile. These are acceptable to
     34     // run in CI, but should not be run on developer machines by default. As an example, at the time
     35     // of writing, this includes LLVM's MIPS backend which takes upwards of 20 minutes longer to
     36     // compile tests than other backends.
     37     slow_backend: bool = false,
     38 };
     39 
     40 const test_targets = blk: {
     41     // getBaselineCpuFeatures calls populateDependencies which has a O(N ^ 2) algorithm
     42     // (where N is roughly 160, which technically makes it O(1), but it adds up to a
     43     // lot of branches)
     44     @setEvalBranchQuota(50000);
     45     break :blk [_]TestTarget{
     46         .{},
     47         .{
     48             .link_libc = true,
     49         },
     50         .{
     51             .single_threaded = true,
     52         },
     53         .{
     54             .optimize_mode = .ReleaseFast,
     55         },
     56         .{
     57             .link_libc = true,
     58             .optimize_mode = .ReleaseFast,
     59         },
     60         .{
     61             .optimize_mode = .ReleaseFast,
     62             .single_threaded = true,
     63         },
     64 
     65         .{
     66             .optimize_mode = .ReleaseSafe,
     67         },
     68         .{
     69             .link_libc = true,
     70             .optimize_mode = .ReleaseSafe,
     71         },
     72         .{
     73             .optimize_mode = .ReleaseSafe,
     74             .single_threaded = true,
     75         },
     76 
     77         .{
     78             .optimize_mode = .ReleaseSmall,
     79         },
     80         .{
     81             .link_libc = true,
     82             .optimize_mode = .ReleaseSmall,
     83         },
     84         .{
     85             .optimize_mode = .ReleaseSmall,
     86             .single_threaded = true,
     87         },
     88 
     89         .{
     90             .target = .{
     91                 .ofmt = .c,
     92             },
     93             .link_libc = true,
     94         },
     95         .{
     96             .target = .{
     97                 .cpu_arch = .x86_64,
     98                 .os_tag = .linux,
     99                 .abi = .none,
    100             },
    101             .use_llvm = false,
    102             .use_lld = false,
    103         },
    104         .{
    105             .target = .{
    106                 .cpu_arch = .x86_64,
    107                 .cpu_model = .{ .explicit = &std.Target.x86.cpu.x86_64_v2 },
    108                 .os_tag = .linux,
    109                 .abi = .none,
    110             },
    111             .use_llvm = false,
    112             .use_lld = false,
    113             .pic = true,
    114         },
    115         .{
    116             .target = .{
    117                 .cpu_arch = .x86_64,
    118                 .cpu_model = .{ .explicit = &std.Target.x86.cpu.x86_64_v3 },
    119                 .os_tag = .linux,
    120                 .abi = .none,
    121             },
    122             .use_llvm = false,
    123             .use_lld = false,
    124             .strip = true,
    125         },
    126         // Doesn't support new liveness
    127         //.{
    128         //    .target = .{
    129         //        .cpu_arch = .aarch64,
    130         //        .os_tag = .linux,
    131         //    },
    132         //    .use_llvm = false,
    133         //    .use_lld = false,
    134         //},
    135         .{
    136             .target = .{
    137                 .cpu_arch = .wasm32,
    138                 .os_tag = .wasi,
    139             },
    140             .use_llvm = false,
    141             .use_lld = false,
    142         },
    143         // https://github.com/ziglang/zig/issues/13623
    144         //.{
    145         //    .target = .{
    146         //        .cpu_arch = .arm,
    147         //        .os_tag = .linux,
    148         //    },
    149         //    .use_llvm = false,
    150         //    .use_lld = false,
    151         //},
    152         // https://github.com/ziglang/zig/issues/13623
    153         //.{
    154         //    .target = std.Target.Query.parse(.{
    155         //        .arch_os_abi = "arm-linux-none",
    156         //        .cpu_features = "generic+v8a",
    157         //    }) catch unreachable,
    158         //    .use_llvm = false,
    159         //    .use_lld = false,
    160         //},
    161         // Doesn't support new liveness
    162         //.{
    163         //    .target = .{
    164         //        .cpu_arch = .aarch64,
    165         //        .os_tag = .macos,
    166         //        .abi = .none,
    167         //    },
    168         //    .use_llvm = false,
    169         //    .use_lld = false,
    170         //},
    171         .{
    172             .target = .{
    173                 .cpu_arch = .x86_64,
    174                 .os_tag = .macos,
    175                 .abi = .none,
    176             },
    177             .use_llvm = false,
    178             .use_lld = false,
    179         },
    180         .{
    181             .target = .{
    182                 .cpu_arch = .x86_64,
    183                 .os_tag = .windows,
    184                 .abi = .gnu,
    185             },
    186             .use_llvm = false,
    187             .use_lld = false,
    188         },
    189 
    190         .{
    191             .target = .{
    192                 .cpu_arch = .wasm32,
    193                 .os_tag = .wasi,
    194             },
    195             .link_libc = false,
    196         },
    197         .{
    198             .target = .{
    199                 .cpu_arch = .wasm32,
    200                 .os_tag = .wasi,
    201             },
    202             .link_libc = true,
    203         },
    204 
    205         .{
    206             .target = .{
    207                 .cpu_arch = .x86_64,
    208                 .os_tag = .linux,
    209                 .abi = .none,
    210             },
    211         },
    212         .{
    213             .target = .{
    214                 .cpu_arch = .x86_64,
    215                 .os_tag = .linux,
    216                 .abi = .gnu,
    217             },
    218             .link_libc = true,
    219         },
    220         .{
    221             .target = .{
    222                 .cpu_arch = .x86_64,
    223                 .os_tag = .linux,
    224                 .abi = .gnux32,
    225             },
    226             .link_libc = true,
    227         },
    228         .{
    229             .target = .{
    230                 .cpu_arch = .x86_64,
    231                 .os_tag = .linux,
    232                 .abi = .musl,
    233             },
    234             .link_libc = true,
    235         },
    236         .{
    237             .target = .{
    238                 .cpu_arch = .x86_64,
    239                 .os_tag = .linux,
    240                 .abi = .muslx32,
    241             },
    242             .link_libc = true,
    243         },
    244         .{
    245             .target = .{
    246                 .cpu_arch = .x86_64,
    247                 .os_tag = .linux,
    248                 .abi = .musl,
    249             },
    250             .link_libc = true,
    251             .use_lld = false,
    252         },
    253 
    254         .{
    255             .target = .{
    256                 .cpu_arch = .x86,
    257                 .os_tag = .linux,
    258                 .abi = .none,
    259             },
    260         },
    261         .{
    262             .target = .{
    263                 .cpu_arch = .x86,
    264                 .os_tag = .linux,
    265                 .abi = .musl,
    266             },
    267             .link_libc = true,
    268         },
    269         .{
    270             .target = .{
    271                 .cpu_arch = .x86,
    272                 .os_tag = .linux,
    273                 .abi = .gnu,
    274             },
    275             .link_libc = true,
    276         },
    277 
    278         .{
    279             .target = .{
    280                 .cpu_arch = .aarch64,
    281                 .os_tag = .linux,
    282                 .abi = .none,
    283             },
    284         },
    285         .{
    286             .target = .{
    287                 .cpu_arch = .aarch64,
    288                 .os_tag = .linux,
    289                 .abi = .musl,
    290             },
    291             .link_libc = true,
    292         },
    293         .{
    294             .target = .{
    295                 .cpu_arch = .aarch64,
    296                 .os_tag = .linux,
    297                 .abi = .gnu,
    298             },
    299             .link_libc = true,
    300         },
    301         .{
    302             .target = .{
    303                 .cpu_arch = .aarch64,
    304                 .os_tag = .windows,
    305                 .abi = .gnu,
    306             },
    307             .link_libc = true,
    308         },
    309 
    310         .{
    311             .target = .{
    312                 .cpu_arch = .arm,
    313                 .os_tag = .linux,
    314                 .abi = .eabi,
    315             },
    316         },
    317         .{
    318             .target = .{
    319                 .cpu_arch = .arm,
    320                 .os_tag = .linux,
    321                 .abi = .eabihf,
    322             },
    323         },
    324         .{
    325             .target = .{
    326                 .cpu_arch = .arm,
    327                 .os_tag = .linux,
    328                 .abi = .musleabi,
    329             },
    330             .link_libc = true,
    331         },
    332         .{
    333             .target = .{
    334                 .cpu_arch = .arm,
    335                 .os_tag = .linux,
    336                 .abi = .musleabihf,
    337             },
    338             .link_libc = true,
    339         },
    340         .{
    341             .target = .{
    342                 .cpu_arch = .arm,
    343                 .os_tag = .linux,
    344                 .abi = .gnueabi,
    345             },
    346             .link_libc = true,
    347         },
    348         .{
    349             .target = .{
    350                 .cpu_arch = .arm,
    351                 .os_tag = .linux,
    352                 .abi = .gnueabihf,
    353             },
    354             .link_libc = true,
    355         },
    356 
    357         .{
    358             .target = .{
    359                 .cpu_arch = .armeb,
    360                 .os_tag = .linux,
    361                 .abi = .eabi,
    362             },
    363         },
    364         .{
    365             .target = .{
    366                 .cpu_arch = .armeb,
    367                 .os_tag = .linux,
    368                 .abi = .eabihf,
    369             },
    370         },
    371         .{
    372             .target = .{
    373                 .cpu_arch = .armeb,
    374                 .os_tag = .linux,
    375                 .abi = .musleabi,
    376             },
    377             .link_libc = true,
    378         },
    379         .{
    380             .target = .{
    381                 .cpu_arch = .armeb,
    382                 .os_tag = .linux,
    383                 .abi = .musleabihf,
    384             },
    385             .link_libc = true,
    386         },
    387         .{
    388             .target = .{
    389                 .cpu_arch = .armeb,
    390                 .os_tag = .linux,
    391                 .abi = .gnueabi,
    392             },
    393             .link_libc = true,
    394         },
    395         .{
    396             .target = .{
    397                 .cpu_arch = .armeb,
    398                 .os_tag = .linux,
    399                 .abi = .gnueabihf,
    400             },
    401             .link_libc = true,
    402         },
    403 
    404         .{
    405             .target = .{
    406                 .cpu_arch = .thumb,
    407                 .os_tag = .linux,
    408                 .abi = .eabi,
    409             },
    410         },
    411         .{
    412             .target = .{
    413                 .cpu_arch = .thumb,
    414                 .os_tag = .linux,
    415                 .abi = .eabihf,
    416             },
    417         },
    418         .{
    419             .target = .{
    420                 .cpu_arch = .thumb,
    421                 .os_tag = .linux,
    422                 .abi = .musleabi,
    423             },
    424             .link_libc = true,
    425             .skip_modules = &.{"std"},
    426         },
    427         .{
    428             .target = .{
    429                 .cpu_arch = .thumb,
    430                 .os_tag = .linux,
    431                 .abi = .musleabihf,
    432             },
    433             .link_libc = true,
    434             .skip_modules = &.{"std"},
    435         },
    436         // Calls are normally lowered to branch instructions that only support +/- 16 MB range when
    437         // targeting Thumb. This is not sufficient for the std test binary linked statically with
    438         // musl, so use long calls to avoid out-of-range relocations.
    439         .{
    440             .target = std.Target.Query.parse(.{
    441                 .arch_os_abi = "thumb-linux-musleabi",
    442                 .cpu_features = "baseline+long_calls",
    443             }) catch unreachable,
    444             .link_libc = true,
    445             .pic = false, // Long calls don't work with PIC.
    446             .skip_modules = &.{
    447                 "behavior",
    448                 "c-import",
    449                 "compiler-rt",
    450                 "universal-libc",
    451             },
    452         },
    453         .{
    454             .target = std.Target.Query.parse(.{
    455                 .arch_os_abi = "thumb-linux-musleabihf",
    456                 .cpu_features = "baseline+long_calls",
    457             }) catch unreachable,
    458             .link_libc = true,
    459             .pic = false, // Long calls don't work with PIC.
    460             .skip_modules = &.{
    461                 "behavior",
    462                 "c-import",
    463                 "compiler-rt",
    464                 "universal-libc",
    465             },
    466         },
    467 
    468         .{
    469             .target = .{
    470                 .cpu_arch = .thumbeb,
    471                 .os_tag = .linux,
    472                 .abi = .eabi,
    473             },
    474         },
    475         .{
    476             .target = .{
    477                 .cpu_arch = .thumbeb,
    478                 .os_tag = .linux,
    479                 .abi = .eabihf,
    480             },
    481         },
    482         .{
    483             .target = .{
    484                 .cpu_arch = .thumbeb,
    485                 .os_tag = .linux,
    486                 .abi = .musleabi,
    487             },
    488             .link_libc = true,
    489             .skip_modules = &.{"std"},
    490         },
    491         .{
    492             .target = .{
    493                 .cpu_arch = .thumbeb,
    494                 .os_tag = .linux,
    495                 .abi = .musleabihf,
    496             },
    497             .link_libc = true,
    498             .skip_modules = &.{"std"},
    499         },
    500         // Calls are normally lowered to branch instructions that only support +/- 16 MB range when
    501         // targeting Thumb. This is not sufficient for the std test binary linked statically with
    502         // musl, so use long calls to avoid out-of-range relocations.
    503         .{
    504             .target = std.Target.Query.parse(.{
    505                 .arch_os_abi = "thumbeb-linux-musleabi",
    506                 .cpu_features = "baseline+long_calls",
    507             }) catch unreachable,
    508             .link_libc = true,
    509             .pic = false, // Long calls don't work with PIC.
    510             .skip_modules = &.{
    511                 "behavior",
    512                 "c-import",
    513                 "compiler-rt",
    514                 "universal-libc",
    515             },
    516         },
    517         .{
    518             .target = std.Target.Query.parse(.{
    519                 .arch_os_abi = "thumbeb-linux-musleabihf",
    520                 .cpu_features = "baseline+long_calls",
    521             }) catch unreachable,
    522             .link_libc = true,
    523             .pic = false, // Long calls don't work with PIC.
    524             .skip_modules = &.{
    525                 "behavior",
    526                 "c-import",
    527                 "compiler-rt",
    528                 "universal-libc",
    529             },
    530         },
    531 
    532         .{
    533             .target = .{
    534                 .cpu_arch = .mips,
    535                 .os_tag = .linux,
    536                 .abi = .eabi,
    537             },
    538             .slow_backend = true,
    539         },
    540         .{
    541             .target = .{
    542                 .cpu_arch = .mips,
    543                 .os_tag = .linux,
    544                 .abi = .eabihf,
    545             },
    546             .slow_backend = true,
    547         },
    548         .{
    549             .target = .{
    550                 .cpu_arch = .mips,
    551                 .os_tag = .linux,
    552                 .abi = .musleabi,
    553             },
    554             .link_libc = true,
    555             .slow_backend = true,
    556         },
    557         .{
    558             .target = .{
    559                 .cpu_arch = .mips,
    560                 .os_tag = .linux,
    561                 .abi = .musleabihf,
    562             },
    563             .link_libc = true,
    564             .slow_backend = true,
    565         },
    566         .{
    567             .target = .{
    568                 .cpu_arch = .mips,
    569                 .os_tag = .linux,
    570                 .abi = .gnueabi,
    571             },
    572             .link_libc = true,
    573             .slow_backend = true,
    574         },
    575         .{
    576             .target = .{
    577                 .cpu_arch = .mips,
    578                 .os_tag = .linux,
    579                 .abi = .gnueabihf,
    580             },
    581             .link_libc = true,
    582             .slow_backend = true,
    583         },
    584 
    585         .{
    586             .target = .{
    587                 .cpu_arch = .mipsel,
    588                 .os_tag = .linux,
    589                 .abi = .eabi,
    590             },
    591             .slow_backend = true,
    592         },
    593         .{
    594             .target = .{
    595                 .cpu_arch = .mipsel,
    596                 .os_tag = .linux,
    597                 .abi = .eabihf,
    598             },
    599             .slow_backend = true,
    600         },
    601         .{
    602             .target = .{
    603                 .cpu_arch = .mipsel,
    604                 .os_tag = .linux,
    605                 .abi = .musleabi,
    606             },
    607             .link_libc = true,
    608             .slow_backend = true,
    609         },
    610         .{
    611             .target = .{
    612                 .cpu_arch = .mipsel,
    613                 .os_tag = .linux,
    614                 .abi = .musleabihf,
    615             },
    616             .link_libc = true,
    617             .slow_backend = true,
    618         },
    619         .{
    620             .target = .{
    621                 .cpu_arch = .mipsel,
    622                 .os_tag = .linux,
    623                 .abi = .gnueabi,
    624             },
    625             .link_libc = true,
    626             .slow_backend = true,
    627         },
    628         .{
    629             .target = .{
    630                 .cpu_arch = .mipsel,
    631                 .os_tag = .linux,
    632                 .abi = .gnueabihf,
    633             },
    634             .link_libc = true,
    635             .slow_backend = true,
    636         },
    637 
    638         .{
    639             .target = .{
    640                 .cpu_arch = .mips64,
    641                 .os_tag = .linux,
    642                 .abi = .none,
    643             },
    644         },
    645         .{
    646             .target = .{
    647                 .cpu_arch = .mips64,
    648                 .os_tag = .linux,
    649                 .abi = .muslabi64,
    650             },
    651             .link_libc = true,
    652         },
    653         .{
    654             .target = .{
    655                 .cpu_arch = .mips64,
    656                 .os_tag = .linux,
    657                 .abi = .gnuabi64,
    658             },
    659             .link_libc = true,
    660         },
    661 
    662         .{
    663             .target = .{
    664                 .cpu_arch = .mips64el,
    665                 .os_tag = .linux,
    666                 .abi = .none,
    667             },
    668         },
    669         .{
    670             .target = .{
    671                 .cpu_arch = .mips64el,
    672                 .os_tag = .linux,
    673                 .abi = .muslabi64,
    674             },
    675             .link_libc = true,
    676         },
    677         .{
    678             .target = .{
    679                 .cpu_arch = .mips64el,
    680                 .os_tag = .linux,
    681                 .abi = .gnuabi64,
    682             },
    683             .link_libc = true,
    684         },
    685 
    686         .{
    687             .target = .{
    688                 .cpu_arch = .powerpc,
    689                 .os_tag = .linux,
    690                 .abi = .eabi,
    691             },
    692         },
    693         .{
    694             .target = .{
    695                 .cpu_arch = .powerpc,
    696                 .os_tag = .linux,
    697                 .abi = .eabihf,
    698             },
    699         },
    700         .{
    701             .target = .{
    702                 .cpu_arch = .powerpc,
    703                 .os_tag = .linux,
    704                 .abi = .musleabi,
    705             },
    706             .link_libc = true,
    707         },
    708         .{
    709             .target = .{
    710                 .cpu_arch = .powerpc,
    711                 .os_tag = .linux,
    712                 .abi = .musleabihf,
    713             },
    714             .link_libc = true,
    715         },
    716         // https://github.com/ziglang/zig/issues/2256
    717         //.{
    718         //    .target = .{
    719         //        .cpu_arch = .powerpc,
    720         //        .os_tag = .linux,
    721         //        .abi = .gnueabihf,
    722         //    },
    723         //    .link_libc = true,
    724         //},
    725 
    726         .{
    727             .target = .{
    728                 .cpu_arch = .powerpc64,
    729                 .os_tag = .linux,
    730                 .abi = .none,
    731             },
    732         },
    733         .{
    734             .target = .{
    735                 .cpu_arch = .powerpc64,
    736                 .os_tag = .linux,
    737                 .abi = .musl,
    738             },
    739             .link_libc = true,
    740         },
    741         // Requires ELFv1 linker support.
    742         // .{
    743         //     .target = .{
    744         //         .cpu_arch = .powerpc64,
    745         //         .os_tag = .linux,
    746         //         .abi = .gnu,
    747         //     },
    748         //     .link_libc = true,
    749         // },
    750         .{
    751             .target = .{
    752                 .cpu_arch = .powerpc64le,
    753                 .os_tag = .linux,
    754                 .abi = .none,
    755             },
    756         },
    757         .{
    758             .target = .{
    759                 .cpu_arch = .powerpc64le,
    760                 .os_tag = .linux,
    761                 .abi = .musl,
    762             },
    763             .link_libc = true,
    764         },
    765         .{
    766             .target = .{
    767                 .cpu_arch = .powerpc64le,
    768                 .os_tag = .linux,
    769                 .abi = .gnu,
    770             },
    771             .link_libc = true,
    772         },
    773 
    774         .{
    775             .target = std.Target.Query.parse(.{
    776                 .arch_os_abi = "riscv32-linux-none",
    777                 .cpu_features = "baseline-d-f",
    778             }) catch unreachable,
    779         },
    780         .{
    781             .target = std.Target.Query.parse(.{
    782                 .arch_os_abi = "riscv32-linux-musl",
    783                 .cpu_features = "baseline-d-f",
    784             }) catch unreachable,
    785             .link_libc = true,
    786         },
    787 
    788         .{
    789             .target = .{
    790                 .cpu_arch = .riscv32,
    791                 .os_tag = .linux,
    792                 .abi = .none,
    793             },
    794         },
    795         .{
    796             .target = .{
    797                 .cpu_arch = .riscv32,
    798                 .os_tag = .linux,
    799                 .abi = .musl,
    800             },
    801             .link_libc = true,
    802         },
    803         .{
    804             .target = .{
    805                 .cpu_arch = .riscv32,
    806                 .os_tag = .linux,
    807                 .abi = .gnu,
    808             },
    809             .link_libc = true,
    810         },
    811 
    812         .{
    813             .target = std.Target.Query.parse(.{
    814                 .arch_os_abi = "riscv64-linux-none",
    815                 .cpu_features = "baseline-d-f",
    816             }) catch unreachable,
    817         },
    818         .{
    819             .target = std.Target.Query.parse(.{
    820                 .arch_os_abi = "riscv64-linux-musl",
    821                 .cpu_features = "baseline-d-f",
    822             }) catch unreachable,
    823             .link_libc = true,
    824         },
    825 
    826         .{
    827             .target = .{
    828                 .cpu_arch = .riscv64,
    829                 .os_tag = .linux,
    830                 .abi = .none,
    831             },
    832         },
    833         .{
    834             .target = .{
    835                 .cpu_arch = .riscv64,
    836                 .os_tag = .linux,
    837                 .abi = .musl,
    838             },
    839             .link_libc = true,
    840         },
    841         .{
    842             .target = .{
    843                 .cpu_arch = .riscv64,
    844                 .os_tag = .linux,
    845                 .abi = .gnu,
    846             },
    847             .link_libc = true,
    848         },
    849 
    850         .{
    851             .target = std.Target.Query.parse(.{
    852                 .arch_os_abi = "riscv64-linux-musl",
    853                 .cpu_features = "baseline+v+zbb",
    854             }) catch unreachable,
    855             .use_llvm = false,
    856             .use_lld = false,
    857         },
    858 
    859         .{
    860             .target = .{
    861                 .cpu_arch = .s390x,
    862                 .os_tag = .linux,
    863                 .abi = .none,
    864             },
    865         },
    866         .{
    867             .target = .{
    868                 .cpu_arch = .s390x,
    869                 .os_tag = .linux,
    870                 .abi = .musl,
    871             },
    872             .link_libc = true,
    873         },
    874         .{
    875             .target = .{
    876                 .cpu_arch = .s390x,
    877                 .os_tag = .linux,
    878                 .abi = .gnu,
    879             },
    880             .link_libc = true,
    881         },
    882 
    883         .{
    884             .target = .{
    885                 .cpu_arch = .x86_64,
    886                 .os_tag = .macos,
    887                 .abi = .none,
    888             },
    889         },
    890 
    891         .{
    892             .target = .{
    893                 .cpu_arch = .aarch64,
    894                 .os_tag = .macos,
    895                 .abi = .none,
    896             },
    897         },
    898 
    899         .{
    900             .target = .{
    901                 .cpu_arch = .x86,
    902                 .os_tag = .windows,
    903                 .abi = .msvc,
    904             },
    905         },
    906 
    907         .{
    908             .target = .{
    909                 .cpu_arch = .x86_64,
    910                 .os_tag = .windows,
    911                 .abi = .msvc,
    912             },
    913         },
    914 
    915         .{
    916             .target = .{
    917                 .cpu_arch = .x86,
    918                 .os_tag = .windows,
    919                 .abi = .gnu,
    920             },
    921             .link_libc = true,
    922         },
    923 
    924         .{
    925             .target = .{
    926                 .cpu_arch = .x86_64,
    927                 .os_tag = .windows,
    928                 .abi = .gnu,
    929             },
    930             .link_libc = true,
    931         },
    932     };
    933 };
    934 
    935 const CAbiTarget = struct {
    936     target: std.Target.Query = .{},
    937     use_llvm: ?bool = null,
    938     use_lld: ?bool = null,
    939     pic: ?bool = null,
    940     strip: ?bool = null,
    941     c_defines: []const []const u8 = &.{},
    942 };
    943 
    944 const c_abi_targets = [_]CAbiTarget{
    945     .{},
    946     .{
    947         .target = .{
    948             .cpu_arch = .x86_64,
    949             .os_tag = .linux,
    950             .abi = .musl,
    951         },
    952     },
    953     .{
    954         .target = .{
    955             .cpu_arch = .x86_64,
    956             .os_tag = .linux,
    957             .abi = .musl,
    958         },
    959         .use_llvm = false,
    960         .use_lld = false,
    961         .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
    962     },
    963     .{
    964         .target = .{
    965             .cpu_arch = .x86_64,
    966             .cpu_model = .{ .explicit = &std.Target.x86.cpu.x86_64_v2 },
    967             .os_tag = .linux,
    968             .abi = .musl,
    969         },
    970         .use_llvm = false,
    971         .use_lld = false,
    972         .strip = true,
    973         .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
    974     },
    975     .{
    976         .target = .{
    977             .cpu_arch = .x86_64,
    978             .cpu_model = .{ .explicit = &std.Target.x86.cpu.x86_64_v3 },
    979             .os_tag = .linux,
    980             .abi = .musl,
    981         },
    982         .use_llvm = false,
    983         .use_lld = false,
    984         .pic = true,
    985         .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
    986     },
    987     .{
    988         .target = .{
    989             .cpu_arch = .x86,
    990             .os_tag = .linux,
    991             .abi = .musl,
    992         },
    993     },
    994     .{
    995         .target = .{
    996             .cpu_arch = .aarch64,
    997             .os_tag = .linux,
    998             .abi = .musl,
    999         },
   1000     },
   1001     .{
   1002         .target = .{
   1003             .cpu_arch = .arm,
   1004             .os_tag = .linux,
   1005             .abi = .musleabihf,
   1006         },
   1007     },
   1008     .{
   1009         .target = .{
   1010             .cpu_arch = .mips,
   1011             .os_tag = .linux,
   1012             .abi = .musleabihf,
   1013         },
   1014     },
   1015     .{
   1016         .target = .{
   1017             .cpu_arch = .riscv64,
   1018             .os_tag = .linux,
   1019             .abi = .musl,
   1020         },
   1021     },
   1022     .{
   1023         .target = .{
   1024             .cpu_arch = .wasm32,
   1025             .os_tag = .wasi,
   1026             .abi = .musl,
   1027         },
   1028     },
   1029     .{
   1030         .target = .{
   1031             .cpu_arch = .powerpc,
   1032             .os_tag = .linux,
   1033             .abi = .musleabihf,
   1034         },
   1035     },
   1036     .{
   1037         .target = .{
   1038             .cpu_arch = .powerpc64le,
   1039             .os_tag = .linux,
   1040             .abi = .musl,
   1041         },
   1042     },
   1043     .{
   1044         .target = .{
   1045             .cpu_arch = .x86,
   1046             .os_tag = .windows,
   1047             .abi = .gnu,
   1048         },
   1049     },
   1050     .{
   1051         .target = .{
   1052             .cpu_arch = .x86_64,
   1053             .os_tag = .windows,
   1054             .abi = .gnu,
   1055         },
   1056     },
   1057 };
   1058 
   1059 pub fn addCompareOutputTests(
   1060     b: *std.Build,
   1061     test_filters: []const []const u8,
   1062     optimize_modes: []const OptimizeMode,
   1063 ) *Step {
   1064     const cases = b.allocator.create(CompareOutputContext) catch @panic("OOM");
   1065     cases.* = CompareOutputContext{
   1066         .b = b,
   1067         .step = b.step("test-compare-output", "Run the compare output tests"),
   1068         .test_index = 0,
   1069         .test_filters = test_filters,
   1070         .optimize_modes = optimize_modes,
   1071     };
   1072 
   1073     compare_output.addCases(cases);
   1074 
   1075     return cases.step;
   1076 }
   1077 
   1078 pub fn addStackTraceTests(
   1079     b: *std.Build,
   1080     test_filters: []const []const u8,
   1081     optimize_modes: []const OptimizeMode,
   1082 ) *Step {
   1083     const check_exe = b.addExecutable(.{
   1084         .name = "check-stack-trace",
   1085         .root_source_file = b.path("test/src/check-stack-trace.zig"),
   1086         .target = b.graph.host,
   1087         .optimize = .Debug,
   1088     });
   1089 
   1090     const cases = b.allocator.create(StackTracesContext) catch @panic("OOM");
   1091     cases.* = .{
   1092         .b = b,
   1093         .step = b.step("test-stack-traces", "Run the stack trace tests"),
   1094         .test_index = 0,
   1095         .test_filters = test_filters,
   1096         .optimize_modes = optimize_modes,
   1097         .check_exe = check_exe,
   1098     };
   1099 
   1100     stack_traces.addCases(cases);
   1101 
   1102     return cases.step;
   1103 }
   1104 
   1105 fn compilerHasPackageManager(b: *std.Build) bool {
   1106     // We can only use dependencies if the compiler was built with support for package management.
   1107     // (zig2 doesn't support it, but we still need to construct a build graph to build stage3.)
   1108     return b.available_deps.len != 0;
   1109 }
   1110 
   1111 pub fn addStandaloneTests(
   1112     b: *std.Build,
   1113     optimize_modes: []const OptimizeMode,
   1114     enable_macos_sdk: bool,
   1115     enable_ios_sdk: bool,
   1116     enable_symlinks_windows: bool,
   1117 ) *Step {
   1118     const step = b.step("test-standalone", "Run the standalone tests");
   1119     if (compilerHasPackageManager(b)) {
   1120         const test_cases_dep_name = "standalone_test_cases";
   1121         const test_cases_dep = b.dependency(test_cases_dep_name, .{
   1122             .enable_ios_sdk = enable_ios_sdk,
   1123             .enable_macos_sdk = enable_macos_sdk,
   1124             .enable_symlinks_windows = enable_symlinks_windows,
   1125             .simple_skip_debug = mem.indexOfScalar(OptimizeMode, optimize_modes, .Debug) == null,
   1126             .simple_skip_release_safe = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseSafe) == null,
   1127             .simple_skip_release_fast = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseFast) == null,
   1128             .simple_skip_release_small = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseSmall) == null,
   1129         });
   1130         const test_cases_dep_step = test_cases_dep.builder.default_step;
   1131         test_cases_dep_step.name = b.dupe(test_cases_dep_name);
   1132         step.dependOn(test_cases_dep.builder.default_step);
   1133     }
   1134     return step;
   1135 }
   1136 
   1137 pub fn addLinkTests(
   1138     b: *std.Build,
   1139     enable_macos_sdk: bool,
   1140     enable_ios_sdk: bool,
   1141     enable_symlinks_windows: bool,
   1142 ) *Step {
   1143     const step = b.step("test-link", "Run the linker tests");
   1144     if (compilerHasPackageManager(b)) {
   1145         const test_cases_dep_name = "link_test_cases";
   1146         const test_cases_dep = b.dependency(test_cases_dep_name, .{
   1147             .enable_ios_sdk = enable_ios_sdk,
   1148             .enable_macos_sdk = enable_macos_sdk,
   1149             .enable_symlinks_windows = enable_symlinks_windows,
   1150         });
   1151         const test_cases_dep_step = test_cases_dep.builder.default_step;
   1152         test_cases_dep_step.name = b.dupe(test_cases_dep_name);
   1153         step.dependOn(test_cases_dep.builder.default_step);
   1154     }
   1155     return step;
   1156 }
   1157 
   1158 pub fn addCliTests(b: *std.Build) *Step {
   1159     const step = b.step("test-cli", "Test the command line interface");
   1160     const s = std.fs.path.sep_str;
   1161 
   1162     {
   1163         // Test `zig init`.
   1164         const tmp_path = b.makeTempPath();
   1165         const init_exe = b.addSystemCommand(&.{ b.graph.zig_exe, "init" });
   1166         init_exe.setCwd(.{ .cwd_relative = tmp_path });
   1167         init_exe.setName("zig init");
   1168         init_exe.expectStdOutEqual("");
   1169         init_exe.expectStdErrEqual("info: created build.zig\n" ++
   1170             "info: created build.zig.zon\n" ++
   1171             "info: created src" ++ s ++ "main.zig\n" ++
   1172             "info: created src" ++ s ++ "root.zig\n" ++
   1173             "info: see `zig build --help` for a menu of options\n");
   1174 
   1175         // Test missing output path.
   1176         const bad_out_arg = "-femit-bin=does" ++ s ++ "not" ++ s ++ "exist" ++ s ++ "foo.exe";
   1177         const ok_src_arg = "src" ++ s ++ "main.zig";
   1178         const expected = "error: unable to open output directory 'does" ++ s ++ "not" ++ s ++ "exist': FileNotFound\n";
   1179         const run_bad = b.addSystemCommand(&.{ b.graph.zig_exe, "build-exe", ok_src_arg, bad_out_arg });
   1180         run_bad.setName("zig build-exe error message for bad -femit-bin arg");
   1181         run_bad.expectExitCode(1);
   1182         run_bad.expectStdErrEqual(expected);
   1183         run_bad.expectStdOutEqual("");
   1184         run_bad.step.dependOn(&init_exe.step);
   1185 
   1186         const run_test = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "test" });
   1187         run_test.setCwd(.{ .cwd_relative = tmp_path });
   1188         run_test.setName("zig build test");
   1189         run_test.expectStdOutEqual("");
   1190         run_test.step.dependOn(&init_exe.step);
   1191 
   1192         const run_run = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "run" });
   1193         run_run.setCwd(.{ .cwd_relative = tmp_path });
   1194         run_run.setName("zig build run");
   1195         run_run.expectStdOutEqual("Run `zig build test` to run the tests.\n");
   1196         run_run.expectStdErrEqual("All your codebase are belong to us.\n");
   1197         run_run.step.dependOn(&init_exe.step);
   1198 
   1199         const cleanup = b.addRemoveDirTree(.{ .cwd_relative = tmp_path });
   1200         cleanup.step.dependOn(&run_test.step);
   1201         cleanup.step.dependOn(&run_run.step);
   1202         cleanup.step.dependOn(&run_bad.step);
   1203 
   1204         step.dependOn(&cleanup.step);
   1205     }
   1206 
   1207     // Test Godbolt API
   1208     if (builtin.os.tag == .linux and builtin.cpu.arch == .x86_64) {
   1209         const tmp_path = b.makeTempPath();
   1210 
   1211         const example_zig = b.addWriteFiles().add("example.zig",
   1212             \\// Type your code here, or load an example.
   1213             \\export fn square(num: i32) i32 {
   1214             \\    return num * num;
   1215             \\}
   1216             \\extern fn zig_panic() noreturn;
   1217             \\pub fn panic(msg: []const u8, error_return_trace: ?*@import("std").builtin.StackTrace, _: ?usize) noreturn {
   1218             \\    _ = msg;
   1219             \\    _ = error_return_trace;
   1220             \\    zig_panic();
   1221             \\}
   1222         );
   1223 
   1224         // This is intended to be the exact CLI usage used by godbolt.org.
   1225         const run = b.addSystemCommand(&.{
   1226             b.graph.zig_exe, "build-obj",
   1227             "--cache-dir",   tmp_path,
   1228             "--name",        "example",
   1229             "-fno-emit-bin", "-fno-emit-h",
   1230             "-fstrip",       "-OReleaseFast",
   1231         });
   1232         run.addFileArg(example_zig);
   1233         const example_s = run.addPrefixedOutputFileArg("-femit-asm=", "example.s");
   1234 
   1235         const checkfile = b.addCheckFile(example_s, .{
   1236             .expected_matches = &.{
   1237                 "square:",
   1238                 "mov\teax, edi",
   1239                 "imul\teax, edi",
   1240             },
   1241         });
   1242         checkfile.setName("check godbolt.org CLI usage generating valid asm");
   1243 
   1244         const cleanup = b.addRemoveDirTree(.{ .cwd_relative = tmp_path });
   1245         cleanup.step.dependOn(&checkfile.step);
   1246 
   1247         step.dependOn(&cleanup.step);
   1248     }
   1249 
   1250     {
   1251         // Test `zig fmt`.
   1252         // This test must use a temporary directory rather than a cache
   1253         // directory because this test will be mutating the files. The cache
   1254         // system relies on cache directories being mutated only by their
   1255         // owners.
   1256         const tmp_path = b.makeTempPath();
   1257         const unformatted_code = "    // no reason for indent";
   1258 
   1259         var dir = std.fs.cwd().openDir(tmp_path, .{}) catch @panic("unhandled");
   1260         defer dir.close();
   1261         dir.writeFile(.{ .sub_path = "fmt1.zig", .data = unformatted_code }) catch @panic("unhandled");
   1262         dir.writeFile(.{ .sub_path = "fmt2.zig", .data = unformatted_code }) catch @panic("unhandled");
   1263         dir.makeDir("subdir") catch @panic("unhandled");
   1264         var subdir = dir.openDir("subdir", .{}) catch @panic("unhandled");
   1265         defer subdir.close();
   1266         subdir.writeFile(.{ .sub_path = "fmt3.zig", .data = unformatted_code }) catch @panic("unhandled");
   1267 
   1268         // Test zig fmt affecting only the appropriate files.
   1269         const run1 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "fmt1.zig" });
   1270         run1.setName("run zig fmt one file");
   1271         run1.setCwd(.{ .cwd_relative = tmp_path });
   1272         run1.has_side_effects = true;
   1273         // stdout should be file path + \n
   1274         run1.expectStdOutEqual("fmt1.zig\n");
   1275 
   1276         // Test excluding files and directories from a run
   1277         const run2 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "subdir", "." });
   1278         run2.setName("run zig fmt on directory with exclusions");
   1279         run2.setCwd(.{ .cwd_relative = tmp_path });
   1280         run2.has_side_effects = true;
   1281         run2.expectStdOutEqual("");
   1282         run2.step.dependOn(&run1.step);
   1283 
   1284         // Test excluding non-existent file
   1285         const run3 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "nonexistent.zig", "." });
   1286         run3.setName("run zig fmt on directory with non-existent exclusion");
   1287         run3.setCwd(.{ .cwd_relative = tmp_path });
   1288         run3.has_side_effects = true;
   1289         run3.expectStdOutEqual("." ++ s ++ "subdir" ++ s ++ "fmt3.zig\n");
   1290         run3.step.dependOn(&run2.step);
   1291 
   1292         // running it on the dir, only the new file should be changed
   1293         const run4 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." });
   1294         run4.setName("run zig fmt the directory");
   1295         run4.setCwd(.{ .cwd_relative = tmp_path });
   1296         run4.has_side_effects = true;
   1297         run4.expectStdOutEqual("." ++ s ++ "fmt2.zig\n");
   1298         run4.step.dependOn(&run3.step);
   1299 
   1300         // both files have been formatted, nothing should change now
   1301         const run5 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." });
   1302         run5.setName("run zig fmt with nothing to do");
   1303         run5.setCwd(.{ .cwd_relative = tmp_path });
   1304         run5.has_side_effects = true;
   1305         run5.expectStdOutEqual("");
   1306         run5.step.dependOn(&run4.step);
   1307 
   1308         const unformatted_code_utf16 = "\xff\xfe \x00 \x00 \x00 \x00/\x00/\x00 \x00n\x00o\x00 \x00r\x00e\x00a\x00s\x00o\x00n\x00";
   1309         const fmt6_path = std.fs.path.join(b.allocator, &.{ tmp_path, "fmt6.zig" }) catch @panic("OOM");
   1310         const write6 = b.addUpdateSourceFiles();
   1311         write6.addBytesToSource(unformatted_code_utf16, fmt6_path);
   1312         write6.step.dependOn(&run5.step);
   1313 
   1314         // Test `zig fmt` handling UTF-16 decoding.
   1315         const run6 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." });
   1316         run6.setName("run zig fmt convert UTF-16 to UTF-8");
   1317         run6.setCwd(.{ .cwd_relative = tmp_path });
   1318         run6.has_side_effects = true;
   1319         run6.expectStdOutEqual("." ++ s ++ "fmt6.zig\n");
   1320         run6.step.dependOn(&write6.step);
   1321 
   1322         // TODO change this to an exact match
   1323         const check6 = b.addCheckFile(.{ .cwd_relative = fmt6_path }, .{
   1324             .expected_matches = &.{
   1325                 "// no reason",
   1326             },
   1327         });
   1328         check6.step.dependOn(&run6.step);
   1329 
   1330         const cleanup = b.addRemoveDirTree(.{ .cwd_relative = tmp_path });
   1331         cleanup.step.dependOn(&check6.step);
   1332 
   1333         step.dependOn(&cleanup.step);
   1334     }
   1335 
   1336     {
   1337         // TODO this should move to become a CLI test rather than standalone
   1338         //    cases.addBuildFile("test/standalone/options/build.zig", .{
   1339         //        .extra_argv = &.{
   1340         //            "-Dbool_true",
   1341         //            "-Dbool_false=false",
   1342         //            "-Dint=1234",
   1343         //            "-De=two",
   1344         //            "-Dstring=hello",
   1345         //        },
   1346         //    });
   1347     }
   1348 
   1349     return step;
   1350 }
   1351 
   1352 pub fn addAssembleAndLinkTests(b: *std.Build, test_filters: []const []const u8, optimize_modes: []const OptimizeMode) *Step {
   1353     const cases = b.allocator.create(CompareOutputContext) catch @panic("OOM");
   1354     cases.* = CompareOutputContext{
   1355         .b = b,
   1356         .step = b.step("test-asm-link", "Run the assemble and link tests"),
   1357         .test_index = 0,
   1358         .test_filters = test_filters,
   1359         .optimize_modes = optimize_modes,
   1360     };
   1361 
   1362     assemble_and_link.addCases(cases);
   1363 
   1364     return cases.step;
   1365 }
   1366 
   1367 pub fn addTranslateCTests(
   1368     b: *std.Build,
   1369     parent_step: *std.Build.Step,
   1370     test_filters: []const []const u8,
   1371     test_target_filters: []const []const u8,
   1372 ) void {
   1373     const cases = b.allocator.create(TranslateCContext) catch @panic("OOM");
   1374     cases.* = TranslateCContext{
   1375         .b = b,
   1376         .step = parent_step,
   1377         .test_index = 0,
   1378         .test_filters = test_filters,
   1379         .test_target_filters = test_target_filters,
   1380     };
   1381 
   1382     translate_c.addCases(cases);
   1383 }
   1384 
   1385 pub fn addRunTranslatedCTests(
   1386     b: *std.Build,
   1387     parent_step: *std.Build.Step,
   1388     test_filters: []const []const u8,
   1389     target: std.Build.ResolvedTarget,
   1390 ) void {
   1391     const cases = b.allocator.create(RunTranslatedCContext) catch @panic("OOM");
   1392     cases.* = .{
   1393         .b = b,
   1394         .step = parent_step,
   1395         .test_index = 0,
   1396         .test_filters = test_filters,
   1397         .target = target,
   1398     };
   1399 
   1400     run_translated_c.addCases(cases);
   1401 }
   1402 
   1403 const ModuleTestOptions = struct {
   1404     test_filters: []const []const u8,
   1405     test_target_filters: []const []const u8,
   1406     test_slow_targets: bool,
   1407     root_src: []const u8,
   1408     name: []const u8,
   1409     desc: []const u8,
   1410     optimize_modes: []const OptimizeMode,
   1411     include_paths: []const []const u8,
   1412     skip_single_threaded: bool,
   1413     skip_non_native: bool,
   1414     skip_libc: bool,
   1415     max_rss: usize = 0,
   1416     no_builtin: bool = false,
   1417 };
   1418 
   1419 pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
   1420     const step = b.step(b.fmt("test-{s}", .{options.name}), options.desc);
   1421 
   1422     for_targets: for (test_targets) |test_target| {
   1423         if (test_target.skip_modules.len > 0) {
   1424             for (test_target.skip_modules) |skip_mod| {
   1425                 if (std.mem.eql(u8, options.name, skip_mod)) continue :for_targets;
   1426             }
   1427         }
   1428 
   1429         if (!options.test_slow_targets and test_target.slow_backend) continue;
   1430 
   1431         if (options.skip_non_native and !test_target.target.isNative())
   1432             continue;
   1433 
   1434         const resolved_target = b.resolveTargetQuery(test_target.target);
   1435         const target = resolved_target.result;
   1436         const triple_txt = target.zigTriple(b.allocator) catch @panic("OOM");
   1437 
   1438         if (options.test_target_filters.len > 0) {
   1439             for (options.test_target_filters) |filter| {
   1440                 if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
   1441             } else continue;
   1442         }
   1443 
   1444         if (options.skip_libc and test_target.link_libc == true)
   1445             continue;
   1446 
   1447         if (options.skip_single_threaded and test_target.single_threaded == true)
   1448             continue;
   1449 
   1450         // TODO get compiler-rt tests passing for self-hosted backends.
   1451         if ((target.cpu.arch != .x86_64 or target.ofmt != .elf) and
   1452             test_target.use_llvm == false and mem.eql(u8, options.name, "compiler-rt"))
   1453             continue;
   1454 
   1455         // TODO get compiler-rt tests passing for wasm32-wasi
   1456         // currently causes "LLVM ERROR: Unable to expand fixed point multiplication."
   1457         if (target.cpu.arch == .wasm32 and target.os.tag == .wasi and
   1458             mem.eql(u8, options.name, "compiler-rt"))
   1459         {
   1460             continue;
   1461         }
   1462 
   1463         // TODO get universal-libc tests passing for other self-hosted backends.
   1464         if (target.cpu.arch != .x86_64 and
   1465             test_target.use_llvm == false and mem.eql(u8, options.name, "universal-libc"))
   1466             continue;
   1467 
   1468         // TODO get std lib tests passing for other self-hosted backends.
   1469         if ((target.cpu.arch != .x86_64 or target.os.tag != .linux) and
   1470             test_target.use_llvm == false and mem.eql(u8, options.name, "std"))
   1471             continue;
   1472 
   1473         if (target.cpu.arch != .x86_64 and
   1474             test_target.use_llvm == false and mem.eql(u8, options.name, "c-import"))
   1475             continue;
   1476 
   1477         const want_this_mode = for (options.optimize_modes) |m| {
   1478             if (m == test_target.optimize_mode) break true;
   1479         } else false;
   1480         if (!want_this_mode) continue;
   1481 
   1482         const libc_suffix = if (test_target.link_libc == true) "-libc" else "";
   1483         const model_txt = target.cpu.model.name;
   1484 
   1485         // wasm32-wasi builds need more RAM, idk why
   1486         const max_rss = if (target.os.tag == .wasi)
   1487             options.max_rss * 2
   1488         else
   1489             options.max_rss;
   1490 
   1491         const these_tests = b.addTest(.{
   1492             .root_source_file = b.path(options.root_src),
   1493             .optimize = test_target.optimize_mode,
   1494             .target = resolved_target,
   1495             .max_rss = max_rss,
   1496             .filters = options.test_filters,
   1497             .link_libc = test_target.link_libc,
   1498             .single_threaded = test_target.single_threaded,
   1499             .use_llvm = test_target.use_llvm,
   1500             .use_lld = test_target.use_lld,
   1501             .zig_lib_dir = b.path("lib"),
   1502             .pic = test_target.pic,
   1503             .strip = test_target.strip,
   1504         });
   1505         if (options.no_builtin) these_tests.no_builtin = true;
   1506         const single_threaded_suffix = if (test_target.single_threaded == true) "-single" else "";
   1507         const backend_suffix = if (test_target.use_llvm == true)
   1508             "-llvm"
   1509         else if (target.ofmt == std.Target.ObjectFormat.c)
   1510             "-cbe"
   1511         else if (test_target.use_llvm == false)
   1512             "-selfhosted"
   1513         else
   1514             "";
   1515         const use_lld = if (test_target.use_lld == false) "-no-lld" else "";
   1516         const use_pic = if (test_target.pic == true) "-pic" else "";
   1517 
   1518         for (options.include_paths) |include_path| these_tests.addIncludePath(b.path(include_path));
   1519 
   1520         const qualified_name = b.fmt("{s}-{s}-{s}-{s}{s}{s}{s}{s}{s}", .{
   1521             options.name,
   1522             triple_txt,
   1523             model_txt,
   1524             @tagName(test_target.optimize_mode),
   1525             libc_suffix,
   1526             single_threaded_suffix,
   1527             backend_suffix,
   1528             use_lld,
   1529             use_pic,
   1530         });
   1531 
   1532         if (target.ofmt == std.Target.ObjectFormat.c) {
   1533             var altered_query = test_target.target;
   1534             altered_query.ofmt = null;
   1535 
   1536             const compile_c = b.addExecutable(.{
   1537                 .name = qualified_name,
   1538                 .link_libc = test_target.link_libc,
   1539                 .target = b.resolveTargetQuery(altered_query),
   1540                 .zig_lib_dir = b.path("lib"),
   1541             });
   1542             compile_c.addCSourceFile(.{
   1543                 .file = these_tests.getEmittedBin(),
   1544                 .flags = &.{
   1545                     // Tracking issue for making the C backend generate C89 compatible code:
   1546                     // https://github.com/ziglang/zig/issues/19468
   1547                     "-std=c99",
   1548                     "-Werror",
   1549 
   1550                     "-Wall",
   1551                     "-Wembedded-directive",
   1552                     "-Wempty-translation-unit",
   1553                     "-Wextra",
   1554                     "-Wgnu",
   1555                     "-Winvalid-utf8",
   1556                     "-Wkeyword-macro",
   1557                     "-Woverlength-strings",
   1558 
   1559                     // Tracking issue for making the C backend generate code
   1560                     // that does not trigger warnings:
   1561                     // https://github.com/ziglang/zig/issues/19467
   1562 
   1563                     // spotted everywhere
   1564                     "-Wno-builtin-requires-header",
   1565 
   1566                     // spotted on linux
   1567                     "-Wno-braced-scalar-init",
   1568                     "-Wno-excess-initializers",
   1569                     "-Wno-incompatible-pointer-types-discards-qualifiers",
   1570                     "-Wno-unused",
   1571                     "-Wno-unused-parameter",
   1572 
   1573                     // spotted on darwin
   1574                     "-Wno-incompatible-pointer-types",
   1575                 },
   1576             });
   1577             compile_c.addIncludePath(b.path("lib")); // for zig.h
   1578             if (target.os.tag == .windows) {
   1579                 if (true) {
   1580                     // Unfortunately this requires about 8G of RAM for clang to compile
   1581                     // and our Windows CI runners do not have this much.
   1582                     step.dependOn(&these_tests.step);
   1583                     continue;
   1584                 }
   1585                 if (test_target.link_libc == false) {
   1586                     compile_c.subsystem = .Console;
   1587                     compile_c.linkSystemLibrary("kernel32");
   1588                     compile_c.linkSystemLibrary("ntdll");
   1589                 }
   1590                 if (mem.eql(u8, options.name, "std")) {
   1591                     if (test_target.link_libc == false) {
   1592                         compile_c.linkSystemLibrary("shell32");
   1593                         compile_c.linkSystemLibrary("advapi32");
   1594                     }
   1595                     compile_c.linkSystemLibrary("crypt32");
   1596                     compile_c.linkSystemLibrary("ws2_32");
   1597                     compile_c.linkSystemLibrary("ole32");
   1598                 }
   1599             }
   1600 
   1601             const run = b.addRunArtifact(compile_c);
   1602             run.skip_foreign_checks = true;
   1603             run.enableTestRunnerMode();
   1604             run.setName(b.fmt("run test {s}", .{qualified_name}));
   1605 
   1606             step.dependOn(&run.step);
   1607         } else {
   1608             const run = b.addRunArtifact(these_tests);
   1609             run.skip_foreign_checks = true;
   1610             run.setName(b.fmt("run test {s}", .{qualified_name}));
   1611 
   1612             step.dependOn(&run.step);
   1613         }
   1614     }
   1615     return step;
   1616 }
   1617 
   1618 const CAbiTestOptions = struct {
   1619     test_target_filters: []const []const u8,
   1620     skip_non_native: bool,
   1621     skip_release: bool,
   1622 };
   1623 
   1624 pub fn addCAbiTests(b: *std.Build, options: CAbiTestOptions) *Step {
   1625     const step = b.step("test-c-abi", "Run the C ABI tests");
   1626 
   1627     const optimize_modes: [3]OptimizeMode = .{ .Debug, .ReleaseSafe, .ReleaseFast };
   1628 
   1629     for (optimize_modes) |optimize_mode| {
   1630         if (optimize_mode != .Debug and options.skip_release) continue;
   1631 
   1632         for (c_abi_targets) |c_abi_target| {
   1633             if (options.skip_non_native and !c_abi_target.target.isNative()) continue;
   1634 
   1635             const resolved_target = b.resolveTargetQuery(c_abi_target.target);
   1636             const target = resolved_target.result;
   1637             const triple_txt = target.zigTriple(b.allocator) catch @panic("OOM");
   1638 
   1639             if (options.test_target_filters.len > 0) {
   1640                 for (options.test_target_filters) |filter| {
   1641                     if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
   1642                 } else continue;
   1643             }
   1644 
   1645             if (target.os.tag == .windows and target.cpu.arch == .aarch64) {
   1646                 // https://github.com/ziglang/zig/issues/14908
   1647                 continue;
   1648             }
   1649 
   1650             const test_step = b.addTest(.{
   1651                 .name = b.fmt("test-c-abi-{s}-{s}-{s}{s}{s}{s}", .{
   1652                     triple_txt,
   1653                     target.cpu.model.name,
   1654                     @tagName(optimize_mode),
   1655                     if (c_abi_target.use_llvm == true)
   1656                         "-llvm"
   1657                     else if (target.ofmt == .c)
   1658                         "-cbe"
   1659                     else if (c_abi_target.use_llvm == false)
   1660                         "-selfhosted"
   1661                     else
   1662                         "",
   1663                     if (c_abi_target.use_lld == false) "-no-lld" else "",
   1664                     if (c_abi_target.pic == true) "-pic" else "",
   1665                 }),
   1666                 .root_source_file = b.path("test/c_abi/main.zig"),
   1667                 .target = resolved_target,
   1668                 .optimize = optimize_mode,
   1669                 .link_libc = true,
   1670                 .use_llvm = c_abi_target.use_llvm,
   1671                 .use_lld = c_abi_target.use_lld,
   1672                 .pic = c_abi_target.pic,
   1673                 .strip = c_abi_target.strip,
   1674             });
   1675             test_step.addCSourceFile(.{
   1676                 .file = b.path("test/c_abi/cfuncs.c"),
   1677                 .flags = &.{"-std=c99"},
   1678             });
   1679             for (c_abi_target.c_defines) |define| test_step.defineCMacro(define, null);
   1680 
   1681             // This test is intentionally trying to check if the external ABI is
   1682             // done properly. LTO would be a hindrance to this.
   1683             test_step.want_lto = false;
   1684 
   1685             const run = b.addRunArtifact(test_step);
   1686             run.skip_foreign_checks = true;
   1687             step.dependOn(&run.step);
   1688         }
   1689     }
   1690     return step;
   1691 }
   1692 
   1693 pub fn addCases(
   1694     b: *std.Build,
   1695     parent_step: *Step,
   1696     test_filters: []const []const u8,
   1697     test_target_filters: []const []const u8,
   1698     target: std.Build.ResolvedTarget,
   1699     translate_c_options: @import("src/Cases.zig").TranslateCOptions,
   1700     build_options: @import("cases.zig").BuildOptions,
   1701 ) !void {
   1702     const arena = b.allocator;
   1703     const gpa = b.allocator;
   1704 
   1705     var cases = @import("src/Cases.zig").init(gpa, arena);
   1706 
   1707     var dir = try b.build_root.handle.openDir("test/cases", .{ .iterate = true });
   1708     defer dir.close();
   1709 
   1710     cases.addFromDir(dir, b);
   1711     try @import("cases.zig").addCases(&cases, build_options, b);
   1712 
   1713     cases.lowerToTranslateCSteps(b, parent_step, test_filters, test_target_filters, target, translate_c_options);
   1714 
   1715     cases.lowerToBuildSteps(
   1716         b,
   1717         parent_step,
   1718         test_filters,
   1719         test_target_filters,
   1720     );
   1721 }
   1722 
   1723 pub fn addDebuggerTests(b: *std.Build, options: DebuggerContext.Options) ?*Step {
   1724     const step = b.step("test-debugger", "Run the debugger tests");
   1725     if (options.gdb == null and options.lldb == null) {
   1726         step.dependOn(&b.addFail("test-debugger requires -Dgdb and/or -Dlldb").step);
   1727         return null;
   1728     }
   1729 
   1730     var context: DebuggerContext = .{
   1731         .b = b,
   1732         .options = options,
   1733         .root_step = step,
   1734     };
   1735     context.addTestsForTarget(.{
   1736         .resolved = b.resolveTargetQuery(.{
   1737             .cpu_arch = .x86_64,
   1738             .os_tag = .linux,
   1739             .abi = .none,
   1740         }),
   1741         .pic = false,
   1742         .test_name_suffix = "x86_64-linux",
   1743     });
   1744     context.addTestsForTarget(.{
   1745         .resolved = b.resolveTargetQuery(.{
   1746             .cpu_arch = .x86_64,
   1747             .os_tag = .linux,
   1748             .abi = .none,
   1749         }),
   1750         .pic = true,
   1751         .test_name_suffix = "x86_64-linux-pic",
   1752     });
   1753     return step;
   1754 }
   1755 
   1756 pub fn addIncrementalTests(b: *std.Build, test_step: *Step) !void {
   1757     const incr_check = b.addExecutable(.{
   1758         .name = "incr-check",
   1759         .root_source_file = b.path("tools/incr-check.zig"),
   1760         .target = b.graph.host,
   1761         .optimize = .Debug,
   1762     });
   1763 
   1764     var dir = try b.build_root.handle.openDir("test/incremental", .{ .iterate = true });
   1765     defer dir.close();
   1766 
   1767     var it = try dir.walk(b.graph.arena);
   1768     while (try it.next()) |entry| {
   1769         if (entry.kind != .file) continue;
   1770 
   1771         const run = b.addRunArtifact(incr_check);
   1772         run.setName(b.fmt("incr-check '{s}'", .{entry.basename}));
   1773 
   1774         run.addArg(b.graph.zig_exe);
   1775         run.addFileArg(b.path("test/incremental/").path(b, entry.path));
   1776         run.addArgs(&.{ "--zig-lib-dir", b.fmt("{}", .{b.graph.zig_lib_directory}) });
   1777 
   1778         run.addCheck(.{ .expect_term = .{ .Exited = 0 } });
   1779 
   1780         test_step.dependOn(&run.step);
   1781     }
   1782 }