authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-10 13:44:43+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-10 13:44:43+01:00
log7566a8fbd81a71d4b61022fd2b6f5f80a4679fb0
tree2981d3abee93cd1c3e599ad9529cc9bf60b5807b
parent197fd41e27647d846b6e6bf6197bad0ab14634ae

test/link: spawn ELF and MachO tests from the same root test/link/link.zig


4 files changed, 215 insertions(+), 9 deletions(-)

test/link.zig+5-6
......@@ -4,6 +4,11 @@ pub const Case = struct {
44};
55
66pub const cases = [_]Case{
7 .{
8 .build_root = "test/link",
9 .import = @import("link/link.zig"),
10 },
11
712 .{
813 .build_root = "test/link/bss",
914 .import = @import("link/bss/build.zig"),
......@@ -29,12 +34,6 @@ pub const cases = [_]Case{
2934 .import = @import("link/glibc_compat/build.zig"),
3035 },
3136
32 // Elf Cases
33 .{
34 .build_root = "test/link",
35 .import = @import("link/elf.zig"),
36 },
37
3837 // WASM Cases
3938 // https://github.com/ziglang/zig/issues/16938
4039 //.{
test/link/elf.zig+3-3
......@@ -2,9 +2,8 @@
22//! Currently, we support linking x86_64 Linux, but in the future we
33//! will progressively relax those to exercise more combinations.
44
5pub fn build(b: *Build) void {
5pub fn testAll(b: *Build) *Step {
66 const elf_step = b.step("test-elf", "Run ELF tests");
7 b.default_step = elf_step;
87
98 const default_target = CrossTarget{
109 .cpu_arch = .x86_64, // TODO relax this once ELF linker is able to handle other archs
......@@ -123,6 +122,8 @@ pub fn build(b: *Build) void {
123122 elf_step.dependOn(testZNow(b, .{ .target = glibc_target }));
124123 elf_step.dependOn(testZStackSize(b, .{ .target = glibc_target }));
125124 elf_step.dependOn(testZText(b, .{ .target = glibc_target }));
125
126 return elf_step;
126127}
127128
128129fn testAbsSymbols(b: *Build, opts: Options) *Step {
......@@ -3582,7 +3583,6 @@ const std = @import("std");
35823583const Build = std.Build;
35833584const Compile = Step.Compile;
35843585const CrossTarget = std.zig.CrossTarget;
3585const LazyPath = Build.LazyPath;
35863586const Run = Step.Run;
35873587const Step = Build.Step;
35883588const WriteFile = Step.WriteFile;
test/link/link.zig created+114
......@@ -0,0 +1,114 @@
1pub fn build(b: *Build) void {
2 const test_step = b.step("test-link", "Run link tests");
3 b.default_step = test_step;
4
5 test_step.dependOn(@import("elf.zig").testAll(b));
6 test_step.dependOn(@import("macho.zig").testAll(b));
7}
8
9pub const Options = struct {
10 target: CrossTarget,
11 optimize: std.builtin.OptimizeMode = .Debug,
12 use_llvm: bool = true,
13 use_lld: bool = false,
14};
15
16pub fn addTestStep(b: *Build, comptime prefix: []const u8, opts: Options) *Step {
17 const target = opts.target.zigTriple(b.allocator) catch @panic("OOM");
18 const optimize = @tagName(opts.optimize);
19 const use_llvm = if (opts.use_llvm) "llvm" else "no-llvm";
20 const name = std.fmt.allocPrint(b.allocator, "test-" ++ prefix ++ "-{s}-{s}-{s}", .{
21 target,
22 optimize,
23 use_llvm,
24 }) catch @panic("OOM");
25 return b.step(name, "");
26}
27
28pub fn addExecutable(b: *Build, name: []const u8, opts: Options) *Compile {
29 return b.addExecutable(.{
30 .name = name,
31 .target = opts.target,
32 .optimize = opts.optimize,
33 .use_llvm = opts.use_llvm,
34 .use_lld = opts.use_lld,
35 });
36}
37
38pub fn addObject(b: *Build, name: []const u8, opts: Options) *Compile {
39 return b.addObject(.{
40 .name = name,
41 .target = opts.target,
42 .optimize = opts.optimize,
43 .use_llvm = opts.use_llvm,
44 .use_lld = opts.use_lld,
45 });
46}
47
48pub fn addStaticLibrary(b: *Build, name: []const u8, opts: Options) *Compile {
49 return b.addStaticLibrary(.{
50 .name = name,
51 .target = opts.target,
52 .optimize = opts.optimize,
53 .use_llvm = opts.use_llvm,
54 .use_lld = opts.use_lld,
55 });
56}
57
58pub fn addSharedLibrary(b: *Build, name: []const u8, opts: Options) *Compile {
59 return b.addSharedLibrary(.{
60 .name = name,
61 .target = opts.target,
62 .optimize = opts.optimize,
63 .use_llvm = opts.use_llvm,
64 .use_lld = opts.use_lld,
65 });
66}
67
68pub fn addRunArtifact(comp: *Compile) *Run {
69 const b = comp.step.owner;
70 const run = b.addRunArtifact(comp);
71 run.skip_foreign_checks = true;
72 return run;
73}
74
75pub fn addZigSourceBytes(comp: *Compile, bytes: []const u8) void {
76 const b = comp.step.owner;
77 const file = WriteFile.create(b).add("a.zig", bytes);
78 file.addStepDependencies(&comp.step);
79 comp.root_src = file;
80}
81
82pub fn addCSourceBytes(comp: *Compile, bytes: []const u8, flags: []const []const u8) void {
83 const b = comp.step.owner;
84 const file = WriteFile.create(b).add("a.c", bytes);
85 comp.addCSourceFile(.{ .file = file, .flags = flags });
86}
87
88pub fn addCppSourceBytes(comp: *Compile, bytes: []const u8, flags: []const []const u8) void {
89 const b = comp.step.owner;
90 const file = WriteFile.create(b).add("a.cpp", bytes);
91 comp.addCSourceFile(.{ .file = file, .flags = flags });
92}
93
94pub fn addAsmSourceBytes(comp: *Compile, bytes: []const u8) void {
95 const b = comp.step.owner;
96 const actual_bytes = std.fmt.allocPrint(b.allocator, "{s}\n", .{bytes}) catch @panic("OOM");
97 const file = WriteFile.create(b).add("a.s", actual_bytes);
98 comp.addAssemblyFile(file);
99}
100
101pub fn expectLinkErrors(comp: *Compile, test_step: *Step, expected_errors: Compile.ExpectedCompileErrors) void {
102 comp.expect_errors = expected_errors;
103 const bin_file = comp.getEmittedBin();
104 bin_file.addStepDependencies(test_step);
105}
106
107const std = @import("std");
108
109const Build = std.Build;
110const Compile = Step.Compile;
111const CrossTarget = std.zig.CrossTarget;
112const Run = Step.Run;
113const Step = Build.Step;
114const WriteFile = Step.WriteFile;
test/link/macho.zig created+93
......@@ -0,0 +1,93 @@
1//! Here we test our MachO linker for correctness and functionality.
2//! TODO migrate standalone tests from test/link/macho/* to here.
3
4pub fn testAll(b: *Build) *Step {
5 const macho_step = b.step("test-macho", "Run MachO tests");
6
7 const default_target = CrossTarget{ .os_tag = .macos };
8
9 macho_step.dependOn(testResolvingBoundarySymbols(b, .{ .target = default_target }));
10
11 return macho_step;
12}
13
14fn testResolvingBoundarySymbols(b: *Build, opts: Options) *Step {
15 const test_step = addTestStep(b, "macho-resolving-boundary-symbols", opts);
16
17 const obj1 = addObject(b, "obj1", opts);
18 addCppSourceBytes(obj1,
19 \\constexpr const char* MESSAGE __attribute__((used, section("__DATA_CONST,__message_ptr"))) = "codebase";
20 , &.{});
21
22 const main_o = addObject(b, "main", opts);
23 addZigSourceBytes(main_o,
24 \\const std = @import("std");
25 \\extern fn interop() [*:0]const u8;
26 \\pub fn main() !void {
27 \\ std.debug.print("All your {s} are belong to us.\n", .{
28 \\ std.mem.span(interop()),
29 \\ });
30 \\}
31 );
32
33 {
34 const obj2 = addObject(b, "obj2", opts);
35 addCppSourceBytes(obj2,
36 \\extern const char* message_pointer __asm("section$start$__DATA_CONST$__message_ptr");
37 \\extern "C" const char* interop() {
38 \\ return message_pointer;
39 \\}
40 , &.{});
41
42 const exe = addExecutable(b, "test", opts);
43 exe.addObject(obj1);
44 exe.addObject(obj2);
45 exe.addObject(main_o);
46
47 const run = addRunArtifact(exe);
48 run.expectStdErrEqual("All your codebase are belong to us.\n");
49 test_step.dependOn(&run.step);
50
51 const check = exe.checkObject();
52 check.checkInSymtab();
53 check.checkNotPresent("section$start$__DATA_CONST$__message_ptr");
54 test_step.dependOn(&check.step);
55 }
56
57 {
58 const obj3 = addObject(b, "obj3", opts);
59 addCppSourceBytes(obj3,
60 \\extern const char* message_pointer __asm("section$start$__DATA$__message_ptr");
61 \\extern "C" const char* interop() {
62 \\ return message_pointer;
63 \\}
64 , &.{});
65
66 const exe = addExecutable(b, "test", opts);
67 exe.addObject(obj1);
68 exe.addObject(obj3);
69 exe.addObject(main_o);
70
71 expectLinkErrors(exe, test_step, .{ .exact = &.{
72 "section not found: __DATA,__message_ptr",
73 "note: while resolving section$start$__DATA$__message_ptr",
74 } });
75 }
76
77 return test_step;
78}
79
80const addCppSourceBytes = link.addCppSourceBytes;
81const addExecutable = link.addExecutable;
82const addObject = link.addObject;
83const addRunArtifact = link.addRunArtifact;
84const addTestStep = link.addTestStep;
85const addZigSourceBytes = link.addZigSourceBytes;
86const expectLinkErrors = link.expectLinkErrors;
87const link = @import("link.zig");
88const std = @import("std");
89
90const Build = std.Build;
91const CrossTarget = std.zig.CrossTarget;
92const Options = link.Options;
93const Step = Build.Step;