authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-03-13 14:46:45+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-03-13 14:46:45+01:00
logb9cca3b63dbcedadbda1c884e5b3333c8458b30d
tree48279d466c04e4771d4b315db590c9bbfcbd4868
parent153ba46a5b20f178d48ef2f09e0e638a3749af0e
parent7ba2453b8ec56ccacfccc466183e1aaafbd5210e
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #19257 from ziglang/elf-aarch64-thunks-2

elf+aarch64: fix off-by-one in converging on groups interleaved with thunks

4 files changed, 131 insertions(+), 68 deletions(-)

src/link/Elf.zig+27-7
...@@ -4565,6 +4565,22 @@ fn writeAtoms(self: *Elf) !void {...@@ -4565,6 +4565,22 @@ fn writeAtoms(self: *Elf) !void {
4565 try self.base.file.?.pwriteAll(buffer, sh_offset);4565 try self.base.file.?.pwriteAll(buffer, sh_offset);
4566 }4566 }
45674567
4568 if (self.requiresThunks()) {
4569 var buffer = std.ArrayList(u8).init(gpa);
4570 defer buffer.deinit();
4571
4572 for (self.thunks.items) |th| {
4573 const thunk_size = th.size(self);
4574 try buffer.ensureUnusedCapacity(thunk_size);
4575 const shdr = self.shdrs.items[th.output_section_index];
4576 const offset = th.value + shdr.sh_offset;
4577 try th.write(self, buffer.writer());
4578 assert(buffer.items.len == thunk_size);
4579 try self.base.file.?.pwriteAll(buffer.items, offset);
4580 buffer.clearRetainingCapacity();
4581 }
4582 }
4583
4568 try self.reportUndefinedSymbols(&undefs);4584 try self.reportUndefinedSymbols(&undefs);
45694585
4570 if (has_reloc_errors) return error.FlushFailure;4586 if (has_reloc_errors) return error.FlushFailure;
...@@ -4593,12 +4609,12 @@ pub fn updateSymtabSize(self: *Elf) !void {...@@ -4593,12 +4609,12 @@ pub fn updateSymtabSize(self: *Elf) !void {
4593 nlocals += 1;4609 nlocals += 1;
4594 }4610 }
45954611
4596 for (self.thunks.items) |*th| {4612 if (self.requiresThunks()) for (self.thunks.items) |*th| {
4597 th.output_symtab_ctx.ilocal = nlocals + 1;4613 th.output_symtab_ctx.ilocal = nlocals + 1;
4598 th.calcSymtabSize(self);4614 th.calcSymtabSize(self);
4599 nlocals += th.output_symtab_ctx.nlocals;4615 nlocals += th.output_symtab_ctx.nlocals;
4600 strsize += th.output_symtab_ctx.strsize;4616 strsize += th.output_symtab_ctx.strsize;
4601 }4617 };
46024618
4603 for (files.items) |index| {4619 for (files.items) |index| {
4604 const file_ptr = self.file(index).?;4620 const file_ptr = self.file(index).?;
...@@ -4830,9 +4846,9 @@ pub fn writeSymtab(self: *Elf) !void {...@@ -4830,9 +4846,9 @@ pub fn writeSymtab(self: *Elf) !void {
48304846
4831 self.writeSectionSymbols();4847 self.writeSectionSymbols();
48324848
4833 for (self.thunks.items) |th| {4849 if (self.requiresThunks()) for (self.thunks.items) |th| {
4834 th.writeSymtab(self);4850 th.writeSymtab(self);
4835 }4851 };
48364852
4837 if (self.zigObjectPtr()) |zig_object| {4853 if (self.zigObjectPtr()) |zig_object| {
4838 zig_object.asFile().writeSymtab(self);4854 zig_object.asFile().writeSymtab(self);
...@@ -5997,10 +6013,14 @@ fn fmtDumpState(...@@ -5997,10 +6013,14 @@ fn fmtDumpState(
5997 try writer.print("linker_defined({d}) : (linker defined)\n", .{index});6013 try writer.print("linker_defined({d}) : (linker defined)\n", .{index});
5998 try writer.print("{}\n", .{linker_defined.fmtSymtab(self)});6014 try writer.print("{}\n", .{linker_defined.fmtSymtab(self)});
5999 }6015 }
6000 try writer.writeAll("thunks\n");6016
6001 for (self.thunks.items, 0..) |th, index| {6017 if (self.requiresThunks()) {
6002 try writer.print("thunk({d}) : {}\n", .{ index, th.fmt(self) });6018 try writer.writeAll("thunks\n");
6019 for (self.thunks.items, 0..) |th, index| {
6020 try writer.print("thunk({d}) : {}\n", .{ index, th.fmt(self) });
6021 }
6003 }6022 }
6023
6004 try writer.print("{}\n", .{self.zig_got.fmt(self)});6024 try writer.print("{}\n", .{self.zig_got.fmt(self)});
6005 try writer.print("{}\n", .{self.got.fmt(self)});6025 try writer.print("{}\n", .{self.got.fmt(self)});
6006 try writer.print("{}\n", .{self.plt.fmt(self)});6026 try writer.print("{}\n", .{self.plt.fmt(self)});
src/link/Elf/thunks.zig+4-4
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1pub fn createThunks(shndx: u32, elf_file: *Elf) !void {1pub fn createThunks(shndx: u32, elf_file: *Elf) !void {
2 const gpa = elf_file.base.comp.gpa;2 const gpa = elf_file.base.comp.gpa;
3 const cpu_arch = elf_file.getTarget().cpu.arch;3 const cpu_arch = elf_file.getTarget().cpu.arch;
4 const max_distance = maxAllowedDistance(cpu_arch);
4 const shdr = &elf_file.shdrs.items[shndx];5 const shdr = &elf_file.shdrs.items[shndx];
5 const atoms = elf_file.output_sections.get(shndx).?.items;6 const atoms = elf_file.output_sections.get(shndx).?.items;
6 assert(atoms.len > 0);7 assert(atoms.len > 0);
...@@ -17,12 +18,11 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {...@@ -17,12 +18,11 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {
17 start_atom.value = try advance(shdr, start_atom.size, start_atom.alignment);18 start_atom.value = try advance(shdr, start_atom.size, start_atom.alignment);
18 i += 1;19 i += 1;
1920
20 while (i < atoms.len and21 while (i < atoms.len) : (i += 1) {
21 shdr.sh_size - start_atom.value < maxAllowedDistance(cpu_arch)) : (i += 1)
22 {
23 const atom_index = atoms[i];22 const atom_index = atoms[i];
24 const atom = elf_file.atom(atom_index).?;23 const atom = elf_file.atom(atom_index).?;
25 assert(atom.flags.alive);24 assert(atom.flags.alive);
25 if (atom.alignment.forward(shdr.sh_size) - start_atom.value >= max_distance) break;
26 atom.value = try advance(shdr, atom.size, atom.alignment);26 atom.value = try advance(shdr, atom.size, atom.alignment);
27 }27 }
2828
...@@ -103,7 +103,7 @@ pub const Thunk = struct {...@@ -103,7 +103,7 @@ pub const Thunk = struct {
103 }103 }
104104
105 pub fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void {105 pub fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void {
106 switch (elf_file.options.cpu_arch.?) {106 switch (elf_file.getTarget().cpu.arch) {
107 .aarch64 => try aarch64.write(thunk, elf_file, writer),107 .aarch64 => try aarch64.write(thunk, elf_file, writer),
108 .x86_64, .riscv64 => unreachable,108 .x86_64, .riscv64 => unreachable,
109 else => @panic("unhandled arch"),109 else => @panic("unhandled arch"),
test/link/elf.zig+53-10
...@@ -20,16 +20,11 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {...@@ -20,16 +20,11 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
20 .os_tag = .linux,20 .os_tag = .linux,
21 .abi = .gnu,21 .abi = .gnu,
22 });22 });
23 // const aarch64_musl = b.resolveTargetQuery(.{23 const aarch64_musl = b.resolveTargetQuery(.{
24 // .cpu_arch = .aarch64,24 .cpu_arch = .aarch64,
25 // .os_tag = .linux,25 .os_tag = .linux,
26 // .abi = .musl,26 .abi = .musl,
27 // });27 });
28 // const aarch64_gnu = b.resolveTargetQuery(.{
29 // .cpu_arch = .aarch64,
30 // .os_tag = .linux,
31 // .abi = .gnu,
32 // });
33 const riscv64_musl = b.resolveTargetQuery(.{28 const riscv64_musl = b.resolveTargetQuery(.{
34 .cpu_arch = .riscv64,29 .cpu_arch = .riscv64,
35 .os_tag = .linux,30 .os_tag = .linux,
...@@ -153,6 +148,9 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {...@@ -153,6 +148,9 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
153 elf_step.dependOn(testMismatchedCpuArchitectureError(b, .{ .target = x86_64_musl }));148 elf_step.dependOn(testMismatchedCpuArchitectureError(b, .{ .target = x86_64_musl }));
154 elf_step.dependOn(testZText(b, .{ .target = x86_64_gnu }));149 elf_step.dependOn(testZText(b, .{ .target = x86_64_gnu }));
155150
151 // aarch64 specific tests
152 elf_step.dependOn(testThunks(b, .{ .target = aarch64_musl }));
153
156 // x86_64 self-hosted backend154 // x86_64 self-hosted backend
157 elf_step.dependOn(testEmitRelocatable(b, .{ .use_llvm = false, .target = x86_64_musl }));155 elf_step.dependOn(testEmitRelocatable(b, .{ .use_llvm = false, .target = x86_64_musl }));
158 elf_step.dependOn(testEmitStaticLibZig(b, .{ .use_llvm = false, .target = x86_64_musl }));156 elf_step.dependOn(testEmitStaticLibZig(b, .{ .use_llvm = false, .target = x86_64_musl }));
...@@ -2670,6 +2668,51 @@ fn testStrip(b: *Build, opts: Options) *Step {...@@ -2670,6 +2668,51 @@ fn testStrip(b: *Build, opts: Options) *Step {
2670 return test_step;2668 return test_step;
2671}2669}
26722670
2671fn testThunks(b: *Build, opts: Options) *Step {
2672 const test_step = addTestStep(b, "thunks", opts);
2673
2674 const src =
2675 \\#include <stdio.h>
2676 \\__attribute__((aligned(0x8000000))) int bar() {
2677 \\ return 42;
2678 \\}
2679 \\int foobar();
2680 \\int foo() {
2681 \\ return bar() - foobar();
2682 \\}
2683 \\__attribute__((aligned(0x8000000))) int foobar() {
2684 \\ return 42;
2685 \\}
2686 \\int main() {
2687 \\ printf("bar=%d, foo=%d, foobar=%d", bar(), foo(), foobar());
2688 \\ return foo();
2689 \\}
2690 ;
2691
2692 {
2693 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = src });
2694 exe.link_function_sections = true;
2695 exe.linkLibC();
2696
2697 const run = addRunArtifact(exe);
2698 run.expectStdOutEqual("bar=42, foo=0, foobar=42");
2699 run.expectExitCode(0);
2700 test_step.dependOn(&run.step);
2701 }
2702
2703 {
2704 const exe = addExecutable(b, opts, .{ .name = "main2", .c_source_bytes = src });
2705 exe.linkLibC();
2706
2707 const run = addRunArtifact(exe);
2708 run.expectStdOutEqual("bar=42, foo=0, foobar=42");
2709 run.expectExitCode(0);
2710 test_step.dependOn(&run.step);
2711 }
2712
2713 return test_step;
2714}
2715
2673fn testTlsDfStaticTls(b: *Build, opts: Options) *Step {2716fn testTlsDfStaticTls(b: *Build, opts: Options) *Step {
2674 const test_step = addTestStep(b, "tls-df-static-tls", opts);2717 const test_step = addTestStep(b, "tls-df-static-tls", opts);
26752718
test/link/macho.zig+47-47
...@@ -91,7 +91,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {...@@ -91,7 +91,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
91}91}
9292
93fn testDeadStrip(b: *Build, opts: Options) *Step {93fn testDeadStrip(b: *Build, opts: Options) *Step {
94 const test_step = addTestStep(b, "macho-dead-strip", opts);94 const test_step = addTestStep(b, "dead-strip", opts);
9595
96 const obj = addObject(b, opts, .{ .name = "a", .cpp_source_bytes = 96 const obj = addObject(b, opts, .{ .name = "a", .cpp_source_bytes =
97 \\#include <stdio.h>97 \\#include <stdio.h>
...@@ -172,7 +172,7 @@ fn testDeadStrip(b: *Build, opts: Options) *Step {...@@ -172,7 +172,7 @@ fn testDeadStrip(b: *Build, opts: Options) *Step {
172}172}
173173
174fn testDeadStripDylibs(b: *Build, opts: Options) *Step {174fn testDeadStripDylibs(b: *Build, opts: Options) *Step {
175 const test_step = addTestStep(b, "macho-dead-strip-dylibs", opts);175 const test_step = addTestStep(b, "dead-strip-dylibs", opts);
176176
177 const main_o = addObject(b, opts, .{ .name = "main", .c_source_bytes = 177 const main_o = addObject(b, opts, .{ .name = "main", .c_source_bytes =
178 \\#include <objc/runtime.h>178 \\#include <objc/runtime.h>
...@@ -221,7 +221,7 @@ fn testDeadStripDylibs(b: *Build, opts: Options) *Step {...@@ -221,7 +221,7 @@ fn testDeadStripDylibs(b: *Build, opts: Options) *Step {
221}221}
222222
223fn testDylib(b: *Build, opts: Options) *Step {223fn testDylib(b: *Build, opts: Options) *Step {
224 const test_step = addTestStep(b, "macho-dylib", opts);224 const test_step = addTestStep(b, "dylib", opts);
225225
226 const dylib = addSharedLibrary(b, opts, .{ .name = "a", .c_source_bytes = 226 const dylib = addSharedLibrary(b, opts, .{ .name = "a", .c_source_bytes =
227 \\#include<stdio.h>227 \\#include<stdio.h>
...@@ -258,7 +258,7 @@ fn testDylib(b: *Build, opts: Options) *Step {...@@ -258,7 +258,7 @@ fn testDylib(b: *Build, opts: Options) *Step {
258}258}
259259
260fn testDylibVersionTbd(b: *Build, opts: Options) *Step {260fn testDylibVersionTbd(b: *Build, opts: Options) *Step {
261 const test_step = addTestStep(b, "macho-dylib-version-tbd", opts);261 const test_step = addTestStep(b, "dylib-version-tbd", opts);
262262
263 const tbd = tbd: {263 const tbd = tbd: {
264 const wf = WriteFile.create(b);264 const wf = WriteFile.create(b);
...@@ -294,7 +294,7 @@ fn testDylibVersionTbd(b: *Build, opts: Options) *Step {...@@ -294,7 +294,7 @@ fn testDylibVersionTbd(b: *Build, opts: Options) *Step {
294}294}
295295
296fn testEmptyObject(b: *Build, opts: Options) *Step {296fn testEmptyObject(b: *Build, opts: Options) *Step {
297 const test_step = addTestStep(b, "macho-empty-object", opts);297 const test_step = addTestStep(b, "empty-object", opts);
298298
299 const empty = addObject(b, opts, .{ .name = "empty", .c_source_bytes = "" });299 const empty = addObject(b, opts, .{ .name = "empty", .c_source_bytes = "" });
300300
...@@ -314,7 +314,7 @@ fn testEmptyObject(b: *Build, opts: Options) *Step {...@@ -314,7 +314,7 @@ fn testEmptyObject(b: *Build, opts: Options) *Step {
314}314}
315315
316fn testEmptyZig(b: *Build, opts: Options) *Step {316fn testEmptyZig(b: *Build, opts: Options) *Step {
317 const test_step = addTestStep(b, "macho-empty-zig", opts);317 const test_step = addTestStep(b, "empty-zig", opts);
318318
319 const exe = addExecutable(b, opts, .{ .name = "empty", .zig_source_bytes = "pub fn main() void {}" });319 const exe = addExecutable(b, opts, .{ .name = "empty", .zig_source_bytes = "pub fn main() void {}" });
320320
...@@ -326,7 +326,7 @@ fn testEmptyZig(b: *Build, opts: Options) *Step {...@@ -326,7 +326,7 @@ fn testEmptyZig(b: *Build, opts: Options) *Step {
326}326}
327327
328fn testEntryPoint(b: *Build, opts: Options) *Step {328fn testEntryPoint(b: *Build, opts: Options) *Step {
329 const test_step = addTestStep(b, "macho-entry-point", opts);329 const test_step = addTestStep(b, "entry-point", opts);
330330
331 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = 331 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes =
332 \\#include<stdio.h>332 \\#include<stdio.h>
...@@ -357,7 +357,7 @@ fn testEntryPoint(b: *Build, opts: Options) *Step {...@@ -357,7 +357,7 @@ fn testEntryPoint(b: *Build, opts: Options) *Step {
357}357}
358358
359fn testEntryPointArchive(b: *Build, opts: Options) *Step {359fn testEntryPointArchive(b: *Build, opts: Options) *Step {
360 const test_step = addTestStep(b, "macho-entry-point-archive", opts);360 const test_step = addTestStep(b, "entry-point-archive", opts);
361361
362 const lib = addStaticLibrary(b, opts, .{ .name = "main", .c_source_bytes = "int main() { return 0; }" });362 const lib = addStaticLibrary(b, opts, .{ .name = "main", .c_source_bytes = "int main() { return 0; }" });
363363
...@@ -386,7 +386,7 @@ fn testEntryPointArchive(b: *Build, opts: Options) *Step {...@@ -386,7 +386,7 @@ fn testEntryPointArchive(b: *Build, opts: Options) *Step {
386}386}
387387
388fn testEntryPointDylib(b: *Build, opts: Options) *Step {388fn testEntryPointDylib(b: *Build, opts: Options) *Step {
389 const test_step = addTestStep(b, "macho-entry-point-dylib", opts);389 const test_step = addTestStep(b, "entry-point-dylib", opts);
390390
391 const dylib = addSharedLibrary(b, opts, .{ .name = "a" });391 const dylib = addSharedLibrary(b, opts, .{ .name = "a" });
392 addCSourceBytes(dylib,392 addCSourceBytes(dylib,
...@@ -440,7 +440,7 @@ fn testEntryPointDylib(b: *Build, opts: Options) *Step {...@@ -440,7 +440,7 @@ fn testEntryPointDylib(b: *Build, opts: Options) *Step {
440}440}
441441
442fn testHeaderpad(b: *Build, opts: Options) *Step {442fn testHeaderpad(b: *Build, opts: Options) *Step {
443 const test_step = addTestStep(b, "macho-headerpad", opts);443 const test_step = addTestStep(b, "headerpad", opts);
444444
445 const addExe = struct {445 const addExe = struct {
446 fn addExe(bb: *Build, o: Options, name: []const u8) *Compile {446 fn addExe(bb: *Build, o: Options, name: []const u8) *Compile {
...@@ -548,7 +548,7 @@ fn testHeaderpad(b: *Build, opts: Options) *Step {...@@ -548,7 +548,7 @@ fn testHeaderpad(b: *Build, opts: Options) *Step {
548548
549// Adapted from https://github.com/llvm/llvm-project/blob/main/lld/test/MachO/weak-header-flags.s549// Adapted from https://github.com/llvm/llvm-project/blob/main/lld/test/MachO/weak-header-flags.s
550fn testHeaderWeakFlags(b: *Build, opts: Options) *Step {550fn testHeaderWeakFlags(b: *Build, opts: Options) *Step {
551 const test_step = addTestStep(b, "macho-header-weak-flags", opts);551 const test_step = addTestStep(b, "header-weak-flags", opts);
552552
553 const obj1 = addObject(b, opts, .{ .name = "a", .asm_source_bytes = 553 const obj1 = addObject(b, opts, .{ .name = "a", .asm_source_bytes =
554 \\.globl _x554 \\.globl _x
...@@ -635,7 +635,7 @@ fn testHeaderWeakFlags(b: *Build, opts: Options) *Step {...@@ -635,7 +635,7 @@ fn testHeaderWeakFlags(b: *Build, opts: Options) *Step {
635}635}
636636
637fn testHelloC(b: *Build, opts: Options) *Step {637fn testHelloC(b: *Build, opts: Options) *Step {
638 const test_step = addTestStep(b, "macho-hello-c", opts);638 const test_step = addTestStep(b, "hello-c", opts);
639639
640 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = 640 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes =
641 \\#include <stdio.h>641 \\#include <stdio.h>
...@@ -659,7 +659,7 @@ fn testHelloC(b: *Build, opts: Options) *Step {...@@ -659,7 +659,7 @@ fn testHelloC(b: *Build, opts: Options) *Step {
659}659}
660660
661fn testHelloZig(b: *Build, opts: Options) *Step {661fn testHelloZig(b: *Build, opts: Options) *Step {
662 const test_step = addTestStep(b, "macho-hello-zig", opts);662 const test_step = addTestStep(b, "hello-zig", opts);
663663
664 const exe = addExecutable(b, opts, .{ .name = "main", .zig_source_bytes = 664 const exe = addExecutable(b, opts, .{ .name = "main", .zig_source_bytes =
665 \\const std = @import("std");665 \\const std = @import("std");
...@@ -676,7 +676,7 @@ fn testHelloZig(b: *Build, opts: Options) *Step {...@@ -676,7 +676,7 @@ fn testHelloZig(b: *Build, opts: Options) *Step {
676}676}
677677
678fn testLargeBss(b: *Build, opts: Options) *Step {678fn testLargeBss(b: *Build, opts: Options) *Step {
679 const test_step = addTestStep(b, "macho-large-bss", opts);679 const test_step = addTestStep(b, "large-bss", opts);
680680
681 // TODO this test used use a 4GB zerofill section but this actually fails and causes every681 // TODO this test used use a 4GB zerofill section but this actually fails and causes every
682 // linker I tried misbehave in different ways. This only happened on arm64. I thought that682 // linker I tried misbehave in different ways. This only happened on arm64. I thought that
...@@ -697,7 +697,7 @@ fn testLargeBss(b: *Build, opts: Options) *Step {...@@ -697,7 +697,7 @@ fn testLargeBss(b: *Build, opts: Options) *Step {
697}697}
698698
699fn testLayout(b: *Build, opts: Options) *Step {699fn testLayout(b: *Build, opts: Options) *Step {
700 const test_step = addTestStep(b, "macho-layout", opts);700 const test_step = addTestStep(b, "layout", opts);
701701
702 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = 702 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes =
703 \\#include <stdio.h>703 \\#include <stdio.h>
...@@ -816,7 +816,7 @@ fn testLayout(b: *Build, opts: Options) *Step {...@@ -816,7 +816,7 @@ fn testLayout(b: *Build, opts: Options) *Step {
816}816}
817817
818fn testLinkDirectlyCppTbd(b: *Build, opts: Options) *Step {818fn testLinkDirectlyCppTbd(b: *Build, opts: Options) *Step {
819 const test_step = addTestStep(b, "macho-link-directly-cpp-tbd", opts);819 const test_step = addTestStep(b, "link-directly-cpp-tbd", opts);
820820
821 const sdk = std.zig.system.darwin.getSdk(b.allocator, opts.target.result) orelse821 const sdk = std.zig.system.darwin.getSdk(b.allocator, opts.target.result) orelse
822 @panic("macOS SDK is required to run the test");822 @panic("macOS SDK is required to run the test");
...@@ -887,7 +887,7 @@ fn testLinkingStaticLib(b: *Build, opts: Options) *Step {...@@ -887,7 +887,7 @@ fn testLinkingStaticLib(b: *Build, opts: Options) *Step {
887}887}
888888
889fn testLinksection(b: *Build, opts: Options) *Step {889fn testLinksection(b: *Build, opts: Options) *Step {
890 const test_step = addTestStep(b, "macho-linksection", opts);890 const test_step = addTestStep(b, "linksection", opts);
891891
892 const obj = addObject(b, opts, .{ .name = "main", .zig_source_bytes = 892 const obj = addObject(b, opts, .{ .name = "main", .zig_source_bytes =
893 \\export var test_global: u32 linksection("__DATA,__TestGlobal") = undefined;893 \\export var test_global: u32 linksection("__DATA,__TestGlobal") = undefined;
...@@ -914,7 +914,7 @@ fn testLinksection(b: *Build, opts: Options) *Step {...@@ -914,7 +914,7 @@ fn testLinksection(b: *Build, opts: Options) *Step {
914}914}
915915
916fn testMhExecuteHeader(b: *Build, opts: Options) *Step {916fn testMhExecuteHeader(b: *Build, opts: Options) *Step {
917 const test_step = addTestStep(b, "macho-mh-execute-header", opts);917 const test_step = addTestStep(b, "mh-execute-header", opts);
918918
919 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = "int main() { return 0; }" });919 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = "int main() { return 0; }" });
920920
...@@ -927,7 +927,7 @@ fn testMhExecuteHeader(b: *Build, opts: Options) *Step {...@@ -927,7 +927,7 @@ fn testMhExecuteHeader(b: *Build, opts: Options) *Step {
927}927}
928928
929fn testNoDeadStrip(b: *Build, opts: Options) *Step {929fn testNoDeadStrip(b: *Build, opts: Options) *Step {
930 const test_step = addTestStep(b, "macho-no-dead-strip", opts);930 const test_step = addTestStep(b, "no-dead-strip", opts);
931931
932 const exe = addExecutable(b, opts, .{ .name = "name", .c_source_bytes = 932 const exe = addExecutable(b, opts, .{ .name = "name", .c_source_bytes =
933 \\__attribute__((used)) int bogus1 = 0;933 \\__attribute__((used)) int bogus1 = 0;
...@@ -954,7 +954,7 @@ fn testNoDeadStrip(b: *Build, opts: Options) *Step {...@@ -954,7 +954,7 @@ fn testNoDeadStrip(b: *Build, opts: Options) *Step {
954}954}
955955
956fn testNoExportsDylib(b: *Build, opts: Options) *Step {956fn testNoExportsDylib(b: *Build, opts: Options) *Step {
957 const test_step = addTestStep(b, "macho-no-exports-dylib", opts);957 const test_step = addTestStep(b, "no-exports-dylib", opts);
958958
959 const dylib = addSharedLibrary(b, opts, .{ .name = "a", .c_source_bytes = "static void abc() {}" });959 const dylib = addSharedLibrary(b, opts, .{ .name = "a", .c_source_bytes = "static void abc() {}" });
960960
...@@ -967,7 +967,7 @@ fn testNoExportsDylib(b: *Build, opts: Options) *Step {...@@ -967,7 +967,7 @@ fn testNoExportsDylib(b: *Build, opts: Options) *Step {
967}967}
968968
969fn testNeededFramework(b: *Build, opts: Options) *Step {969fn testNeededFramework(b: *Build, opts: Options) *Step {
970 const test_step = addTestStep(b, "macho-needed-framework", opts);970 const test_step = addTestStep(b, "needed-framework", opts);
971971
972 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = "int main() { return 0; }" });972 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = "int main() { return 0; }" });
973 exe.root_module.linkFramework("Cocoa", .{ .needed = true });973 exe.root_module.linkFramework("Cocoa", .{ .needed = true });
...@@ -987,7 +987,7 @@ fn testNeededFramework(b: *Build, opts: Options) *Step {...@@ -987,7 +987,7 @@ fn testNeededFramework(b: *Build, opts: Options) *Step {
987}987}
988988
989fn testNeededLibrary(b: *Build, opts: Options) *Step {989fn testNeededLibrary(b: *Build, opts: Options) *Step {
990 const test_step = addTestStep(b, "macho-needed-library", opts);990 const test_step = addTestStep(b, "needed-library", opts);
991991
992 const dylib = addSharedLibrary(b, opts, .{ .name = "a", .c_source_bytes = "int a = 42;" });992 const dylib = addSharedLibrary(b, opts, .{ .name = "a", .c_source_bytes = "int a = 42;" });
993993
...@@ -1011,7 +1011,7 @@ fn testNeededLibrary(b: *Build, opts: Options) *Step {...@@ -1011,7 +1011,7 @@ fn testNeededLibrary(b: *Build, opts: Options) *Step {
1011}1011}
10121012
1013fn testObjc(b: *Build, opts: Options) *Step {1013fn testObjc(b: *Build, opts: Options) *Step {
1014 const test_step = addTestStep(b, "macho-objc", opts);1014 const test_step = addTestStep(b, "objc", opts);
10151015
1016 const lib = addStaticLibrary(b, opts, .{ .name = "a", .objc_source_bytes = 1016 const lib = addStaticLibrary(b, opts, .{ .name = "a", .objc_source_bytes =
1017 \\#import <Foundation/Foundation.h>1017 \\#import <Foundation/Foundation.h>
...@@ -1058,7 +1058,7 @@ fn testObjc(b: *Build, opts: Options) *Step {...@@ -1058,7 +1058,7 @@ fn testObjc(b: *Build, opts: Options) *Step {
1058}1058}
10591059
1060fn testObjcpp(b: *Build, opts: Options) *Step {1060fn testObjcpp(b: *Build, opts: Options) *Step {
1061 const test_step = addTestStep(b, "macho-objcpp", opts);1061 const test_step = addTestStep(b, "objcpp", opts);
10621062
1063 const foo_h = foo_h: {1063 const foo_h = foo_h: {
1064 const wf = WriteFile.create(b);1064 const wf = WriteFile.create(b);
...@@ -1111,7 +1111,7 @@ fn testObjcpp(b: *Build, opts: Options) *Step {...@@ -1111,7 +1111,7 @@ fn testObjcpp(b: *Build, opts: Options) *Step {
1111}1111}
11121112
1113fn testPagezeroSize(b: *Build, opts: Options) *Step {1113fn testPagezeroSize(b: *Build, opts: Options) *Step {
1114 const test_step = addTestStep(b, "macho-pagezero-size", opts);1114 const test_step = addTestStep(b, "pagezero-size", opts);
11151115
1116 {1116 {
1117 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = "int main () { return 0; }" });1117 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = "int main () { return 0; }" });
...@@ -1145,7 +1145,7 @@ fn testPagezeroSize(b: *Build, opts: Options) *Step {...@@ -1145,7 +1145,7 @@ fn testPagezeroSize(b: *Build, opts: Options) *Step {
1145}1145}
11461146
1147fn testReexportsZig(b: *Build, opts: Options) *Step {1147fn testReexportsZig(b: *Build, opts: Options) *Step {
1148 const test_step = addTestStep(b, "macho-reexports-zig", opts);1148 const test_step = addTestStep(b, "reexports-zig", opts);
11491149
1150 const lib = addStaticLibrary(b, opts, .{ .name = "a", .zig_source_bytes = 1150 const lib = addStaticLibrary(b, opts, .{ .name = "a", .zig_source_bytes =
1151 \\const x: i32 = 42;1151 \\const x: i32 = 42;
...@@ -1174,7 +1174,7 @@ fn testReexportsZig(b: *Build, opts: Options) *Step {...@@ -1174,7 +1174,7 @@ fn testReexportsZig(b: *Build, opts: Options) *Step {
1174}1174}
11751175
1176fn testRelocatable(b: *Build, opts: Options) *Step {1176fn testRelocatable(b: *Build, opts: Options) *Step {
1177 const test_step = addTestStep(b, "macho-relocatable", opts);1177 const test_step = addTestStep(b, "relocatable", opts);
11781178
1179 const a_o = addObject(b, opts, .{ .name = "a", .cpp_source_bytes = 1179 const a_o = addObject(b, opts, .{ .name = "a", .cpp_source_bytes =
1180 \\#include <stdexcept>1180 \\#include <stdexcept>
...@@ -1242,7 +1242,7 @@ fn testRelocatable(b: *Build, opts: Options) *Step {...@@ -1242,7 +1242,7 @@ fn testRelocatable(b: *Build, opts: Options) *Step {
1242}1242}
12431243
1244fn testRelocatableZig(b: *Build, opts: Options) *Step {1244fn testRelocatableZig(b: *Build, opts: Options) *Step {
1245 const test_step = addTestStep(b, "macho-relocatable-zig", opts);1245 const test_step = addTestStep(b, "relocatable-zig", opts);
12461246
1247 const a_o = addObject(b, opts, .{ .name = "a", .zig_source_bytes = 1247 const a_o = addObject(b, opts, .{ .name = "a", .zig_source_bytes =
1248 \\const std = @import("std");1248 \\const std = @import("std");
...@@ -1293,7 +1293,7 @@ fn testRelocatableZig(b: *Build, opts: Options) *Step {...@@ -1293,7 +1293,7 @@ fn testRelocatableZig(b: *Build, opts: Options) *Step {
1293}1293}
12941294
1295fn testSearchStrategy(b: *Build, opts: Options) *Step {1295fn testSearchStrategy(b: *Build, opts: Options) *Step {
1296 const test_step = addTestStep(b, "macho-search-strategy", opts);1296 const test_step = addTestStep(b, "search-strategy", opts);
12971297
1298 const obj = addObject(b, opts, .{ .name = "a", .c_source_bytes = 1298 const obj = addObject(b, opts, .{ .name = "a", .c_source_bytes =
1299 \\#include<stdio.h>1299 \\#include<stdio.h>
...@@ -1361,7 +1361,7 @@ fn testSearchStrategy(b: *Build, opts: Options) *Step {...@@ -1361,7 +1361,7 @@ fn testSearchStrategy(b: *Build, opts: Options) *Step {
1361}1361}
13621362
1363fn testSectionBoundarySymbols(b: *Build, opts: Options) *Step {1363fn testSectionBoundarySymbols(b: *Build, opts: Options) *Step {
1364 const test_step = addTestStep(b, "macho-section-boundary-symbols", opts);1364 const test_step = addTestStep(b, "section-boundary-symbols", opts);
13651365
1366 const obj1 = addObject(b, opts, .{1366 const obj1 = addObject(b, opts, .{
1367 .name = "obj1",1367 .name = "obj1",
...@@ -1441,7 +1441,7 @@ fn testSectionBoundarySymbols(b: *Build, opts: Options) *Step {...@@ -1441,7 +1441,7 @@ fn testSectionBoundarySymbols(b: *Build, opts: Options) *Step {
1441}1441}
14421442
1443fn testSegmentBoundarySymbols(b: *Build, opts: Options) *Step {1443fn testSegmentBoundarySymbols(b: *Build, opts: Options) *Step {
1444 const test_step = addTestStep(b, "macho-segment-boundary-symbols", opts);1444 const test_step = addTestStep(b, "segment-boundary-symbols", opts);
14451445
1446 const obj1 = addObject(b, opts, .{ .name = "a", .cpp_source_bytes = 1446 const obj1 = addObject(b, opts, .{ .name = "a", .cpp_source_bytes =
1447 \\constexpr const char* MESSAGE __attribute__((used, section("__DATA_CONST_1,__message_ptr"))) = "codebase";1447 \\constexpr const char* MESSAGE __attribute__((used, section("__DATA_CONST_1,__message_ptr"))) = "codebase";
...@@ -1509,7 +1509,7 @@ fn testSegmentBoundarySymbols(b: *Build, opts: Options) *Step {...@@ -1509,7 +1509,7 @@ fn testSegmentBoundarySymbols(b: *Build, opts: Options) *Step {
1509}1509}
15101510
1511fn testStackSize(b: *Build, opts: Options) *Step {1511fn testStackSize(b: *Build, opts: Options) *Step {
1512 const test_step = addTestStep(b, "macho-stack-size", opts);1512 const test_step = addTestStep(b, "stack-size", opts);
15131513
1514 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = "int main() { return 0; }" });1514 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = "int main() { return 0; }" });
1515 exe.stack_size = 0x100000000;1515 exe.stack_size = 0x100000000;
...@@ -1528,7 +1528,7 @@ fn testStackSize(b: *Build, opts: Options) *Step {...@@ -1528,7 +1528,7 @@ fn testStackSize(b: *Build, opts: Options) *Step {
1528}1528}
15291529
1530fn testTbdv3(b: *Build, opts: Options) *Step {1530fn testTbdv3(b: *Build, opts: Options) *Step {
1531 const test_step = addTestStep(b, "macho-tbdv3", opts);1531 const test_step = addTestStep(b, "tbdv3", opts);
15321532
1533 const dylib = addSharedLibrary(b, opts, .{ .name = "a", .c_source_bytes = "int getFoo() { return 42; }" });1533 const dylib = addSharedLibrary(b, opts, .{ .name = "a", .c_source_bytes = "int getFoo() { return 42; }" });
15341534
...@@ -1566,7 +1566,7 @@ fn testTbdv3(b: *Build, opts: Options) *Step {...@@ -1566,7 +1566,7 @@ fn testTbdv3(b: *Build, opts: Options) *Step {
1566}1566}
15671567
1568fn testTentative(b: *Build, opts: Options) *Step {1568fn testTentative(b: *Build, opts: Options) *Step {
1569 const test_step = addTestStep(b, "macho-tentative", opts);1569 const test_step = addTestStep(b, "tentative", opts);
15701570
1571 const exe = addExecutable(b, opts, .{ .name = "main" });1571 const exe = addExecutable(b, opts, .{ .name = "main" });
1572 addCSourceBytes(exe,1572 addCSourceBytes(exe,
...@@ -1592,7 +1592,7 @@ fn testTentative(b: *Build, opts: Options) *Step {...@@ -1592,7 +1592,7 @@ fn testTentative(b: *Build, opts: Options) *Step {
1592}1592}
15931593
1594fn testThunks(b: *Build, opts: Options) *Step {1594fn testThunks(b: *Build, opts: Options) *Step {
1595 const test_step = addTestStep(b, "macho-thunks", opts);1595 const test_step = addTestStep(b, "thunks", opts);
15961596
1597 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = 1597 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes =
1598 \\#include <stdio.h>1598 \\#include <stdio.h>
...@@ -1621,7 +1621,7 @@ fn testThunks(b: *Build, opts: Options) *Step {...@@ -1621,7 +1621,7 @@ fn testThunks(b: *Build, opts: Options) *Step {
1621}1621}
16221622
1623fn testTls(b: *Build, opts: Options) *Step {1623fn testTls(b: *Build, opts: Options) *Step {
1624 const test_step = addTestStep(b, "macho-tls", opts);1624 const test_step = addTestStep(b, "tls", opts);
16251625
1626 const dylib = addSharedLibrary(b, opts, .{ .name = "a", .c_source_bytes = 1626 const dylib = addSharedLibrary(b, opts, .{ .name = "a", .c_source_bytes =
1627 \\_Thread_local int a;1627 \\_Thread_local int a;
...@@ -1655,7 +1655,7 @@ fn testTls(b: *Build, opts: Options) *Step {...@@ -1655,7 +1655,7 @@ fn testTls(b: *Build, opts: Options) *Step {
1655}1655}
16561656
1657fn testTlsLargeTbss(b: *Build, opts: Options) *Step {1657fn testTlsLargeTbss(b: *Build, opts: Options) *Step {
1658 const test_step = addTestStep(b, "macho-tls-large-tbss", opts);1658 const test_step = addTestStep(b, "tls-large-tbss", opts);
16591659
1660 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = 1660 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes =
1661 \\#include <stdio.h>1661 \\#include <stdio.h>
...@@ -1676,7 +1676,7 @@ fn testTlsLargeTbss(b: *Build, opts: Options) *Step {...@@ -1676,7 +1676,7 @@ fn testTlsLargeTbss(b: *Build, opts: Options) *Step {
1676}1676}
16771677
1678fn testTwoLevelNamespace(b: *Build, opts: Options) *Step {1678fn testTwoLevelNamespace(b: *Build, opts: Options) *Step {
1679 const test_step = addTestStep(b, "macho-two-level-namespace", opts);1679 const test_step = addTestStep(b, "two-level-namespace", opts);
16801680
1681 const liba = addSharedLibrary(b, opts, .{ .name = "a", .c_source_bytes = 1681 const liba = addSharedLibrary(b, opts, .{ .name = "a", .c_source_bytes =
1682 \\#include <stdio.h>1682 \\#include <stdio.h>
...@@ -1796,7 +1796,7 @@ fn testTwoLevelNamespace(b: *Build, opts: Options) *Step {...@@ -1796,7 +1796,7 @@ fn testTwoLevelNamespace(b: *Build, opts: Options) *Step {
1796}1796}
17971797
1798fn testUndefinedFlag(b: *Build, opts: Options) *Step {1798fn testUndefinedFlag(b: *Build, opts: Options) *Step {
1799 const test_step = addTestStep(b, "macho-undefined-flag", opts);1799 const test_step = addTestStep(b, "undefined-flag", opts);
18001800
1801 const obj = addObject(b, opts, .{ .name = "a", .c_source_bytes = "int foo = 42;" });1801 const obj = addObject(b, opts, .{ .name = "a", .c_source_bytes = "int foo = 42;" });
18021802
...@@ -1873,7 +1873,7 @@ fn testUndefinedFlag(b: *Build, opts: Options) *Step {...@@ -1873,7 +1873,7 @@ fn testUndefinedFlag(b: *Build, opts: Options) *Step {
1873}1873}
18741874
1875fn testUnwindInfo(b: *Build, opts: Options) *Step {1875fn testUnwindInfo(b: *Build, opts: Options) *Step {
1876 const test_step = addTestStep(b, "macho-unwind-info", opts);1876 const test_step = addTestStep(b, "unwind-info", opts);
18771877
1878 const all_h = all_h: {1878 const all_h = all_h: {
1879 const wf = WriteFile.create(b);1879 const wf = WriteFile.create(b);
...@@ -2031,7 +2031,7 @@ fn testUnwindInfo(b: *Build, opts: Options) *Step {...@@ -2031,7 +2031,7 @@ fn testUnwindInfo(b: *Build, opts: Options) *Step {
2031}2031}
20322032
2033fn testUnwindInfoNoSubsectionsArm64(b: *Build, opts: Options) *Step {2033fn testUnwindInfoNoSubsectionsArm64(b: *Build, opts: Options) *Step {
2034 const test_step = addTestStep(b, "macho-unwind-info-no-subsections-arm64", opts);2034 const test_step = addTestStep(b, "unwind-info-no-subsections-arm64", opts);
20352035
2036 const a_o = addObject(b, opts, .{ .name = "a", .asm_source_bytes = 2036 const a_o = addObject(b, opts, .{ .name = "a", .asm_source_bytes =
2037 \\.globl _foo2037 \\.globl _foo
...@@ -2091,7 +2091,7 @@ fn testUnwindInfoNoSubsectionsArm64(b: *Build, opts: Options) *Step {...@@ -2091,7 +2091,7 @@ fn testUnwindInfoNoSubsectionsArm64(b: *Build, opts: Options) *Step {
2091}2091}
20922092
2093fn testUnwindInfoNoSubsectionsX64(b: *Build, opts: Options) *Step {2093fn testUnwindInfoNoSubsectionsX64(b: *Build, opts: Options) *Step {
2094 const test_step = addTestStep(b, "macho-unwind-info-no-subsections-x64", opts);2094 const test_step = addTestStep(b, "unwind-info-no-subsections-x64", opts);
20952095
2096 const a_o = addObject(b, opts, .{ .name = "a", .asm_source_bytes = 2096 const a_o = addObject(b, opts, .{ .name = "a", .asm_source_bytes =
2097 \\.globl _foo2097 \\.globl _foo
...@@ -2144,7 +2144,7 @@ fn testUnwindInfoNoSubsectionsX64(b: *Build, opts: Options) *Step {...@@ -2144,7 +2144,7 @@ fn testUnwindInfoNoSubsectionsX64(b: *Build, opts: Options) *Step {
21442144
2145// Adapted from https://github.com/llvm/llvm-project/blob/main/lld/test/MachO/weak-binding.s2145// Adapted from https://github.com/llvm/llvm-project/blob/main/lld/test/MachO/weak-binding.s
2146fn testWeakBind(b: *Build, opts: Options) *Step {2146fn testWeakBind(b: *Build, opts: Options) *Step {
2147 const test_step = addTestStep(b, "macho-weak-bind", opts);2147 const test_step = addTestStep(b, "weak-bind", opts);
21482148
2149 const lib = addSharedLibrary(b, opts, .{ .name = "foo", .asm_source_bytes = 2149 const lib = addSharedLibrary(b, opts, .{ .name = "foo", .asm_source_bytes =
2150 \\.globl _weak_dysym2150 \\.globl _weak_dysym
...@@ -2275,7 +2275,7 @@ fn testWeakBind(b: *Build, opts: Options) *Step {...@@ -2275,7 +2275,7 @@ fn testWeakBind(b: *Build, opts: Options) *Step {
2275}2275}
22762276
2277fn testWeakFramework(b: *Build, opts: Options) *Step {2277fn testWeakFramework(b: *Build, opts: Options) *Step {
2278 const test_step = addTestStep(b, "macho-weak-framework", opts);2278 const test_step = addTestStep(b, "weak-framework", opts);
22792279
2280 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = "int main() { return 0; }" });2280 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = "int main() { return 0; }" });
2281 exe.root_module.linkFramework("Cocoa", .{ .weak = true });2281 exe.root_module.linkFramework("Cocoa", .{ .weak = true });
...@@ -2294,7 +2294,7 @@ fn testWeakFramework(b: *Build, opts: Options) *Step {...@@ -2294,7 +2294,7 @@ fn testWeakFramework(b: *Build, opts: Options) *Step {
2294}2294}
22952295
2296fn testWeakLibrary(b: *Build, opts: Options) *Step {2296fn testWeakLibrary(b: *Build, opts: Options) *Step {
2297 const test_step = addTestStep(b, "macho-weak-library", opts);2297 const test_step = addTestStep(b, "weak-library", opts);
22982298
2299 const dylib = addSharedLibrary(b, opts, .{ .name = "a", .c_source_bytes = 2299 const dylib = addSharedLibrary(b, opts, .{ .name = "a", .c_source_bytes =
2300 \\#include<stdio.h>2300 \\#include<stdio.h>
...@@ -2337,7 +2337,7 @@ fn testWeakLibrary(b: *Build, opts: Options) *Step {...@@ -2337,7 +2337,7 @@ fn testWeakLibrary(b: *Build, opts: Options) *Step {
2337}2337}
23382338
2339fn testWeakRef(b: *Build, opts: Options) *Step {2339fn testWeakRef(b: *Build, opts: Options) *Step {
2340 const test_step = addTestStep(b, "macho-weak-ref", opts);2340 const test_step = addTestStep(b, "weak-ref", opts);
23412341
2342 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = 2342 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes =
2343 \\#include <stdio.h>2343 \\#include <stdio.h>
...@@ -2356,7 +2356,7 @@ fn testWeakRef(b: *Build, opts: Options) *Step {...@@ -2356,7 +2356,7 @@ fn testWeakRef(b: *Build, opts: Options) *Step {
2356}2356}
23572357
2358fn addTestStep(b: *Build, comptime prefix: []const u8, opts: Options) *Step {2358fn addTestStep(b: *Build, comptime prefix: []const u8, opts: Options) *Step {
2359 return link.addTestStep(b, "macho-" ++ prefix, opts);2359 return link.addTestStep(b, "" ++ prefix, opts);
2360}2360}
23612361
2362const builtin = @import("builtin");2362const builtin = @import("builtin");