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