| ... | ... | @@ -514,6 +514,119 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 514 | 514 | } |
| 515 | 515 | } |
| 516 | 516 | |
| 517 | fn resolvePaths( |
| 518 | arena: *Allocator, |
| 519 | resolved_paths: *std.ArrayList([]const u8), |
| 520 | syslibroot: ?[]const u8, |
| 521 | search_dirs: []const []const u8, |
| 522 | lib_names: []const []const u8, |
| 523 | kind: enum { lib, framework }, |
| 524 | ) !void { |
| 525 | var resolved_dirs = std.ArrayList([]const u8).init(arena); |
| 526 | for (search_dirs) |dir| { |
| 527 | if (fs.path.isAbsolute(dir)) { |
| 528 | var candidates = std.ArrayList([]const u8).init(arena); |
| 529 | if (syslibroot) |root| { |
| 530 | const full_path = try fs.path.join(arena, &[_][]const u8{ root, dir }); |
| 531 | try candidates.append(full_path); |
| 532 | } |
| 533 | try candidates.append(dir); |
| 534 | |
| 535 | var found = false; |
| 536 | for (candidates.items) |candidate| { |
| 537 | // Verify that search path actually exists |
| 538 | var tmp = fs.cwd().openDir(candidate, .{}) catch |err| switch (err) { |
| 539 | error.FileNotFound => continue, |
| 540 | else => |e| return e, |
| 541 | }; |
| 542 | defer tmp.close(); |
| 543 | |
| 544 | try resolved_dirs.append(candidate); |
| 545 | found = true; |
| 546 | break; |
| 547 | } |
| 548 | |
| 549 | if (!found) { |
| 550 | switch (kind) { |
| 551 | .lib => log.warn("directory not found for '-L{s}'", .{dir}), |
| 552 | .framework => log.warn("directory not found for '-F{s}'", .{dir}), |
| 553 | } |
| 554 | } |
| 555 | } else { |
| 556 | // Verify that search path actually exists |
| 557 | var tmp = fs.cwd().openDir(dir, .{}) catch |err| switch (err) { |
| 558 | error.FileNotFound => { |
| 559 | switch (kind) { |
| 560 | .lib => log.warn("directory not found for '-L{s}'", .{dir}), |
| 561 | .framework => log.warn("directory not found for '-F{s}'", .{dir}), |
| 562 | } |
| 563 | continue; |
| 564 | }, |
| 565 | else => |e| return e, |
| 566 | }; |
| 567 | defer tmp.close(); |
| 568 | |
| 569 | try resolved_dirs.append(dir); |
| 570 | } |
| 571 | } |
| 572 | |
| 573 | // Assume ld64 default: -search_paths_first |
| 574 | // Look in each directory for a dylib (next, tbd), and then for archive |
| 575 | // TODO implement alternative: -search_dylibs_first |
| 576 | const exts = switch (kind) { |
| 577 | .lib => &[_][]const u8{ "dylib", "tbd", "a" }, |
| 578 | .framework => &[_][]const u8{ "dylib", "tbd" }, |
| 579 | }; |
| 580 | |
| 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 | }; |
| 595 | |
| 596 | for (resolved_dirs.items) |dir| { |
| 597 | const full_path = try fs.path.join(arena, &[_][]const u8{ dir, lib_name_ext }); |
| 598 | |
| 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(); |
| 605 | |
| 606 | try resolved_paths.append(full_path); |
| 607 | found = true; |
| 608 | break :ext; |
| 609 | } |
| 610 | } |
| 611 | |
| 612 | if (!found) { |
| 613 | switch (kind) { |
| 614 | .lib => { |
| 615 | log.warn("library not found for '-l{s}'", .{lib_name}); |
| 616 | log.warn("Library search paths:", .{}); |
| 617 | }, |
| 618 | .framework => { |
| 619 | log.warn("framework not found for '-f{s}'", .{lib_name}); |
| 620 | log.warn("Framework search paths:", .{}); |
| 621 | }, |
| 622 | } |
| 623 | for (resolved_dirs.items) |dir| { |
| 624 | log.warn(" {s}", .{dir}); |
| 625 | } |
| 626 | } |
| 627 | } |
| 628 | } |
| 629 | |
| 517 | 630 | fn linkWithLLD(self: *MachO, comp: *Compilation) !void { |
| 518 | 631 | const tracy = trace(@src()); |
| 519 | 632 | defer tracy.end(); |
| ... | ... | @@ -700,7 +813,6 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { |
| 700 | 813 | } |
| 701 | 814 | |
| 702 | 815 | // Shared and static libraries passed via `-l` flag. |
| 703 | | var libs = std.ArrayList([]const u8).init(arena); |
| 704 | 816 | var search_lib_names = std.ArrayList([]const u8).init(arena); |
| 705 | 817 | |
| 706 | 818 | const system_libs = self.base.options.system_libs.keys(); |
| ... | ... | @@ -716,84 +828,15 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { |
| 716 | 828 | try search_lib_names.append(link_lib); |
| 717 | 829 | } |
| 718 | 830 | |
| 719 | | var search_lib_dirs = std.ArrayList([]const u8).init(arena); |
| 720 | | |
| 721 | | for (self.base.options.lib_dirs) |path| { |
| 722 | | if (fs.path.isAbsolute(path)) { |
| 723 | | var candidates = std.ArrayList([]const u8).init(arena); |
| 724 | | if (self.base.options.syslibroot) |syslibroot| { |
| 725 | | const full_path = try fs.path.join(arena, &[_][]const u8{ syslibroot, path }); |
| 726 | | try candidates.append(full_path); |
| 727 | | } |
| 728 | | try candidates.append(path); |
| 729 | | |
| 730 | | var found = false; |
| 731 | | for (candidates.items) |candidate| { |
| 732 | | // Verify that search path actually exists |
| 733 | | var tmp = fs.cwd().openDir(candidate, .{}) catch |err| switch (err) { |
| 734 | | error.FileNotFound => continue, |
| 735 | | else => |e| return e, |
| 736 | | }; |
| 737 | | defer tmp.close(); |
| 738 | | |
| 739 | | try search_lib_dirs.append(candidate); |
| 740 | | found = true; |
| 741 | | break; |
| 742 | | } |
| 743 | | |
| 744 | | if (!found) { |
| 745 | | log.warn("directory not found for '-L{s}'", .{path}); |
| 746 | | } |
| 747 | | } else { |
| 748 | | // Verify that search path actually exists |
| 749 | | var tmp = fs.cwd().openDir(path, .{}) catch |err| switch (err) { |
| 750 | | error.FileNotFound => { |
| 751 | | log.warn("directory not found for '-L{s}'", .{path}); |
| 752 | | continue; |
| 753 | | }, |
| 754 | | else => |e| return e, |
| 755 | | }; |
| 756 | | defer tmp.close(); |
| 757 | | |
| 758 | | try search_lib_dirs.append(path); |
| 759 | | } |
| 760 | | } |
| 761 | | |
| 762 | | // Assume ld64 default: -search_paths_first |
| 763 | | // Look in each directory for a dylib (next, tbd), and then for archive |
| 764 | | // TODO implement alternative: -search_dylibs_first |
| 765 | | const exts = &[_][]const u8{ "dylib", "tbd", "a" }; |
| 766 | | |
| 767 | | for (search_lib_names.items) |l_name| { |
| 768 | | var found = false; |
| 769 | | |
| 770 | | ext: for (exts) |ext| { |
| 771 | | const l_name_ext = try std.fmt.allocPrint(arena, "lib{s}.{s}", .{ l_name, ext }); |
| 772 | | |
| 773 | | for (search_lib_dirs.items) |lib_dir| { |
| 774 | | const full_path = try fs.path.join(arena, &[_][]const u8{ lib_dir, l_name_ext }); |
| 775 | | |
| 776 | | // Check if the lib file exists. |
| 777 | | const tmp = fs.cwd().openFile(full_path, .{}) catch |err| switch (err) { |
| 778 | | error.FileNotFound => continue, |
| 779 | | else => |e| return e, |
| 780 | | }; |
| 781 | | defer tmp.close(); |
| 782 | | |
| 783 | | try libs.append(full_path); |
| 784 | | found = true; |
| 785 | | break :ext; |
| 786 | | } |
| 787 | | } |
| 788 | | |
| 789 | | if (!found) { |
| 790 | | log.warn("library not found for '-l{s}'", .{l_name}); |
| 791 | | log.warn("Library search paths:", .{}); |
| 792 | | for (search_lib_dirs.items) |lib_dir| { |
| 793 | | log.warn(" {s}", .{lib_dir}); |
| 794 | | } |
| 795 | | } |
| 796 | | } |
| 831 | var libs = std.ArrayList([]const u8).init(arena); |
| 832 | try resolvePaths( |
| 833 | arena, |
| 834 | &libs, |
| 835 | self.base.options.syslibroot, |
| 836 | self.base.options.lib_dirs, |
| 837 | search_lib_names.items, |
| 838 | .lib, |
| 839 | ); |
| 797 | 840 | |
| 798 | 841 | // rpaths |
| 799 | 842 | var rpath_table = std.StringArrayHashMap(void).init(arena); |
| ... | ... | @@ -809,9 +852,14 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { |
| 809 | 852 | } |
| 810 | 853 | |
| 811 | 854 | // frameworks |
| 812 | | for (self.base.options.frameworks) |framework| { |
| 813 | | log.warn("frameworks not yet supported for '-framework {s}'", .{framework}); |
| 814 | | } |
| 855 | try resolvePaths( |
| 856 | arena, |
| 857 | &libs, |
| 858 | self.base.options.syslibroot, |
| 859 | self.base.options.framework_dirs, |
| 860 | self.base.options.frameworks, |
| 861 | .framework, |
| 862 | ); |
| 815 | 863 | |
| 816 | 864 | if (self.base.options.verbose_link) { |
| 817 | 865 | var argv = std.ArrayList([]const u8).init(arena); |