| author | |
| committer | |
| log | bd0dd225e843801b4b6162cbd2709c7325ab87b7 |
| tree | 6bbaa9f240311c52f7f24fc294c8c838710989e2 |
| parent | 71f876295981ecf5dfb8daadc05e7e9c1c7e1cbe |
| signature |
* Sema: implement linksection on functions
* Implement function linksection in Sema.
* Don't clobber function linksection/align/addrspace in Sema.
* Fix copy-paste typo in tests.
* Add a bunch of missing test_step.dependOn.
* Fix checkInSymtab match.
Closes #1254614 files changed, 97 insertions(+), 56 deletions(-)
lib/std/build/CheckObjectStep.zig+1| ... | @@ -436,6 +436,7 @@ const MachODumper = struct { | ... | @@ -436,6 +436,7 @@ const MachODumper = struct { |
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | if (opts.dump_symtab) { | 438 | if (opts.dump_symtab) { |
| 439 | try writer.print("{s}\n", .{symtab_label}); | ||
| 439 | for (symtab) |sym| { | 440 | for (symtab) |sym| { |
| 440 | if (sym.stab()) continue; | 441 | if (sym.stab()) continue; |
| 441 | const sym_name = mem.sliceTo(@ptrCast([*:0]const u8, strtab.ptr + sym.n_strx), 0); | 442 | const sym_name = mem.sliceTo(@ptrCast([*:0]const u8, strtab.ptr + sym.n_strx), 0); |
src/Module.zig+35-40| ... | @@ -4592,40 +4592,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4592,40 +4592,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4592 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 }; | 4592 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 }; |
| 4593 | const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 }; | 4593 | const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 }; |
| 4594 | const decl_tv = try sema.resolveInstValue(&block_scope, init_src, result_ref, undefined); | 4594 | const decl_tv = try sema.resolveInstValue(&block_scope, init_src, result_ref, undefined); |
| 4595 | const decl_align: u32 = blk: { | ||
| 4596 | const align_ref = decl.zirAlignRef(); | ||
| 4597 | if (align_ref == .none) break :blk 0; | ||
| 4598 | break :blk try sema.resolveAlign(&block_scope, align_src, align_ref); | ||
| 4599 | }; | ||
| 4600 | const decl_linksection: ?[*:0]const u8 = blk: { | ||
| 4601 | const linksection_ref = decl.zirLinksectionRef(); | ||
| 4602 | if (linksection_ref == .none) break :blk null; | ||
| 4603 | const bytes = try sema.resolveConstString(&block_scope, section_src, linksection_ref, "linksection must be comptime-known"); | ||
| 4604 | if (mem.indexOfScalar(u8, bytes, 0) != null) { | ||
| 4605 | return sema.fail(&block_scope, section_src, "linksection cannot contain null bytes", .{}); | ||
| 4606 | } else if (bytes.len == 0) { | ||
| 4607 | return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{}); | ||
| 4608 | } | ||
| 4609 | break :blk (try decl_arena_allocator.dupeZ(u8, bytes)).ptr; | ||
| 4610 | }; | ||
| 4611 | const target = sema.mod.getTarget(); | ||
| 4612 | const address_space = blk: { | ||
| 4613 | const addrspace_ctx: Sema.AddressSpaceContext = switch (decl_tv.val.tag()) { | ||
| 4614 | .function, .extern_fn => .function, | ||
| 4615 | .variable => .variable, | ||
| 4616 | else => .constant, | ||
| 4617 | }; | ||
| 4618 | |||
| 4619 | break :blk switch (decl.zirAddrspaceRef()) { | ||
| 4620 | .none => switch (addrspace_ctx) { | ||
| 4621 | .function => target_util.defaultAddressSpace(target, .function), | ||
| 4622 | .variable => target_util.defaultAddressSpace(target, .global_mutable), | ||
| 4623 | .constant => target_util.defaultAddressSpace(target, .global_constant), | ||
| 4624 | else => unreachable, | ||
| 4625 | }, | ||
| 4626 | else => |addrspace_ref| try sema.analyzeAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx), | ||
| 4627 | }; | ||
| 4628 | }; | ||
| 4629 | 4595 | ||
| 4630 | // Note this resolves the type of the Decl, not the value; if this Decl | 4596 | // Note this resolves the type of the Decl, not the value; if this Decl |
| 4631 | // is a struct, for example, this resolves `type` (which needs no resolution), | 4597 | // is a struct, for example, this resolves `type` (which needs no resolution), |
| ... | @@ -4679,9 +4645,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4679,9 +4645,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4679 | 4645 | ||
| 4680 | decl.ty = try decl_tv.ty.copy(decl_arena_allocator); | 4646 | decl.ty = try decl_tv.ty.copy(decl_arena_allocator); |
| 4681 | decl.val = try decl_tv.val.copy(decl_arena_allocator); | 4647 | decl.val = try decl_tv.val.copy(decl_arena_allocator); |
| 4682 | decl.@"align" = decl_align; | 4648 | // linksection, align, and addrspace were already set by Sema |
| 4683 | decl.@"linksection" = decl_linksection; | ||
| 4684 | decl.@"addrspace" = address_space; | ||
| 4685 | decl.has_tv = true; | 4649 | decl.has_tv = true; |
| 4686 | decl.owns_tv = owns_tv; | 4650 | decl.owns_tv = owns_tv; |
| 4687 | decl_arena_state.* = decl_arena.state; | 4651 | decl_arena_state.* = decl_arena.state; |
| ... | @@ -4759,9 +4723,40 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4759,9 +4723,40 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4759 | 4723 | ||
| 4760 | decl.ty = try decl_tv.ty.copy(decl_arena_allocator); | 4724 | decl.ty = try decl_tv.ty.copy(decl_arena_allocator); |
| 4761 | decl.val = try decl_tv.val.copy(decl_arena_allocator); | 4725 | decl.val = try decl_tv.val.copy(decl_arena_allocator); |
| 4762 | decl.@"align" = decl_align; | 4726 | decl.@"align" = blk: { |
| 4763 | decl.@"linksection" = decl_linksection; | 4727 | const align_ref = decl.zirAlignRef(); |
| 4764 | decl.@"addrspace" = address_space; | 4728 | if (align_ref == .none) break :blk 0; |
| 4729 | break :blk try sema.resolveAlign(&block_scope, align_src, align_ref); | ||
| 4730 | }; | ||
| 4731 | decl.@"linksection" = blk: { | ||
| 4732 | const linksection_ref = decl.zirLinksectionRef(); | ||
| 4733 | if (linksection_ref == .none) break :blk null; | ||
| 4734 | const bytes = try sema.resolveConstString(&block_scope, section_src, linksection_ref, "linksection must be comptime-known"); | ||
| 4735 | if (mem.indexOfScalar(u8, bytes, 0) != null) { | ||
| 4736 | return sema.fail(&block_scope, section_src, "linksection cannot contain null bytes", .{}); | ||
| 4737 | } else if (bytes.len == 0) { | ||
| 4738 | return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{}); | ||
| 4739 | } | ||
| 4740 | break :blk (try decl_arena_allocator.dupeZ(u8, bytes)).ptr; | ||
| 4741 | }; | ||
| 4742 | decl.@"addrspace" = blk: { | ||
| 4743 | const addrspace_ctx: Sema.AddressSpaceContext = switch (decl_tv.val.tag()) { | ||
| 4744 | .function, .extern_fn => .function, | ||
| 4745 | .variable => .variable, | ||
| 4746 | else => .constant, | ||
| 4747 | }; | ||
| 4748 | |||
| 4749 | const target = sema.mod.getTarget(); | ||
| 4750 | break :blk switch (decl.zirAddrspaceRef()) { | ||
| 4751 | .none => switch (addrspace_ctx) { | ||
| 4752 | .function => target_util.defaultAddressSpace(target, .function), | ||
| 4753 | .variable => target_util.defaultAddressSpace(target, .global_mutable), | ||
| 4754 | .constant => target_util.defaultAddressSpace(target, .global_constant), | ||
| 4755 | else => unreachable, | ||
| 4756 | }, | ||
| 4757 | else => |addrspace_ref| try sema.analyzeAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx), | ||
| 4758 | }; | ||
| 4759 | }; | ||
| 4765 | decl.has_tv = true; | 4760 | decl.has_tv = true; |
| 4766 | decl_arena_state.* = decl_arena.state; | 4761 | decl_arena_state.* = decl_arena.state; |
| 4767 | decl.value_arena = decl_arena_state; | 4762 | decl.value_arena = decl_arena_state; |
src/Sema.zig+13-15| ... | @@ -7899,7 +7899,7 @@ fn handleExternLibName( | ... | @@ -7899,7 +7899,7 @@ fn handleExternLibName( |
| 7899 | const FuncLinkSection = union(enum) { | 7899 | const FuncLinkSection = union(enum) { |
| 7900 | generic, | 7900 | generic, |
| 7901 | default, | 7901 | default, |
| 7902 | explicit: [*:0]const u8, | 7902 | explicit: []const u8, |
| 7903 | }; | 7903 | }; |
| 7904 | 7904 | ||
| 7905 | fn funcCommon( | 7905 | fn funcCommon( |
| ... | @@ -8185,15 +8185,13 @@ fn funcCommon( | ... | @@ -8185,15 +8185,13 @@ fn funcCommon( |
| 8185 | }); | 8185 | }); |
| 8186 | }; | 8186 | }; |
| 8187 | 8187 | ||
| 8188 | if (sema.owner_decl.owns_tv) { | 8188 | sema.owner_decl.@"linksection" = switch (section) { |
| 8189 | switch (section) { | 8189 | .generic => undefined, |
| 8190 | .generic => sema.owner_decl.@"linksection" = undefined, | 8190 | .default => null, |
| 8191 | .default => sema.owner_decl.@"linksection" = null, | 8191 | .explicit => |section_name| try sema.perm_arena.dupeZ(u8, section_name), |
| 8192 | .explicit => |s| sema.owner_decl.@"linksection" = s, | 8192 | }; |
| 8193 | } | 8193 | sema.owner_decl.@"align" = alignment orelse 0; |
| 8194 | if (alignment) |a| sema.owner_decl.@"align" = a; | 8194 | sema.owner_decl.@"addrspace" = address_space orelse .generic; |
| 8195 | if (address_space) |a| sema.owner_decl.@"addrspace" = a; | ||
| 8196 | } | ||
| 8197 | 8195 | ||
| 8198 | if (is_extern) { | 8196 | if (is_extern) { |
| 8199 | const new_extern_fn = try sema.gpa.create(Module.ExternFn); | 8197 | const new_extern_fn = try sema.gpa.create(Module.ExternFn); |
| ... | @@ -20717,22 +20715,22 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -20717,22 +20715,22 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 20717 | const body = sema.code.extra[extra_index..][0..body_len]; | 20715 | const body = sema.code.extra[extra_index..][0..body_len]; |
| 20718 | extra_index += body.len; | 20716 | extra_index += body.len; |
| 20719 | 20717 | ||
| 20720 | const val = try sema.resolveGenericBody(block, section_src, body, inst, Type.initTag(.const_slice_u8), "linksection must be comptime-known"); | 20718 | const ty = Type.initTag(.const_slice_u8); |
| 20719 | const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, "linksection must be comptime-known"); | ||
| 20721 | if (val.tag() == .generic_poison) { | 20720 | if (val.tag() == .generic_poison) { |
| 20722 | break :blk FuncLinkSection{ .generic = {} }; | 20721 | break :blk FuncLinkSection{ .generic = {} }; |
| 20723 | } | 20722 | } |
| 20724 | return sema.fail(block, section_src, "TODO implement linksection on functions", .{}); | 20723 | break :blk FuncLinkSection{ .explicit = try val.toAllocatedBytes(ty, sema.arena, sema.mod) }; |
| 20725 | } else if (extra.data.bits.has_section_ref) blk: { | 20724 | } else if (extra.data.bits.has_section_ref) blk: { |
| 20726 | const section_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 20725 | const section_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 20727 | extra_index += 1; | 20726 | extra_index += 1; |
| 20728 | const section_tv = sema.resolveInstConst(block, section_src, section_ref, "linksection must be comptime-known") catch |err| switch (err) { | 20727 | const section_name = sema.resolveConstString(block, section_src, section_ref, "linksection must be comptime-known") catch |err| switch (err) { |
| 20729 | error.GenericPoison => { | 20728 | error.GenericPoison => { |
| 20730 | break :blk FuncLinkSection{ .generic = {} }; | 20729 | break :blk FuncLinkSection{ .generic = {} }; |
| 20731 | }, | 20730 | }, |
| 20732 | else => |e| return e, | 20731 | else => |e| return e, |
| 20733 | }; | 20732 | }; |
| 20734 | _ = section_tv; | 20733 | break :blk FuncLinkSection{ .explicit = section_name }; |
| 20735 | return sema.fail(block, section_src, "TODO implement linksection on functions", .{}); | ||
| 20736 | } else FuncLinkSection{ .default = {} }; | 20734 | } else FuncLinkSection{ .default = {} }; |
| 20737 | 20735 | ||
| 20738 | const cc: ?std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: { | 20736 | const cc: ?std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: { |
test/link.zig+4| ... | @@ -92,6 +92,10 @@ fn addMachOCases(cases: *tests.StandaloneContext) void { | ... | @@ -92,6 +92,10 @@ fn addMachOCases(cases: *tests.StandaloneContext) void { |
| 92 | .requires_macos_sdk = true, | 92 | .requires_macos_sdk = true, |
| 93 | }); | 93 | }); |
| 94 | 94 | ||
| 95 | cases.addBuildFile("test/link/macho/linksection/build.zig", .{ | ||
| 96 | .build_modes = true, | ||
| 97 | }); | ||
| 98 | |||
| 95 | cases.addBuildFile("test/link/macho/needed_framework/build.zig", .{ | 99 | cases.addBuildFile("test/link/macho/needed_framework/build.zig", .{ |
| 96 | .build_modes = true, | 100 | .build_modes = true, |
| 97 | .requires_macos_sdk = true, | 101 | .requires_macos_sdk = true, |
test/link/macho/dead_strip/build.zig+2| ... | @@ -16,6 +16,7 @@ pub fn build(b: *Builder) void { | ... | @@ -16,6 +16,7 @@ pub fn build(b: *Builder) void { |
| 16 | const check = exe.checkObject(.macho); | 16 | const check = exe.checkObject(.macho); |
| 17 | check.checkInSymtab(); | 17 | check.checkInSymtab(); |
| 18 | check.checkNext("{*} (__TEXT,__text) external _iAmUnused"); | 18 | check.checkNext("{*} (__TEXT,__text) external _iAmUnused"); |
| 19 | test_step.dependOn(&check.step); | ||
| 19 | 20 | ||
| 20 | const run_cmd = check.runAndCompare(); | 21 | const run_cmd = check.runAndCompare(); |
| 21 | run_cmd.expectStdOutEqual("Hello!\n"); | 22 | run_cmd.expectStdOutEqual("Hello!\n"); |
| ... | @@ -30,6 +31,7 @@ pub fn build(b: *Builder) void { | ... | @@ -30,6 +31,7 @@ pub fn build(b: *Builder) void { |
| 30 | const check = exe.checkObject(.macho); | 31 | const check = exe.checkObject(.macho); |
| 31 | check.checkInSymtab(); | 32 | check.checkInSymtab(); |
| 32 | check.checkNotPresent("{*} (__TEXT,__text) external _iAmUnused"); | 33 | check.checkNotPresent("{*} (__TEXT,__text) external _iAmUnused"); |
| 34 | test_step.dependOn(&check.step); | ||
| 33 | 35 | ||
| 34 | const run_cmd = check.runAndCompare(); | 36 | const run_cmd = check.runAndCompare(); |
| 35 | run_cmd.expectStdOutEqual("Hello!\n"); | 37 | run_cmd.expectStdOutEqual("Hello!\n"); |
test/link/macho/dylib/build.zig+2| ... | @@ -40,6 +40,8 @@ pub fn build(b: *Builder) void { | ... | @@ -40,6 +40,8 @@ pub fn build(b: *Builder) void { |
| 40 | check_exe.checkNext("current version 10000"); | 40 | check_exe.checkNext("current version 10000"); |
| 41 | check_exe.checkNext("compatibility version 10000"); | 41 | check_exe.checkNext("compatibility version 10000"); |
| 42 | 42 | ||
| 43 | test_step.dependOn(&check_exe.step); | ||
| 44 | |||
| 43 | check_exe.checkStart("cmd RPATH"); | 45 | check_exe.checkStart("cmd RPATH"); |
| 44 | check_exe.checkNext(std.fmt.allocPrint(b.allocator, "path {s}", .{b.pathFromRoot("zig-out/lib")}) catch unreachable); | 46 | check_exe.checkNext(std.fmt.allocPrint(b.allocator, "path {s}", .{b.pathFromRoot("zig-out/lib")}) catch unreachable); |
| 45 | 47 |
test/link/macho/entry/build.zig+1| ... | @@ -26,6 +26,7 @@ pub fn build(b: *Builder) void { | ... | @@ -26,6 +26,7 @@ pub fn build(b: *Builder) void { |
| 26 | check_exe.checkNext("{n_value} (__TEXT,__text) external _non_main"); | 26 | check_exe.checkNext("{n_value} (__TEXT,__text) external _non_main"); |
| 27 | 27 | ||
| 28 | check_exe.checkComputeCompare("vmaddr entryoff +", .{ .op = .eq, .value = .{ .variable = "n_value" } }); | 28 | check_exe.checkComputeCompare("vmaddr entryoff +", .{ .op = .eq, .value = .{ .variable = "n_value" } }); |
| 29 | test_step.dependOn(&check_exe.step); | ||
| 29 | 30 | ||
| 30 | const run = check_exe.runAndCompare(); | 31 | const run = check_exe.runAndCompare(); |
| 31 | run.expectStdOutEqual("42"); | 32 | run.expectStdOutEqual("42"); |
test/link/macho/linksection/build.zig created+28| ... | @@ -0,0 +1,28 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn build(b: *std.build.Builder) void { | ||
| 4 | const mode = b.standardReleaseOptions(); | ||
| 5 | const target = std.zig.CrossTarget{ .os_tag = .macos }; | ||
| 6 | |||
| 7 | const test_step = b.step("test", "Test"); | ||
| 8 | test_step.dependOn(b.getInstallStep()); | ||
| 9 | |||
| 10 | const obj = b.addObject("test", "main.zig"); | ||
| 11 | obj.setBuildMode(mode); | ||
| 12 | obj.setTarget(target); | ||
| 13 | |||
| 14 | const check = obj.checkObject(.macho); | ||
| 15 | |||
| 16 | check.checkInSymtab(); | ||
| 17 | check.checkNext("{*} (__DATA,__TestGlobal) external _test_global"); | ||
| 18 | |||
| 19 | check.checkInSymtab(); | ||
| 20 | check.checkNext("{*} (__TEXT,__TestFn) external _testFn"); | ||
| 21 | |||
| 22 | if (mode == .Debug) { | ||
| 23 | check.checkInSymtab(); | ||
| 24 | check.checkNext("{*} (__TEXT,__TestGenFnA) _main.testGenericFn__anon_{*}"); | ||
| 25 | } | ||
| 26 | |||
| 27 | test_step.dependOn(&check.step); | ||
| 28 | } | ||
test/link/macho/linksection/main.zig created+5| ... | @@ -0,0 +1,5 @@ | ||
| 1 | export var test_global: u32 linksection("__DATA,__TestGlobal") = undefined; | ||
| 2 | export fn testFn() linksection("__TEXT,__TestFn") callconv(.C) void { | ||
| 3 | testGenericFn("A"); | ||
| 4 | } | ||
| 5 | fn testGenericFn(comptime suffix: []const u8) linksection("__TEXT,__TestGenFn" ++ suffix) void {} | ||
test/link/macho/needed_library/build.zig+1| ... | @@ -31,6 +31,7 @@ pub fn build(b: *Builder) void { | ... | @@ -31,6 +31,7 @@ pub fn build(b: *Builder) void { |
| 31 | const check = exe.checkObject(.macho); | 31 | const check = exe.checkObject(.macho); |
| 32 | check.checkStart("cmd LOAD_DYLIB"); | 32 | check.checkStart("cmd LOAD_DYLIB"); |
| 33 | check.checkNext("name @rpath/liba.dylib"); | 33 | check.checkNext("name @rpath/liba.dylib"); |
| 34 | test_step.dependOn(&check.step); | ||
| 34 | 35 | ||
| 35 | const run_cmd = check.runAndCompare(); | 36 | const run_cmd = check.runAndCompare(); |
| 36 | test_step.dependOn(&run_cmd.step); | 37 | test_step.dependOn(&run_cmd.step); |
test/link/macho/search_strategy/build.zig+1| ... | @@ -17,6 +17,7 @@ pub fn build(b: *Builder) void { | ... | @@ -17,6 +17,7 @@ pub fn build(b: *Builder) void { |
| 17 | const check = exe.checkObject(.macho); | 17 | const check = exe.checkObject(.macho); |
| 18 | check.checkStart("cmd LOAD_DYLIB"); | 18 | check.checkStart("cmd LOAD_DYLIB"); |
| 19 | check.checkNext("name @rpath/liba.dylib"); | 19 | check.checkNext("name @rpath/liba.dylib"); |
| 20 | test_step.dependOn(&check.step); | ||
| 20 | 21 | ||
| 21 | const run = check.runAndCompare(); | 22 | const run = check.runAndCompare(); |
| 22 | run.cwd = b.pathFromRoot("."); | 23 | run.cwd = b.pathFromRoot("."); |
test/link/macho/stack_size/build.zig+1| ... | @@ -18,6 +18,7 @@ pub fn build(b: *Builder) void { | ... | @@ -18,6 +18,7 @@ pub fn build(b: *Builder) void { |
| 18 | const check_exe = exe.checkObject(.macho); | 18 | const check_exe = exe.checkObject(.macho); |
| 19 | check_exe.checkStart("cmd MAIN"); | 19 | check_exe.checkStart("cmd MAIN"); |
| 20 | check_exe.checkNext("stacksize 100000000"); | 20 | check_exe.checkNext("stacksize 100000000"); |
| 21 | test_step.dependOn(&check_exe.step); | ||
| 21 | 22 | ||
| 22 | const run = check_exe.runAndCompare(); | 23 | const run = check_exe.runAndCompare(); |
| 23 | test_step.dependOn(&run.step); | 24 | test_step.dependOn(&run.step); |
test/link/macho/weak_library/build.zig+2| ... | @@ -33,6 +33,8 @@ pub fn build(b: *Builder) void { | ... | @@ -33,6 +33,8 @@ pub fn build(b: *Builder) void { |
| 33 | check.checkNext("(undefined) weak external _a (from liba)"); | 33 | check.checkNext("(undefined) weak external _a (from liba)"); |
| 34 | check.checkNext("(undefined) weak external _asStr (from liba)"); | 34 | check.checkNext("(undefined) weak external _asStr (from liba)"); |
| 35 | 35 | ||
| 36 | test_step.dependOn(&check.step); | ||
| 37 | |||
| 36 | const run_cmd = check.runAndCompare(); | 38 | const run_cmd = check.runAndCompare(); |
| 37 | run_cmd.expectStdOutEqual("42 42"); | 39 | run_cmd.expectStdOutEqual("42 42"); |
| 38 | test_step.dependOn(&run_cmd.step); | 40 | test_step.dependOn(&run_cmd.step); |
test/tests.zig+1-1| ... | @@ -83,7 +83,7 @@ const test_targets = blk: { | ... | @@ -83,7 +83,7 @@ const test_targets = blk: { |
| 83 | .cpu_arch = .arm, | 83 | .cpu_arch = .arm, |
| 84 | .os_tag = .linux, | 84 | .os_tag = .linux, |
| 85 | }, | 85 | }, |
| 86 | .backend = .stage2_wasm, | 86 | .backend = .stage2_arm, |
| 87 | }, | 87 | }, |
| 88 | .{ | 88 | .{ |
| 89 | .target = CrossTarget.parse(.{ | 89 | .target = CrossTarget.parse(.{ |