master
 1const std = @import("std");
 2
 3pub fn build(b: *std.Build) void {
 4    const test_step = b.step("test", "Test");
 5    b.default_step = test_step;
 6
 7    add(b, test_step, .Debug);
 8    add(b, test_step, .ReleaseFast);
 9}
10
11fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.OptimizeMode) void {
12    const exe = b.addExecutable(.{
13        .name = "lib",
14        .root_module = b.createModule(.{
15            .root_source_file = b.path("lib.zig"),
16            .target = b.resolveTargetQuery(.{
17                .cpu_arch = .wasm32,
18                .cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp },
19                .cpu_features_add = std.Target.wasm.featureSet(&.{ .atomics, .bulk_memory }),
20                .os_tag = .freestanding,
21            }),
22            .optimize = optimize_mode,
23            .strip = false,
24            .single_threaded = false,
25        }),
26    });
27    exe.entry = .disabled;
28    exe.use_lld = false;
29    exe.import_memory = true;
30    exe.export_memory = true;
31    exe.shared_memory = true;
32    exe.max_memory = 67108864;
33    exe.root_module.export_symbol_names = &.{"foo"};
34    // Don't pull in ubsan, since we're just expecting a very minimal executable.
35    exe.bundle_ubsan_rt = false;
36
37    const check_exe = exe.checkObject();
38
39    check_exe.checkInHeaders();
40    check_exe.checkExact("Section import");
41    check_exe.checkExact("entries 1");
42    check_exe.checkExact("module env");
43    check_exe.checkExact("name memory"); // ensure we are importing memory
44
45    check_exe.checkInHeaders();
46    check_exe.checkExact("Section export");
47    check_exe.checkExact("entries 2");
48    check_exe.checkExact("name foo");
49    check_exe.checkExact("name memory"); // ensure we also export memory again
50
51    // This section *must* be emit as the start function is set to the index
52    // of __wasm_init_memory
53    // release modes will have the TLS segment optimized out in our test-case.
54    // This means we won't have __wasm_init_memory in such case, and therefore
55    // should also not have a section "start"
56    if (optimize_mode == .Debug) {
57        check_exe.checkInHeaders();
58        check_exe.checkExact("Section start");
59    }
60
61    // This section is only and *must* be emit when shared-memory is enabled
62    // release modes will have the TLS segment optimized out in our test-case.
63    if (optimize_mode == .Debug) {
64        check_exe.checkInHeaders();
65        check_exe.checkExact("Section data_count");
66        check_exe.checkExact("count 1");
67    }
68
69    check_exe.checkInHeaders();
70    check_exe.checkExact("Section custom");
71    check_exe.checkExact("name name");
72    check_exe.checkExact("type function");
73    if (optimize_mode == .Debug) {
74        check_exe.checkExact("name __wasm_init_memory");
75        check_exe.checkExact("name __wasm_init_tls");
76    }
77    check_exe.checkExact("type global");
78
79    // In debug mode the symbol __tls_base is resolved to an undefined symbol
80    // from the object file, hence its placement differs than in release modes
81    // where the entire tls segment is optimized away, and tls_base will have
82    // its original position.
83    if (optimize_mode == .Debug) {
84        check_exe.checkExact("name __tls_base");
85        check_exe.checkExact("name __tls_size");
86        check_exe.checkExact("name __tls_align");
87
88        check_exe.checkExact("type data_segment");
89        check_exe.checkExact("names 1");
90        check_exe.checkExact("index 0");
91        check_exe.checkExact("name .tdata");
92    } else {
93        check_exe.checkNotPresent("name __tls_base");
94        check_exe.checkNotPresent("name __tls_size");
95        check_exe.checkNotPresent("name __tls_align");
96    }
97
98    test_step.dependOn(&check_exe.step);
99}