╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ tests.zig ────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
2810 .optimize_mode = optimize, 2811 .use_llvm = true, 2812 }, 2813 }; 2814 const resolved_target = b.resolveTargetQuery(test_target.target); 2815 const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM"); 2816 addOneModuleTest(b, step, test_target, &resolved_target, triple_txt, options); 2817 2818 return step; 2819 } 2820 2821 for_targets: for (module_test_targets) |test_target| { 2822 if (test_target.skip_modules.len > 0) { 2823 for (test_target.skip_modules) |skip_mod| { 2824 if (std.mem.eql(u8, options.name, skip_mod)) continue :for_targets; 2825 } 2826 } 2827 2828 const resolved_target = b.resolveTargetQuery(test_target.target); 2829 2830 if (!options.test_extra_targets and test_target.extra_target) continue; 2831 2832 if (options.skip_non_native and !isNative(&resolved_target, &b.graph.host.result)) 2833 continue; 2834 2835 const target = &resolved_target.result; 2836 2837 if (target.cpu.arch.isAarch64() and target.os.tag == .openbsd and target.ofmt == .c) { 2838 continue; // https://codeberg.org/ziglang/zig/issues/36766 2839 } 2840 2841 if (std.mem.eql(u8, options.name, "libc")) { 2842 // The libc API tests obviously need to link libc. So for test 2843 // target entries where we wouldn't link libc by default, skip the 2844 // libc API tests. 2845 if (test_target.link_libc == null and !std.os.targetRequiresLibC(target)) continue; 2846 } 2847 2848 if (options.skip_spirv and target.cpu.arch.isSpirV()) continue; 2849 if (options.skip_wasm and target.cpu.arch.isWasm()) continue; 2850 2851 if (options.skip_freebsd and target.os.tag == .freebsd) continue; 2852 if (options.skip_netbsd and target.os.tag == .netbsd) continue; 2853 if (options.skip_openbsd and target.os.tag == .openbsd) continue; 2854 if (options.skip_windows and target.os.tag == .windows) continue; 2855 if (options.skip_darwin and target.os.tag.isDarwin()) continue; 2856 if (options.skip_linux and target.os.tag == .linux) continue; 2857 2858 const would_use_llvm = wouldUseLlvm(test_target.use_llvm, test_target.target, test_target.optimize_mode); 2859 if (options.skip_llvm and would_use_llvm) continue; 2860 2861 const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM"); 2862 2863 if (options.test_target_filters.len > 0) { 2864 for (options.test_target_filters) |filter| { 2865 if (std.mem.find(u8, triple_txt, filter) != null) break; 2866 } else continue; 2867 } 2868 2869 if (options.skip_libc and (test_target.link_libc == true or std.os.targetRequiresLibC(target))) 2870 continue; 2871 2872 // We can't provide MSVC libc when cross-compiling. 2873 if (target.abi == .msvc and test_target.link_libc == true and builtin.os.tag != .windows) 2874 continue; 2875 2876 if (options.skip_single_threaded and test_target.single_threaded == true) 2877 continue; 2878 2879 const want_this_mode = for (options.optimize_modes) |m| { 2880 if (m == test_target.optimize_mode) break true; 2881 } else false; 2882 if (!want_this_mode) continue; 2883 2884 addOneModuleTest(b, step, test_target, &resolved_target, triple_txt, options); 2885 } 2886 return step; 2887 } 2888 2889 fn addOneModuleTest( 2890 b: *std.Build, 2891 step: *Step, 2892 test_target: ModuleTestTarget, 2893 resolved_target: *const std.Build.ResolvedTarget, 2894 triple_txt: []const u8, 2895 options: ModuleTestOptions, 2896 ) void { 2897 const target = &resolved_target.result; 2898 const libc_suffix = if (test_target.link_libc == true) "-libc" else ""; 2899 const model_txt = target.cpu.model.name; 2900 2901 // These emulated targets need a lot more RAM for unknown reasons. 2902 const max_rss = if (mem.eql(u8, options.name, "std") and 2903 (target.cpu.arch == .hexagon or 2904 (target.cpu.arch.isRISCV() and !resolved_target.query.isNative()) or 2905 target.cpu.arch.isWasm())) 2906 options.max_rss * 2 2907 else 2908 options.max_rss; 2909 2910 const these_tests = b.addTest(.{ 2911 .root_module = b.createModule(.{ 2912 .root_source_file = b.path(options.root_src), 2913 .optimize = test_target.optimize_mode, 2914 .target = resolved_target.*, 2915 .link_libc = test_target.link_libc, 2916 .pic = test_target.pic, 2917 .strip = test_target.strip, 2918 .sanitize_thread = options.sanitize_thread, 2919 .single_threaded = test_target.single_threaded, 2920 }), 2921 .max_rss = max_rss, 2922 .filters = options.test_filters, 2923 .use_llvm = test_target.use_llvm, 2924 .use_lld = test_target.use_lld, 2925 .zig_lib_dir = b.path("lib"), 2926 }); 2927 these_tests.linkage = test_target.linkage; 2928 these_tests.use_new_linker = test_target.new_linker; 2929 // https://codeberg.org/ziglang/zig/issues/31701 2930 if (!(mem.eql(u8, options.name, "compiler-rt") or mem.eql(u8, options.name, "libc"))) { 2931 if (options.no_builtin) these_tests.root_module.no_builtin = true; 2932 } 2933 // https://codeberg.org/ziglang/zig/issues/31702 2934 if (mem.eql(u8, options.name, "compiler-rt") or mem.eql(u8, options.name, "libc")) { 2935 these_tests.root_module.stack_protector = false; 2936 } 2937 // https://github.com/llvm/llvm-project/issues/195561 2938 if (target.cpu.arch.isPowerPC()) { 2939 these_tests.root_module.stack_protector = false; 2940 } 2941 if (options.build_options) |build_options| { 2942 these_tests.root_module.addOptions("build_options", build_options); 2943 } 2944 if (test_target.function_sections) |fs| these_tests.link_function_sections = fs; 2945 if (test_target.data_sections) |ds| these_tests.link_data_sections = ds; 2946 const single_threaded_suffix = if (test_target.single_threaded == true) "-single" else ""; 2947 const backend_suffix = if (test_target.use_llvm == true) 2948 "-llvm" 2949 else if (target.ofmt == .c) 2950 "-cbe" 2951 else if (test_target.use_llvm == false) 2952 "-selfhosted" 2953 else 2954 ""; 2955 const linker_suffix: []const u8 = s: { 2956 if (test_target.new_linker == true) break :s "-new-linker"; 2957 if (test_target.use_lld == false) break :s "-no-lld"; 2958 break :s ""; 2959 }; 2960 const linkage_name = if (test_target.linkage) |linkage| switch (linkage) { 2961 inline else => |t| "-" ++ @tagName(t), 2962 } else ""; 2963 const use_pic = if (test_target.pic == true) "-pic" else ""; 2964 2965 for (options.include_paths) |include_path| these_tests.root_module.addIncludePath(b.path(include_path)); 2966 2967 const qualified_name = b.fmt("{s}-{s}-{s}-{t}{s}{s}{s}{s}{s}{s}", .{ 2968 options.name, 2969 triple_txt, 2970 model_txt, 2971 test_target.optimize_mode, 2972 libc_suffix, 2973 single_threaded_suffix, 2974 backend_suffix, 2975 linker_suffix, 2976 linkage_name, 2977 use_pic, 2978 }); 2979 2980 if (target.ofmt == .c) { 2981 var altered_query = test_target.target; 2982 altered_query.ofmt = null; 2983 2984 const compile_c = b.createModule(.{ 2985 .root_source_file = null, 2986 .link_libc = test_target.link_libc, 2987 .target = b.resolveTargetQuery(altered_query), 2988 }); 2989 const compile_c_exe = b.addExecutable(.{ 2990 .name = qualified_name, 2991 .root_module = compile_c, 2992 .zig_lib_dir = b.path("lib"), 2993 }); 2994 2995 compile_c.addCSourceFile(.{ 2996 .file = these_tests.getEmittedBin(), 2997 .flags = blk: { 2998 const invariant_cflags: []const []const u8 = &.{ 2999 // Tracking issue for making the C backend generate C89 compatible code: 3000 // https://github.com/ziglang/zig/issues/19468 3001 "-std=c99", 3002 "-Werror", 3003 3004 "-Wall", 3005 "-Wembedded-directive", 3006 "-Wempty-translation-unit", 3007 "-Wextra", 3008 "-Wgnu", 3009 "-Winvalid-utf8", 3010 "-Wkeyword-macro", 3011 "-Woverlength-strings", 3012 3013 // Tracking issue for making the C backend generate code 3014 // that does not trigger warnings: 3015 // https://github.com/ziglang/zig/issues/19467 3016 3017 // spotted everywhere 3018 "-Wno-builtin-requires-header", 3019 3020 // spotted on linux 3021 "-Wno-braced-scalar-init", 3022 "-Wno-excess-initializers", 3023 "-Wno-incompatible-pointer-types-discards-qualifiers", 3024 "-Wno-unused", 3025 "-Wno-unused-parameter", 3026 3027 // spotted on darwin 3028 "-Wno-incompatible-pointer-types", 3029 3030 // https://github.com/llvm/llvm-project/issues/153314 3031 "-Wno-unterminated-string-initialization", 3032 3033 // In both Zig and C it is legal to return a pointer to a 3034 // local. The C backend lowers such thing directly, so the 3035 // corresponding warning in C must be disabled. 3036 "-Wno-return-stack-address", 3037 }; 3038 3039 const function_data_sections = switch (target.cpu.arch) { 3040 .arm, 3041 .armeb, 3042 .thumb, 3043 .thumbeb, 3044 .hexagon, 3045 .powerpc, 3046 .powerpcle, 3047 .powerpc64, 3048 .powerpc64le, 3049 => true, 3050 else => false, 3051 }; 3052 3053 break :blk if (function_data_sections) invariant_cflags ++ &[_][]const u8{ 3054 "-ffunction-sections", 3055 "-fdata-sections", 3056 } else invariant_cflags; 3057 }, 3058 }); 3059 compile_c.addIncludePath(b.path("lib")); // for zig.h 3060 if (target.os.tag == .windows) { 3061 if (true) { 3062 // Unfortunately this requires about 8G of RAM for clang to compile 3063 // and our Windows CI runners do not have this much. 3064 // TODO This is not an appropriate way to work around this problem. 3065 step.dependOn(&these_tests.step); 3066 return; 3067 } 3068 if (test_target.link_libc == false) { 3069 compile_c_exe.subsystem = .Console; 3070 compile_c.linkSystemLibrary("kernel32", .{}); 3071 compile_c.linkSystemLibrary("ntdll", .{}); 3072 } 3073 if (mem.eql(u8, options.name, "std")) { 3074 if (test_target.link_libc == false) { 3075 compile_c.linkSystemLibrary("shell32", .{}); 3076 compile_c.linkSystemLibrary("advapi32", .{}); 3077 } 3078 compile_c.linkSystemLibrary("crypt32", .{}); 3079 compile_c.linkSystemLibrary("ole32", .{}); 3080 } 3081 } 3082 3083 const run = b.addRunArtifact(compile_c_exe); 3084 run.skip_foreign_checks = true; 3085 run.enableTestRunnerMode(); 3086 run.setName(b.fmt("run test {s}", .{qualified_name})); 3087 3088 step.dependOn(&run.step); 3089 } else if (target.cpu.arch.isSpirV()) { 3090 // Don't run spirv binaries 3091 _ = these_tests.getEmittedBin(); 3092 step.dependOn(&these_tests.step); 3093 } else if (target.cpu.arch == .x86_64 and target.os.tag.isDarwin()) { 3094 // https://codeberg.org/ziglang/zig/issues/35267 3095 _ = these_tests.getEmittedBin(); 3096 step.dependOn(&these_tests.step); 3097 } else { 3098 const run = b.addRunArtifact(these_tests); 3099 run.skip_foreign_checks = true; 3100 run.setName(b.fmt("run test {s}", .{qualified_name})); 3101 3102 step.dependOn(&run.step); 3103 } 3104 } 3105 3106 pub fn wouldUseLlvm(use_llvm: ?bool, query: std.Target.Query, optimize_mode: OptimizeMode) bool { 3107 if (comptime builtin.cpu.arch.endian() == .big) return true; // https://github.com/ziglang/zig/issues/25961 3108 if (use_llvm) |x| return x; 3109 if (query.ofmt == .c) return false; 3110 switch (optimize_mode) { 3111 .debug => {}, 3112 else => return true, 3113 } 3114 const cpu_arch = query.cpu_arch orelse builtin.cpu.arch; 3115 const os_tag = query.os_tag orelse builtin.os.tag; 3116 const ofmt: std.Target.ObjectFormat = query.ofmt orelse .default(os_tag, cpu_arch); 3117 switch (cpu_arch) { 3118 .x86_64 => { 3119 if (std.Target.ptrBitWidth_arch_abi(cpu_arch, query.abi orelse .none) != 64) return true; 3120 if (os_tag == .illumos) return true; 3121 switch (os_tag) { 3122 .dragonfly, 3123 .freebsd, 3124 .netbsd, 3125 .openbsd, 3126 => return true, 3127 else => {}, 3128 } 3129 return switch (ofmt) { 3130 .elf => return false, 3131 .macho => return true, // https://codeberg.org/ziglang/zig/issues/35267 3132 else => return true, 3133 }; 3134 }, 3135 .spirv32, .spirv64 => return false, 3136 else => return true, 3137 } 3138 } 3139 3140 const CAbiTestOptions = struct { 3141 test_target_filters: []const []const u8, 3142 optimize_modes: []const OptimizeMode, 3143 skip_non_native: bool, 3144 skip_wasm: bool, 3145 skip_freebsd: bool, 3146 skip_netbsd: bool, 3147 skip_openbsd: bool, 3148 skip_windows: bool, 3149 skip_darwin: bool, 3150 skip_linux: bool, 3151 skip_llvm: bool, 3152 max_rss: u64 = 0, 3153 }; 3154 3155 pub fn addCAbiTests(b: *std.Build, options: CAbiTestOptions) *Step { 3156 const step = b.step("test-c-abi", "Run the C ABI tests"); 3157 3158 for (c_abi_targets) |c_abi_target| { 3159 if (options.skip_wasm and c_abi_target.target.cpu_arch != null and c_abi_target.target.cpu_arch.?.isWasm()) continue; 3160 3161 if (options.skip_freebsd and c_abi_target.target.os_tag == .freebsd) continue; 3162 if (options.skip_netbsd and c_abi_target.target.os_tag == .netbsd) continue; 3163 if (options.skip_openbsd and c_abi_target.target.os_tag == .openbsd) continue; 3164 if (options.skip_windows and c_abi_target.target.os_tag == .windows) continue; 3165 if (options.skip_darwin and c_abi_target.target.os_tag != null and c_abi_target.target.os_tag.?.isDarwin()) continue; 3166 if (options.skip_linux and c_abi_target.target.os_tag == .linux) continue; 3167 3168 const resolved_target = b.resolveTargetQuery(c_abi_target.target); 3169 const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM"); 3170 const target = &resolved_target.result; 3171 3172 if (options.skip_non_native and !isNative(&resolved_target, &b.graph.host.result)) 3173 continue; 3174 3175 if (options.test_target_filters.len > 0) { 3176 for (options.test_target_filters) |filter| { 3177 if (std.mem.find(u8, triple_txt, filter) != null) break; 3178 } else continue; 3179 } 3180 3181 for (options.optimize_modes) |optimize_mode| { 3182 const would_use_llvm = wouldUseLlvm(c_abi_target.use_llvm, c_abi_target.target, optimize_mode); 3183 if (options.skip_llvm and would_use_llvm) continue; 3184 3185 const test_mod = b.createModule(.{ 3186 .root_source_file = b.path("test/c_abi/main.zig"), 3187 .target = resolved_target, 3188 .optimize = optimize_mode, 3189 .link_libc = true, 3190 .pic = c_abi_target.pic, 3191 .strip = c_abi_target.strip, 3192 }); 3193 test_mod.addCSourceFile(.{ 3194 .file = b.path("test/c_abi/cfuncs.c"), 3195 .flags = &.{"-std=c99"}, 3196 }); 3197 for (c_abi_target.c_defines) |define| test_mod.addCMacro(define, "1"); 3198 3199 const test_step = b.addTest(.{ 3200 .name = b.fmt("test-c-abi-{s}-{s}-{s}{s}{s}{s}", .{ 3201 triple_txt, 3202 target.cpu.model.name, 3203 @tagName(optimize_mode), 3204 if (c_abi_target.use_llvm == true) 3205 "-llvm" 3206 else if (target.ofmt == .c) 3207 "-cbe" 3208 else if (c_abi_target.use_llvm == false) 3209 "-selfhosted" 3210 else 3211 "", 3212 if (c_abi_target.use_lld == false) "-no-lld" else "", 3213 if (c_abi_target.pic == true) "-pic" else "", 3214 }), 3215 .root_module = test_mod, 3216 .use_llvm = c_abi_target.use_llvm, 3217 .use_lld = c_abi_target.use_lld, 3218 .max_rss = options.max_rss, 3219 }); 3220 3221 // https://github.com/llvm/llvm-project/issues/195561 3222 if (target.cpu.arch.isPowerPC()) { 3223 test_step.root_module.stack_protector = false; 3224 } 3225 3226 // This test is intentionally trying to check if the external ABI is 3227 // done properly. LTO would be a hindrance to this. 3228 test_step.lto = .none; 3229 3230 const run = b.addRunArtifact(test_step); 3231 run.skip_foreign_checks = true; 3232 step.dependOn(&run.step); 3233 } 3234 } 3235 return step; 3236 } 3237 3238 const LinkTestOptions = struct { 3239 test_target_filters: []const []const u8, 3240 test_filters: []const []const u8, 3241 optimize_modes: []const OptimizeMode, 3242 skip_non_native: bool, 3243 skip_freebsd: bool, 3244 skip_netbsd: bool, 3245 skip_openbsd: bool, 3246 skip_windows: bool, 3247 skip_darwin: bool, 3248 skip_linux: bool, 3249 skip_llvm: bool, 3250 skip_libc: bool, 3251 max_rss: usize, 3252 }; 3253 3254 pub fn addLinkTests(b: *std.Build, options: LinkTestOptions) *Step { 3255 const step = b.step("test-link", "Run the linker tests"); 3256 const update_snapshots = b.option( 3257 bool, 3258 "link-snapshot-update", 3259 "Update linker test snapshots in-place instead of testing against them", 3260 ) orelse false; 3261 3262 for (link_targets) |link_target| { 3263 const resolved_target = b.resolveTargetQuery(link_target.target); 3264 3265 if (options.skip_non_native and !isNative(&resolved_target, &b.graph.host.result)) 3266 continue; 3267 3268 const target = &resolved_target.result; 3269 3270 if (options.skip_freebsd and target.os.tag == .freebsd) continue; 3271 if (options.skip_netbsd and target.os.tag == .netbsd) continue; 3272 if (options.skip_openbsd and target.os.tag == .openbsd) continue; 3273 if (options.skip_windows and target.os.tag == .windows) continue; 3274 if (options.skip_darwin and target.os.tag.isDarwin()) continue; 3275 if (options.skip_linux and target.os.tag == .linux) continue; 3276 3277 const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM"); 3278 3279 if (options.test_target_filters.len > 0) { 3280 for (options.test_target_filters) |filter| { 3281 if (std.mem.find(u8, triple_txt, filter) != null) break; 3282 } else continue; 3283 } 3284 3285 if (options.skip_libc and (link_target.link_libc == true or std.os.targetRequiresLibC(target))) 3286 continue; 3287 3288 // We can't provide MSVC libc when cross-compiling. 3289 if (target.abi == .msvc and link_target.link_libc == true and builtin.os.tag != .windows) 3290 continue; 3291 3292 for (options.optimize_modes) |optimize_mode| { 3293 if (link_target.optimize_mode != optimize_mode) continue; 3294 const would_use_llvm = wouldUseLlvm(link_target.use_llvm, link_target.target, optimize_mode); 3295 if (options.skip_llvm and would_use_llvm) continue; 3296 3297 const opt_update_step = if (update_snapshots) update: { 3298 const update_step = Step.UpdateSourceFiles.create(b); 3299 step.dependOn(&update_step.step); 3300 break :update update_step; 3301 } else null; 3302 3303 var context: LinkContext = .{ 3304 .b = b, 3305 .step = step, 3306 .optimize = optimize_mode, 3307 .target = resolved_target, 3308 .target_desc = std.fmt.allocPrint(b.allocator, "{s}-{t}{s}{s}{s}", .{ 3309 target.zigTriple(b.allocator) catch @panic("OOM"), 3310 optimize_mode, 3311 if (link_target.use_llvm) "-llvm" else "", 3312 if (link_target.use_lld) "-lld" else "", 3313 if (link_target.link_libc) "-libc" else "", 3314 }) catch @panic("OOM"), 3315 .use_llvm = link_target.use_llvm, 3316 .use_lld = link_target.use_lld, 3317 .link_libc = link_target.link_libc, 3318 .test_filters = options.test_filters, 3319 .update_step = opt_update_step, 3320 .updated_snapshots = .empty, 3321 .max_rss = options.max_rss, 3322 }; 3323 3324 link.addCases(&context); 3325 } 3326 } 3327 return step; 3328 } 3329 3330 pub fn addCases( 3331 b: *std.Build, 3332 parent_step: *Step, 3333 case_test_options: @import("src/Cases.zig").CaseTestOptions, 3334 build_options: @import("cases.zig").BuildOptions, 3335 ) !void { 3336 const arena = b.allocator; 3337 const gpa = b.allocator; 3338 const io = b.graph.io; 3339 3340 var cases = @import("src/Cases.zig").init(gpa, arena, io); 3341 3342 b.dependOnDirectoryContents(b.path("test/cases")); 3343 3344 var dir = try b.root.openDir(io, "test/cases", .{ .iterate = true }); 3345 defer dir.close(io); 3346 3347 cases.addFromDir(dir, "test/cases", b); 3348 try @import("cases.zig").addCases(&cases, build_options, b); 3349 3350 cases.lowerToBuildSteps( 3351 b, 3352 parent_step, 3353 case_test_options, 3354 ); 3355 } 3356 3357 pub fn addDebuggerTests(b: *std.Build, options: DebuggerContext.Options) ?*Step { 3358 const step = b.step("test-debugger", "Run the debugger tests"); 3359 if (options.gdb == null and options.lldb == null) { 3360 step.dependOn(&b.addFail("test-debugger requires -Dgdb and/or -Dlldb").step); 3361 return null; 3362 } 3363 3364 var context: DebuggerContext = .{ 3365 .b = b, 3366 .options = options, 3367 .root_step = step, 3368 .test_matrix = debugger_matrix, 3369 }; 3370 context.addTests(); 3371 return step; 3372 } 3373 3374 const IncrementalTestOptions = struct { 3375 test_filters: []const []const u8, 3376 test_target_filters: []const []const u8, 3377 skip_non_native: bool, 3378 skip_wasm: bool, 3379 skip_freebsd: bool, 3380 skip_netbsd: bool, 3381 skip_openbsd: bool, 3382 skip_windows: bool, 3383 skip_darwin: bool, 3384 skip_linux: bool, 3385 skip_llvm: bool, 3386 }; 3387 3388 pub fn addIncrementalTests( 3389 b: *std.Build, 3390 test_step: *Step, 3391 options: IncrementalTestOptions, 3392 ) !void { 3393 const io = b.graph.io; 3394 3395 const incr_check = b.addExecutable(.{ 3396 .name = "incr-check", 3397 .root_module = b.createModule(.{ 3398 .root_source_file = b.path("tools/incr-check.zig"), 3399 .target = b.graph.host, 3400 .optimize = .debug, 3401 }), 3402 }); 3403 3404 b.dependOnDirectoryContents(b.path("test/incremental")); 3405 3406 var dir = try b.root.openDir(io, "test/incremental", .{ .iterate = true }); 3407 defer dir.close(io); 3408 3409 var it = try dir.walk(b.graph.arena); 3410 while (try it.next(io)) |entry| { 3411 if (std.mem.endsWith(u8, entry.basename, ".swp")) continue; 3412 3413 for (options.test_filters) |test_filter| { 3414 if (std.mem.find(u8, entry.path, test_filter)) |_| break; 3415 } else if (options.test_filters.len > 0) continue; 3416 3417 switch (entry.kind) { 3418 .file => {}, 3419 .directory => { 3420 b.dependOnDirectoryContents(b.path(b.pathJoin(&.{ "test", "incremental", entry.path }))); 3421 }, 3422 else => continue, 3423 } 3424 b.dependOnFileContents(b.path(b.pathJoin(&.{ "test", "incremental", entry.path }))); 3425 3426 for (incremental_targets) |test_target| { 3427 const resolved_target = b.resolveTargetQuery(test_target.target); 3428 3429 if (options.skip_non_native and !isNative(&resolved_target, &b.graph.host.result)) 3430 continue; 3431 3432 const target = &resolved_target.result; 3433 3434 if (options.skip_wasm and target.cpu.arch.isWasm()) continue; 3435 3436 if (options.skip_freebsd and target.os.tag == .freebsd) continue; 3437 if (options.skip_netbsd and target.os.tag == .netbsd) continue; 3438 if (options.skip_openbsd and target.os.tag == .openbsd) continue; 3439 if (options.skip_windows and target.os.tag == .windows) continue; 3440 if (options.skip_darwin and target.os.tag.isDarwin()) continue; 3441 if (options.skip_linux and target.os.tag == .linux) continue; 3442 3443 if (options.skip_llvm and test_target.backend == .llvm) continue; 3444 3445 const target_str = b.fmt("{s}-{t}", .{ 3446 resolved_target.query.zigTriple(b.allocator) catch @panic("OOM"), 3447 test_target.backend, 3448 }); 3449 3450 if (options.test_target_filters.len > 0) { 3451 for (options.test_target_filters) |filter| { 3452 if (std.mem.find(u8, target_str, filter) != null) break; 3453 } else continue; 3454 } 3455 3456 const run = b.addRunArtifact(incr_check); 3457 run.setName(b.fmt("incr-check {s} '{s}'", .{ target_str, entry.basename })); 3458 3459 run.addArg(b.graph.zig_exe); 3460 run.addFileArg(b.path("test/incremental/").path(b, entry.path)); 3461 3462 run.addArg("--zig-lib-dir"); 3463 run.addDirectoryArg(.zig_lib); 3464 3465 run.addArgs(&.{ "--target", target_str }); 3466 3467 run.addArg("--quiet"); // don't fill stderr telling us about skipped tests etc 3468 3469 run.addThirdPartyEnabledArgDarling(.{ .enabled = "-fdarling" }); 3470 run.addThirdPartyEnabledArgQemu(.{ .enabled = "-fqemu" }); 3471 run.addThirdPartyEnabledArgRosetta(.{ .enabled = "-frosetta" }); 3472 run.addThirdPartyEnabledArgWasmtime(.{ .enabled = "-fwasmtime" }); 3473 run.addThirdPartyEnabledArgWine(.{ .enabled = "-fwine" }); 3474 3475 run.addCheck(.{ .expect_term = .{ .exited = 0 } }); 3476 test_step.dependOn(&run.step); 3477 } 3478 } 3479 } 3480 3481 pub fn addLlvmIrTests(b: *std.Build, options: LlvmIrContext.Options) ?*Step { 3482 const step = b.step("test-llvm-ir", "Run the LLVM IR tests"); 3483 3484 if (!options.enable_llvm) { 3485 step.dependOn(&b.addFail("test-llvm-ir requires -Denable-llvm").step); 3486 return null; 3487 } 3488 3489 var context: LlvmIrContext = .{ 3490 .b = b, 3491 .options = options, 3492 .root_step = step, 3493 }; 3494 3495 llvm_ir.addCases(&context); 3496 3497 return step; 3498 } 3499 3500 const libc_test_nsz_targets: []const std.Target.Query = &.{ 3501 .{ 3502 .cpu_arch = .arm, 3503 .os_tag = .linux, 3504 .abi = .musleabi, 3505 }, 3506 .{ 3507 .cpu_arch = .arm, 3508 .os_tag = .linux, 3509 .abi = .musleabihf, 3510 }, 3511 .{ 3512 .cpu_arch = .armeb, 3513 .os_tag = .linux, 3514 .abi = .musleabi, 3515 }, 3516 .{ 3517 .cpu_arch = .armeb, 3518 .os_tag = .linux, 3519 .abi = .musleabihf, 3520 }, 3521 .{ 3522 .cpu_arch = .thumb, 3523 .os_tag = .linux, 3524 .abi = .musleabi, 3525 }, 3526 .{ 3527 .cpu_arch = .thumb, 3528 .os_tag = .linux, 3529 .abi = .musleabihf, 3530 }, 3531 .{ 3532 .cpu_arch = .thumbeb, 3533 .os_tag = .linux, 3534 .abi = .musleabi, 3535 }, 3536 .{ 3537 .cpu_arch = .thumbeb, 3538 .os_tag = .linux, 3539 .abi = .musleabihf, 3540 }, 3541 .{ 3542 .cpu_arch = .aarch64, 3543 .os_tag = .linux, 3544 .abi = .musl, 3545 }, 3546 .{ 3547 .cpu_arch = .aarch64_be, 3548 .os_tag = .linux, 3549 .abi = .musl, 3550 }, 3551 // .{ 3552 // .cpu_arch = .hexagon, 3553 // .os_tag = .linux, 3554 // .abi = .musl, 3555 // }, 3556 .{ 3557 .cpu_arch = .loongarch64, 3558 .os_tag = .linux, 3559 .abi = .musl, 3560 }, 3561 .{ 3562 .cpu_arch = .loongarch64, 3563 .os_tag = .linux, 3564 .abi = .muslsf, 3565 }, 3566 // .{ 3567 // .cpu_arch = .mips, 3568 // .os_tag = .linux, 3569 // .abi = .musleabi, 3570 // }, 3571 // .{ 3572 // .cpu_arch = .mips, 3573 // .os_tag = .linux, 3574 // .abi = .musleabihf, 3575 // }, 3576 // .{ 3577 // .cpu_arch = .mipsel, 3578 // .os_tag = .linux, 3579 // .abi = .musleabi, 3580 // }, 3581 // .{ 3582 // .cpu_arch = .mipsel, 3583 // .os_tag = .linux, 3584 // .abi = .musleabihf, 3585 // }, 3586 // .{ 3587 // .cpu_arch = .mips64, 3588 // .os_tag = .linux, 3589 // .abi = .muslabi64, 3590 // }, 3591 // .{ 3592 // .cpu_arch = .mips64, 3593 // .os_tag = .linux, 3594 // .abi = .muslabin32, 3595 // }, 3596 // .{ 3597 // .cpu_arch = .mips64el, 3598 // .os_tag = .linux, 3599 // .abi = .muslabi64, 3600 // }, 3601 // .{ 3602 // .cpu_arch = .mips64el, 3603 // .os_tag = .linux, 3604 // .abi = .muslabin32, 3605 // }, 3606 .{ 3607 .cpu_arch = .powerpc, 3608 .os_tag = .linux, 3609 .abi = .musleabi, 3610 }, 3611 .{ 3612 .cpu_arch = .powerpc, 3613 .os_tag = .linux, 3614 .abi = .musleabihf, 3615 }, 3616 .{ 3617 .cpu_arch = .powerpc64, 3618 .os_tag = .linux, 3619 .abi = .musl, 3620 }, 3621 .{ 3622 .cpu_arch = .powerpc64le, 3623 .os_tag = .linux, 3624 .abi = .musl, 3625 }, 3626 .{ 3627 .cpu_arch = .riscv32, 3628 .os_tag = .linux, 3629 .abi = .musl, 3630 }, 3631 .{ 3632 .cpu_arch = .riscv64, 3633 .os_tag = .linux, 3634 .abi = .musl, 3635 }, 3636 .{ 3637 .cpu_arch = .s390x, 3638 .os_tag = .linux, 3639 .abi = .musl, 3640 }, 3641 .{ 3642 .cpu_arch = .wasm32, 3643 .os_tag = .wasi, 3644 .abi = .musl, 3645 }, 3646 .{ 3647 .cpu_arch = .x86, 3648 .os_tag = .linux, 3649 .abi = .musl, 3650 }, 3651 .{ 3652 .cpu_arch = .x86_64, 3653 .os_tag = .linux, 3654 .abi = .musl, 3655 }, 3656 .{ 3657 .cpu_arch = .x86_64, 3658 .os_tag = .linux, 3659 .abi = .muslx32, 3660 }, 3661 }; 3662 3663 pub fn addLibcTestNszTests(b: *std.Build, options: LibcContext.Options) ?*Step { 3664 const step = b.step("test-libc-nsz", "Run external libc-test test cases"); 3665 const opt_libc_test_path = b.option(std.Build.LazyPath, "libc-test-path", "path to libc-test source directory"); 3666 if (opt_libc_test_path) |libc_test_path| { 3667 var context: LibcContext = .{ 3668 .b = b, 3669 .options = options, 3670 .root_step = step, 3671 .libc_test_src_path = libc_test_path.path(b, "src"), 3672 }; 3673 3674 libc.addCases(&context); 3675 3676 for (libc_test_nsz_targets) |target_query| { 3677 const target = b.resolveTargetQuery(target_query); 3678 context.addTarget(target); 3679 } 3680 3681 return step; 3682 } else { 3683 step.dependOn(&b.addFail("The -Dlibc-test-path=... option is required for this step").step); 3684 return null; 3685 } 3686 } 3687