| ... | ... | @@ -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 | 523 | arena: *Allocator, |
| 519 | | resolved_paths: *std.ArrayList([]const u8), |
| 524 | resolved_dirs: *std.ArrayList([]const u8), |
| 520 | 525 | syslibroot: ?[]const u8, |
| 521 | 526 | search_dirs: []const []const u8, |
| 522 | | lib_names: []const []const u8, |
| 523 | | kind: enum { lib, framework }, |
| 527 | lib_kind: LibKind, |
| 524 | 528 | ) !void { |
| 525 | | var resolved_dirs = std.ArrayList([]const u8).init(arena); |
| 526 | 529 | for (search_dirs) |dir| { |
| 527 | 530 | if (fs.path.isAbsolute(dir)) { |
| 528 | 531 | var candidates = std.ArrayList([]const u8).init(arena); |
| ... | ... | @@ -547,7 +550,7 @@ fn resolvePaths( |
| 547 | 550 | } |
| 548 | 551 | |
| 549 | 552 | if (!found) { |
| 550 | | switch (kind) { |
| 553 | switch (lib_kind) { |
| 551 | 554 | .lib => log.warn("directory not found for '-L{s}'", .{dir}), |
| 552 | 555 | .framework => log.warn("directory not found for '-F{s}'", .{dir}), |
| 553 | 556 | } |
| ... | ... | @@ -556,7 +559,7 @@ fn resolvePaths( |
| 556 | 559 | // Verify that search path actually exists |
| 557 | 560 | var tmp = fs.cwd().openDir(dir, .{}) catch |err| switch (err) { |
| 558 | 561 | error.FileNotFound => { |
| 559 | | switch (kind) { |
| 562 | switch (lib_kind) { |
| 560 | 563 | .lib => log.warn("directory not found for '-L{s}'", .{dir}), |
| 561 | 564 | .framework => log.warn("directory not found for '-F{s}'", .{dir}), |
| 562 | 565 | } |
| ... | ... | @@ -569,48 +572,63 @@ fn resolvePaths( |
| 569 | 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 | 583 | // Assume ld64 default: -search_paths_first |
| 574 | 584 | // Look in each directory for a dylib (next, tbd), and then for archive |
| 575 | 585 | // TODO implement alternative: -search_dylibs_first |
| 576 | | const exts = switch (kind) { |
| 586 | const exts = switch (lib_kind) { |
| 577 | 587 | .lib => &[_][]const u8{ "dylib", "tbd", "a" }, |
| 578 | 588 | .framework => &[_][]const u8{ "dylib", "tbd" }, |
| 579 | 589 | }; |
| 580 | 590 | |
| 581 | | for (lib_names) |lib_name| { |
| 582 | | var found = false; |
| 583 | | |
| 584 | | ext: for (exts) |ext| { |
| 585 | | const lib_name_ext = blk: { |
| 586 | | switch (kind) { |
| 587 | | .lib => break :blk try std.fmt.allocPrint(arena, "lib{s}.{s}", .{ lib_name, ext }), |
| 588 | | .framework => { |
| 589 | | const prefix = try std.fmt.allocPrint(arena, "{s}.framework", .{lib_name}); |
| 590 | | const nn = try std.fmt.allocPrint(arena, "{s}.{s}", .{ lib_name, ext }); |
| 591 | | break :blk try fs.path.join(arena, &[_][]const u8{ prefix, nn }); |
| 592 | | }, |
| 593 | | } |
| 594 | | }; |
| 591 | for (exts) |ext| { |
| 592 | const lib_name_ext = blk: { |
| 593 | switch (lib_kind) { |
| 594 | .lib => break :blk try std.fmt.allocPrint(arena, "lib{s}.{s}", .{ lib_name, ext }), |
| 595 | .framework => { |
| 596 | const prefix = try std.fmt.allocPrint(arena, "{s}.framework", .{lib_name}); |
| 597 | const nn = try std.fmt.allocPrint(arena, "{s}.{s}", .{ lib_name, ext }); |
| 598 | break :blk try fs.path.join(arena, &[_][]const u8{ prefix, nn }); |
| 599 | }, |
| 600 | } |
| 601 | }; |
| 595 | 602 | |
| 596 | | for (resolved_dirs.items) |dir| { |
| 597 | | const full_path = try fs.path.join(arena, &[_][]const u8{ dir, lib_name_ext }); |
| 603 | for (lib_dirs) |dir| { |
| 604 | const full_path = try fs.path.join(arena, &[_][]const u8{ dir, lib_name_ext }); |
| 598 | 605 | |
| 599 | | // Check if the lib file exists. |
| 600 | | const tmp = fs.cwd().openFile(full_path, .{}) catch |err| switch (err) { |
| 601 | | error.FileNotFound => continue, |
| 602 | | else => |e| return e, |
| 603 | | }; |
| 604 | | defer tmp.close(); |
| 606 | // Check if the lib file exists. |
| 607 | const tmp = fs.cwd().openFile(full_path, .{}) catch |err| switch (err) { |
| 608 | error.FileNotFound => continue, |
| 609 | else => |e| return e, |
| 610 | }; |
| 611 | defer tmp.close(); |
| 605 | 612 | |
| 606 | | try resolved_paths.append(full_path); |
| 607 | | found = true; |
| 608 | | break :ext; |
| 609 | | } |
| 613 | return full_path; |
| 610 | 614 | } |
| 615 | } |
| 616 | |
| 617 | return null; |
| 618 | } |
| 611 | 619 | |
| 612 | | if (!found) { |
| 613 | | switch (kind) { |
| 620 | fn resolveLibs( |
| 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 | 632 | .lib => { |
| 615 | 633 | log.warn("library not found for '-l{s}'", .{lib_name}); |
| 616 | 634 | log.warn("Library search paths:", .{}); |
| ... | ... | @@ -620,7 +638,7 @@ fn resolvePaths( |
| 620 | 638 | log.warn("Framework search paths:", .{}); |
| 621 | 639 | }, |
| 622 | 640 | } |
| 623 | | for (resolved_dirs.items) |dir| { |
| 641 | for (lib_dirs) |dir| { |
| 624 | 642 | log.warn(" {s}", .{dir}); |
| 625 | 643 | } |
| 626 | 644 | } |
| ... | ... | @@ -789,7 +807,6 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { |
| 789 | 807 | zld.deinit(); |
| 790 | 808 | } |
| 791 | 809 | zld.arch = target.cpu.arch; |
| 792 | | zld.syslibroot = self.base.options.sysroot; |
| 793 | 810 | zld.stack_size = stack_size; |
| 794 | 811 | |
| 795 | 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 | 846 | try search_lib_names.append(link_lib); |
| 830 | 847 | } |
| 831 | 848 | |
| 832 | | var libs = std.ArrayList([]const u8).init(arena); |
| 833 | | try resolvePaths( |
| 849 | var lib_dirs = std.ArrayList([]const u8).init(arena); |
| 850 | try resolveDirs( |
| 834 | 851 | arena, |
| 835 | | &libs, |
| 852 | &lib_dirs, |
| 836 | 853 | self.base.options.sysroot, |
| 837 | 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 | 863 | search_lib_names.items, |
| 839 | 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 | 899 | // rpaths |
| 843 | 900 | var rpath_table = std.StringArrayHashMap(void).init(arena); |
| 844 | 901 | for (self.base.options.rpath_list) |rpath| { |
| ... | ... | @@ -852,16 +909,6 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { |
| 852 | 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 | 912 | if (self.base.options.verbose_link) { |
| 866 | 913 | var argv = std.ArrayList([]const u8).init(arena); |
| 867 | 914 | |
| ... | ... | @@ -895,11 +942,10 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { |
| 895 | 942 | } |
| 896 | 943 | |
| 897 | 944 | try zld.link(positionals.items, full_out_path, .{ |
| 945 | .syslibroot = self.base.options.sysroot, |
| 898 | 946 | .libs = libs.items, |
| 899 | 947 | .rpaths = rpaths.items, |
| 900 | | .libc_stub_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ |
| 901 | | "libc", "darwin", "libSystem.B.tbd", |
| 902 | | }), |
| 948 | .libc_stub_path = libc_stub_path, |
| 903 | 949 | }); |
| 904 | 950 | |
| 905 | 951 | break :outer; |