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 // https://codeberg.org/ziglang/zig/issues/31773
2290 // .{
2291 // .target = .{
2292 // .cpu_arch = .x86_64,
2293 // .os_tag = .windows,
2294 // },
2295 // .backend = .selfhosted,
2296 // },
2297 .{
2298 .target = .{
2299 .cpu_arch = .wasm32,
2300 .os_tag = .wasi,
2301 },
2302 .backend = .selfhosted,
2303 },
2304};
2305
2306fn compatible32bitArch(host: *const std.Target) ?std.Target.Cpu.Arch {
2307 return switch (host.os.tag) {
2308 .freebsd => switch (host.cpu.arch) {
2309 .aarch64 => .arm,
2310 .powerpc64 => .powerpc,
2311 else => null,
2312 },
2313 .illumos => switch (host.cpu.arch) {
2314 .x86_64 => .x86,
2315 else => null,
2316 },
2317 .linux => switch (host.cpu.arch) {
2318 .aarch64 => .arm,
2319 .aarch64_be => .armeb,
2320 .mips64 => .mips,
2321 .mips64el => .mipsel,
2322 .powerpc64 => .powerpc,
2323 .sparc64 => .sparc,
2324 .x86_64 => .x86,
2325 else => null,
2326 },
2327 .netbsd => switch (host.cpu.arch) {
2328 .riscv64 => .riscv32,
2329 .sparc64 => .sparc,
2330 .x86_64 => .x86,
2331 else => null,
2332 },
2333 .windows => switch (host.cpu.arch) {
2334 .x86_64 => .x86,
2335 else => null,
2336 },
2337 else => null,
2338 };
2339}
2340
2341pub fn isNative(actual_target: *const std.Build.ResolvedTarget, host: *const std.Target) bool {
2342 if (actual_target.query.isNative()) return true;
2343 const actual = &actual_target.result;
2344
2345 if (actual.cpu.arch != host.cpu.arch and
2346 actual.cpu.arch != compatible32bitArch(host))
2347 {
2348 return false;
2349 }
2350
2351 if (actual.os.tag != host.os.tag)
2352 return false;
2353
2354 // Remove features that don't actually affect compatibility.
2355 const irrelevant: std.Target.Cpu.Feature.Set = switch (host.cpu.arch) {
2356 .x86_64 => std.Target.x86.featureSet(&.{
2357 .@"16bit_mode",
2358 .@"32bit_mode",
2359 .@"64bit",
2360 .false_deps_getmant,
2361 .false_deps_lzcnt_tzcnt,
2362 .false_deps_mulc,
2363 .false_deps_mullq,
2364 .false_deps_perm,
2365 .false_deps_popcnt,
2366 .false_deps_range,
2367 .fast_11bytenop,
2368 .fast_15bytenop,
2369 .fast_7bytenop,
2370 .fast_bextr,
2371 .fast_dpwssd,
2372 .fast_gather,
2373 .fast_hops,
2374 .fast_imm16,
2375 .fast_lzcnt,
2376 .fast_movbe,
2377 .fast_scalar_fsqrt,
2378 .fast_scalar_shift_masks,
2379 .fast_shld_rotate,
2380 .fast_variable_crosslane_shuffle,
2381 .fast_variable_perlane_shuffle,
2382 .fast_vector_fsqrt,
2383 .fast_vector_shift_masks,
2384 .faster_shift_than_shuffle,
2385 .no_bypass_delay,
2386 .no_bypass_delay_blend,
2387 .no_bypass_delay_mov,
2388 .no_bypass_delay_shuffle,
2389 .prefer_128_bit,
2390 .prefer_256_bit,
2391 .prefer_legacy_setcc,
2392 .prefer_mask_registers,
2393 .prefer_movmsk_over_vtest,
2394 .prefer_no_gather,
2395 .prefer_no_scatter,
2396 .slow_3ops_lea,
2397 .slow_incdec,
2398 .slow_lea,
2399 .slow_pmaddwd,
2400 .slow_pmulld,
2401 .slow_pmullq,
2402 .slow_shld,
2403 .slow_two_mem_ops,
2404 .slow_unaligned_mem_16,
2405 .slow_unaligned_mem_32,
2406 }),
2407 .aarch64, .aarch64_be => std.Target.aarch64.featureSet(&.{
2408 .addr_lsl_slow_14,
2409 .alu_lsl_fast,
2410 .avoid_ldapur,
2411 .disable_fast_inc_vl,
2412 .exynos_cheap_as_move,
2413 .fuse_address,
2414 .fuse_addsub_2reg_const1,
2415 .fuse_adrp_add,
2416 .fuse_aes,
2417 .fuse_arith_logic,
2418 .fuse_crypto_eor,
2419 .fuse_csel,
2420 .fuse_cset,
2421 .fuse_literals,
2422 .predictable_select_expensive,
2423 .slow_misaligned_128store,
2424 .slow_paired_128,
2425 .slow_strqro_store,
2426 .use_experimental_zeroing_pseudos,
2427 .use_fixed_over_scalable_if_equal_cost,
2428 .use_postra_scheduler,
2429 .use_reciprocal_square_root,
2430 .use_wzr_to_vec_move,
2431 }),
2432 else => .empty,
2433 };
2434 var set = actual.cpu.features;
2435 set.removeFeatureSet(irrelevant);
2436
2437 if (!host.cpu.features.isSuperSetOf(set))
2438 return false;
2439
2440 return true;
2441}
2442
2443pub fn addStackTraceTests(b: *std.Build, options: StackTracesContext.Options) *Step {
2444 const step = b.step("test-stack-traces", "Run the stack trace tests");
2445
2446 const convert_exe = b.addExecutable(.{
2447 .name = "convert-stack-trace",
2448 .root_module = b.createModule(.{
2449 .root_source_file = b.path("test/src/convert-stack-trace.zig"),
2450 .target = b.graph.host,
2451 .optimize = .debug,
2452 }),
2453 });
2454
2455 const stack_traces_context = b.allocator.create(StackTracesContext) catch @panic("OOM");
2456 stack_traces_context.* = .{
2457 .b = b,
2458 .step = step,
2459 .options = options,
2460 .convert_exe = convert_exe,
2461 };
2462 stack_traces_context.addCases();
2463
2464 return step;
2465}
2466
2467pub fn addErrorTraceTests(b: *std.Build, options: ErrorTracesContext.Options) *Step {
2468 const step = b.step("test-error-traces", "Run the error trace tests");
2469
2470 const convert_exe = b.addExecutable(.{
2471 .name = "convert-stack-trace",
2472 .root_module = b.createModule(.{
2473 .root_source_file = b.path("test/src/convert-stack-trace.zig"),
2474 .target = b.graph.host,
2475 .optimize = .debug,
2476 }),
2477 });
2478
2479 const error_traces_context = b.allocator.create(ErrorTracesContext) catch @panic("OOM");
2480 error_traces_context.* = .{
2481 .b = b,
2482 .step = step,
2483 .options = options,
2484 .convert_exe = convert_exe,
2485 };
2486 error_traces_context.addCases();
2487
2488 return step;
2489}
2490
2491pub fn addStandaloneTests(
2492 b: *std.Build,
2493 optimize_modes: []const OptimizeMode,
2494 enable_macos_sdk: bool,
2495 enable_ios_sdk: bool,
2496 enable_symlinks_windows: bool,
2497) *Step {
2498 const step = b.step("test-standalone", "Run the standalone tests");
2499 const test_cases_dep_name = "standalone_test_cases";
2500 const test_cases_dep = b.dependency(test_cases_dep_name, .{
2501 .enable_ios_sdk = enable_ios_sdk,
2502 .enable_macos_sdk = enable_macos_sdk,
2503 .enable_symlinks_windows = enable_symlinks_windows,
2504 .simple_skip_debug = mem.findScalar(OptimizeMode, optimize_modes, .debug) == null,
2505 .simple_skip_release_safe = mem.findScalar(OptimizeMode, optimize_modes, .safe) == null,
2506 .simple_skip_release_fast = mem.findScalar(OptimizeMode, optimize_modes, .fast) == null,
2507 .simple_skip_release_small = mem.findScalar(OptimizeMode, optimize_modes, .small) == null,
2508 });
2509 const test_cases_dep_step = test_cases_dep.builder.default_step;
2510 test_cases_dep_step.name = b.graph.dupeString(test_cases_dep_name);
2511 step.dependOn(test_cases_dep.builder.default_step);
2512 return step;
2513}
2514
2515pub fn addCliTests(b: *std.Build) *Step {
2516 const step = b.step("test-cli", "Test the command line interface");
2517 const s = std.fs.path.sep_str;
2518
2519 {
2520 // Test that all JIT'd commands compile.
2521 for (&[_][]const u8{
2522 "libc",
2523 "objcopy",
2524 "objdump",
2525 "rc",
2526 "reduce",
2527 "std",
2528 }) |cmd| {
2529 const run_help = b.addSystemCommand(&.{ b.graph.zig_exe, cmd, "--help" });
2530 run_help.setName(b.fmt("zig {s} --help", .{cmd}));
2531 run_help.expectStdErrEqual("");
2532 run_help.expectExitCode(0);
2533 step.dependOn(&run_help.step);
2534 }
2535 }
2536
2537 {
2538 // Test `zig init`.
2539 const tmp_path = b.tmpPath();
2540 const init_exe = b.addSystemCommand(&.{ b.graph.zig_exe, "init" });
2541 init_exe.setCwd(tmp_path);
2542 init_exe.setName("zig init");
2543 init_exe.expectStdOutEqual("");
2544 init_exe.expectStdErrEqual("info: created build.zig\n" ++
2545 "info: created build.zig.zon\n" ++
2546 "info: created src" ++ s ++ "main.zig\n" ++
2547 "info: created src" ++ s ++ "root.zig\n" ++
2548 "info: see `zig build --help` for a menu of options\n");
2549
2550 // Test missing output path.
2551 const bad_out_arg = "-femit-bin=does" ++ s ++ "not" ++ s ++ "exist" ++ s ++ "foo.exe";
2552 const ok_src_arg = "src" ++ s ++ "main.zig";
2553 const es = if (builtin.os.tag == .windows) "\\\\" else "/";
2554 const expected = "error: unable to open output directory \"does" ++ es ++ "not" ++ es ++ "exist\": FileNotFound\n";
2555 const run_bad = b.addSystemCommand(&.{ b.graph.zig_exe, "build-exe", ok_src_arg, bad_out_arg });
2556 run_bad.setName("zig build-exe error message for bad -femit-bin arg");
2557 run_bad.expectExitCode(1);
2558 run_bad.expectStdErrEqual(expected);
2559 run_bad.expectStdOutEqual("");
2560 run_bad.step.dependOn(&init_exe.step);
2561
2562 const run_test = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "test" });
2563 run_test.setCwd(tmp_path);
2564 run_test.setName("zig build test");
2565 run_test.expectStdOutEqual("");
2566 run_test.step.dependOn(&init_exe.step);
2567
2568 const run_run = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "run" });
2569 run_run.setCwd(tmp_path);
2570 run_run.setName("zig build run");
2571 run_run.expectStdOutEqual("Run `zig build test` to run the tests.\n");
2572 run_run.expectStdErrMatch("All your codebase are belong to us.\n");
2573 run_run.step.dependOn(&init_exe.step);
2574
2575 step.dependOn(&run_test.step);
2576 step.dependOn(&run_run.step);
2577 step.dependOn(&run_bad.step);
2578 }
2579
2580 {
2581 // Test `zig init -m`.
2582 const tmp_path = b.tmpPath();
2583 const init_exe = b.addSystemCommand(&.{ b.graph.zig_exe, "init", "-m" });
2584 init_exe.setCwd(tmp_path);
2585 init_exe.setName("zig init -m");
2586 init_exe.expectStdOutEqual("");
2587 init_exe.expectStdErrEqual("info: successfully populated 'build.zig.zon' and 'build.zig'\n");
2588 }
2589
2590 // Test Godbolt API
2591 if (builtin.os.tag == .linux and builtin.cpu.arch == .x86_64) {
2592 const tmp_path = b.tmpPath();
2593
2594 const example_zig = b.addWriteFiles().add("example.zig",
2595 \\// Type your code here, or load an example.
2596 \\export fn square(num: i32) i32 {
2597 \\ return num * num;
2598 \\}
2599 \\extern fn zig_panic() noreturn;
2600 \\pub fn panic(msg: []const u8, error_return_trace: ?*@import("std").builtin.StackTrace, _: ?usize) noreturn {
2601 \\ _ = msg;
2602 \\ _ = error_return_trace;
2603 \\ zig_panic();
2604 \\}
2605 );
2606
2607 // This is intended to be the exact CLI usage used by godbolt.org.
2608 const run = b.addSystemCommand(&.{ b.graph.zig_exe, "build-obj", "--cache-dir" });
2609 run.addDirectoryArg(tmp_path);
2610 run.addArgs(&.{ "--name", "example", "-fno-emit-bin", "-fno-emit-h", "-fstrip", "-Ofast" });
2611 run.addFileArg(example_zig);
2612 const example_s = run.addPrefixedOutputFileArg("-femit-asm=", "example.s");
2613
2614 const checkfile = b.addCheckFile(example_s, .{
2615 .expected_matches = &.{
2616 "square:",
2617 "mov\teax, edi",
2618 "imul\teax, edi",
2619 },
2620 });
2621 checkfile.setName("check godbolt.org CLI usage generating valid asm");
2622
2623 step.dependOn(&checkfile.step);
2624 }
2625
2626 {
2627 // Test `zig fmt`.
2628 // This test must use a temporary directory rather than a cache
2629 // directory because this test will be mutating the files. The cache
2630 // system relies on cache directories being mutated only by their
2631 // owners.
2632 const tmp_wf = b.addTempFiles();
2633 const unformatted_code = " // no reason for indent";
2634
2635 _ = tmp_wf.add("fmt1.zig", unformatted_code);
2636 _ = tmp_wf.add("fmt2.zig", unformatted_code);
2637 _ = tmp_wf.add("subdir/fmt3.zig", unformatted_code);
2638
2639 const tmp_path = tmp_wf.getDirectory();
2640
2641 // Test zig fmt affecting only the appropriate files.
2642 const run1 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "fmt1.zig" });
2643 run1.setName("run zig fmt one file");
2644 run1.setCwd(tmp_path);
2645 run1.has_side_effects = true;
2646 // stdout should be file path + \n
2647 run1.expectStdOutEqual("fmt1.zig\n");
2648
2649 // Test excluding files and directories from a run
2650 const run2 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "subdir", "." });
2651 run2.setName("run zig fmt on directory with exclusions");
2652 run2.setCwd(tmp_path);
2653 run2.has_side_effects = true;
2654 run2.expectStdOutEqual("");
2655 run2.step.dependOn(&run1.step);
2656
2657 // Test excluding non-existent file
2658 const run3 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "nonexistent.zig", "." });
2659 run3.setName("run zig fmt on directory with non-existent exclusion");
2660 run3.setCwd(tmp_path);
2661 run3.has_side_effects = true;
2662 run3.expectStdOutEqual("." ++ s ++ "subdir" ++ s ++ "fmt3.zig\n");
2663 run3.step.dependOn(&run2.step);
2664
2665 // running it on the dir, only the new file should be changed
2666 const run4 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." });
2667 run4.setName("run zig fmt the directory");
2668 run4.setCwd(tmp_path);
2669 run4.has_side_effects = true;
2670 run4.expectStdOutEqual("." ++ s ++ "fmt2.zig\n");
2671 run4.step.dependOn(&run3.step);
2672
2673 // both files have been formatted, nothing should change now
2674 const run5 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." });
2675 run5.setName("run zig fmt with nothing to do");
2676 run5.setCwd(tmp_path);
2677 run5.has_side_effects = true;
2678 run5.expectStdOutEqual("");
2679 run5.step.dependOn(&run4.step);
2680
2681 const unformatted_code_utf16 = "\xff\xfe \x00 \x00 \x00 \x00/\x00/\x00 \x00n\x00o\x00 \x00r\x00e\x00a\x00s\x00o\x00n\x00";
2682 const write6 = b.addMutateFiles(tmp_path);
2683 const fmt6_path = write6.add("fmt6.zig", unformatted_code_utf16);
2684 write6.step.dependOn(&run5.step);
2685
2686 // Test `zig fmt` handling UTF-16 decoding.
2687 const run6 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." });
2688 run6.setName("run zig fmt convert UTF-16 to UTF-8");
2689 run6.setCwd(tmp_path);
2690 run6.has_side_effects = true;
2691 run6.expectStdOutEqual("." ++ s ++ "fmt6.zig\n");
2692 run6.step.dependOn(&write6.step);
2693
2694 // TODO change this to an exact match
2695 const check6 = b.addCheckFile(fmt6_path, .{
2696 .expected_matches = &.{
2697 "// no reason",
2698 },
2699 });
2700 check6.step.dependOn(&run6.step);
2701
2702 step.dependOn(&check6.step);
2703 }
2704
2705 {
2706 const run_test = b.addSystemCommand(&.{
2707 b.graph.zig_exe,
2708 "build",
2709 "test",
2710 "-Dbool_true",
2711 "-Dbool_false=false",
2712 "-Dint=1234",
2713 "-De=two",
2714 "-Dstring=hello",
2715 });
2716 run_test.addArg("--build-file");
2717 run_test.addFileArg(b.path("test/cli/options/build.zig"));
2718
2719 run_test.addArg("--cache-dir");
2720 run_test.addFileArg(.cache_root);
2721
2722 run_test.setName("test build options");
2723
2724 step.dependOn(&run_test.step);
2725 }
2726
2727 return step;
2728}
2729
2730pub const ModuleTestOptions = struct {
2731 test_filters: []const []const u8,
2732 test_target_filters: []const []const u8,
2733 test_extra_targets: bool,
2734 root_src: []const u8,
2735 name: []const u8,
2736 desc: []const u8,
2737 optimize_modes: []const OptimizeMode,
2738 include_paths: []const []const u8,
2739 test_only: ?TestOnly,
2740 skip_single_threaded: bool,
2741 skip_non_native: bool,
2742 skip_spirv: bool,
2743 skip_wasm: bool,
2744 skip_freebsd: bool,
2745 skip_netbsd: bool,
2746 skip_openbsd: bool,
2747 skip_windows: bool,
2748 skip_darwin: bool,
2749 skip_linux: bool,
2750 skip_llvm: bool,
2751 skip_libc: bool,
2752 max_rss: u64 = 0,
2753 no_builtin: bool = false,
2754 sanitize_thread: ?bool = null,
2755 build_options: ?*Step.Options = null,
2756
2757 pub const TestOnly = union(enum) {
2758 default: void,
2759 fuzz: OptimizeMode,
2760 };
2761};
2762
2763pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
2764 const step = b.step(b.fmt("test-{s}", .{options.name}), options.desc);
2765
2766 if (options.test_only) |test_only| {
2767 const test_target: ModuleTestTarget = switch (test_only) {
2768 .default => .{
2769 .link_libc = if (std.mem.eql(u8, options.name, "libc")) true else null,
2770 },
2771 .fuzz => |optimize| .{
2772 .optimize_mode = optimize,
2773 .use_llvm = true,
2774 },
2775 };
2776 const resolved_target = b.resolveTargetQuery(test_target.target);
2777 const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM");
2778 addOneModuleTest(b, step, test_target, &resolved_target, triple_txt, options);
2779
2780 return step;
2781 }
2782
2783 for_targets: for (module_test_targets) |test_target| {
2784 if (test_target.skip_modules.len > 0) {
2785 for (test_target.skip_modules) |skip_mod| {
2786 if (std.mem.eql(u8, options.name, skip_mod)) continue :for_targets;
2787 }
2788 }
2789
2790 const resolved_target = b.resolveTargetQuery(test_target.target);
2791
2792 if (!options.test_extra_targets and test_target.extra_target) continue;
2793
2794 if (options.skip_non_native and !isNative(&resolved_target, &b.graph.host.result))
2795 continue;
2796
2797 const target = &resolved_target.result;
2798
2799 if (std.mem.eql(u8, options.name, "libc")) {
2800 // The libc API tests obviously need to link libc. So for test
2801 // target entries where we wouldn't link libc by default, skip the
2802 // libc API tests.
2803 if (test_target.link_libc == null and !std.os.targetRequiresLibC(target)) continue;
2804 }
2805
2806 if (options.skip_spirv and target.cpu.arch.isSpirV()) continue;
2807 if (options.skip_wasm and target.cpu.arch.isWasm()) continue;
2808
2809 if (options.skip_freebsd and target.os.tag == .freebsd) continue;
2810 if (options.skip_netbsd and target.os.tag == .netbsd) continue;
2811 if (options.skip_openbsd and target.os.tag == .openbsd) continue;
2812 if (options.skip_windows and target.os.tag == .windows) continue;
2813 if (options.skip_darwin and target.os.tag.isDarwin()) continue;
2814 if (options.skip_linux and target.os.tag == .linux) continue;
2815
2816 const would_use_llvm = wouldUseLlvm(test_target.use_llvm, test_target.target, test_target.optimize_mode);
2817 if (options.skip_llvm and would_use_llvm) continue;
2818
2819 const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM");
2820
2821 if (options.test_target_filters.len > 0) {
2822 for (options.test_target_filters) |filter| {
2823 if (std.mem.find(u8, triple_txt, filter) != null) break;
2824 } else continue;
2825 }
2826
2827 if (options.skip_libc and (test_target.link_libc == true or std.os.targetRequiresLibC(target)))
2828 continue;
2829
2830 // We can't provide MSVC libc when cross-compiling.
2831 if (target.abi == .msvc and test_target.link_libc == true and builtin.os.tag != .windows)
2832 continue;
2833
2834 if (options.skip_single_threaded and test_target.single_threaded == true)
2835 continue;
2836
2837 const want_this_mode = for (options.optimize_modes) |m| {
2838 if (m == test_target.optimize_mode) break true;
2839 } else false;
2840 if (!want_this_mode) continue;
2841
2842 addOneModuleTest(b, step, test_target, &resolved_target, triple_txt, options);
2843 }
2844 return step;
2845}
2846
2847fn addOneModuleTest(
2848 b: *std.Build,
2849 step: *Step,
2850 test_target: ModuleTestTarget,
2851 resolved_target: *const std.Build.ResolvedTarget,
2852 triple_txt: []const u8,
2853 options: ModuleTestOptions,
2854) void {
2855 const target = &resolved_target.result;
2856 const libc_suffix = if (test_target.link_libc == true) "-libc" else "";
2857 const model_txt = target.cpu.model.name;
2858
2859 // These emulated targets need a lot more RAM for unknown reasons.
2860 const max_rss = if (mem.eql(u8, options.name, "std") and
2861 (target.cpu.arch == .hexagon or
2862 (target.cpu.arch.isRISCV() and !resolved_target.query.isNative()) or
2863 target.cpu.arch.isWasm()))
2864 options.max_rss * 2
2865 else
2866 options.max_rss;
2867
2868 const these_tests = b.addTest(.{
2869 .root_module = b.createModule(.{
2870 .root_source_file = b.path(options.root_src),
2871 .optimize = test_target.optimize_mode,
2872 .target = resolved_target.*,
2873 .link_libc = test_target.link_libc,
2874 .pic = test_target.pic,
2875 .strip = test_target.strip,
2876 .sanitize_thread = options.sanitize_thread,
2877 .single_threaded = test_target.single_threaded,
2878 }),
2879 .max_rss = max_rss,
2880 .filters = options.test_filters,
2881 .use_llvm = test_target.use_llvm,
2882 .use_lld = test_target.use_lld,
2883 .zig_lib_dir = b.path("lib"),
2884 });
2885 these_tests.linkage = test_target.linkage;
2886 these_tests.use_new_linker = test_target.new_linker;
2887 // https://codeberg.org/ziglang/zig/issues/31701
2888 if (!(mem.eql(u8, options.name, "compiler-rt") or mem.eql(u8, options.name, "libc"))) {
2889 if (options.no_builtin) these_tests.root_module.no_builtin = true;
2890 }
2891 // https://codeberg.org/ziglang/zig/issues/31702
2892 if (mem.eql(u8, options.name, "compiler-rt") or mem.eql(u8, options.name, "libc")) {
2893 these_tests.root_module.stack_protector = false;
2894 }
2895 // https://github.com/llvm/llvm-project/issues/195561
2896 if (target.cpu.arch.isPowerPC()) {
2897 these_tests.root_module.stack_protector = false;
2898 }
2899 if (options.build_options) |build_options| {
2900 these_tests.root_module.addOptions("build_options", build_options);
2901 }
2902 if (test_target.function_sections) |fs| these_tests.link_function_sections = fs;
2903 if (test_target.data_sections) |ds| these_tests.link_data_sections = ds;
2904 const single_threaded_suffix = if (test_target.single_threaded == true) "-single" else "";
2905 const backend_suffix = if (test_target.use_llvm == true)
2906 "-llvm"
2907 else if (target.ofmt == .c)
2908 "-cbe"
2909 else if (test_target.use_llvm == false)
2910 "-selfhosted"
2911 else
2912 "";
2913 const linker_suffix: []const u8 = s: {
2914 if (test_target.new_linker == true) break :s "-new-linker";
2915 if (test_target.use_lld == false) break :s "-no-lld";
2916 break :s "";
2917 };
2918 const linkage_name = if (test_target.linkage) |linkage| switch (linkage) {
2919 inline else => |t| "-" ++ @tagName(t),
2920 } else "";
2921 const use_pic = if (test_target.pic == true) "-pic" else "";
2922
2923 for (options.include_paths) |include_path| these_tests.root_module.addIncludePath(b.path(include_path));
2924
2925 const qualified_name = b.fmt("{s}-{s}-{s}-{t}{s}{s}{s}{s}{s}{s}", .{
2926 options.name,
2927 triple_txt,
2928 model_txt,
2929 test_target.optimize_mode,
2930 libc_suffix,
2931 single_threaded_suffix,
2932 backend_suffix,
2933 linker_suffix,
2934 linkage_name,
2935 use_pic,
2936 });
2937
2938 if (target.ofmt == .c) {
2939 var altered_query = test_target.target;
2940 altered_query.ofmt = null;
2941
2942 const compile_c = b.createModule(.{
2943 .root_source_file = null,
2944 .link_libc = test_target.link_libc,
2945 .target = b.resolveTargetQuery(altered_query),
2946 });
2947 const compile_c_exe = b.addExecutable(.{
2948 .name = qualified_name,
2949 .root_module = compile_c,
2950 .zig_lib_dir = b.path("lib"),
2951 });
2952
2953 compile_c.addCSourceFile(.{
2954 .file = these_tests.getEmittedBin(),
2955 .flags = blk: {
2956 const invariant_cflags: []const []const u8 = &.{
2957 // Tracking issue for making the C backend generate C89 compatible code:
2958 // https://github.com/ziglang/zig/issues/19468
2959 "-std=c99",
2960 "-Werror",
2961
2962 "-Wall",
2963 "-Wembedded-directive",
2964 "-Wempty-translation-unit",
2965 "-Wextra",
2966 "-Wgnu",
2967 "-Winvalid-utf8",
2968 "-Wkeyword-macro",
2969 "-Woverlength-strings",
2970
2971 // Tracking issue for making the C backend generate code
2972 // that does not trigger warnings:
2973 // https://github.com/ziglang/zig/issues/19467
2974
2975 // spotted everywhere
2976 "-Wno-builtin-requires-header",
2977
2978 // spotted on linux
2979 "-Wno-braced-scalar-init",
2980 "-Wno-excess-initializers",
2981 "-Wno-incompatible-pointer-types-discards-qualifiers",
2982 "-Wno-unused",
2983 "-Wno-unused-parameter",
2984
2985 // spotted on darwin
2986 "-Wno-incompatible-pointer-types",
2987
2988 // https://github.com/llvm/llvm-project/issues/153314
2989 "-Wno-unterminated-string-initialization",
2990
2991 // In both Zig and C it is legal to return a pointer to a
2992 // local. The C backend lowers such thing directly, so the
2993 // corresponding warning in C must be disabled.
2994 "-Wno-return-stack-address",
2995 };
2996
2997 const function_data_sections = switch (target.cpu.arch) {
2998 .arm,
2999 .armeb,
3000 .thumb,
3001 .thumbeb,
3002 .hexagon,
3003 .powerpc,
3004 .powerpcle,
3005 .powerpc64,
3006 .powerpc64le,
3007 => true,
3008 else => false,
3009 };
3010
3011 break :blk if (function_data_sections) invariant_cflags ++ &[_][]const u8{
3012 "-ffunction-sections",
3013 "-fdata-sections",
3014 } else invariant_cflags;
3015 },
3016 });
3017 compile_c.addIncludePath(b.path("lib")); // for zig.h
3018 if (target.os.tag == .windows) {
3019 if (true) {
3020 // Unfortunately this requires about 8G of RAM for clang to compile
3021 // and our Windows CI runners do not have this much.
3022 // TODO This is not an appropriate way to work around this problem.
3023 step.dependOn(&these_tests.step);
3024 return;
3025 }
3026 if (test_target.link_libc == false) {
3027 compile_c_exe.subsystem = .Console;
3028 compile_c.linkSystemLibrary("kernel32", .{});
3029 compile_c.linkSystemLibrary("ntdll", .{});
3030 }
3031 if (mem.eql(u8, options.name, "std")) {
3032 if (test_target.link_libc == false) {
3033 compile_c.linkSystemLibrary("shell32", .{});
3034 compile_c.linkSystemLibrary("advapi32", .{});
3035 }
3036 compile_c.linkSystemLibrary("crypt32", .{});
3037 compile_c.linkSystemLibrary("ole32", .{});
3038 }
3039 }
3040
3041 const run = b.addRunArtifact(compile_c_exe);
3042 run.skip_foreign_checks = true;
3043 run.enableTestRunnerMode();
3044 run.setName(b.fmt("run test {s}", .{qualified_name}));
3045
3046 step.dependOn(&run.step);
3047 } else if (target.cpu.arch.isSpirV()) {
3048 // Don't run spirv binaries
3049 _ = these_tests.getEmittedBin();
3050 step.dependOn(&these_tests.step);
3051 } else if (target.cpu.arch == .x86_64 and target.os.tag.isDarwin()) {
3052 // https://codeberg.org/ziglang/zig/issues/35267
3053 _ = these_tests.getEmittedBin();
3054 step.dependOn(&these_tests.step);
3055 } else {
3056 const run = b.addRunArtifact(these_tests);
3057 run.skip_foreign_checks = true;
3058 run.setName(b.fmt("run test {s}", .{qualified_name}));
3059
3060 step.dependOn(&run.step);
3061 }
3062}
3063
3064pub fn wouldUseLlvm(use_llvm: ?bool, query: std.Target.Query, optimize_mode: OptimizeMode) bool {
3065 if (comptime builtin.cpu.arch.endian() == .big) return true; // https://github.com/ziglang/zig/issues/25961
3066 if (use_llvm) |x| return x;
3067 if (query.ofmt == .c) return false;
3068 switch (optimize_mode) {
3069 .debug => {},
3070 else => return true,
3071 }
3072 const cpu_arch = query.cpu_arch orelse builtin.cpu.arch;
3073 const os_tag = query.os_tag orelse builtin.os.tag;
3074 const ofmt: std.Target.ObjectFormat = query.ofmt orelse .default(os_tag, cpu_arch);
3075 switch (cpu_arch) {
3076 .x86_64 => {
3077 if (std.Target.ptrBitWidth_arch_abi(cpu_arch, query.abi orelse .none) != 64) return true;
3078 if (os_tag == .illumos) return true;
3079 switch (os_tag) {
3080 .dragonfly,
3081 .freebsd,
3082 .netbsd,
3083 .openbsd,
3084 => return true,
3085 else => {},
3086 }
3087 return switch (ofmt) {
3088 .elf => return false,
3089 .macho => return true, // https://codeberg.org/ziglang/zig/issues/35267
3090 else => return true,
3091 };
3092 },
3093 .spirv32, .spirv64 => return false,
3094 else => return true,
3095 }
3096}
3097
3098const CAbiTestOptions = struct {
3099 test_target_filters: []const []const u8,
3100 optimize_modes: []const OptimizeMode,
3101 skip_non_native: bool,
3102 skip_wasm: bool,
3103 skip_freebsd: bool,
3104 skip_netbsd: bool,
3105 skip_openbsd: bool,
3106 skip_windows: bool,
3107 skip_darwin: bool,
3108 skip_linux: bool,
3109 skip_llvm: bool,
3110 max_rss: u64 = 0,
3111};
3112
3113pub fn addCAbiTests(b: *std.Build, options: CAbiTestOptions) *Step {
3114 const step = b.step("test-c-abi", "Run the C ABI tests");
3115
3116 for (c_abi_targets) |c_abi_target| {
3117 if (options.skip_wasm and c_abi_target.target.cpu_arch != null and c_abi_target.target.cpu_arch.?.isWasm()) continue;
3118
3119 if (options.skip_freebsd and c_abi_target.target.os_tag == .freebsd) continue;
3120 if (options.skip_netbsd and c_abi_target.target.os_tag == .netbsd) continue;
3121 if (options.skip_openbsd and c_abi_target.target.os_tag == .openbsd) continue;
3122 if (options.skip_windows and c_abi_target.target.os_tag == .windows) continue;
3123 if (options.skip_darwin and c_abi_target.target.os_tag != null and c_abi_target.target.os_tag.?.isDarwin()) continue;
3124 if (options.skip_linux and c_abi_target.target.os_tag == .linux) continue;
3125
3126 const resolved_target = b.resolveTargetQuery(c_abi_target.target);
3127 const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM");
3128 const target = &resolved_target.result;
3129
3130 if (options.skip_non_native and !isNative(&resolved_target, &b.graph.host.result))
3131 continue;
3132
3133 if (options.test_target_filters.len > 0) {
3134 for (options.test_target_filters) |filter| {
3135 if (std.mem.find(u8, triple_txt, filter) != null) break;
3136 } else continue;
3137 }
3138
3139 for (options.optimize_modes) |optimize_mode| {
3140 const would_use_llvm = wouldUseLlvm(c_abi_target.use_llvm, c_abi_target.target, optimize_mode);
3141 if (options.skip_llvm and would_use_llvm) continue;
3142
3143 const test_mod = b.createModule(.{
3144 .root_source_file = b.path("test/c_abi/main.zig"),
3145 .target = resolved_target,
3146 .optimize = optimize_mode,
3147 .link_libc = true,
3148 .pic = c_abi_target.pic,
3149 .strip = c_abi_target.strip,
3150 });
3151 test_mod.addCSourceFile(.{
3152 .file = b.path("test/c_abi/cfuncs.c"),
3153 .flags = &.{"-std=c99"},
3154 });
3155 for (c_abi_target.c_defines) |define| test_mod.addCMacro(define, "1");
3156
3157 const test_step = b.addTest(.{
3158 .name = b.fmt("test-c-abi-{s}-{s}-{s}{s}{s}{s}", .{
3159 triple_txt,
3160 target.cpu.model.name,
3161 @tagName(optimize_mode),
3162 if (c_abi_target.use_llvm == true)
3163 "-llvm"
3164 else if (target.ofmt == .c)
3165 "-cbe"
3166 else if (c_abi_target.use_llvm == false)
3167 "-selfhosted"
3168 else
3169 "",
3170 if (c_abi_target.use_lld == false) "-no-lld" else "",
3171 if (c_abi_target.pic == true) "-pic" else "",
3172 }),
3173 .root_module = test_mod,
3174 .use_llvm = c_abi_target.use_llvm,
3175 .use_lld = c_abi_target.use_lld,
3176 .max_rss = options.max_rss,
3177 });
3178
3179 // https://github.com/llvm/llvm-project/issues/195561
3180 if (target.cpu.arch.isPowerPC()) {
3181 test_step.root_module.stack_protector = false;
3182 }
3183
3184 // This test is intentionally trying to check if the external ABI is
3185 // done properly. LTO would be a hindrance to this.
3186 test_step.lto = .none;
3187
3188 const run = b.addRunArtifact(test_step);
3189 run.skip_foreign_checks = true;
3190 step.dependOn(&run.step);
3191 }
3192 }
3193 return step;
3194}
3195
3196const LinkTestOptions = struct {
3197 test_target_filters: []const []const u8,
3198 test_filters: []const []const u8,
3199 optimize_modes: []const OptimizeMode,
3200 skip_non_native: bool,
3201 skip_freebsd: bool,
3202 skip_netbsd: bool,
3203 skip_openbsd: bool,
3204 skip_windows: bool,
3205 skip_darwin: bool,
3206 skip_linux: bool,
3207 skip_llvm: bool,
3208 skip_libc: bool,
3209 max_rss: usize,
3210};
3211
3212pub fn addLinkTests(b: *std.Build, options: LinkTestOptions) *Step {
3213 const step = b.step("test-link", "Run the linker tests");
3214 const update_snapshots = b.option(
3215 bool,
3216 "link-snapshot-update",
3217 "Update linker test snapshots in-place instead of testing against them",
3218 ) orelse false;
3219
3220 for (link_targets) |link_target| {
3221 const resolved_target = b.resolveTargetQuery(link_target.target);
3222
3223 if (options.skip_non_native and !isNative(&resolved_target, &b.graph.host.result))
3224 continue;
3225
3226 const target = &resolved_target.result;
3227
3228 if (options.skip_freebsd and target.os.tag == .freebsd) continue;
3229 if (options.skip_netbsd and target.os.tag == .netbsd) continue;
3230 if (options.skip_openbsd and target.os.tag == .openbsd) continue;
3231 if (options.skip_windows and target.os.tag == .windows) continue;
3232 if (options.skip_darwin and target.os.tag.isDarwin()) continue;
3233 if (options.skip_linux and target.os.tag == .linux) continue;
3234
3235 const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM");
3236
3237 if (options.test_target_filters.len > 0) {
3238 for (options.test_target_filters) |filter| {
3239 if (std.mem.find(u8, triple_txt, filter) != null) break;
3240 } else continue;
3241 }
3242
3243 if (options.skip_libc and (link_target.link_libc == true or std.os.targetRequiresLibC(target)))
3244 continue;
3245
3246 // We can't provide MSVC libc when cross-compiling.
3247 if (target.abi == .msvc and link_target.link_libc == true and builtin.os.tag != .windows)
3248 continue;
3249
3250 for (options.optimize_modes) |optimize_mode| {
3251 if (link_target.optimize_mode != optimize_mode) continue;
3252 const would_use_llvm = wouldUseLlvm(link_target.use_llvm, link_target.target, optimize_mode);
3253 if (options.skip_llvm and would_use_llvm) continue;
3254
3255 const opt_update_step = if (update_snapshots) update: {
3256 const update_step = Step.UpdateSourceFiles.create(b);
3257 step.dependOn(&update_step.step);
3258 break :update update_step;
3259 } else null;
3260
3261 var context: LinkContext = .{
3262 .b = b,
3263 .step = step,
3264 .optimize = optimize_mode,
3265 .target = resolved_target,
3266 .target_desc = std.fmt.allocPrint(b.allocator, "{s}-{t}{s}{s}{s}", .{
3267 target.zigTriple(b.allocator) catch @panic("OOM"),
3268 optimize_mode,
3269 if (link_target.use_llvm) "-llvm" else "",
3270 if (link_target.use_lld) "-lld" else "",
3271 if (link_target.link_libc) "-libc" else "",
3272 }) catch @panic("OOM"),
3273 .use_llvm = link_target.use_llvm,
3274 .use_lld = link_target.use_lld,
3275 .link_libc = link_target.link_libc,
3276 .test_filters = options.test_filters,
3277 .update_step = opt_update_step,
3278 .updated_snapshots = .empty,
3279 .max_rss = options.max_rss,
3280 };
3281
3282 link.addCases(&context);
3283 }
3284 }
3285 return step;
3286}
3287
3288pub fn addCases(
3289 b: *std.Build,
3290 parent_step: *Step,
3291 case_test_options: @import("src/Cases.zig").CaseTestOptions,
3292 build_options: @import("cases.zig").BuildOptions,
3293) !void {
3294 const arena = b.allocator;
3295 const gpa = b.allocator;
3296 const io = b.graph.io;
3297
3298 var cases = @import("src/Cases.zig").init(gpa, arena, io);
3299
3300 b.dependOnDirectory(b.path("test/cases"));
3301
3302 var dir = try b.root.openDir(io, "test/cases", .{ .iterate = true });
3303 defer dir.close(io);
3304
3305 cases.addFromDir(dir, "test/cases", b);
3306 try @import("cases.zig").addCases(&cases, build_options, b);
3307
3308 cases.lowerToBuildSteps(
3309 b,
3310 parent_step,
3311 case_test_options,
3312 );
3313}
3314
3315pub fn addDebuggerTests(b: *std.Build, options: DebuggerContext.Options) ?*Step {
3316 const step = b.step("test-debugger", "Run the debugger tests");
3317 if (options.gdb == null and options.lldb == null) {
3318 step.dependOn(&b.addFail("test-debugger requires -Dgdb and/or -Dlldb").step);
3319 return null;
3320 }
3321
3322 var context: DebuggerContext = .{
3323 .b = b,
3324 .options = options,
3325 .root_step = step,
3326 };
3327 context.addTestsForTarget(&.{
3328 .resolved = b.resolveTargetQuery(.{
3329 .cpu_arch = .x86_64,
3330 .os_tag = .linux,
3331 .abi = .none,
3332 }),
3333 .pic = false,
3334 .test_name_suffix = "x86_64-linux",
3335 });
3336 context.addTestsForTarget(&.{
3337 .resolved = b.resolveTargetQuery(.{
3338 .cpu_arch = .x86_64,
3339 .os_tag = .linux,
3340 .abi = .none,
3341 }),
3342 .pic = true,
3343 .test_name_suffix = "x86_64-linux-pic",
3344 });
3345 return step;
3346}
3347
3348const IncrementalTestOptions = struct {
3349 test_filters: []const []const u8,
3350 test_target_filters: []const []const u8,
3351 skip_non_native: bool,
3352 skip_wasm: bool,
3353 skip_freebsd: bool,
3354 skip_netbsd: bool,
3355 skip_openbsd: bool,
3356 skip_windows: bool,
3357 skip_darwin: bool,
3358 skip_linux: bool,
3359 skip_llvm: bool,
3360};
3361
3362pub fn addIncrementalTests(
3363 b: *std.Build,
3364 test_step: *Step,
3365 options: IncrementalTestOptions,
3366) !void {
3367 const io = b.graph.io;
3368
3369 const incr_check = b.addExecutable(.{
3370 .name = "incr-check",
3371 .root_module = b.createModule(.{
3372 .root_source_file = b.path("tools/incr-check.zig"),
3373 .target = b.graph.host,
3374 .optimize = .debug,
3375 }),
3376 });
3377
3378 b.dependOnDirectory(b.path("test/incremental"));
3379
3380 var dir = try b.root.openDir(io, "test/incremental", .{ .iterate = true });
3381 defer dir.close(io);
3382
3383 var it = try dir.walk(b.graph.arena);
3384 while (try it.next(io)) |entry| {
3385 if (std.mem.endsWith(u8, entry.basename, ".swp")) continue;
3386
3387 for (options.test_filters) |test_filter| {
3388 if (std.mem.find(u8, entry.path, test_filter)) |_| break;
3389 } else if (options.test_filters.len > 0) continue;
3390
3391 switch (entry.kind) {
3392 .file => {},
3393 .directory => {
3394 b.dependOnDirectory(b.path(b.pathJoin(&.{ "test", "incremental", entry.path })));
3395 },
3396 else => continue,
3397 }
3398 b.dependOnFileContents(b.path(b.pathJoin(&.{ "test", "incremental", entry.path })));
3399
3400 for (incremental_targets) |test_target| {
3401 const resolved_target = b.resolveTargetQuery(test_target.target);
3402
3403 if (options.skip_non_native and !isNative(&resolved_target, &b.graph.host.result))
3404 continue;
3405
3406 const target = &resolved_target.result;
3407
3408 if (options.skip_wasm and target.cpu.arch.isWasm()) continue;
3409
3410 if (options.skip_freebsd and target.os.tag == .freebsd) continue;
3411 if (options.skip_netbsd and target.os.tag == .netbsd) continue;
3412 if (options.skip_openbsd and target.os.tag == .openbsd) continue;
3413 if (options.skip_windows and target.os.tag == .windows) continue;
3414 if (options.skip_darwin and target.os.tag.isDarwin()) continue;
3415 if (options.skip_linux and target.os.tag == .linux) continue;
3416
3417 if (options.skip_llvm and test_target.backend == .llvm) continue;
3418
3419 const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM");
3420
3421 if (options.test_target_filters.len > 0) {
3422 for (options.test_target_filters) |filter| {
3423 if (std.mem.find(u8, triple_txt, filter) != null) break;
3424 } else continue;
3425 }
3426
3427 const target_str = b.fmt("{s}-{t}", .{ triple_txt, test_target.backend });
3428
3429 const run = b.addRunArtifact(incr_check);
3430 run.setName(b.fmt("incr-check {s} '{s}'", .{ target_str, entry.basename }));
3431
3432 run.addArg(b.graph.zig_exe);
3433 run.addFileArg(b.path("test/incremental/").path(b, entry.path));
3434
3435 run.addArg("--zig-lib-dir");
3436 run.addDirectoryArg(.zig_lib);
3437
3438 run.addArgs(&.{ "--target", target_str });
3439
3440 run.addArg("--quiet"); // don't fill stderr telling us about skipped tests etc
3441
3442 run.addThirdPartyEnabledArgDarling(.{ .enabled = "-fdarling" });
3443 run.addThirdPartyEnabledArgQemu(.{ .enabled = "-fqemu" });
3444 run.addThirdPartyEnabledArgRosetta(.{ .enabled = "-frosetta" });
3445 run.addThirdPartyEnabledArgWasmtime(.{ .enabled = "-fwasmtime" });
3446 run.addThirdPartyEnabledArgWine(.{ .enabled = "-fwine" });
3447
3448 run.addCheck(.{ .expect_term = .{ .exited = 0 } });
3449 test_step.dependOn(&run.step);
3450 }
3451 }
3452}
3453
3454pub fn addLlvmIrTests(b: *std.Build, options: LlvmIrContext.Options) ?*Step {
3455 const step = b.step("test-llvm-ir", "Run the LLVM IR tests");
3456
3457 if (!options.enable_llvm) {
3458 step.dependOn(&b.addFail("test-llvm-ir requires -Denable-llvm").step);
3459 return null;
3460 }
3461
3462 var context: LlvmIrContext = .{
3463 .b = b,
3464 .options = options,
3465 .root_step = step,
3466 };
3467
3468 llvm_ir.addCases(&context);
3469
3470 return step;
3471}
3472
3473const libc_test_nsz_targets: []const std.Target.Query = &.{
3474 .{
3475 .cpu_arch = .arm,
3476 .os_tag = .linux,
3477 .abi = .musleabi,
3478 },
3479 .{
3480 .cpu_arch = .arm,
3481 .os_tag = .linux,
3482 .abi = .musleabihf,
3483 },
3484 .{
3485 .cpu_arch = .armeb,
3486 .os_tag = .linux,
3487 .abi = .musleabi,
3488 },
3489 .{
3490 .cpu_arch = .armeb,
3491 .os_tag = .linux,
3492 .abi = .musleabihf,
3493 },
3494 .{
3495 .cpu_arch = .thumb,
3496 .os_tag = .linux,
3497 .abi = .musleabi,
3498 },
3499 .{
3500 .cpu_arch = .thumb,
3501 .os_tag = .linux,
3502 .abi = .musleabihf,
3503 },
3504 .{
3505 .cpu_arch = .thumbeb,
3506 .os_tag = .linux,
3507 .abi = .musleabi,
3508 },
3509 .{
3510 .cpu_arch = .thumbeb,
3511 .os_tag = .linux,
3512 .abi = .musleabihf,
3513 },
3514 .{
3515 .cpu_arch = .aarch64,
3516 .os_tag = .linux,
3517 .abi = .musl,
3518 },
3519 .{
3520 .cpu_arch = .aarch64_be,
3521 .os_tag = .linux,
3522 .abi = .musl,
3523 },
3524 // .{
3525 // .cpu_arch = .hexagon,
3526 // .os_tag = .linux,
3527 // .abi = .musl,
3528 // },
3529 .{
3530 .cpu_arch = .loongarch64,
3531 .os_tag = .linux,
3532 .abi = .musl,
3533 },
3534 .{
3535 .cpu_arch = .loongarch64,
3536 .os_tag = .linux,
3537 .abi = .muslsf,
3538 },
3539 // .{
3540 // .cpu_arch = .mips,
3541 // .os_tag = .linux,
3542 // .abi = .musleabi,
3543 // },
3544 // .{
3545 // .cpu_arch = .mips,
3546 // .os_tag = .linux,
3547 // .abi = .musleabihf,
3548 // },
3549 // .{
3550 // .cpu_arch = .mipsel,
3551 // .os_tag = .linux,
3552 // .abi = .musleabi,
3553 // },
3554 // .{
3555 // .cpu_arch = .mipsel,
3556 // .os_tag = .linux,
3557 // .abi = .musleabihf,
3558 // },
3559 // .{
3560 // .cpu_arch = .mips64,
3561 // .os_tag = .linux,
3562 // .abi = .muslabi64,
3563 // },
3564 // .{
3565 // .cpu_arch = .mips64,
3566 // .os_tag = .linux,
3567 // .abi = .muslabin32,
3568 // },
3569 // .{
3570 // .cpu_arch = .mips64el,
3571 // .os_tag = .linux,
3572 // .abi = .muslabi64,
3573 // },
3574 // .{
3575 // .cpu_arch = .mips64el,
3576 // .os_tag = .linux,
3577 // .abi = .muslabin32,
3578 // },
3579 .{
3580 .cpu_arch = .powerpc,
3581 .os_tag = .linux,
3582 .abi = .musleabi,
3583 },
3584 .{
3585 .cpu_arch = .powerpc,
3586 .os_tag = .linux,
3587 .abi = .musleabihf,
3588 },
3589 .{
3590 .cpu_arch = .powerpc64,
3591 .os_tag = .linux,
3592 .abi = .musl,
3593 },
3594 .{
3595 .cpu_arch = .powerpc64le,
3596 .os_tag = .linux,
3597 .abi = .musl,
3598 },
3599 .{
3600 .cpu_arch = .riscv32,
3601 .os_tag = .linux,
3602 .abi = .musl,
3603 },
3604 .{
3605 .cpu_arch = .riscv64,
3606 .os_tag = .linux,
3607 .abi = .musl,
3608 },
3609 .{
3610 .cpu_arch = .s390x,
3611 .os_tag = .linux,
3612 .abi = .musl,
3613 },
3614 .{
3615 .cpu_arch = .wasm32,
3616 .os_tag = .wasi,
3617 .abi = .musl,
3618 },
3619 .{
3620 .cpu_arch = .x86,
3621 .os_tag = .linux,
3622 .abi = .musl,
3623 },
3624 .{
3625 .cpu_arch = .x86_64,
3626 .os_tag = .linux,
3627 .abi = .musl,
3628 },
3629 .{
3630 .cpu_arch = .x86_64,
3631 .os_tag = .linux,
3632 .abi = .muslx32,
3633 },
3634};
3635
3636pub fn addLibcTestNszTests(b: *std.Build, options: LibcContext.Options) ?*Step {
3637 const step = b.step("test-libc-nsz", "Run external libc-test test cases");
3638 const opt_libc_test_path = b.option(std.Build.LazyPath, "libc-test-path", "path to libc-test source directory");
3639 if (opt_libc_test_path) |libc_test_path| {
3640 var context: LibcContext = .{
3641 .b = b,
3642 .options = options,
3643 .root_step = step,
3644 .libc_test_src_path = libc_test_path.path(b, "src"),
3645 };
3646
3647 libc.addCases(&context);
3648
3649 for (libc_test_nsz_targets) |target_query| {
3650 const target = b.resolveTargetQuery(target_query);
3651 context.addTarget(target);
3652 }
3653
3654 return step;
3655 } else {
3656 step.dependOn(&b.addFail("The -Dlibc-test-path=... option is required for this step").step);
3657 return null;
3658 }
3659}