| ... | @@ -514,15 +514,18 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { | ... | @@ -514,15 +514,18 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 514 | } | 514 | } |
| 515 | } | 515 | } |
| 516 | | 516 | |
| 517 | fn resolvePaths( | 517 | const LibKind = enum { |
| | 518 | lib, |
| | 519 | framework, |
| | 520 | }; |
| | 521 | |
| | 522 | fn resolveDirs( |
| 518 | arena: *Allocator, | 523 | arena: *Allocator, |
| 519 | resolved_paths: *std.ArrayList([]const u8), | 524 | resolved_dirs: *std.ArrayList([]const u8), |
| 520 | syslibroot: ?[]const u8, | 525 | syslibroot: ?[]const u8, |
| 521 | search_dirs: []const []const u8, | 526 | search_dirs: []const []const u8, |
| 522 | lib_names: []const []const u8, | 527 | lib_kind: LibKind, |
| 523 | kind: enum { lib, framework }, | | |
| 524 | ) !void { | 528 | ) !void { |
| 525 | var resolved_dirs = std.ArrayList([]const u8).init(arena); | | |
| 526 | for (search_dirs) |dir| { | 529 | for (search_dirs) |dir| { |
| 527 | if (fs.path.isAbsolute(dir)) { | 530 | if (fs.path.isAbsolute(dir)) { |
| 528 | var candidates = std.ArrayList([]const u8).init(arena); | 531 | var candidates = std.ArrayList([]const u8).init(arena); |
| ... | @@ -547,7 +550,7 @@ fn resolvePaths( | ... | @@ -547,7 +550,7 @@ fn resolvePaths( |
| 547 | } | 550 | } |
| 548 | | 551 | |
| 549 | if (!found) { | 552 | if (!found) { |
| 550 | switch (kind) { | 553 | switch (lib_kind) { |
| 551 | .lib => log.warn("directory not found for '-L{s}'", .{dir}), | 554 | .lib => log.warn("directory not found for '-L{s}'", .{dir}), |
| 552 | .framework => log.warn("directory not found for '-F{s}'", .{dir}), | 555 | .framework => log.warn("directory not found for '-F{s}'", .{dir}), |
| 553 | } | 556 | } |
| ... | @@ -556,7 +559,7 @@ fn resolvePaths( | ... | @@ -556,7 +559,7 @@ fn resolvePaths( |
| 556 | // Verify that search path actually exists | 559 | // Verify that search path actually exists |
| 557 | var tmp = fs.cwd().openDir(dir, .{}) catch |err| switch (err) { | 560 | var tmp = fs.cwd().openDir(dir, .{}) catch |err| switch (err) { |
| 558 | error.FileNotFound => { | 561 | error.FileNotFound => { |
| 559 | switch (kind) { | 562 | switch (lib_kind) { |
| 560 | .lib => log.warn("directory not found for '-L{s}'", .{dir}), | 563 | .lib => log.warn("directory not found for '-L{s}'", .{dir}), |
| 561 | .framework => log.warn("directory not found for '-F{s}'", .{dir}), | 564 | .framework => log.warn("directory not found for '-F{s}'", .{dir}), |
| 562 | } | 565 | } |
| ... | @@ -569,48 +572,63 @@ fn resolvePaths( | ... | @@ -569,48 +572,63 @@ fn resolvePaths( |
| 569 | try resolved_dirs.append(dir); | 572 | try resolved_dirs.append(dir); |
| 570 | } | 573 | } |
| 571 | } | 574 | } |
| | 575 | } |
| 572 | | 576 | |
| | 577 | fn resolveLib( |
| | 578 | arena: *Allocator, |
| | 579 | lib_dirs: []const []const u8, |
| | 580 | lib_name: []const u8, |
| | 581 | lib_kind: LibKind, |
| | 582 | ) !?[]const u8 { |
| 573 | // Assume ld64 default: -search_paths_first | 583 | // Assume ld64 default: -search_paths_first |
| 574 | // Look in each directory for a dylib (next, tbd), and then for archive | 584 | // Look in each directory for a dylib (next, tbd), and then for archive |
| 575 | // TODO implement alternative: -search_dylibs_first | 585 | // TODO implement alternative: -search_dylibs_first |
| 576 | const exts = switch (kind) { | 586 | const exts = switch (lib_kind) { |
| 577 | .lib => &[_][]const u8{ "dylib", "tbd", "a" }, | 587 | .lib => &[_][]const u8{ "dylib", "tbd", "a" }, |
| 578 | .framework => &[_][]const u8{ "dylib", "tbd" }, | 588 | .framework => &[_][]const u8{ "dylib", "tbd" }, |
| 579 | }; | 589 | }; |
| 580 | | 590 | |
| 581 | for (lib_names) |lib_name| { | 591 | for (exts) |ext| { |
| 582 | var found = false; | 592 | const lib_name_ext = blk: { |
| 583 | | 593 | switch (lib_kind) { |
| 584 | ext: for (exts) |ext| { | 594 | .lib => break :blk try std.fmt.allocPrint(arena, "lib{s}.{s}", .{ lib_name, ext }), |
| 585 | const lib_name_ext = blk: { | 595 | .framework => { |
| 586 | switch (kind) { | 596 | const prefix = try std.fmt.allocPrint(arena, "{s}.framework", .{lib_name}); |
| 587 | .lib => break :blk try std.fmt.allocPrint(arena, "lib{s}.{s}", .{ lib_name, ext }), | 597 | const nn = try std.fmt.allocPrint(arena, "{s}.{s}", .{ lib_name, ext }); |
| 588 | .framework => { | 598 | break :blk try fs.path.join(arena, &[_][]const u8{ prefix, nn }); |
| 589 | const prefix = try std.fmt.allocPrint(arena, "{s}.framework", .{lib_name}); | 599 | }, |
| 590 | const nn = try std.fmt.allocPrint(arena, "{s}.{s}", .{ lib_name, ext }); | 600 | } |
| 591 | break :blk try fs.path.join(arena, &[_][]const u8{ prefix, nn }); | 601 | }; |
| 592 | }, | | |
| 593 | } | | |
| 594 | }; | | |
| 595 | | 602 | |
| 596 | for (resolved_dirs.items) |dir| { | 603 | for (lib_dirs) |dir| { |
| 597 | const full_path = try fs.path.join(arena, &[_][]const u8{ dir, lib_name_ext }); | 604 | const full_path = try fs.path.join(arena, &[_][]const u8{ dir, lib_name_ext }); |
| 598 | | 605 | |
| 599 | // Check if the lib file exists. | 606 | // Check if the lib file exists. |
| 600 | const tmp = fs.cwd().openFile(full_path, .{}) catch |err| switch (err) { | 607 | const tmp = fs.cwd().openFile(full_path, .{}) catch |err| switch (err) { |
| 601 | error.FileNotFound => continue, | 608 | error.FileNotFound => continue, |
| 602 | else => |e| return e, | 609 | else => |e| return e, |
| 603 | }; | 610 | }; |
| 604 | defer tmp.close(); | 611 | defer tmp.close(); |
| 605 | | 612 | |
| 606 | try resolved_paths.append(full_path); | 613 | return full_path; |
| 607 | found = true; | | |
| 608 | break :ext; | | |
| 609 | } | | |
| 610 | } | 614 | } |
| | 615 | } |
| | 616 | |
| | 617 | return null; |
| | 618 | } |
| 611 | | 619 | |
| 612 | if (!found) { | 620 | fn resolveLibs( |
| 613 | switch (kind) { | 621 | arena: *Allocator, |
| | 622 | resolved_libs: *std.ArrayList([]const u8), |
| | 623 | lib_dirs: []const []const u8, |
| | 624 | lib_names: []const []const u8, |
| | 625 | lib_kind: LibKind, |
| | 626 | ) !void { |
| | 627 | for (lib_names) |lib_name| { |
| | 628 | if (try resolveLib(arena, lib_dirs, lib_name, lib_kind)) |full_path| { |
| | 629 | try resolved_libs.append(full_path); |
| | 630 | } else { |
| | 631 | switch (lib_kind) { |
| 614 | .lib => { | 632 | .lib => { |
| 615 | log.warn("library not found for '-l{s}'", .{lib_name}); | 633 | log.warn("library not found for '-l{s}'", .{lib_name}); |
| 616 | log.warn("Library search paths:", .{}); | 634 | log.warn("Library search paths:", .{}); |
| ... | @@ -620,7 +638,7 @@ fn resolvePaths( | ... | @@ -620,7 +638,7 @@ fn resolvePaths( |
| 620 | log.warn("Framework search paths:", .{}); | 638 | log.warn("Framework search paths:", .{}); |
| 621 | }, | 639 | }, |
| 622 | } | 640 | } |
| 623 | for (resolved_dirs.items) |dir| { | 641 | for (lib_dirs) |dir| { |
| 624 | log.warn(" {s}", .{dir}); | 642 | log.warn(" {s}", .{dir}); |
| 625 | } | 643 | } |
| 626 | } | 644 | } |
| ... | @@ -789,7 +807,6 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { | ... | @@ -789,7 +807,6 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { |
| 789 | zld.deinit(); | 807 | zld.deinit(); |
| 790 | } | 808 | } |
| 791 | zld.arch = target.cpu.arch; | 809 | zld.arch = target.cpu.arch; |
| 792 | zld.syslibroot = self.base.options.sysroot; | | |
| 793 | zld.stack_size = stack_size; | 810 | zld.stack_size = stack_size; |
| 794 | | 811 | |
| 795 | // Positional arguments to the linker such as object files and static archives. | 812 | // Positional arguments to the linker such as object files and static archives. |
| ... | @@ -829,16 +846,56 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { | ... | @@ -829,16 +846,56 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { |
| 829 | try search_lib_names.append(link_lib); | 846 | try search_lib_names.append(link_lib); |
| 830 | } | 847 | } |
| 831 | | 848 | |
| 832 | var libs = std.ArrayList([]const u8).init(arena); | 849 | var lib_dirs = std.ArrayList([]const u8).init(arena); |
| 833 | try resolvePaths( | 850 | try resolveDirs( |
| 834 | arena, | 851 | arena, |
| 835 | &libs, | 852 | &lib_dirs, |
| 836 | self.base.options.sysroot, | 853 | self.base.options.sysroot, |
| 837 | self.base.options.lib_dirs, | 854 | self.base.options.lib_dirs, |
| | 855 | .lib, |
| | 856 | ); |
| | 857 | |
| | 858 | var libs = std.ArrayList([]const u8).init(arena); |
| | 859 | try resolveLibs( |
| | 860 | arena, |
| | 861 | &libs, |
| | 862 | lib_dirs.items, |
| 838 | search_lib_names.items, | 863 | search_lib_names.items, |
| 839 | .lib, | 864 | .lib, |
| 840 | ); | 865 | ); |
| 841 | | 866 | |
| | 867 | // If we're compiling native and we can find libSystem.B.{dylib, tbd}, |
| | 868 | // we link against that instead of embedded libSystem.B.tbd file. |
| | 869 | const libc_stub_path = blk: { |
| | 870 | if (self.base.options.is_native_os) { |
| | 871 | if (try resolveLib(arena, lib_dirs.items, "System", .lib)) |full_path| { |
| | 872 | break :blk full_path; |
| | 873 | } |
| | 874 | } |
| | 875 | |
| | 876 | break :blk try comp.zig_lib_directory.join(arena, &[_][]const u8{ |
| | 877 | "libc", "darwin", "libSystem.B.tbd", |
| | 878 | }); |
| | 879 | }; |
| | 880 | |
| | 881 | // frameworks |
| | 882 | var framework_dirs = std.ArrayList([]const u8).init(arena); |
| | 883 | try resolveDirs( |
| | 884 | arena, |
| | 885 | &framework_dirs, |
| | 886 | self.base.options.sysroot, |
| | 887 | self.base.options.framework_dirs, |
| | 888 | .framework, |
| | 889 | ); |
| | 890 | |
| | 891 | try resolveLibs( |
| | 892 | arena, |
| | 893 | &libs, |
| | 894 | framework_dirs.items, |
| | 895 | self.base.options.frameworks, |
| | 896 | .framework, |
| | 897 | ); |
| | 898 | |
| 842 | // rpaths | 899 | // rpaths |
| 843 | var rpath_table = std.StringArrayHashMap(void).init(arena); | 900 | var rpath_table = std.StringArrayHashMap(void).init(arena); |
| 844 | for (self.base.options.rpath_list) |rpath| { | 901 | for (self.base.options.rpath_list) |rpath| { |
| ... | @@ -852,16 +909,6 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { | ... | @@ -852,16 +909,6 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { |
| 852 | rpaths.appendAssumeCapacity(key.*); | 909 | rpaths.appendAssumeCapacity(key.*); |
| 853 | } | 910 | } |
| 854 | | 911 | |
| 855 | // frameworks | | |
| 856 | try resolvePaths( | | |
| 857 | arena, | | |
| 858 | &libs, | | |
| 859 | self.base.options.sysroot, | | |
| 860 | self.base.options.framework_dirs, | | |
| 861 | self.base.options.frameworks, | | |
| 862 | .framework, | | |
| 863 | ); | | |
| 864 | | | |
| 865 | if (self.base.options.verbose_link) { | 912 | if (self.base.options.verbose_link) { |
| 866 | var argv = std.ArrayList([]const u8).init(arena); | 913 | var argv = std.ArrayList([]const u8).init(arena); |
| 867 | | 914 | |
| ... | @@ -895,11 +942,10 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { | ... | @@ -895,11 +942,10 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { |
| 895 | } | 942 | } |
| 896 | | 943 | |
| 897 | try zld.link(positionals.items, full_out_path, .{ | 944 | try zld.link(positionals.items, full_out_path, .{ |
| | 945 | .syslibroot = self.base.options.sysroot, |
| 898 | .libs = libs.items, | 946 | .libs = libs.items, |
| 899 | .rpaths = rpaths.items, | 947 | .rpaths = rpaths.items, |
| 900 | .libc_stub_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ | 948 | .libc_stub_path = libc_stub_path, |
| 901 | "libc", "darwin", "libSystem.B.tbd", | | |
| 902 | }), | | |
| 903 | }); | 949 | }); |
| 904 | | 950 | |
| 905 | break :outer; | 951 | break :outer; |