| ... | @@ -29,6 +29,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { | ... | @@ -29,6 +29,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { |
| 29 | if (build_opts.has_symlinks_windows) { | 29 | if (build_opts.has_symlinks_windows) { |
| 30 | macho_step.dependOn(testNeededLibrary(b, .{ .target = default_target })); | 30 | macho_step.dependOn(testNeededLibrary(b, .{ .target = default_target })); |
| 31 | macho_step.dependOn(testWeakLibrary(b, .{ .target = default_target })); | 31 | macho_step.dependOn(testWeakLibrary(b, .{ .target = default_target })); |
| | 32 | macho_step.dependOn(testTwoLevelNamespace(b, .{ .target = default_target })); |
| 32 | | 33 | |
| 33 | // Tests requiring presence of macOS SDK in system path | 34 | // Tests requiring presence of macOS SDK in system path |
| 34 | if (build_opts.has_macos_sdk) { | 35 | if (build_opts.has_macos_sdk) { |
| ... | @@ -659,6 +660,126 @@ fn testTlsLargeTbss(b: *Build, opts: Options) *Step { | ... | @@ -659,6 +660,126 @@ fn testTlsLargeTbss(b: *Build, opts: Options) *Step { |
| 659 | return test_step; | 660 | return test_step; |
| 660 | } | 661 | } |
| 661 | | 662 | |
| | 663 | fn testTwoLevelNamespace(b: *Build, opts: Options) *Step { |
| | 664 | const test_step = addTestStep(b, "macho-two-level-namespace", opts); |
| | 665 | |
| | 666 | const liba = addSharedLibrary(b, opts, .{ .name = "a", .c_source_bytes = |
| | 667 | \\#include <stdio.h> |
| | 668 | \\int foo = 1; |
| | 669 | \\int* ptr_to_foo = &foo; |
| | 670 | \\int getFoo() { |
| | 671 | \\ return foo; |
| | 672 | \\} |
| | 673 | \\void printInA() { |
| | 674 | \\ printf("liba: getFoo()=%d, ptr_to_foo=%d\n", getFoo(), *ptr_to_foo); |
| | 675 | \\} |
| | 676 | }); |
| | 677 | |
| | 678 | { |
| | 679 | const check = liba.checkObject(); |
| | 680 | check.checkInDyldLazyBind(); |
| | 681 | check.checkNotPresent("(flat lookup) _getFoo"); |
| | 682 | check.checkInIndirectSymtab(); |
| | 683 | check.checkNotPresent("_getFoo"); |
| | 684 | test_step.dependOn(&check.step); |
| | 685 | } |
| | 686 | |
| | 687 | const libb = addSharedLibrary(b, opts, .{ .name = "b", .c_source_bytes = |
| | 688 | \\#include <stdio.h> |
| | 689 | \\int foo = 2; |
| | 690 | \\int* ptr_to_foo = &foo; |
| | 691 | \\int getFoo() { |
| | 692 | \\ return foo; |
| | 693 | \\} |
| | 694 | \\void printInB() { |
| | 695 | \\ printf("libb: getFoo()=%d, ptr_to_foo=%d\n", getFoo(), *ptr_to_foo); |
| | 696 | \\} |
| | 697 | }); |
| | 698 | |
| | 699 | { |
| | 700 | const check = libb.checkObject(); |
| | 701 | check.checkInDyldLazyBind(); |
| | 702 | check.checkNotPresent("(flat lookup) _getFoo"); |
| | 703 | check.checkInIndirectSymtab(); |
| | 704 | check.checkNotPresent("_getFoo"); |
| | 705 | test_step.dependOn(&check.step); |
| | 706 | } |
| | 707 | |
| | 708 | const main_o = addObject(b, opts, .{ .name = "main", .c_source_bytes = |
| | 709 | \\#include <stdio.h> |
| | 710 | \\int getFoo(); |
| | 711 | \\extern int* ptr_to_foo; |
| | 712 | \\void printInA(); |
| | 713 | \\void printInB(); |
| | 714 | \\int main() { |
| | 715 | \\ printf("main: getFoo()=%d, ptr_to_foo=%d\n", getFoo(), *ptr_to_foo); |
| | 716 | \\ printInA(); |
| | 717 | \\ printInB(); |
| | 718 | \\ return 0; |
| | 719 | \\} |
| | 720 | }); |
| | 721 | |
| | 722 | { |
| | 723 | const exe = addExecutable(b, opts, .{ .name = "main1" }); |
| | 724 | exe.addObject(main_o); |
| | 725 | exe.root_module.linkSystemLibrary("a", .{}); |
| | 726 | exe.root_module.linkSystemLibrary("b", .{}); |
| | 727 | exe.addLibraryPath(liba.getEmittedBinDirectory()); |
| | 728 | exe.addLibraryPath(libb.getEmittedBinDirectory()); |
| | 729 | exe.addRPath(liba.getEmittedBinDirectory()); |
| | 730 | exe.addRPath(libb.getEmittedBinDirectory()); |
| | 731 | |
| | 732 | const check = exe.checkObject(); |
| | 733 | check.checkInSymtab(); |
| | 734 | check.checkExact("(undefined) external _getFoo (from liba)"); |
| | 735 | check.checkInSymtab(); |
| | 736 | check.checkExact("(undefined) external _printInA (from liba)"); |
| | 737 | check.checkInSymtab(); |
| | 738 | check.checkExact("(undefined) external _printInB (from libb)"); |
| | 739 | test_step.dependOn(&check.step); |
| | 740 | |
| | 741 | const run = addRunArtifact(exe); |
| | 742 | run.expectStdOutEqual( |
| | 743 | \\main: getFoo()=1, ptr_to_foo=1 |
| | 744 | \\liba: getFoo()=1, ptr_to_foo=1 |
| | 745 | \\libb: getFoo()=2, ptr_to_foo=2 |
| | 746 | \\ |
| | 747 | ); |
| | 748 | test_step.dependOn(&run.step); |
| | 749 | } |
| | 750 | |
| | 751 | { |
| | 752 | const exe = addExecutable(b, opts, .{ .name = "main2" }); |
| | 753 | exe.addObject(main_o); |
| | 754 | exe.root_module.linkSystemLibrary("b", .{}); |
| | 755 | exe.root_module.linkSystemLibrary("a", .{}); |
| | 756 | exe.addLibraryPath(liba.getEmittedBinDirectory()); |
| | 757 | exe.addLibraryPath(libb.getEmittedBinDirectory()); |
| | 758 | exe.addRPath(liba.getEmittedBinDirectory()); |
| | 759 | exe.addRPath(libb.getEmittedBinDirectory()); |
| | 760 | |
| | 761 | const check = exe.checkObject(); |
| | 762 | check.checkInSymtab(); |
| | 763 | check.checkExact("(undefined) external _getFoo (from libb)"); |
| | 764 | check.checkInSymtab(); |
| | 765 | check.checkExact("(undefined) external _printInA (from liba)"); |
| | 766 | check.checkInSymtab(); |
| | 767 | check.checkExact("(undefined) external _printInB (from libb)"); |
| | 768 | test_step.dependOn(&check.step); |
| | 769 | |
| | 770 | const run = addRunArtifact(exe); |
| | 771 | run.expectStdOutEqual( |
| | 772 | \\main: getFoo()=2, ptr_to_foo=2 |
| | 773 | \\liba: getFoo()=1, ptr_to_foo=1 |
| | 774 | \\libb: getFoo()=2, ptr_to_foo=2 |
| | 775 | \\ |
| | 776 | ); |
| | 777 | test_step.dependOn(&run.step); |
| | 778 | } |
| | 779 | |
| | 780 | return test_step; |
| | 781 | } |
| | 782 | |
| 662 | fn testUndefinedFlag(b: *Build, opts: Options) *Step { | 783 | fn testUndefinedFlag(b: *Build, opts: Options) *Step { |
| 663 | const test_step = addTestStep(b, "macho-undefined-flag", opts); | 784 | const test_step = addTestStep(b, "macho-undefined-flag", opts); |
| 664 | | 785 | |