From 5790e89b5aa5c8a939ea92e76a0a88655c4f55d4 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Sun, 14 Jan 2024 10:53:09 +0100 Subject: [PATCH] test/link/macho: test twolevel namespacing --- test/link/macho.zig | 121 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/test/link/macho.zig b/test/link/macho.zig index 58ef007565..ff02bee33d 100644 --- a/test/link/macho.zig +++ b/test/link/macho.zig @@ -29,6 +29,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { if (build_opts.has_symlinks_windows) { macho_step.dependOn(testNeededLibrary(b, .{ .target = default_target })); macho_step.dependOn(testWeakLibrary(b, .{ .target = default_target })); + macho_step.dependOn(testTwoLevelNamespace(b, .{ .target = default_target })); // Tests requiring presence of macOS SDK in system path if (build_opts.has_macos_sdk) { @@ -659,6 +660,126 @@ fn testTlsLargeTbss(b: *Build, opts: Options) *Step { return test_step; } +fn testTwoLevelNamespace(b: *Build, opts: Options) *Step { + const test_step = addTestStep(b, "macho-two-level-namespace", opts); + + const liba = addSharedLibrary(b, opts, .{ .name = "a", .c_source_bytes = + \\#include + \\int foo = 1; + \\int* ptr_to_foo = &foo; + \\int getFoo() { + \\ return foo; + \\} + \\void printInA() { + \\ printf("liba: getFoo()=%d, ptr_to_foo=%d\n", getFoo(), *ptr_to_foo); + \\} + }); + + { + const check = liba.checkObject(); + check.checkInDyldLazyBind(); + check.checkNotPresent("(flat lookup) _getFoo"); + check.checkInIndirectSymtab(); + check.checkNotPresent("_getFoo"); + test_step.dependOn(&check.step); + } + + const libb = addSharedLibrary(b, opts, .{ .name = "b", .c_source_bytes = + \\#include + \\int foo = 2; + \\int* ptr_to_foo = &foo; + \\int getFoo() { + \\ return foo; + \\} + \\void printInB() { + \\ printf("libb: getFoo()=%d, ptr_to_foo=%d\n", getFoo(), *ptr_to_foo); + \\} + }); + + { + const check = libb.checkObject(); + check.checkInDyldLazyBind(); + check.checkNotPresent("(flat lookup) _getFoo"); + check.checkInIndirectSymtab(); + check.checkNotPresent("_getFoo"); + test_step.dependOn(&check.step); + } + + const main_o = addObject(b, opts, .{ .name = "main", .c_source_bytes = + \\#include + \\int getFoo(); + \\extern int* ptr_to_foo; + \\void printInA(); + \\void printInB(); + \\int main() { + \\ printf("main: getFoo()=%d, ptr_to_foo=%d\n", getFoo(), *ptr_to_foo); + \\ printInA(); + \\ printInB(); + \\ return 0; + \\} + }); + + { + const exe = addExecutable(b, opts, .{ .name = "main1" }); + exe.addObject(main_o); + exe.root_module.linkSystemLibrary("a", .{}); + exe.root_module.linkSystemLibrary("b", .{}); + exe.addLibraryPath(liba.getEmittedBinDirectory()); + exe.addLibraryPath(libb.getEmittedBinDirectory()); + exe.addRPath(liba.getEmittedBinDirectory()); + exe.addRPath(libb.getEmittedBinDirectory()); + + const check = exe.checkObject(); + check.checkInSymtab(); + check.checkExact("(undefined) external _getFoo (from liba)"); + check.checkInSymtab(); + check.checkExact("(undefined) external _printInA (from liba)"); + check.checkInSymtab(); + check.checkExact("(undefined) external _printInB (from libb)"); + test_step.dependOn(&check.step); + + const run = addRunArtifact(exe); + run.expectStdOutEqual( + \\main: getFoo()=1, ptr_to_foo=1 + \\liba: getFoo()=1, ptr_to_foo=1 + \\libb: getFoo()=2, ptr_to_foo=2 + \\ + ); + test_step.dependOn(&run.step); + } + + { + const exe = addExecutable(b, opts, .{ .name = "main2" }); + exe.addObject(main_o); + exe.root_module.linkSystemLibrary("b", .{}); + exe.root_module.linkSystemLibrary("a", .{}); + exe.addLibraryPath(liba.getEmittedBinDirectory()); + exe.addLibraryPath(libb.getEmittedBinDirectory()); + exe.addRPath(liba.getEmittedBinDirectory()); + exe.addRPath(libb.getEmittedBinDirectory()); + + const check = exe.checkObject(); + check.checkInSymtab(); + check.checkExact("(undefined) external _getFoo (from libb)"); + check.checkInSymtab(); + check.checkExact("(undefined) external _printInA (from liba)"); + check.checkInSymtab(); + check.checkExact("(undefined) external _printInB (from libb)"); + test_step.dependOn(&check.step); + + const run = addRunArtifact(exe); + run.expectStdOutEqual( + \\main: getFoo()=2, ptr_to_foo=2 + \\liba: getFoo()=1, ptr_to_foo=1 + \\libb: getFoo()=2, ptr_to_foo=2 + \\ + ); + test_step.dependOn(&run.step); + } + + return test_step; +} + fn testUndefinedFlag(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "macho-undefined-flag", opts);