master
1const std = @import("std");
2const builtin = @import("builtin");
3const assert = std.debug.assert;
4const mem = std.mem;
5const OptimizeMode = std.builtin.OptimizeMode;
6const Step = std.Build.Step;
7
8// Cases
9const error_traces = @import("error_traces.zig");
10const stack_traces = @import("stack_traces.zig");
11const llvm_ir = @import("llvm_ir.zig");
12const libc = @import("libc.zig");
13
14// Implementations
15pub const ErrorTracesContext = @import("src/ErrorTrace.zig");
16pub const StackTracesContext = @import("src/StackTrace.zig");
17pub const DebuggerContext = @import("src/Debugger.zig");
18pub const LlvmIrContext = @import("src/LlvmIr.zig");
19pub const LibcContext = @import("src/Libc.zig");
20
21const TestTarget = struct {
22 linkage: ?std.builtin.LinkMode = null,
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, for any reason, shouldn't be run as part of a normal test
34 // invocation. This could be because of a slow backend, requiring a newer LLVM version, being
35 // too niche, etc.
36 extra_target: bool = false,
37};
38
39const test_targets = blk: {
40 // getBaselineCpuFeatures calls populateDependencies which has a O(N ^ 2) algorithm
41 // (where N is roughly 160, which technically makes it O(1), but it adds up to a
42 // lot of branches)
43 @setEvalBranchQuota(60000);
44 break :blk [_]TestTarget{
45 // Native Targets
46
47 .{}, // 0 index must be all defaults
48 .{
49 .link_libc = true,
50 },
51 .{
52 .single_threaded = true,
53 },
54
55 .{
56 .optimize_mode = .ReleaseFast,
57 },
58 .{
59 .link_libc = true,
60 .optimize_mode = .ReleaseFast,
61 },
62 .{
63 .optimize_mode = .ReleaseFast,
64 .single_threaded = true,
65 },
66
67 .{
68 .optimize_mode = .ReleaseSafe,
69 },
70 .{
71 .link_libc = true,
72 .optimize_mode = .ReleaseSafe,
73 },
74 .{
75 .optimize_mode = .ReleaseSafe,
76 .single_threaded = true,
77 },
78
79 .{
80 .optimize_mode = .ReleaseSmall,
81 },
82 .{
83 .link_libc = true,
84 .optimize_mode = .ReleaseSmall,
85 },
86 .{
87 .optimize_mode = .ReleaseSmall,
88 .single_threaded = true,
89 },
90
91 .{
92 .target = .{
93 .ofmt = .c,
94 },
95 .link_libc = true,
96 },
97
98 // FreeBSD Targets
99
100 .{
101 .target = .{
102 .cpu_arch = .aarch64,
103 .os_tag = .freebsd,
104 .abi = .none,
105 },
106 .link_libc = true,
107 },
108
109 .{
110 .target = .{
111 .cpu_arch = .arm,
112 .os_tag = .freebsd,
113 .abi = .eabihf,
114 },
115 .link_libc = true,
116 },
117
118 .{
119 .target = .{
120 .cpu_arch = .powerpc64,
121 .os_tag = .freebsd,
122 .abi = .none,
123 },
124 .link_libc = true,
125 },
126
127 .{
128 .target = .{
129 .cpu_arch = .powerpc64le,
130 .os_tag = .freebsd,
131 .abi = .none,
132 },
133 .link_libc = true,
134 },
135
136 .{
137 .target = .{
138 .cpu_arch = .riscv64,
139 .os_tag = .freebsd,
140 .abi = .none,
141 },
142 .link_libc = true,
143 },
144
145 .{
146 .target = .{
147 .cpu_arch = .x86_64,
148 .os_tag = .freebsd,
149 .abi = .none,
150 },
151 .link_libc = true,
152 },
153
154 // Linux Targets
155
156 .{
157 .target = .{
158 .cpu_arch = .aarch64,
159 .os_tag = .linux,
160 .abi = .none,
161 },
162 },
163 .{
164 .target = .{
165 .cpu_arch = .aarch64,
166 .os_tag = .linux,
167 .abi = .musl,
168 },
169 .link_libc = true,
170 },
171 .{
172 .target = .{
173 .cpu_arch = .aarch64,
174 .os_tag = .linux,
175 .abi = .musl,
176 },
177 .linkage = .dynamic,
178 .link_libc = true,
179 .extra_target = true,
180 },
181 .{
182 .target = .{
183 .cpu_arch = .aarch64,
184 .os_tag = .linux,
185 .abi = .gnu,
186 },
187 .link_libc = true,
188 },
189
190 .{
191 .target = .{
192 .cpu_arch = .aarch64,
193 .os_tag = .linux,
194 .abi = .none,
195 },
196 .use_llvm = false,
197 .use_lld = false,
198 .optimize_mode = .ReleaseFast,
199 .strip = true,
200 },
201 .{
202 .target = .{
203 .cpu_arch = .aarch64,
204 .cpu_model = .{ .explicit = &std.Target.aarch64.cpu.neoverse_n1 },
205 .os_tag = .linux,
206 .abi = .none,
207 },
208 .use_llvm = false,
209 .use_lld = false,
210 .optimize_mode = .ReleaseFast,
211 .strip = true,
212 },
213
214 .{
215 .target = .{
216 .cpu_arch = .aarch64_be,
217 .os_tag = .linux,
218 .abi = .none,
219 },
220 },
221 .{
222 .target = .{
223 .cpu_arch = .aarch64_be,
224 .os_tag = .linux,
225 .abi = .musl,
226 },
227 .link_libc = true,
228 },
229 .{
230 .target = .{
231 .cpu_arch = .aarch64_be,
232 .os_tag = .linux,
233 .abi = .musl,
234 },
235 .linkage = .dynamic,
236 .link_libc = true,
237 .extra_target = true,
238 },
239 .{
240 .target = .{
241 .cpu_arch = .aarch64_be,
242 .os_tag = .linux,
243 .abi = .gnu,
244 },
245 .link_libc = true,
246 },
247
248 .{
249 .target = .{
250 .cpu_arch = .arm,
251 .os_tag = .linux,
252 .abi = .eabi,
253 },
254 },
255 .{
256 .target = .{
257 .cpu_arch = .arm,
258 .os_tag = .linux,
259 .abi = .eabihf,
260 },
261 },
262 .{
263 .target = .{
264 .cpu_arch = .arm,
265 .os_tag = .linux,
266 .abi = .musleabi,
267 },
268 .link_libc = true,
269 },
270 // Crashes in weird ways when applying relocations.
271 // .{
272 // .target = .{
273 // .cpu_arch = .arm,
274 // .os_tag = .linux,
275 // .abi = .musleabi,
276 // },
277 // .linkage = .dynamic,
278 // .link_libc = true,
279 // .extra_target = true,
280 // },
281 .{
282 .target = .{
283 .cpu_arch = .arm,
284 .os_tag = .linux,
285 .abi = .musleabihf,
286 },
287 .link_libc = true,
288 },
289 // Crashes in weird ways when applying relocations.
290 // .{
291 // .target = .{
292 // .cpu_arch = .arm,
293 // .os_tag = .linux,
294 // .abi = .musleabihf,
295 // },
296 // .linkage = .dynamic,
297 // .link_libc = true,
298 // .extra_target = true,
299 // },
300 .{
301 .target = .{
302 .cpu_arch = .arm,
303 .os_tag = .linux,
304 .abi = .gnueabi,
305 },
306 .link_libc = true,
307 },
308 .{
309 .target = .{
310 .cpu_arch = .arm,
311 .os_tag = .linux,
312 .abi = .gnueabihf,
313 },
314 .link_libc = true,
315 },
316
317 .{
318 .target = .{
319 .cpu_arch = .armeb,
320 .os_tag = .linux,
321 .abi = .eabi,
322 },
323 },
324 .{
325 .target = .{
326 .cpu_arch = .armeb,
327 .os_tag = .linux,
328 .abi = .eabihf,
329 },
330 },
331 .{
332 .target = .{
333 .cpu_arch = .armeb,
334 .os_tag = .linux,
335 .abi = .musleabi,
336 },
337 .link_libc = true,
338 },
339 // Crashes in weird ways when applying relocations.
340 // .{
341 // .target = .{
342 // .cpu_arch = .armeb,
343 // .os_tag = .linux,
344 // .abi = .musleabi,
345 // },
346 // .linkage = .dynamic,
347 // .link_libc = true,
348 // .extra_target = true,
349 // },
350 .{
351 .target = .{
352 .cpu_arch = .armeb,
353 .os_tag = .linux,
354 .abi = .musleabihf,
355 },
356 .link_libc = true,
357 },
358 // Crashes in weird ways when applying relocations.
359 // .{
360 // .target = .{
361 // .cpu_arch = .armeb,
362 // .os_tag = .linux,
363 // .abi = .musleabihf,
364 // },
365 // .linkage = .dynamic,
366 // .link_libc = true,
367 // .extra_target = true,
368 // },
369 .{
370 .target = .{
371 .cpu_arch = .armeb,
372 .os_tag = .linux,
373 .abi = .gnueabi,
374 },
375 .link_libc = true,
376 },
377 .{
378 .target = .{
379 .cpu_arch = .armeb,
380 .os_tag = .linux,
381 .abi = .gnueabihf,
382 },
383 .link_libc = true,
384 },
385
386 // Similar to Thumb, we need long calls on Hexagon due to relocation range issues.
387 .{
388 .target = std.Target.Query.parse(.{
389 .arch_os_abi = "hexagon-linux-none",
390 .cpu_features = "baseline+long_calls",
391 }) catch unreachable,
392 },
393 .{
394 .target = std.Target.Query.parse(.{
395 .arch_os_abi = "hexagon-linux-musl",
396 .cpu_features = "baseline+long_calls",
397 }) catch unreachable,
398 .link_libc = true,
399 },
400 .{
401 .target = std.Target.Query.parse(.{
402 .arch_os_abi = "hexagon-linux-musl",
403 .cpu_features = "baseline+long_calls",
404 }) catch unreachable,
405 .linkage = .dynamic,
406 .link_libc = true,
407 .extra_target = true,
408 },
409
410 .{
411 .target = .{
412 .cpu_arch = .loongarch64,
413 .os_tag = .linux,
414 .abi = .none,
415 },
416 },
417 .{
418 .target = .{
419 .cpu_arch = .loongarch64,
420 .os_tag = .linux,
421 .abi = .musl,
422 },
423 .link_libc = true,
424 },
425 .{
426 .target = .{
427 .cpu_arch = .loongarch64,
428 .os_tag = .linux,
429 .abi = .musl,
430 },
431 .linkage = .dynamic,
432 .link_libc = true,
433 .extra_target = true,
434 },
435 .{
436 .target = .{
437 .cpu_arch = .loongarch64,
438 .os_tag = .linux,
439 .abi = .gnu,
440 },
441 .link_libc = true,
442 },
443
444 .{
445 .target = .{
446 .cpu_arch = .mips,
447 .os_tag = .linux,
448 .abi = .eabi,
449 },
450 },
451 .{
452 .target = .{
453 .cpu_arch = .mips,
454 .os_tag = .linux,
455 .abi = .eabihf,
456 },
457 },
458 .{
459 .target = .{
460 .cpu_arch = .mips,
461 .os_tag = .linux,
462 .abi = .musleabi,
463 },
464 .link_libc = true,
465 },
466 .{
467 .target = .{
468 .cpu_arch = .mips,
469 .os_tag = .linux,
470 .abi = .musleabi,
471 },
472 .linkage = .dynamic,
473 .link_libc = true,
474 .extra_target = true,
475 },
476 .{
477 .target = .{
478 .cpu_arch = .mips,
479 .os_tag = .linux,
480 .abi = .musleabihf,
481 },
482 .link_libc = true,
483 },
484 .{
485 .target = .{
486 .cpu_arch = .mips,
487 .os_tag = .linux,
488 .abi = .musleabihf,
489 },
490 .linkage = .dynamic,
491 .link_libc = true,
492 .extra_target = true,
493 },
494 .{
495 .target = .{
496 .cpu_arch = .mips,
497 .os_tag = .linux,
498 .abi = .gnueabi,
499 },
500 .link_libc = true,
501 },
502 .{
503 .target = .{
504 .cpu_arch = .mips,
505 .os_tag = .linux,
506 .abi = .gnueabihf,
507 },
508 .link_libc = true,
509 },
510
511 .{
512 .target = .{
513 .cpu_arch = .mipsel,
514 .os_tag = .linux,
515 .abi = .eabi,
516 },
517 },
518 .{
519 .target = .{
520 .cpu_arch = .mipsel,
521 .os_tag = .linux,
522 .abi = .eabihf,
523 },
524 },
525 .{
526 .target = .{
527 .cpu_arch = .mipsel,
528 .os_tag = .linux,
529 .abi = .musleabi,
530 },
531 .link_libc = true,
532 },
533 .{
534 .target = .{
535 .cpu_arch = .mipsel,
536 .os_tag = .linux,
537 .abi = .musleabi,
538 },
539 .linkage = .dynamic,
540 .link_libc = true,
541 .extra_target = true,
542 },
543 .{
544 .target = .{
545 .cpu_arch = .mipsel,
546 .os_tag = .linux,
547 .abi = .musleabihf,
548 },
549 .link_libc = true,
550 },
551 .{
552 .target = .{
553 .cpu_arch = .mipsel,
554 .os_tag = .linux,
555 .abi = .musleabihf,
556 },
557 .linkage = .dynamic,
558 .link_libc = true,
559 .extra_target = true,
560 },
561 .{
562 .target = .{
563 .cpu_arch = .mipsel,
564 .os_tag = .linux,
565 .abi = .gnueabi,
566 },
567 .link_libc = true,
568 },
569 .{
570 .target = .{
571 .cpu_arch = .mipsel,
572 .os_tag = .linux,
573 .abi = .gnueabihf,
574 },
575 .link_libc = true,
576 },
577
578 .{
579 .target = .{
580 .cpu_arch = .mips64,
581 .os_tag = .linux,
582 .abi = .none,
583 },
584 },
585 .{
586 .target = .{
587 .cpu_arch = .mips64,
588 .os_tag = .linux,
589 .abi = .muslabi64,
590 },
591 .link_libc = true,
592 },
593 .{
594 .target = .{
595 .cpu_arch = .mips64,
596 .os_tag = .linux,
597 .abi = .muslabi64,
598 },
599 .linkage = .dynamic,
600 .link_libc = true,
601 .extra_target = true,
602 },
603 .{
604 .target = .{
605 .cpu_arch = .mips64,
606 .os_tag = .linux,
607 .abi = .muslabin32,
608 },
609 .link_libc = true,
610 .extra_target = true,
611 },
612 .{
613 .target = .{
614 .cpu_arch = .mips64,
615 .os_tag = .linux,
616 .abi = .muslabin32,
617 },
618 .linkage = .dynamic,
619 .link_libc = true,
620 .extra_target = true,
621 },
622 .{
623 .target = .{
624 .cpu_arch = .mips64,
625 .os_tag = .linux,
626 .abi = .gnuabi64,
627 },
628 .link_libc = true,
629 },
630 .{
631 .target = .{
632 .cpu_arch = .mips64,
633 .os_tag = .linux,
634 .abi = .gnuabin32,
635 },
636 .link_libc = true,
637 .extra_target = true,
638 },
639
640 .{
641 .target = .{
642 .cpu_arch = .mips64el,
643 .os_tag = .linux,
644 .abi = .none,
645 },
646 },
647 .{
648 .target = .{
649 .cpu_arch = .mips64el,
650 .os_tag = .linux,
651 .abi = .muslabi64,
652 },
653 .link_libc = true,
654 },
655 .{
656 .target = .{
657 .cpu_arch = .mips64el,
658 .os_tag = .linux,
659 .abi = .muslabi64,
660 },
661 .linkage = .dynamic,
662 .link_libc = true,
663 .extra_target = true,
664 },
665 .{
666 .target = .{
667 .cpu_arch = .mips64el,
668 .os_tag = .linux,
669 .abi = .muslabin32,
670 },
671 .link_libc = true,
672 .extra_target = true,
673 },
674 .{
675 .target = .{
676 .cpu_arch = .mips64el,
677 .os_tag = .linux,
678 .abi = .muslabin32,
679 },
680 .linkage = .dynamic,
681 .link_libc = true,
682 .extra_target = true,
683 },
684 .{
685 .target = .{
686 .cpu_arch = .mips64el,
687 .os_tag = .linux,
688 .abi = .gnuabi64,
689 },
690 .link_libc = true,
691 },
692 .{
693 .target = .{
694 .cpu_arch = .mips64el,
695 .os_tag = .linux,
696 .abi = .gnuabin32,
697 },
698 .link_libc = true,
699 .extra_target = true,
700 },
701
702 .{
703 .target = .{
704 .cpu_arch = .powerpc,
705 .os_tag = .linux,
706 .abi = .eabi,
707 },
708 .extra_target = true,
709 },
710 .{
711 .target = .{
712 .cpu_arch = .powerpc,
713 .os_tag = .linux,
714 .abi = .eabihf,
715 },
716 },
717 .{
718 .target = .{
719 .cpu_arch = .powerpc,
720 .os_tag = .linux,
721 .abi = .musleabi,
722 },
723 .link_libc = true,
724 .extra_target = true,
725 },
726 .{
727 .target = .{
728 .cpu_arch = .powerpc,
729 .os_tag = .linux,
730 .abi = .musleabi,
731 },
732 .linkage = .dynamic,
733 .link_libc = true,
734 // https://github.com/ziglang/zig/issues/2256
735 .skip_modules = &.{"std"},
736 .extra_target = true,
737 },
738 .{
739 .target = .{
740 .cpu_arch = .powerpc,
741 .os_tag = .linux,
742 .abi = .musleabihf,
743 },
744 .link_libc = true,
745 },
746 .{
747 .target = .{
748 .cpu_arch = .powerpc,
749 .os_tag = .linux,
750 .abi = .musleabihf,
751 },
752 .linkage = .dynamic,
753 .link_libc = true,
754 // https://github.com/ziglang/zig/issues/2256
755 .skip_modules = &.{"std"},
756 .extra_target = true,
757 },
758 .{
759 .target = .{
760 .cpu_arch = .powerpc,
761 .os_tag = .linux,
762 .abi = .gnueabi,
763 },
764 .link_libc = true,
765 // https://github.com/ziglang/zig/issues/2256
766 .skip_modules = &.{"std"},
767 .extra_target = true,
768 },
769 .{
770 .target = .{
771 .cpu_arch = .powerpc,
772 .os_tag = .linux,
773 .abi = .gnueabihf,
774 },
775 .link_libc = true,
776 // https://github.com/ziglang/zig/issues/2256
777 .skip_modules = &.{"std"},
778 },
779
780 .{
781 .target = .{
782 .cpu_arch = .powerpc64,
783 .os_tag = .linux,
784 .abi = .none,
785 },
786 },
787 .{
788 .target = .{
789 .cpu_arch = .powerpc64,
790 .os_tag = .linux,
791 .abi = .musl,
792 },
793 .link_libc = true,
794 },
795 .{
796 .target = .{
797 .cpu_arch = .powerpc64,
798 .os_tag = .linux,
799 .abi = .musl,
800 },
801 .linkage = .dynamic,
802 .link_libc = true,
803 .extra_target = true,
804 },
805 // glibc's build-many-glibcs.py currently only builds this target for ELFv1.
806 // .{
807 // .target = .{
808 // .cpu_arch = .powerpc64,
809 // .os_tag = .linux,
810 // .abi = .gnu,
811 // },
812 // .link_libc = true,
813 // },
814 .{
815 .target = .{
816 .cpu_arch = .powerpc64le,
817 .os_tag = .linux,
818 .abi = .none,
819 },
820 },
821 .{
822 .target = .{
823 .cpu_arch = .powerpc64le,
824 .os_tag = .linux,
825 .abi = .musl,
826 },
827 .link_libc = true,
828 },
829 .{
830 .target = .{
831 .cpu_arch = .powerpc64le,
832 .os_tag = .linux,
833 .abi = .musl,
834 },
835 .linkage = .dynamic,
836 .link_libc = true,
837 .extra_target = true,
838 },
839 .{
840 .target = .{
841 .cpu_arch = .powerpc64le,
842 .os_tag = .linux,
843 .abi = .gnu,
844 },
845 .link_libc = true,
846 },
847
848 .{
849 .target = .{
850 .cpu_arch = .riscv32,
851 .os_tag = .linux,
852 .abi = .none,
853 },
854 },
855 .{
856 .target = std.Target.Query.parse(.{
857 .arch_os_abi = "riscv32-linux-none",
858 .cpu_features = "baseline-d-f",
859 }) catch unreachable,
860 .extra_target = true,
861 },
862 .{
863 .target = .{
864 .cpu_arch = .riscv32,
865 .os_tag = .linux,
866 .abi = .musl,
867 },
868 .link_libc = true,
869 },
870 .{
871 .target = .{
872 .cpu_arch = .riscv32,
873 .os_tag = .linux,
874 .abi = .musl,
875 },
876 .linkage = .dynamic,
877 .link_libc = true,
878 .extra_target = true,
879 },
880 .{
881 .target = std.Target.Query.parse(.{
882 .arch_os_abi = "riscv32-linux-musl",
883 .cpu_features = "baseline-d-f",
884 }) catch unreachable,
885 .link_libc = true,
886 .extra_target = true,
887 },
888 .{
889 .target = .{
890 .cpu_arch = .riscv32,
891 .os_tag = .linux,
892 .abi = .gnu,
893 },
894 .link_libc = true,
895 },
896
897 // TODO implement codegen airFieldParentPtr
898 // TODO implement airMemmove for riscv64
899 //.{
900 // .target = std.Target.Query.parse(.{
901 // .arch_os_abi = "riscv64-linux-none",
902 // .cpu_features = "baseline+v+zbb",
903 // }) catch unreachable,
904 // .use_llvm = false,
905 // .use_lld = false,
906 //},
907 .{
908 .target = .{
909 .cpu_arch = .riscv64,
910 .os_tag = .linux,
911 .abi = .none,
912 },
913 },
914 .{
915 .target = std.Target.Query.parse(.{
916 .arch_os_abi = "riscv64-linux-none",
917 .cpu_features = "baseline-d-f",
918 }) catch unreachable,
919 .extra_target = true,
920 },
921 .{
922 .target = .{
923 .cpu_arch = .riscv64,
924 .os_tag = .linux,
925 .abi = .musl,
926 },
927 .link_libc = true,
928 },
929 .{
930 .target = .{
931 .cpu_arch = .riscv64,
932 .os_tag = .linux,
933 .abi = .musl,
934 },
935 .linkage = .dynamic,
936 .link_libc = true,
937 .extra_target = true,
938 },
939 .{
940 .target = std.Target.Query.parse(.{
941 .arch_os_abi = "riscv64-linux-musl",
942 .cpu_features = "baseline-d-f",
943 }) catch unreachable,
944 .link_libc = true,
945 .extra_target = true,
946 },
947 .{
948 .target = .{
949 .cpu_arch = .riscv64,
950 .os_tag = .linux,
951 .abi = .gnu,
952 },
953 .link_libc = true,
954 },
955
956 .{
957 .target = .{
958 .cpu_arch = .s390x,
959 .os_tag = .linux,
960 .abi = .none,
961 },
962 },
963 .{
964 .target = .{
965 .cpu_arch = .s390x,
966 .os_tag = .linux,
967 .abi = .musl,
968 },
969 .link_libc = true,
970 },
971 // Currently hangs in qemu-s390x.
972 // .{
973 // .target = .{
974 // .cpu_arch = .s390x,
975 // .os_tag = .linux,
976 // .abi = .musl,
977 // },
978 // .linkage = .dynamic,
979 // .link_libc = true,
980 // .extra_target = true,
981 // },
982 .{
983 .target = .{
984 .cpu_arch = .s390x,
985 .os_tag = .linux,
986 .abi = .gnu,
987 },
988 .link_libc = true,
989 },
990
991 // Calls are normally lowered to branch instructions that only support +/- 16 MB range when
992 // targeting Thumb. This easily becomes insufficient for our test binaries, so use long
993 // calls to avoid out-of-range relocations.
994 .{
995 .target = std.Target.Query.parse(.{
996 .arch_os_abi = "thumb-linux-eabi",
997 .cpu_features = "baseline+long_calls",
998 }) catch unreachable,
999 .pic = false, // Long calls don't work with PIC.
1000 },
1001 .{
1002 .target = std.Target.Query.parse(.{
1003 .arch_os_abi = "thumb-linux-eabihf",
1004 .cpu_features = "baseline+long_calls",
1005 }) catch unreachable,
1006 .pic = false, // Long calls don't work with PIC.
1007 },
1008 .{
1009 .target = std.Target.Query.parse(.{
1010 .arch_os_abi = "thumb-linux-musleabi",
1011 .cpu_features = "baseline+long_calls",
1012 }) catch unreachable,
1013 .link_libc = true,
1014 .pic = false, // Long calls don't work with PIC.
1015 },
1016 .{
1017 .target = std.Target.Query.parse(.{
1018 .arch_os_abi = "thumb-linux-musleabihf",
1019 .cpu_features = "baseline+long_calls",
1020 }) catch unreachable,
1021 .link_libc = true,
1022 .pic = false, // Long calls don't work with PIC.
1023 },
1024
1025 .{
1026 .target = std.Target.Query.parse(.{
1027 .arch_os_abi = "thumbeb-linux-eabi",
1028 .cpu_features = "baseline+long_calls",
1029 }) catch unreachable,
1030 .pic = false, // Long calls don't work with PIC.
1031 },
1032 .{
1033 .target = std.Target.Query.parse(.{
1034 .arch_os_abi = "thumbeb-linux-eabihf",
1035 .cpu_features = "baseline+long_calls",
1036 }) catch unreachable,
1037 .pic = false, // Long calls don't work with PIC.
1038 },
1039 .{
1040 .target = std.Target.Query.parse(.{
1041 .arch_os_abi = "thumbeb-linux-musleabi",
1042 .cpu_features = "baseline+long_calls",
1043 }) catch unreachable,
1044 .link_libc = true,
1045 .pic = false, // Long calls don't work with PIC.
1046 },
1047 .{
1048 .target = std.Target.Query.parse(.{
1049 .arch_os_abi = "thumbeb-linux-musleabihf",
1050 .cpu_features = "baseline+long_calls",
1051 }) catch unreachable,
1052 .link_libc = true,
1053 .pic = false, // Long calls don't work with PIC.
1054 },
1055
1056 .{
1057 .target = .{
1058 .cpu_arch = .x86,
1059 .os_tag = .linux,
1060 .abi = .none,
1061 },
1062 },
1063 .{
1064 .target = .{
1065 .cpu_arch = .x86,
1066 .os_tag = .linux,
1067 .abi = .musl,
1068 },
1069 .link_libc = true,
1070 },
1071 .{
1072 .target = .{
1073 .cpu_arch = .x86,
1074 .os_tag = .linux,
1075 .abi = .musl,
1076 },
1077 .linkage = .dynamic,
1078 .link_libc = true,
1079 .extra_target = true,
1080 },
1081 .{
1082 .target = .{
1083 .cpu_arch = .x86,
1084 .os_tag = .linux,
1085 .abi = .gnu,
1086 },
1087 .link_libc = true,
1088 },
1089
1090 .{
1091 .target = .{
1092 .cpu_arch = .x86_64,
1093 .os_tag = .linux,
1094 .abi = .none,
1095 },
1096 },
1097 .{
1098 .target = .{
1099 .cpu_arch = .x86_64,
1100 .cpu_model = .{ .explicit = &std.Target.x86.cpu.x86_64_v2 },
1101 .os_tag = .linux,
1102 .abi = .none,
1103 },
1104 .pic = true,
1105 },
1106 .{
1107 .target = .{
1108 .cpu_arch = .x86_64,
1109 .cpu_model = .{ .explicit = &std.Target.x86.cpu.x86_64_v3 },
1110 .os_tag = .linux,
1111 .abi = .none,
1112 },
1113 .strip = true,
1114 },
1115 .{
1116 .target = .{
1117 .cpu_arch = .x86_64,
1118 .os_tag = .linux,
1119 .abi = .none,
1120 },
1121 .use_llvm = true,
1122 .use_lld = true,
1123 },
1124 .{
1125 .target = .{
1126 .cpu_arch = .x86_64,
1127 .os_tag = .linux,
1128 .abi = .gnu,
1129 },
1130 .link_libc = true,
1131 },
1132 .{
1133 .target = .{
1134 .cpu_arch = .x86_64,
1135 .os_tag = .linux,
1136 .abi = .gnux32,
1137 },
1138 .link_libc = true,
1139 .extra_target = true,
1140 },
1141 .{
1142 .target = .{
1143 .cpu_arch = .x86_64,
1144 .os_tag = .linux,
1145 .abi = .musl,
1146 },
1147 .link_libc = true,
1148 },
1149 .{
1150 .target = .{
1151 .cpu_arch = .x86_64,
1152 .os_tag = .linux,
1153 .abi = .musl,
1154 },
1155 .linkage = .dynamic,
1156 .link_libc = true,
1157 .extra_target = true,
1158 },
1159 .{
1160 .target = .{
1161 .cpu_arch = .x86_64,
1162 .os_tag = .linux,
1163 .abi = .muslx32,
1164 },
1165 .link_libc = true,
1166 .extra_target = true,
1167 },
1168 .{
1169 .target = .{
1170 .cpu_arch = .x86_64,
1171 .os_tag = .linux,
1172 .abi = .muslx32,
1173 },
1174 .linkage = .dynamic,
1175 .link_libc = true,
1176 .extra_target = true,
1177 },
1178 .{
1179 .target = .{
1180 .cpu_arch = .x86_64,
1181 .os_tag = .linux,
1182 .abi = .musl,
1183 },
1184 .link_libc = true,
1185 .use_llvm = true,
1186 .use_lld = false,
1187 },
1188
1189 // Darwin Targets
1190
1191 .{
1192 .target = .{
1193 .cpu_arch = .aarch64,
1194 .os_tag = .maccatalyst,
1195 .abi = .none,
1196 },
1197 },
1198
1199 .{
1200 .target = .{
1201 .cpu_arch = .aarch64,
1202 .os_tag = .macos,
1203 .abi = .none,
1204 },
1205 },
1206
1207 .{
1208 .target = .{
1209 .cpu_arch = .aarch64,
1210 .os_tag = .macos,
1211 .abi = .none,
1212 },
1213 .use_llvm = false,
1214 .use_lld = false,
1215 .optimize_mode = .ReleaseFast,
1216 .strip = true,
1217 },
1218
1219 .{
1220 .target = .{
1221 .cpu_arch = .x86_64,
1222 .os_tag = .maccatalyst,
1223 .abi = .none,
1224 },
1225 },
1226
1227 .{
1228 .target = .{
1229 .cpu_arch = .x86_64,
1230 .os_tag = .macos,
1231 .abi = .none,
1232 },
1233 .use_llvm = false,
1234 },
1235 .{
1236 .target = .{
1237 .cpu_arch = .x86_64,
1238 .os_tag = .macos,
1239 .abi = .none,
1240 },
1241 },
1242
1243 // NetBSD Targets
1244
1245 .{
1246 .target = .{
1247 .cpu_arch = .aarch64,
1248 .os_tag = .netbsd,
1249 .abi = .none,
1250 },
1251 .link_libc = true,
1252 },
1253
1254 .{
1255 .target = .{
1256 .cpu_arch = .aarch64_be,
1257 .os_tag = .netbsd,
1258 .abi = .none,
1259 },
1260 .link_libc = true,
1261 },
1262
1263 .{
1264 .target = .{
1265 .cpu_arch = .arm,
1266 .os_tag = .netbsd,
1267 .abi = .eabi,
1268 },
1269 .link_libc = true,
1270 },
1271 .{
1272 .target = .{
1273 .cpu_arch = .arm,
1274 .os_tag = .netbsd,
1275 .abi = .eabihf,
1276 },
1277 .link_libc = true,
1278 },
1279
1280 .{
1281 .target = .{
1282 .cpu_arch = .armeb,
1283 .os_tag = .netbsd,
1284 .abi = .eabi,
1285 },
1286 .link_libc = true,
1287 },
1288 .{
1289 .target = .{
1290 .cpu_arch = .armeb,
1291 .os_tag = .netbsd,
1292 .abi = .eabihf,
1293 },
1294 .link_libc = true,
1295 },
1296
1297 .{
1298 .target = .{
1299 .cpu_arch = .mips,
1300 .os_tag = .netbsd,
1301 .abi = .eabi,
1302 },
1303 .link_libc = true,
1304 },
1305 .{
1306 .target = .{
1307 .cpu_arch = .mips,
1308 .os_tag = .netbsd,
1309 .abi = .eabihf,
1310 },
1311 .link_libc = true,
1312 },
1313
1314 .{
1315 .target = .{
1316 .cpu_arch = .mipsel,
1317 .os_tag = .netbsd,
1318 .abi = .eabi,
1319 },
1320 .link_libc = true,
1321 },
1322 .{
1323 .target = .{
1324 .cpu_arch = .mipsel,
1325 .os_tag = .netbsd,
1326 .abi = .eabihf,
1327 },
1328 .link_libc = true,
1329 },
1330
1331 .{
1332 .target = .{
1333 .cpu_arch = .powerpc,
1334 .os_tag = .netbsd,
1335 .abi = .eabi,
1336 },
1337 .link_libc = true,
1338 .extra_target = true,
1339 },
1340 .{
1341 .target = .{
1342 .cpu_arch = .powerpc,
1343 .os_tag = .netbsd,
1344 .abi = .eabihf,
1345 },
1346 .link_libc = true,
1347 },
1348
1349 .{
1350 .target = .{
1351 .cpu_arch = .x86,
1352 .os_tag = .netbsd,
1353 .abi = .none,
1354 },
1355 .link_libc = true,
1356 },
1357
1358 .{
1359 .target = .{
1360 .cpu_arch = .x86_64,
1361 .os_tag = .netbsd,
1362 .abi = .none,
1363 },
1364 .link_libc = true,
1365 },
1366
1367 // SPIR-V Targets
1368
1369 // Disabled due to no active maintainer (feel free to fix the failures
1370 // and then re-enable at any time). The failures occur due to changing AIR
1371 // from the frontend, and backend being incomplete.
1372 //.{
1373 // .target = std.Target.Query.parse(.{
1374 // .arch_os_abi = "spirv64-vulkan",
1375 // .cpu_features = "vulkan_v1_2+float16+float64",
1376 // }) catch unreachable,
1377 // .use_llvm = false,
1378 // .use_lld = false,
1379 // .skip_modules = &.{ "c-import", "zigc", "std" },
1380 //},
1381
1382 // WASI Targets
1383
1384 // Disabled due to no active maintainer (feel free to fix the failures
1385 // and then re-enable at any time). The failures occur due to backend
1386 // miscompilation of different AIR from the frontend.
1387 //.{
1388 // .target = .{
1389 // .cpu_arch = .wasm32,
1390 // .os_tag = .wasi,
1391 // .abi = .none,
1392 // },
1393 // .use_llvm = false,
1394 // .use_lld = false,
1395 //},
1396 .{
1397 .target = .{
1398 .cpu_arch = .wasm32,
1399 .os_tag = .wasi,
1400 .abi = .none,
1401 },
1402 },
1403 .{
1404 .target = .{
1405 .cpu_arch = .wasm32,
1406 .os_tag = .wasi,
1407 .abi = .musl,
1408 },
1409 .link_libc = true,
1410 },
1411
1412 // Windows Targets
1413
1414 .{
1415 .target = .{
1416 .cpu_arch = .aarch64,
1417 .os_tag = .windows,
1418 .abi = .msvc,
1419 },
1420 },
1421 .{
1422 .target = .{
1423 .cpu_arch = .aarch64,
1424 .os_tag = .windows,
1425 .abi = .msvc,
1426 },
1427 .link_libc = true,
1428 },
1429 .{
1430 .target = .{
1431 .cpu_arch = .aarch64,
1432 .os_tag = .windows,
1433 .abi = .gnu,
1434 },
1435 },
1436 .{
1437 .target = .{
1438 .cpu_arch = .aarch64,
1439 .os_tag = .windows,
1440 .abi = .gnu,
1441 },
1442 .link_libc = true,
1443 },
1444
1445 .{
1446 .target = .{
1447 .cpu_arch = .thumb,
1448 .os_tag = .windows,
1449 .abi = .msvc,
1450 },
1451 },
1452 .{
1453 .target = .{
1454 .cpu_arch = .thumb,
1455 .os_tag = .windows,
1456 .abi = .msvc,
1457 },
1458 .link_libc = true,
1459 },
1460 // https://github.com/ziglang/zig/issues/24016
1461 // .{
1462 // .target = .{
1463 // .cpu_arch = .thumb,
1464 // .os_tag = .windows,
1465 // .abi = .gnu,
1466 // },
1467 // },
1468 // .{
1469 // .target = .{
1470 // .cpu_arch = .thumb,
1471 // .os_tag = .windows,
1472 // .abi = .gnu,
1473 // },
1474 // .link_libc = true,
1475 // },
1476
1477 .{
1478 .target = .{
1479 .cpu_arch = .x86,
1480 .os_tag = .windows,
1481 .abi = .msvc,
1482 },
1483 },
1484 .{
1485 .target = .{
1486 .cpu_arch = .x86,
1487 .os_tag = .windows,
1488 .abi = .msvc,
1489 },
1490 .link_libc = true,
1491 },
1492 .{
1493 .target = .{
1494 .cpu_arch = .x86,
1495 .os_tag = .windows,
1496 .abi = .gnu,
1497 },
1498 },
1499 .{
1500 .target = .{
1501 .cpu_arch = .x86,
1502 .os_tag = .windows,
1503 .abi = .gnu,
1504 },
1505 .link_libc = true,
1506 },
1507
1508 .{
1509 .target = .{
1510 .cpu_arch = .x86_64,
1511 .os_tag = .windows,
1512 .abi = .msvc,
1513 },
1514 .use_llvm = false,
1515 .use_lld = false,
1516 },
1517 .{
1518 .target = .{
1519 .cpu_arch = .x86_64,
1520 .os_tag = .windows,
1521 .abi = .msvc,
1522 },
1523 },
1524 .{
1525 .target = .{
1526 .cpu_arch = .x86_64,
1527 .os_tag = .windows,
1528 .abi = .msvc,
1529 },
1530 .link_libc = true,
1531 },
1532 .{
1533 .target = .{
1534 .cpu_arch = .x86_64,
1535 .os_tag = .windows,
1536 .abi = .gnu,
1537 },
1538 .use_llvm = false,
1539 .use_lld = false,
1540 },
1541 .{
1542 .target = .{
1543 .cpu_arch = .x86_64,
1544 .os_tag = .windows,
1545 .abi = .gnu,
1546 },
1547 },
1548 .{
1549 .target = .{
1550 .cpu_arch = .x86_64,
1551 .os_tag = .windows,
1552 .abi = .gnu,
1553 },
1554 .link_libc = true,
1555 },
1556 };
1557};
1558
1559const CAbiTarget = struct {
1560 target: std.Target.Query = .{},
1561 use_llvm: ?bool = null,
1562 use_lld: ?bool = null,
1563 pic: ?bool = null,
1564 strip: ?bool = null,
1565 c_defines: []const []const u8 = &.{},
1566};
1567
1568const c_abi_targets = blk: {
1569 @setEvalBranchQuota(30000);
1570 break :blk [_]CAbiTarget{
1571 // Native Targets
1572
1573 .{
1574 .use_llvm = true,
1575 },
1576
1577 // Linux Targets
1578
1579 .{
1580 .target = .{
1581 .cpu_arch = .aarch64,
1582 .os_tag = .linux,
1583 .abi = .musl,
1584 },
1585 },
1586
1587 .{
1588 .target = .{
1589 .cpu_arch = .aarch64_be,
1590 .os_tag = .linux,
1591 .abi = .musl,
1592 },
1593 },
1594
1595 .{
1596 .target = .{
1597 .cpu_arch = .arm,
1598 .os_tag = .linux,
1599 .abi = .musleabi,
1600 },
1601 },
1602 .{
1603 .target = .{
1604 .cpu_arch = .arm,
1605 .os_tag = .linux,
1606 .abi = .musleabihf,
1607 },
1608 },
1609
1610 .{
1611 .target = .{
1612 .cpu_arch = .armeb,
1613 .os_tag = .linux,
1614 .abi = .musleabi,
1615 },
1616 },
1617 .{
1618 .target = .{
1619 .cpu_arch = .armeb,
1620 .os_tag = .linux,
1621 .abi = .musleabihf,
1622 },
1623 },
1624
1625 .{
1626 .target = .{
1627 .cpu_arch = .hexagon,
1628 .os_tag = .linux,
1629 .abi = .musl,
1630 },
1631 },
1632
1633 .{
1634 .target = .{
1635 .cpu_arch = .loongarch64,
1636 .os_tag = .linux,
1637 .abi = .musl,
1638 },
1639 },
1640
1641 .{
1642 .target = .{
1643 .cpu_arch = .mips,
1644 .os_tag = .linux,
1645 .abi = .musleabi,
1646 },
1647 },
1648 .{
1649 .target = .{
1650 .cpu_arch = .mips,
1651 .os_tag = .linux,
1652 .abi = .musleabihf,
1653 },
1654 },
1655
1656 .{
1657 .target = .{
1658 .cpu_arch = .mipsel,
1659 .os_tag = .linux,
1660 .abi = .musleabi,
1661 },
1662 },
1663 .{
1664 .target = .{
1665 .cpu_arch = .mipsel,
1666 .os_tag = .linux,
1667 .abi = .musleabihf,
1668 },
1669 },
1670
1671 .{
1672 .target = .{
1673 .cpu_arch = .mips64,
1674 .os_tag = .linux,
1675 .abi = .muslabi64,
1676 },
1677 },
1678 .{
1679 .target = .{
1680 .cpu_arch = .mips64,
1681 .os_tag = .linux,
1682 .abi = .muslabin32,
1683 },
1684 },
1685
1686 .{
1687 .target = .{
1688 .cpu_arch = .mips64el,
1689 .os_tag = .linux,
1690 .abi = .muslabi64,
1691 },
1692 },
1693 .{
1694 .target = .{
1695 .cpu_arch = .mips64el,
1696 .os_tag = .linux,
1697 .abi = .muslabin32,
1698 },
1699 },
1700
1701 .{
1702 .target = .{
1703 .cpu_arch = .powerpc,
1704 .os_tag = .linux,
1705 .abi = .musleabi,
1706 },
1707 },
1708 .{
1709 .target = .{
1710 .cpu_arch = .powerpc,
1711 .os_tag = .linux,
1712 .abi = .musleabihf,
1713 },
1714 },
1715
1716 .{
1717 .target = .{
1718 .cpu_arch = .powerpc64,
1719 .os_tag = .linux,
1720 .abi = .musl,
1721 },
1722 },
1723 .{
1724 .target = .{
1725 .cpu_arch = .powerpc64le,
1726 .os_tag = .linux,
1727 .abi = .musl,
1728 },
1729 },
1730
1731 .{
1732 .target = std.Target.Query.parse(.{
1733 .arch_os_abi = "riscv32-linux-musl",
1734 .cpu_features = "baseline-d-f",
1735 }) catch unreachable,
1736 },
1737 .{
1738 .target = .{
1739 .cpu_arch = .riscv32,
1740 .os_tag = .linux,
1741 .abi = .musl,
1742 },
1743 },
1744
1745 .{
1746 .target = std.Target.Query.parse(.{
1747 .arch_os_abi = "riscv64-linux-musl",
1748 .cpu_features = "baseline-d-f",
1749 }) catch unreachable,
1750 },
1751 .{
1752 .target = .{
1753 .cpu_arch = .riscv64,
1754 .os_tag = .linux,
1755 .abi = .musl,
1756 },
1757 },
1758
1759 .{
1760 .target = .{
1761 .cpu_arch = .s390x,
1762 .os_tag = .linux,
1763 .abi = .musl,
1764 },
1765 },
1766
1767 .{
1768 .target = std.Target.Query.parse(.{
1769 .arch_os_abi = "thumb-linux-musleabi",
1770 .cpu_features = "baseline+long_calls",
1771 }) catch unreachable,
1772 .pic = false, // Long calls don't work with PIC.
1773 },
1774 .{
1775 .target = std.Target.Query.parse(.{
1776 .arch_os_abi = "thumb-linux-musleabihf",
1777 .cpu_features = "baseline+long_calls",
1778 }) catch unreachable,
1779 .pic = false, // Long calls don't work with PIC.
1780 },
1781
1782 .{
1783 .target = std.Target.Query.parse(.{
1784 .arch_os_abi = "thumbeb-linux-musleabi",
1785 .cpu_features = "baseline+long_calls",
1786 }) catch unreachable,
1787 .pic = false, // Long calls don't work with PIC.
1788 },
1789 .{
1790 .target = std.Target.Query.parse(.{
1791 .arch_os_abi = "thumbeb-linux-musleabihf",
1792 .cpu_features = "baseline+long_calls",
1793 }) catch unreachable,
1794 .pic = false, // Long calls don't work with PIC.
1795 },
1796
1797 .{
1798 .target = .{
1799 .cpu_arch = .x86,
1800 .os_tag = .linux,
1801 .abi = .musl,
1802 },
1803 },
1804
1805 .{
1806 .target = .{
1807 .cpu_arch = .x86_64,
1808 .os_tag = .linux,
1809 .abi = .musl,
1810 },
1811 .use_llvm = false,
1812 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
1813 },
1814 .{
1815 .target = .{
1816 .cpu_arch = .x86_64,
1817 .cpu_model = .{ .explicit = &std.Target.x86.cpu.x86_64_v2 },
1818 .os_tag = .linux,
1819 .abi = .musl,
1820 },
1821 .use_llvm = false,
1822 .strip = true,
1823 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
1824 },
1825 .{
1826 .target = .{
1827 .cpu_arch = .x86_64,
1828 .cpu_model = .{ .explicit = &std.Target.x86.cpu.x86_64_v3 },
1829 .os_tag = .linux,
1830 .abi = .musl,
1831 },
1832 .use_llvm = false,
1833 .pic = true,
1834 .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
1835 },
1836 .{
1837 .target = .{
1838 .cpu_arch = .x86_64,
1839 .os_tag = .linux,
1840 .abi = .musl,
1841 },
1842 .use_llvm = true,
1843 },
1844 .{
1845 .target = .{
1846 .cpu_arch = .x86_64,
1847 .os_tag = .linux,
1848 .abi = .muslx32,
1849 },
1850 },
1851
1852 // WASI Targets
1853
1854 .{
1855 .target = .{
1856 .cpu_arch = .wasm32,
1857 .os_tag = .wasi,
1858 .abi = .musl,
1859 },
1860 },
1861
1862 // Windows Targets
1863
1864 .{
1865 .target = .{
1866 .cpu_arch = .x86,
1867 .os_tag = .windows,
1868 .abi = .gnu,
1869 },
1870 },
1871 .{
1872 .target = .{
1873 .cpu_arch = .x86_64,
1874 .os_tag = .windows,
1875 .abi = .gnu,
1876 },
1877 },
1878 };
1879};
1880
1881/// For stack trace tests, we only test native, because external executors are pretty unreliable at
1882/// stack tracing. However, if there's a 32-bit equivalent target which the host can trivially run,
1883/// we may as well at least test that!
1884fn nativeAndCompatible32bit(b: *std.Build, skip_non_native: bool) []const std.Build.ResolvedTarget {
1885 const host = b.graph.host.result;
1886 const only_native = (&b.graph.host)[0..1];
1887 if (skip_non_native) return only_native;
1888 const arch32: std.Target.Cpu.Arch = switch (host.os.tag) {
1889 .windows => switch (host.cpu.arch) {
1890 .x86_64 => .x86,
1891 .aarch64 => .thumb,
1892 .aarch64_be => .thumbeb,
1893 else => return only_native,
1894 },
1895 .freebsd => switch (host.cpu.arch) {
1896 .aarch64 => .arm,
1897 .aarch64_be => .armeb,
1898 else => return only_native,
1899 },
1900 .linux, .netbsd => switch (host.cpu.arch) {
1901 .x86_64 => .x86,
1902 .aarch64 => .arm,
1903 .aarch64_be => .armeb,
1904 else => return only_native,
1905 },
1906 else => return only_native,
1907 };
1908 return b.graph.arena.dupe(std.Build.ResolvedTarget, &.{
1909 b.graph.host,
1910 b.resolveTargetQuery(.{ .cpu_arch = arch32, .os_tag = host.os.tag }),
1911 }) catch @panic("OOM");
1912}
1913
1914pub fn addStackTraceTests(
1915 b: *std.Build,
1916 test_filters: []const []const u8,
1917 skip_non_native: bool,
1918) *Step {
1919 const convert_exe = b.addExecutable(.{
1920 .name = "convert-stack-trace",
1921 .root_module = b.createModule(.{
1922 .root_source_file = b.path("test/src/convert-stack-trace.zig"),
1923 .target = b.graph.host,
1924 .optimize = .Debug,
1925 }),
1926 });
1927
1928 const cases = b.allocator.create(StackTracesContext) catch @panic("OOM");
1929
1930 cases.* = .{
1931 .b = b,
1932 .step = b.step("test-stack-traces", "Run the stack trace tests"),
1933 .test_filters = test_filters,
1934 .targets = nativeAndCompatible32bit(b, skip_non_native),
1935 .convert_exe = convert_exe,
1936 };
1937
1938 stack_traces.addCases(cases);
1939
1940 return cases.step;
1941}
1942
1943pub fn addErrorTraceTests(
1944 b: *std.Build,
1945 test_filters: []const []const u8,
1946 optimize_modes: []const OptimizeMode,
1947 skip_non_native: bool,
1948) *Step {
1949 const convert_exe = b.addExecutable(.{
1950 .name = "convert-stack-trace",
1951 .root_module = b.createModule(.{
1952 .root_source_file = b.path("test/src/convert-stack-trace.zig"),
1953 .target = b.graph.host,
1954 .optimize = .Debug,
1955 }),
1956 });
1957
1958 const cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM");
1959 cases.* = .{
1960 .b = b,
1961 .step = b.step("test-error-traces", "Run the error trace tests"),
1962 .test_filters = test_filters,
1963 .targets = nativeAndCompatible32bit(b, skip_non_native),
1964 .optimize_modes = optimize_modes,
1965 .convert_exe = convert_exe,
1966 };
1967
1968 error_traces.addCases(cases);
1969
1970 return cases.step;
1971}
1972
1973fn compilerHasPackageManager(b: *std.Build) bool {
1974 // We can only use dependencies if the compiler was built with support for package management.
1975 // (zig2 doesn't support it, but we still need to construct a build graph to build stage3.)
1976 return b.available_deps.len != 0;
1977}
1978
1979pub fn addStandaloneTests(
1980 b: *std.Build,
1981 optimize_modes: []const OptimizeMode,
1982 enable_macos_sdk: bool,
1983 enable_ios_sdk: bool,
1984 enable_symlinks_windows: bool,
1985) *Step {
1986 const step = b.step("test-standalone", "Run the standalone tests");
1987 if (compilerHasPackageManager(b)) {
1988 const test_cases_dep_name = "standalone_test_cases";
1989 const test_cases_dep = b.dependency(test_cases_dep_name, .{
1990 .enable_ios_sdk = enable_ios_sdk,
1991 .enable_macos_sdk = enable_macos_sdk,
1992 .enable_symlinks_windows = enable_symlinks_windows,
1993 .simple_skip_debug = mem.indexOfScalar(OptimizeMode, optimize_modes, .Debug) == null,
1994 .simple_skip_release_safe = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseSafe) == null,
1995 .simple_skip_release_fast = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseFast) == null,
1996 .simple_skip_release_small = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseSmall) == null,
1997 });
1998 const test_cases_dep_step = test_cases_dep.builder.default_step;
1999 test_cases_dep_step.name = b.dupe(test_cases_dep_name);
2000 step.dependOn(test_cases_dep.builder.default_step);
2001 }
2002 return step;
2003}
2004
2005pub fn addLinkTests(
2006 b: *std.Build,
2007 enable_macos_sdk: bool,
2008 enable_ios_sdk: bool,
2009 enable_symlinks_windows: bool,
2010) *Step {
2011 const step = b.step("test-link", "Run the linker tests");
2012 if (compilerHasPackageManager(b)) {
2013 const test_cases_dep_name = "link_test_cases";
2014 const test_cases_dep = b.dependency(test_cases_dep_name, .{
2015 .enable_ios_sdk = enable_ios_sdk,
2016 .enable_macos_sdk = enable_macos_sdk,
2017 .enable_symlinks_windows = enable_symlinks_windows,
2018 });
2019 const test_cases_dep_step = test_cases_dep.builder.default_step;
2020 test_cases_dep_step.name = b.dupe(test_cases_dep_name);
2021 step.dependOn(test_cases_dep.builder.default_step);
2022 }
2023 return step;
2024}
2025
2026pub fn addCliTests(b: *std.Build) *Step {
2027 const step = b.step("test-cli", "Test the command line interface");
2028 const s = std.fs.path.sep_str;
2029
2030 {
2031 // Test `zig init`.
2032 const tmp_path = b.makeTempPath();
2033 const init_exe = b.addSystemCommand(&.{ b.graph.zig_exe, "init" });
2034 init_exe.setCwd(.{ .cwd_relative = tmp_path });
2035 init_exe.setName("zig init");
2036 init_exe.expectStdOutEqual("");
2037 init_exe.expectStdErrEqual("info: created build.zig\n" ++
2038 "info: created build.zig.zon\n" ++
2039 "info: created src" ++ s ++ "main.zig\n" ++
2040 "info: created src" ++ s ++ "root.zig\n" ++
2041 "info: see `zig build --help` for a menu of options\n");
2042
2043 // Test missing output path.
2044 const bad_out_arg = "-femit-bin=does" ++ s ++ "not" ++ s ++ "exist" ++ s ++ "foo.exe";
2045 const ok_src_arg = "src" ++ s ++ "main.zig";
2046 const expected = "error: unable to open output directory 'does" ++ s ++ "not" ++ s ++ "exist': FileNotFound\n";
2047 const run_bad = b.addSystemCommand(&.{ b.graph.zig_exe, "build-exe", ok_src_arg, bad_out_arg });
2048 run_bad.setName("zig build-exe error message for bad -femit-bin arg");
2049 run_bad.expectExitCode(1);
2050 run_bad.expectStdErrEqual(expected);
2051 run_bad.expectStdOutEqual("");
2052 run_bad.step.dependOn(&init_exe.step);
2053
2054 const run_test = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "test" });
2055 run_test.setCwd(.{ .cwd_relative = tmp_path });
2056 run_test.setName("zig build test");
2057 run_test.expectStdOutEqual("");
2058 run_test.step.dependOn(&init_exe.step);
2059
2060 const run_run = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "run" });
2061 run_run.setCwd(.{ .cwd_relative = tmp_path });
2062 run_run.setName("zig build run");
2063 run_run.expectStdOutEqual("Run `zig build test` to run the tests.\n");
2064 run_run.expectStdErrEqual("All your codebase are belong to us.\n");
2065 run_run.step.dependOn(&init_exe.step);
2066
2067 const cleanup = b.addRemoveDirTree(.{ .cwd_relative = tmp_path });
2068 cleanup.step.dependOn(&run_test.step);
2069 cleanup.step.dependOn(&run_run.step);
2070 cleanup.step.dependOn(&run_bad.step);
2071
2072 step.dependOn(&cleanup.step);
2073 }
2074
2075 {
2076 // Test `zig init -m`.
2077 const tmp_path = b.makeTempPath();
2078 const init_exe = b.addSystemCommand(&.{ b.graph.zig_exe, "init", "-m" });
2079 init_exe.setCwd(.{ .cwd_relative = tmp_path });
2080 init_exe.setName("zig init -m");
2081 init_exe.expectStdOutEqual("");
2082 init_exe.expectStdErrEqual("info: successfully populated 'build.zig.zon' and 'build.zig'\n");
2083 }
2084
2085 // Test Godbolt API
2086 if (builtin.os.tag == .linux and builtin.cpu.arch == .x86_64) {
2087 const tmp_path = b.makeTempPath();
2088
2089 const example_zig = b.addWriteFiles().add("example.zig",
2090 \\// Type your code here, or load an example.
2091 \\export fn square(num: i32) i32 {
2092 \\ return num * num;
2093 \\}
2094 \\extern fn zig_panic() noreturn;
2095 \\pub fn panic(msg: []const u8, error_return_trace: ?*@import("std").builtin.StackTrace, _: ?usize) noreturn {
2096 \\ _ = msg;
2097 \\ _ = error_return_trace;
2098 \\ zig_panic();
2099 \\}
2100 );
2101
2102 // This is intended to be the exact CLI usage used by godbolt.org.
2103 const run = b.addSystemCommand(&.{
2104 b.graph.zig_exe, "build-obj",
2105 "--cache-dir", tmp_path,
2106 "--name", "example",
2107 "-fno-emit-bin", "-fno-emit-h",
2108 "-fstrip", "-OReleaseFast",
2109 });
2110 run.addFileArg(example_zig);
2111 const example_s = run.addPrefixedOutputFileArg("-femit-asm=", "example.s");
2112
2113 const checkfile = b.addCheckFile(example_s, .{
2114 .expected_matches = &.{
2115 "square:",
2116 "mov\teax, edi",
2117 "imul\teax, edi",
2118 },
2119 });
2120 checkfile.setName("check godbolt.org CLI usage generating valid asm");
2121
2122 const cleanup = b.addRemoveDirTree(.{ .cwd_relative = tmp_path });
2123 cleanup.step.dependOn(&checkfile.step);
2124
2125 step.dependOn(&cleanup.step);
2126 }
2127
2128 {
2129 // Test `zig fmt`.
2130 // This test must use a temporary directory rather than a cache
2131 // directory because this test will be mutating the files. The cache
2132 // system relies on cache directories being mutated only by their
2133 // owners.
2134 const tmp_path = b.makeTempPath();
2135 const unformatted_code = " // no reason for indent";
2136
2137 var dir = std.fs.cwd().openDir(tmp_path, .{}) catch @panic("unhandled");
2138 defer dir.close();
2139 dir.writeFile(.{ .sub_path = "fmt1.zig", .data = unformatted_code }) catch @panic("unhandled");
2140 dir.writeFile(.{ .sub_path = "fmt2.zig", .data = unformatted_code }) catch @panic("unhandled");
2141 dir.makeDir("subdir") catch @panic("unhandled");
2142 var subdir = dir.openDir("subdir", .{}) catch @panic("unhandled");
2143 defer subdir.close();
2144 subdir.writeFile(.{ .sub_path = "fmt3.zig", .data = unformatted_code }) catch @panic("unhandled");
2145
2146 // Test zig fmt affecting only the appropriate files.
2147 const run1 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "fmt1.zig" });
2148 run1.setName("run zig fmt one file");
2149 run1.setCwd(.{ .cwd_relative = tmp_path });
2150 run1.has_side_effects = true;
2151 // stdout should be file path + \n
2152 run1.expectStdOutEqual("fmt1.zig\n");
2153
2154 // Test excluding files and directories from a run
2155 const run2 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "subdir", "." });
2156 run2.setName("run zig fmt on directory with exclusions");
2157 run2.setCwd(.{ .cwd_relative = tmp_path });
2158 run2.has_side_effects = true;
2159 run2.expectStdOutEqual("");
2160 run2.step.dependOn(&run1.step);
2161
2162 // Test excluding non-existent file
2163 const run3 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "nonexistent.zig", "." });
2164 run3.setName("run zig fmt on directory with non-existent exclusion");
2165 run3.setCwd(.{ .cwd_relative = tmp_path });
2166 run3.has_side_effects = true;
2167 run3.expectStdOutEqual("." ++ s ++ "subdir" ++ s ++ "fmt3.zig\n");
2168 run3.step.dependOn(&run2.step);
2169
2170 // running it on the dir, only the new file should be changed
2171 const run4 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." });
2172 run4.setName("run zig fmt the directory");
2173 run4.setCwd(.{ .cwd_relative = tmp_path });
2174 run4.has_side_effects = true;
2175 run4.expectStdOutEqual("." ++ s ++ "fmt2.zig\n");
2176 run4.step.dependOn(&run3.step);
2177
2178 // both files have been formatted, nothing should change now
2179 const run5 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." });
2180 run5.setName("run zig fmt with nothing to do");
2181 run5.setCwd(.{ .cwd_relative = tmp_path });
2182 run5.has_side_effects = true;
2183 run5.expectStdOutEqual("");
2184 run5.step.dependOn(&run4.step);
2185
2186 const unformatted_code_utf16 = "\xff\xfe \x00 \x00 \x00 \x00/\x00/\x00 \x00n\x00o\x00 \x00r\x00e\x00a\x00s\x00o\x00n\x00";
2187 const fmt6_path = b.pathJoin(&.{ tmp_path, "fmt6.zig" });
2188 const write6 = b.addUpdateSourceFiles();
2189 write6.addBytesToSource(unformatted_code_utf16, fmt6_path);
2190 write6.step.dependOn(&run5.step);
2191
2192 // Test `zig fmt` handling UTF-16 decoding.
2193 const run6 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." });
2194 run6.setName("run zig fmt convert UTF-16 to UTF-8");
2195 run6.setCwd(.{ .cwd_relative = tmp_path });
2196 run6.has_side_effects = true;
2197 run6.expectStdOutEqual("." ++ s ++ "fmt6.zig\n");
2198 run6.step.dependOn(&write6.step);
2199
2200 // TODO change this to an exact match
2201 const check6 = b.addCheckFile(.{ .cwd_relative = fmt6_path }, .{
2202 .expected_matches = &.{
2203 "// no reason",
2204 },
2205 });
2206 check6.step.dependOn(&run6.step);
2207
2208 const cleanup = b.addRemoveDirTree(.{ .cwd_relative = tmp_path });
2209 cleanup.step.dependOn(&check6.step);
2210
2211 step.dependOn(&cleanup.step);
2212 }
2213
2214 {
2215 const run_test = b.addSystemCommand(&.{
2216 b.graph.zig_exe,
2217 "build",
2218 "test",
2219 "-Dbool_true",
2220 "-Dbool_false=false",
2221 "-Dint=1234",
2222 "-De=two",
2223 "-Dstring=hello",
2224 });
2225 run_test.addArg("--build-file");
2226 run_test.addFileArg(b.path("test/cli/options/build.zig"));
2227 run_test.addArg("--cache-dir");
2228 run_test.addFileArg(.{ .cwd_relative = b.cache_root.join(b.allocator, &.{}) catch @panic("OOM") });
2229 run_test.setName("test build options");
2230
2231 step.dependOn(&run_test.step);
2232 }
2233
2234 return step;
2235}
2236
2237const ModuleTestOptions = struct {
2238 test_filters: []const []const u8,
2239 test_target_filters: []const []const u8,
2240 test_extra_targets: bool,
2241 root_src: []const u8,
2242 name: []const u8,
2243 desc: []const u8,
2244 optimize_modes: []const OptimizeMode,
2245 include_paths: []const []const u8,
2246 test_default_only: bool,
2247 skip_single_threaded: bool,
2248 skip_non_native: bool,
2249 skip_freebsd: bool,
2250 skip_netbsd: bool,
2251 skip_windows: bool,
2252 skip_darwin: bool,
2253 skip_linux: bool,
2254 skip_llvm: bool,
2255 skip_libc: bool,
2256 max_rss: usize = 0,
2257 no_builtin: bool = false,
2258 build_options: ?*Step.Options = null,
2259};
2260
2261pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
2262 const step = b.step(b.fmt("test-{s}", .{options.name}), options.desc);
2263
2264 if (options.test_default_only) {
2265 const test_target = &test_targets[0];
2266 const resolved_target = b.resolveTargetQuery(test_target.target);
2267 const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM");
2268 addOneModuleTest(b, step, test_target, &resolved_target, triple_txt, options);
2269 return step;
2270 }
2271
2272 for_targets: for (&test_targets) |*test_target| {
2273 if (test_target.skip_modules.len > 0) {
2274 for (test_target.skip_modules) |skip_mod| {
2275 if (std.mem.eql(u8, options.name, skip_mod)) continue :for_targets;
2276 }
2277 }
2278
2279 if (!options.test_extra_targets and test_target.extra_target) continue;
2280
2281 if (options.skip_non_native and !test_target.target.isNative())
2282 continue;
2283
2284 if (options.skip_freebsd and test_target.target.os_tag == .freebsd) continue;
2285 if (options.skip_netbsd and test_target.target.os_tag == .netbsd) continue;
2286 if (options.skip_windows and test_target.target.os_tag == .windows) continue;
2287 if (options.skip_darwin and test_target.target.os_tag != null and test_target.target.os_tag.?.isDarwin()) continue;
2288 if (options.skip_linux and test_target.target.os_tag == .linux) continue;
2289
2290 const would_use_llvm = wouldUseLlvm(test_target.use_llvm, test_target.target, test_target.optimize_mode);
2291 if (options.skip_llvm and would_use_llvm) continue;
2292
2293 const resolved_target = b.resolveTargetQuery(test_target.target);
2294 const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM");
2295 const target = &resolved_target.result;
2296
2297 if (options.test_target_filters.len > 0) {
2298 for (options.test_target_filters) |filter| {
2299 if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
2300 } else continue;
2301 }
2302
2303 if (options.skip_libc and test_target.link_libc == true)
2304 continue;
2305
2306 // We can't provide MSVC libc when cross-compiling.
2307 if (target.abi == .msvc and test_target.link_libc == true and builtin.os.tag != .windows)
2308 continue;
2309
2310 if (options.skip_single_threaded and test_target.single_threaded == true)
2311 continue;
2312
2313 if (!would_use_llvm and target.cpu.arch == .aarch64) {
2314 // TODO get std tests passing for the aarch64 self-hosted backend.
2315 if (mem.eql(u8, options.name, "std")) continue;
2316 // TODO get zigc tests passing for the aarch64 self-hosted backend.
2317 if (mem.eql(u8, options.name, "zigc")) continue;
2318 }
2319
2320 const want_this_mode = for (options.optimize_modes) |m| {
2321 if (m == test_target.optimize_mode) break true;
2322 } else false;
2323 if (!want_this_mode) continue;
2324
2325 addOneModuleTest(b, step, test_target, &resolved_target, triple_txt, options);
2326 }
2327 return step;
2328}
2329
2330fn addOneModuleTest(
2331 b: *std.Build,
2332 step: *Step,
2333 test_target: *const TestTarget,
2334 resolved_target: *const std.Build.ResolvedTarget,
2335 triple_txt: []const u8,
2336 options: ModuleTestOptions,
2337) void {
2338 const target = &resolved_target.result;
2339 const libc_suffix = if (test_target.link_libc == true) "-libc" else "";
2340 const model_txt = target.cpu.model.name;
2341
2342 // wasm32-wasi builds need more RAM, idk why
2343 const max_rss = if (target.os.tag == .wasi)
2344 options.max_rss * 2
2345 else
2346 options.max_rss;
2347
2348 const these_tests = b.addTest(.{
2349 .root_module = b.createModule(.{
2350 .root_source_file = b.path(options.root_src),
2351 .optimize = test_target.optimize_mode,
2352 .target = resolved_target.*,
2353 .link_libc = test_target.link_libc,
2354 .pic = test_target.pic,
2355 .strip = test_target.strip,
2356 .single_threaded = test_target.single_threaded,
2357 }),
2358 .max_rss = max_rss,
2359 .filters = options.test_filters,
2360 .use_llvm = test_target.use_llvm,
2361 .use_lld = test_target.use_lld,
2362 .zig_lib_dir = b.path("lib"),
2363 });
2364 these_tests.linkage = test_target.linkage;
2365 if (options.no_builtin) these_tests.root_module.no_builtin = false;
2366 if (options.build_options) |build_options| {
2367 these_tests.root_module.addOptions("build_options", build_options);
2368 }
2369 const single_threaded_suffix = if (test_target.single_threaded == true) "-single" else "";
2370 const backend_suffix = if (test_target.use_llvm == true)
2371 "-llvm"
2372 else if (target.ofmt == .c)
2373 "-cbe"
2374 else if (test_target.use_llvm == false)
2375 "-selfhosted"
2376 else
2377 "";
2378 const use_lld = if (test_target.use_lld == false) "-no-lld" else "";
2379 const linkage_name = if (test_target.linkage) |linkage| switch (linkage) {
2380 inline else => |t| "-" ++ @tagName(t),
2381 } else "";
2382 const use_pic = if (test_target.pic == true) "-pic" else "";
2383
2384 for (options.include_paths) |include_path| these_tests.root_module.addIncludePath(b.path(include_path));
2385
2386 const qualified_name = b.fmt("{s}-{s}-{s}-{t}{s}{s}{s}{s}{s}{s}", .{
2387 options.name,
2388 triple_txt,
2389 model_txt,
2390 test_target.optimize_mode,
2391 libc_suffix,
2392 single_threaded_suffix,
2393 backend_suffix,
2394 use_lld,
2395 linkage_name,
2396 use_pic,
2397 });
2398
2399 if (target.ofmt == .c) {
2400 var altered_query = test_target.target;
2401 altered_query.ofmt = null;
2402
2403 const compile_c = b.createModule(.{
2404 .root_source_file = null,
2405 .link_libc = test_target.link_libc,
2406 .target = b.resolveTargetQuery(altered_query),
2407 });
2408 const compile_c_exe = b.addExecutable(.{
2409 .name = qualified_name,
2410 .root_module = compile_c,
2411 .zig_lib_dir = b.path("lib"),
2412 });
2413
2414 compile_c.addCSourceFile(.{
2415 .file = these_tests.getEmittedBin(),
2416 .flags = &.{
2417 // Tracking issue for making the C backend generate C89 compatible code:
2418 // https://github.com/ziglang/zig/issues/19468
2419 "-std=c99",
2420 "-Werror",
2421
2422 "-Wall",
2423 "-Wembedded-directive",
2424 "-Wempty-translation-unit",
2425 "-Wextra",
2426 "-Wgnu",
2427 "-Winvalid-utf8",
2428 "-Wkeyword-macro",
2429 "-Woverlength-strings",
2430
2431 // Tracking issue for making the C backend generate code
2432 // that does not trigger warnings:
2433 // https://github.com/ziglang/zig/issues/19467
2434
2435 // spotted everywhere
2436 "-Wno-builtin-requires-header",
2437
2438 // spotted on linux
2439 "-Wno-braced-scalar-init",
2440 "-Wno-excess-initializers",
2441 "-Wno-incompatible-pointer-types-discards-qualifiers",
2442 "-Wno-unused",
2443 "-Wno-unused-parameter",
2444
2445 // spotted on darwin
2446 "-Wno-incompatible-pointer-types",
2447
2448 // https://github.com/llvm/llvm-project/issues/153314
2449 "-Wno-unterminated-string-initialization",
2450
2451 // In both Zig and C it is legal to return a pointer to a
2452 // local. The C backend lowers such thing directly, so the
2453 // corresponding warning in C must be disabled.
2454 "-Wno-return-stack-address",
2455 },
2456 });
2457 compile_c.addIncludePath(b.path("lib")); // for zig.h
2458 if (target.os.tag == .windows) {
2459 if (true) {
2460 // Unfortunately this requires about 8G of RAM for clang to compile
2461 // and our Windows CI runners do not have this much.
2462 // TODO This is not an appropriate way to work around this problem.
2463 step.dependOn(&these_tests.step);
2464 return;
2465 }
2466 if (test_target.link_libc == false) {
2467 compile_c_exe.subsystem = .Console;
2468 compile_c.linkSystemLibrary("kernel32", .{});
2469 compile_c.linkSystemLibrary("ntdll", .{});
2470 }
2471 if (mem.eql(u8, options.name, "std")) {
2472 if (test_target.link_libc == false) {
2473 compile_c.linkSystemLibrary("shell32", .{});
2474 compile_c.linkSystemLibrary("advapi32", .{});
2475 }
2476 compile_c.linkSystemLibrary("crypt32", .{});
2477 compile_c.linkSystemLibrary("ws2_32", .{});
2478 compile_c.linkSystemLibrary("ole32", .{});
2479 }
2480 }
2481
2482 const run = b.addRunArtifact(compile_c_exe);
2483 run.skip_foreign_checks = true;
2484 run.enableTestRunnerMode();
2485 run.setName(b.fmt("run test {s}", .{qualified_name}));
2486
2487 step.dependOn(&run.step);
2488 } else if (target.cpu.arch.isSpirV()) {
2489 // Don't run spirv binaries
2490 _ = these_tests.getEmittedBin();
2491 step.dependOn(&these_tests.step);
2492 } else {
2493 const run = b.addRunArtifact(these_tests);
2494 run.skip_foreign_checks = true;
2495 run.setName(b.fmt("run test {s}", .{qualified_name}));
2496
2497 step.dependOn(&run.step);
2498 }
2499}
2500
2501pub fn wouldUseLlvm(use_llvm: ?bool, query: std.Target.Query, optimize_mode: OptimizeMode) bool {
2502 if (comptime builtin.cpu.arch.endian() == .big) return true; // https://github.com/ziglang/zig/issues/25961
2503 if (use_llvm) |x| return x;
2504 if (query.ofmt == .c) return false;
2505 switch (optimize_mode) {
2506 .Debug => {},
2507 else => return true,
2508 }
2509 const cpu_arch = query.cpu_arch orelse builtin.cpu.arch;
2510 const os_tag = query.os_tag orelse builtin.os.tag;
2511 switch (cpu_arch) {
2512 .x86_64 => if (os_tag.isBSD() or os_tag == .illumos or std.Target.ptrBitWidth_arch_abi(cpu_arch, query.abi orelse .none) != 64) return true,
2513 .spirv32, .spirv64 => return false,
2514 else => return true,
2515 }
2516 return false;
2517}
2518
2519const CAbiTestOptions = struct {
2520 test_target_filters: []const []const u8,
2521 skip_non_native: bool,
2522 skip_freebsd: bool,
2523 skip_netbsd: bool,
2524 skip_windows: bool,
2525 skip_darwin: bool,
2526 skip_linux: bool,
2527 skip_llvm: bool,
2528 skip_release: bool,
2529};
2530
2531pub fn addCAbiTests(b: *std.Build, options: CAbiTestOptions) *Step {
2532 const step = b.step("test-c-abi", "Run the C ABI tests");
2533
2534 const optimize_modes: [3]OptimizeMode = .{ .Debug, .ReleaseSafe, .ReleaseFast };
2535
2536 for (optimize_modes) |optimize_mode| {
2537 if (optimize_mode != .Debug and options.skip_release) continue;
2538
2539 for (c_abi_targets) |c_abi_target| {
2540 if (options.skip_non_native and !c_abi_target.target.isNative()) continue;
2541 if (options.skip_freebsd and c_abi_target.target.os_tag == .freebsd) continue;
2542 if (options.skip_netbsd and c_abi_target.target.os_tag == .netbsd) continue;
2543 if (options.skip_windows and c_abi_target.target.os_tag == .windows) continue;
2544 if (options.skip_darwin and c_abi_target.target.os_tag != null and c_abi_target.target.os_tag.?.isDarwin()) continue;
2545 if (options.skip_linux and c_abi_target.target.os_tag == .linux) continue;
2546
2547 const would_use_llvm = wouldUseLlvm(c_abi_target.use_llvm, c_abi_target.target, .Debug);
2548 if (options.skip_llvm and would_use_llvm) continue;
2549
2550 const resolved_target = b.resolveTargetQuery(c_abi_target.target);
2551 const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM");
2552 const target = &resolved_target.result;
2553
2554 if (options.test_target_filters.len > 0) {
2555 for (options.test_target_filters) |filter| {
2556 if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
2557 } else continue;
2558 }
2559
2560 if (target.os.tag == .windows and target.cpu.arch == .aarch64) {
2561 // https://github.com/ziglang/zig/issues/14908
2562 continue;
2563 }
2564
2565 const test_mod = b.createModule(.{
2566 .root_source_file = b.path("test/c_abi/main.zig"),
2567 .target = resolved_target,
2568 .optimize = optimize_mode,
2569 .link_libc = true,
2570 .pic = c_abi_target.pic,
2571 .strip = c_abi_target.strip,
2572 });
2573 test_mod.addCSourceFile(.{
2574 .file = b.path("test/c_abi/cfuncs.c"),
2575 .flags = &.{"-std=c99"},
2576 });
2577 for (c_abi_target.c_defines) |define| test_mod.addCMacro(define, "1");
2578
2579 const test_step = b.addTest(.{
2580 .name = b.fmt("test-c-abi-{s}-{s}-{s}{s}{s}{s}", .{
2581 triple_txt,
2582 target.cpu.model.name,
2583 @tagName(optimize_mode),
2584 if (c_abi_target.use_llvm == true)
2585 "-llvm"
2586 else if (target.ofmt == .c)
2587 "-cbe"
2588 else if (c_abi_target.use_llvm == false)
2589 "-selfhosted"
2590 else
2591 "",
2592 if (c_abi_target.use_lld == false) "-no-lld" else "",
2593 if (c_abi_target.pic == true) "-pic" else "",
2594 }),
2595 .root_module = test_mod,
2596 .use_llvm = c_abi_target.use_llvm,
2597 .use_lld = c_abi_target.use_lld,
2598 });
2599
2600 // This test is intentionally trying to check if the external ABI is
2601 // done properly. LTO would be a hindrance to this.
2602 test_step.lto = .none;
2603
2604 const run = b.addRunArtifact(test_step);
2605 run.skip_foreign_checks = true;
2606 step.dependOn(&run.step);
2607 }
2608 }
2609 return step;
2610}
2611
2612pub fn addCases(
2613 b: *std.Build,
2614 parent_step: *Step,
2615 case_test_options: @import("src/Cases.zig").CaseTestOptions,
2616 build_options: @import("cases.zig").BuildOptions,
2617) !void {
2618 const arena = b.allocator;
2619 const gpa = b.allocator;
2620
2621 var cases = @import("src/Cases.zig").init(gpa, arena);
2622
2623 var dir = try b.build_root.handle.openDir("test/cases", .{ .iterate = true });
2624 defer dir.close();
2625
2626 cases.addFromDir(dir, b);
2627 try @import("cases.zig").addCases(&cases, build_options, b);
2628
2629 cases.lowerToBuildSteps(
2630 b,
2631 parent_step,
2632 case_test_options,
2633 );
2634}
2635
2636pub fn addDebuggerTests(b: *std.Build, options: DebuggerContext.Options) ?*Step {
2637 const step = b.step("test-debugger", "Run the debugger tests");
2638 if (options.gdb == null and options.lldb == null) {
2639 step.dependOn(&b.addFail("test-debugger requires -Dgdb and/or -Dlldb").step);
2640 return null;
2641 }
2642
2643 var context: DebuggerContext = .{
2644 .b = b,
2645 .options = options,
2646 .root_step = step,
2647 };
2648 context.addTestsForTarget(&.{
2649 .resolved = b.resolveTargetQuery(.{
2650 .cpu_arch = .x86_64,
2651 .os_tag = .linux,
2652 .abi = .none,
2653 }),
2654 .pic = false,
2655 .test_name_suffix = "x86_64-linux",
2656 });
2657 context.addTestsForTarget(&.{
2658 .resolved = b.resolveTargetQuery(.{
2659 .cpu_arch = .x86_64,
2660 .os_tag = .linux,
2661 .abi = .none,
2662 }),
2663 .pic = true,
2664 .test_name_suffix = "x86_64-linux-pic",
2665 });
2666 return step;
2667}
2668
2669pub fn addIncrementalTests(b: *std.Build, test_step: *Step) !void {
2670 const incr_check = b.addExecutable(.{
2671 .name = "incr-check",
2672 .root_module = b.createModule(.{
2673 .root_source_file = b.path("tools/incr-check.zig"),
2674 .target = b.graph.host,
2675 .optimize = .Debug,
2676 }),
2677 });
2678
2679 var dir = try b.build_root.handle.openDir("test/incremental", .{ .iterate = true });
2680 defer dir.close();
2681
2682 var it = try dir.walk(b.graph.arena);
2683 while (try it.next()) |entry| {
2684 if (entry.kind != .file) continue;
2685
2686 const run = b.addRunArtifact(incr_check);
2687 run.setName(b.fmt("incr-check '{s}'", .{entry.basename}));
2688
2689 run.addArg(b.graph.zig_exe);
2690 run.addFileArg(b.path("test/incremental/").path(b, entry.path));
2691 run.addArgs(&.{ "--zig-lib-dir", b.fmt("{f}", .{b.graph.zig_lib_directory}) });
2692
2693 run.addCheck(.{ .expect_term = .{ .Exited = 0 } });
2694
2695 test_step.dependOn(&run.step);
2696 }
2697}
2698
2699pub fn addLlvmIrTests(b: *std.Build, options: LlvmIrContext.Options) ?*Step {
2700 const step = b.step("test-llvm-ir", "Run the LLVM IR tests");
2701
2702 if (!options.enable_llvm) {
2703 step.dependOn(&b.addFail("test-llvm-ir requires -Denable-llvm").step);
2704 return null;
2705 }
2706
2707 var context: LlvmIrContext = .{
2708 .b = b,
2709 .options = options,
2710 .root_step = step,
2711 };
2712
2713 llvm_ir.addCases(&context);
2714
2715 return step;
2716}
2717
2718const libc_targets: []const std.Target.Query = &.{
2719 .{
2720 .cpu_arch = .arm,
2721 .os_tag = .linux,
2722 .abi = .musleabi,
2723 },
2724 .{
2725 .cpu_arch = .arm,
2726 .os_tag = .linux,
2727 .abi = .musleabihf,
2728 },
2729 .{
2730 .cpu_arch = .armeb,
2731 .os_tag = .linux,
2732 .abi = .musleabi,
2733 },
2734 .{
2735 .cpu_arch = .armeb,
2736 .os_tag = .linux,
2737 .abi = .musleabihf,
2738 },
2739 .{
2740 .cpu_arch = .thumb,
2741 .os_tag = .linux,
2742 .abi = .musleabi,
2743 },
2744 .{
2745 .cpu_arch = .thumb,
2746 .os_tag = .linux,
2747 .abi = .musleabihf,
2748 },
2749 .{
2750 .cpu_arch = .thumbeb,
2751 .os_tag = .linux,
2752 .abi = .musleabi,
2753 },
2754 .{
2755 .cpu_arch = .thumbeb,
2756 .os_tag = .linux,
2757 .abi = .musleabihf,
2758 },
2759 .{
2760 .cpu_arch = .aarch64,
2761 .os_tag = .linux,
2762 .abi = .musl,
2763 },
2764 .{
2765 .cpu_arch = .aarch64_be,
2766 .os_tag = .linux,
2767 .abi = .musl,
2768 },
2769 // .{
2770 // .cpu_arch = .hexagon,
2771 // .os_tag = .linux,
2772 // .abi = .musl,
2773 // },
2774 .{
2775 .cpu_arch = .loongarch64,
2776 .os_tag = .linux,
2777 .abi = .musl,
2778 },
2779 .{
2780 .cpu_arch = .loongarch64,
2781 .os_tag = .linux,
2782 .abi = .muslsf,
2783 },
2784 // .{
2785 // .cpu_arch = .mips,
2786 // .os_tag = .linux,
2787 // .abi = .musleabi,
2788 // },
2789 // .{
2790 // .cpu_arch = .mips,
2791 // .os_tag = .linux,
2792 // .abi = .musleabihf,
2793 // },
2794 // .{
2795 // .cpu_arch = .mipsel,
2796 // .os_tag = .linux,
2797 // .abi = .musleabi,
2798 // },
2799 // .{
2800 // .cpu_arch = .mipsel,
2801 // .os_tag = .linux,
2802 // .abi = .musleabihf,
2803 // },
2804 // .{
2805 // .cpu_arch = .mips64,
2806 // .os_tag = .linux,
2807 // .abi = .muslabi64,
2808 // },
2809 // .{
2810 // .cpu_arch = .mips64,
2811 // .os_tag = .linux,
2812 // .abi = .muslabin32,
2813 // },
2814 // .{
2815 // .cpu_arch = .mips64el,
2816 // .os_tag = .linux,
2817 // .abi = .muslabi64,
2818 // },
2819 // .{
2820 // .cpu_arch = .mips64el,
2821 // .os_tag = .linux,
2822 // .abi = .muslabin32,
2823 // },
2824 .{
2825 .cpu_arch = .powerpc,
2826 .os_tag = .linux,
2827 .abi = .musleabi,
2828 },
2829 .{
2830 .cpu_arch = .powerpc,
2831 .os_tag = .linux,
2832 .abi = .musleabihf,
2833 },
2834 .{
2835 .cpu_arch = .powerpc64,
2836 .os_tag = .linux,
2837 .abi = .musl,
2838 },
2839 .{
2840 .cpu_arch = .powerpc64le,
2841 .os_tag = .linux,
2842 .abi = .musl,
2843 },
2844 .{
2845 .cpu_arch = .riscv32,
2846 .os_tag = .linux,
2847 .abi = .musl,
2848 },
2849 .{
2850 .cpu_arch = .riscv64,
2851 .os_tag = .linux,
2852 .abi = .musl,
2853 },
2854 .{
2855 .cpu_arch = .s390x,
2856 .os_tag = .linux,
2857 .abi = .musl,
2858 },
2859 .{
2860 .cpu_arch = .wasm32,
2861 .os_tag = .wasi,
2862 .abi = .musl,
2863 },
2864 .{
2865 .cpu_arch = .x86,
2866 .os_tag = .linux,
2867 .abi = .musl,
2868 },
2869 .{
2870 .cpu_arch = .x86_64,
2871 .os_tag = .linux,
2872 .abi = .musl,
2873 },
2874 .{
2875 .cpu_arch = .x86_64,
2876 .os_tag = .linux,
2877 .abi = .muslx32,
2878 },
2879};
2880
2881pub fn addLibcTests(b: *std.Build, options: LibcContext.Options) ?*Step {
2882 const step = b.step("test-libc", "Run libc-test test cases");
2883 const opt_libc_test_path = b.option(std.Build.LazyPath, "libc-test-path", "path to libc-test source directory");
2884 if (opt_libc_test_path) |libc_test_path| {
2885 var context: LibcContext = .{
2886 .b = b,
2887 .options = options,
2888 .root_step = step,
2889 .libc_test_src_path = libc_test_path.path(b, "src"),
2890 };
2891
2892 libc.addCases(&context);
2893
2894 for (libc_targets) |target_query| {
2895 const target = b.resolveTargetQuery(target_query);
2896 context.addTarget(target);
2897 }
2898
2899 return step;
2900 } else {
2901 step.dependOn(&b.addFail("The -Dlibc-test-path=... option is required for this step").step);
2902 return null;
2903 }
2904}