| author | |
| committer | |
| log | 1340565e22e154db41e90a8d4f0b552176711ba0 |
| tree | 0fcb0dde8105082065f46d1f477c97903f69b7e5 |
| parent | 92ae5818d26925af7816fabcaec85236133b9e46 |
| parent | 2857a3bcb61ad8f119f46acf3a76fd70195f9bd5 |
| signature |
link: fix false positive crtbegin/crtend detection32 files changed, 987 insertions(+), 701 deletions(-)
lib/std/Build/Cache.zig+7| ... | @@ -398,12 +398,19 @@ pub const Manifest = struct { | ... | @@ -398,12 +398,19 @@ pub const Manifest = struct { |
| 398 | return gop.index; | 398 | return gop.index; |
| 399 | } | 399 | } |
| 400 | 400 | ||
| 401 | /// Deprecated, use `addOptionalFilePath`. | ||
| 401 | pub fn addOptionalFile(self: *Manifest, optional_file_path: ?[]const u8) !void { | 402 | pub fn addOptionalFile(self: *Manifest, optional_file_path: ?[]const u8) !void { |
| 402 | self.hash.add(optional_file_path != null); | 403 | self.hash.add(optional_file_path != null); |
| 403 | const file_path = optional_file_path orelse return; | 404 | const file_path = optional_file_path orelse return; |
| 404 | _ = try self.addFile(file_path, null); | 405 | _ = try self.addFile(file_path, null); |
| 405 | } | 406 | } |
| 406 | 407 | ||
| 408 | pub fn addOptionalFilePath(self: *Manifest, optional_file_path: ?Path) !void { | ||
| 409 | self.hash.add(optional_file_path != null); | ||
| 410 | const file_path = optional_file_path orelse return; | ||
| 411 | _ = try self.addFilePath(file_path, null); | ||
| 412 | } | ||
| 413 | |||
| 407 | pub fn addListOfFiles(self: *Manifest, list_of_files: []const []const u8) !void { | 414 | pub fn addListOfFiles(self: *Manifest, list_of_files: []const []const u8) !void { |
| 408 | self.hash.add(list_of_files.len); | 415 | self.hash.add(list_of_files.len); |
| 409 | for (list_of_files) |file_path| { | 416 | for (list_of_files) |file_path| { |
lib/std/Build/Cache/Path.zig+22-2| ... | @@ -11,7 +11,11 @@ pub fn clone(p: Path, arena: Allocator) Allocator.Error!Path { | ... | @@ -11,7 +11,11 @@ pub fn clone(p: Path, arena: Allocator) Allocator.Error!Path { |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | pub fn cwd() Path { | 13 | pub fn cwd() Path { |
| 14 | return .{ .root_dir = Cache.Directory.cwd() }; | 14 | return initCwd(""); |
| 15 | } | ||
| 16 | |||
| 17 | pub fn initCwd(sub_path: []const u8) Path { | ||
| 18 | return .{ .root_dir = Cache.Directory.cwd(), .sub_path = sub_path }; | ||
| 15 | } | 19 | } |
| 16 | 20 | ||
| 17 | pub fn join(p: Path, arena: Allocator, sub_path: []const u8) Allocator.Error!Path { | 21 | pub fn join(p: Path, arena: Allocator, sub_path: []const u8) Allocator.Error!Path { |
| ... | @@ -126,6 +130,14 @@ pub fn makePath(p: Path, sub_path: []const u8) !void { | ... | @@ -126,6 +130,14 @@ pub fn makePath(p: Path, sub_path: []const u8) !void { |
| 126 | return p.root_dir.handle.makePath(joined_path); | 130 | return p.root_dir.handle.makePath(joined_path); |
| 127 | } | 131 | } |
| 128 | 132 | ||
| 133 | pub fn toString(p: Path, allocator: Allocator) Allocator.Error![]u8 { | ||
| 134 | return std.fmt.allocPrint(allocator, "{}", .{p}); | ||
| 135 | } | ||
| 136 | |||
| 137 | pub fn toStringZ(p: Path, allocator: Allocator) Allocator.Error![:0]u8 { | ||
| 138 | return std.fmt.allocPrintZ(allocator, "{}", .{p}); | ||
| 139 | } | ||
| 140 | |||
| 129 | pub fn format( | 141 | pub fn format( |
| 130 | self: Path, | 142 | self: Path, |
| 131 | comptime fmt_string: []const u8, | 143 | comptime fmt_string: []const u8, |
| ... | @@ -137,7 +149,7 @@ pub fn format( | ... | @@ -137,7 +149,7 @@ pub fn format( |
| 137 | const stringEscape = std.zig.stringEscape; | 149 | const stringEscape = std.zig.stringEscape; |
| 138 | const f = switch (fmt_string[0]) { | 150 | const f = switch (fmt_string[0]) { |
| 139 | 'q' => "", | 151 | 'q' => "", |
| 140 | '\'' => '\'', | 152 | '\'' => "\'", |
| 141 | else => @compileError("unsupported format string: " ++ fmt_string), | 153 | else => @compileError("unsupported format string: " ++ fmt_string), |
| 142 | }; | 154 | }; |
| 143 | if (self.root_dir.path) |p| { | 155 | if (self.root_dir.path) |p| { |
| ... | @@ -182,6 +194,14 @@ pub fn subPathOrDot(self: Path) []const u8 { | ... | @@ -182,6 +194,14 @@ pub fn subPathOrDot(self: Path) []const u8 { |
| 182 | return if (self.sub_path.len == 0) "." else self.sub_path; | 194 | return if (self.sub_path.len == 0) "." else self.sub_path; |
| 183 | } | 195 | } |
| 184 | 196 | ||
| 197 | pub fn stem(p: Path) []const u8 { | ||
| 198 | return fs.path.stem(p.sub_path); | ||
| 199 | } | ||
| 200 | |||
| 201 | pub fn basename(p: Path) []const u8 { | ||
| 202 | return fs.path.basename(p.sub_path); | ||
| 203 | } | ||
| 204 | |||
| 185 | /// Useful to make `Path` a key in `std.ArrayHashMap`. | 205 | /// Useful to make `Path` a key in `std.ArrayHashMap`. |
| 186 | pub const TableAdapter = struct { | 206 | pub const TableAdapter = struct { |
| 187 | pub const Hash = std.hash.Wyhash; | 207 | pub const Hash = std.hash.Wyhash; |
lib/std/Build/Step/CheckObject.zig+32-12| ... | @@ -557,15 +557,15 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { | ... | @@ -557,15 +557,15 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { |
| 557 | const check_object: *CheckObject = @fieldParentPtr("step", step); | 557 | const check_object: *CheckObject = @fieldParentPtr("step", step); |
| 558 | try step.singleUnchangingWatchInput(check_object.source); | 558 | try step.singleUnchangingWatchInput(check_object.source); |
| 559 | 559 | ||
| 560 | const src_path = check_object.source.getPath2(b, step); | 560 | const src_path = check_object.source.getPath3(b, step); |
| 561 | const contents = fs.cwd().readFileAllocOptions( | 561 | const contents = src_path.root_dir.handle.readFileAllocOptions( |
| 562 | gpa, | 562 | gpa, |
| 563 | src_path, | 563 | src_path.sub_path, |
| 564 | check_object.max_bytes, | 564 | check_object.max_bytes, |
| 565 | null, | 565 | null, |
| 566 | @alignOf(u64), | 566 | @alignOf(u64), |
| 567 | null, | 567 | null, |
| 568 | ) catch |err| return step.fail("unable to read '{s}': {s}", .{ src_path, @errorName(err) }); | 568 | ) catch |err| return step.fail("unable to read '{'}': {s}", .{ src_path, @errorName(err) }); |
| 569 | 569 | ||
| 570 | var vars = std.StringHashMap(u64).init(gpa); | 570 | var vars = std.StringHashMap(u64).init(gpa); |
| 571 | for (check_object.checks.items) |chk| { | 571 | for (check_object.checks.items) |chk| { |
| ... | @@ -640,8 +640,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { | ... | @@ -640,8 +640,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { |
| 640 | \\{s} | 640 | \\{s} |
| 641 | \\========= but parsed file does not contain it: ======= | 641 | \\========= but parsed file does not contain it: ======= |
| 642 | \\{s} | 642 | \\{s} |
| 643 | \\====================================================== | 643 | \\========= file path: ================================= |
| 644 | , .{ fmtMessageString(chk.kind, act.phrase.resolve(b, step)), fmtMessageString(chk.kind, output) }); | 644 | \\{} |
| 645 | , .{ | ||
| 646 | fmtMessageString(chk.kind, act.phrase.resolve(b, step)), | ||
| 647 | fmtMessageString(chk.kind, output), | ||
| 648 | src_path, | ||
| 649 | }); | ||
| 645 | } | 650 | } |
| 646 | }, | 651 | }, |
| 647 | 652 | ||
| ... | @@ -655,8 +660,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { | ... | @@ -655,8 +660,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { |
| 655 | \\*{s}* | 660 | \\*{s}* |
| 656 | \\========= but parsed file does not contain it: ======= | 661 | \\========= but parsed file does not contain it: ======= |
| 657 | \\{s} | 662 | \\{s} |
| 658 | \\====================================================== | 663 | \\========= file path: ================================= |
| 659 | , .{ fmtMessageString(chk.kind, act.phrase.resolve(b, step)), fmtMessageString(chk.kind, output) }); | 664 | \\{} |
| 665 | , .{ | ||
| 666 | fmtMessageString(chk.kind, act.phrase.resolve(b, step)), | ||
| 667 | fmtMessageString(chk.kind, output), | ||
| 668 | src_path, | ||
| 669 | }); | ||
| 660 | } | 670 | } |
| 661 | }, | 671 | }, |
| 662 | 672 | ||
| ... | @@ -669,8 +679,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { | ... | @@ -669,8 +679,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { |
| 669 | \\{s} | 679 | \\{s} |
| 670 | \\========= but parsed file does contain it: ======== | 680 | \\========= but parsed file does contain it: ======== |
| 671 | \\{s} | 681 | \\{s} |
| 672 | \\=================================================== | 682 | \\========= file path: ============================== |
| 673 | , .{ fmtMessageString(chk.kind, act.phrase.resolve(b, step)), fmtMessageString(chk.kind, output) }); | 683 | \\{} |
| 684 | , .{ | ||
| 685 | fmtMessageString(chk.kind, act.phrase.resolve(b, step)), | ||
| 686 | fmtMessageString(chk.kind, output), | ||
| 687 | src_path, | ||
| 688 | }); | ||
| 674 | } | 689 | } |
| 675 | }, | 690 | }, |
| 676 | 691 | ||
| ... | @@ -684,8 +699,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { | ... | @@ -684,8 +699,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { |
| 684 | \\{s} | 699 | \\{s} |
| 685 | \\========= but parsed file does not contain it: ======= | 700 | \\========= but parsed file does not contain it: ======= |
| 686 | \\{s} | 701 | \\{s} |
| 687 | \\====================================================== | 702 | \\========= file path: ============================== |
| 688 | , .{ act.phrase.resolve(b, step), fmtMessageString(chk.kind, output) }); | 703 | \\{} |
| 704 | , .{ | ||
| 705 | act.phrase.resolve(b, step), | ||
| 706 | fmtMessageString(chk.kind, output), | ||
| 707 | src_path, | ||
| 708 | }); | ||
| 689 | } | 709 | } |
| 690 | }, | 710 | }, |
| 691 | 711 |
lib/std/zig/LibCInstallation.zig+328| ... | @@ -690,12 +690,340 @@ fn appendCcExe(args: *std.ArrayList([]const u8), skip_cc_env_var: bool) !void { | ... | @@ -690,12 +690,340 @@ fn appendCcExe(args: *std.ArrayList([]const u8), skip_cc_env_var: bool) !void { |
| 690 | } | 690 | } |
| 691 | } | 691 | } |
| 692 | 692 | ||
| 693 | /// These are basenames. This data is produced with a pure function. See also | ||
| 694 | /// `CsuPaths`. | ||
| 695 | pub const CrtBasenames = struct { | ||
| 696 | crt0: ?[]const u8 = null, | ||
| 697 | crti: ?[]const u8 = null, | ||
| 698 | crtbegin: ?[]const u8 = null, | ||
| 699 | crtend: ?[]const u8 = null, | ||
| 700 | crtn: ?[]const u8 = null, | ||
| 701 | |||
| 702 | pub const GetArgs = struct { | ||
| 703 | target: std.Target, | ||
| 704 | link_libc: bool, | ||
| 705 | output_mode: std.builtin.OutputMode, | ||
| 706 | link_mode: std.builtin.LinkMode, | ||
| 707 | pie: bool, | ||
| 708 | }; | ||
| 709 | |||
| 710 | /// Determine file system path names of C runtime startup objects for supported | ||
| 711 | /// link modes. | ||
| 712 | pub fn get(args: GetArgs) CrtBasenames { | ||
| 713 | // crt objects are only required for libc. | ||
| 714 | if (!args.link_libc) return .{}; | ||
| 715 | |||
| 716 | // Flatten crt cases. | ||
| 717 | const mode: enum { | ||
| 718 | dynamic_lib, | ||
| 719 | dynamic_exe, | ||
| 720 | dynamic_pie, | ||
| 721 | static_exe, | ||
| 722 | static_pie, | ||
| 723 | } = switch (args.output_mode) { | ||
| 724 | .Obj => return .{}, | ||
| 725 | .Lib => switch (args.link_mode) { | ||
| 726 | .dynamic => .dynamic_lib, | ||
| 727 | .static => return .{}, | ||
| 728 | }, | ||
| 729 | .Exe => switch (args.link_mode) { | ||
| 730 | .dynamic => if (args.pie) .dynamic_pie else .dynamic_exe, | ||
| 731 | .static => if (args.pie) .static_pie else .static_exe, | ||
| 732 | }, | ||
| 733 | }; | ||
| 734 | |||
| 735 | const target = args.target; | ||
| 736 | |||
| 737 | if (target.isAndroid()) return switch (mode) { | ||
| 738 | .dynamic_lib => .{ | ||
| 739 | .crtbegin = "crtbegin_so.o", | ||
| 740 | .crtend = "crtend_so.o", | ||
| 741 | }, | ||
| 742 | .dynamic_exe, .dynamic_pie => .{ | ||
| 743 | .crtbegin = "crtbegin_dynamic.o", | ||
| 744 | .crtend = "crtend_android.o", | ||
| 745 | }, | ||
| 746 | .static_exe, .static_pie => .{ | ||
| 747 | .crtbegin = "crtbegin_static.o", | ||
| 748 | .crtend = "crtend_android.o", | ||
| 749 | }, | ||
| 750 | }; | ||
| 751 | |||
| 752 | return switch (target.os.tag) { | ||
| 753 | .linux => switch (mode) { | ||
| 754 | .dynamic_lib => .{ | ||
| 755 | .crti = "crti.o", | ||
| 756 | .crtn = "crtn.o", | ||
| 757 | }, | ||
| 758 | .dynamic_exe => .{ | ||
| 759 | .crt0 = "crt1.o", | ||
| 760 | .crti = "crti.o", | ||
| 761 | .crtn = "crtn.o", | ||
| 762 | }, | ||
| 763 | .dynamic_pie => .{ | ||
| 764 | .crt0 = "Scrt1.o", | ||
| 765 | .crti = "crti.o", | ||
| 766 | .crtn = "crtn.o", | ||
| 767 | }, | ||
| 768 | .static_exe => .{ | ||
| 769 | .crt0 = "crt1.o", | ||
| 770 | .crti = "crti.o", | ||
| 771 | .crtn = "crtn.o", | ||
| 772 | }, | ||
| 773 | .static_pie => .{ | ||
| 774 | .crt0 = "rcrt1.o", | ||
| 775 | .crti = "crti.o", | ||
| 776 | .crtn = "crtn.o", | ||
| 777 | }, | ||
| 778 | }, | ||
| 779 | .dragonfly => switch (mode) { | ||
| 780 | .dynamic_lib => .{ | ||
| 781 | .crti = "crti.o", | ||
| 782 | .crtbegin = "crtbeginS.o", | ||
| 783 | .crtend = "crtendS.o", | ||
| 784 | .crtn = "crtn.o", | ||
| 785 | }, | ||
| 786 | .dynamic_exe => .{ | ||
| 787 | .crt0 = "crt1.o", | ||
| 788 | .crti = "crti.o", | ||
| 789 | .crtbegin = "crtbegin.o", | ||
| 790 | .crtend = "crtend.o", | ||
| 791 | .crtn = "crtn.o", | ||
| 792 | }, | ||
| 793 | .dynamic_pie => .{ | ||
| 794 | .crt0 = "Scrt1.o", | ||
| 795 | .crti = "crti.o", | ||
| 796 | .crtbegin = "crtbeginS.o", | ||
| 797 | .crtend = "crtendS.o", | ||
| 798 | .crtn = "crtn.o", | ||
| 799 | }, | ||
| 800 | .static_exe => .{ | ||
| 801 | .crt0 = "crt1.o", | ||
| 802 | .crti = "crti.o", | ||
| 803 | .crtbegin = "crtbegin.o", | ||
| 804 | .crtend = "crtend.o", | ||
| 805 | .crtn = "crtn.o", | ||
| 806 | }, | ||
| 807 | .static_pie => .{ | ||
| 808 | .crt0 = "Scrt1.o", | ||
| 809 | .crti = "crti.o", | ||
| 810 | .crtbegin = "crtbeginS.o", | ||
| 811 | .crtend = "crtendS.o", | ||
| 812 | .crtn = "crtn.o", | ||
| 813 | }, | ||
| 814 | }, | ||
| 815 | .freebsd => switch (mode) { | ||
| 816 | .dynamic_lib => .{ | ||
| 817 | .crti = "crti.o", | ||
| 818 | .crtbegin = "crtbeginS.o", | ||
| 819 | .crtend = "crtendS.o", | ||
| 820 | .crtn = "crtn.o", | ||
| 821 | }, | ||
| 822 | .dynamic_exe => .{ | ||
| 823 | .crt0 = "crt1.o", | ||
| 824 | .crti = "crti.o", | ||
| 825 | .crtbegin = "crtbegin.o", | ||
| 826 | .crtend = "crtend.o", | ||
| 827 | .crtn = "crtn.o", | ||
| 828 | }, | ||
| 829 | .dynamic_pie => .{ | ||
| 830 | .crt0 = "Scrt1.o", | ||
| 831 | .crti = "crti.o", | ||
| 832 | .crtbegin = "crtbeginS.o", | ||
| 833 | .crtend = "crtendS.o", | ||
| 834 | .crtn = "crtn.o", | ||
| 835 | }, | ||
| 836 | .static_exe => .{ | ||
| 837 | .crt0 = "crt1.o", | ||
| 838 | .crti = "crti.o", | ||
| 839 | .crtbegin = "crtbeginT.o", | ||
| 840 | .crtend = "crtend.o", | ||
| 841 | .crtn = "crtn.o", | ||
| 842 | }, | ||
| 843 | .static_pie => .{ | ||
| 844 | .crt0 = "Scrt1.o", | ||
| 845 | .crti = "crti.o", | ||
| 846 | .crtbegin = "crtbeginS.o", | ||
| 847 | .crtend = "crtendS.o", | ||
| 848 | .crtn = "crtn.o", | ||
| 849 | }, | ||
| 850 | }, | ||
| 851 | .netbsd => switch (mode) { | ||
| 852 | .dynamic_lib => .{ | ||
| 853 | .crti = "crti.o", | ||
| 854 | .crtbegin = "crtbeginS.o", | ||
| 855 | .crtend = "crtendS.o", | ||
| 856 | .crtn = "crtn.o", | ||
| 857 | }, | ||
| 858 | .dynamic_exe => .{ | ||
| 859 | .crt0 = "crt0.o", | ||
| 860 | .crti = "crti.o", | ||
| 861 | .crtbegin = "crtbegin.o", | ||
| 862 | .crtend = "crtend.o", | ||
| 863 | .crtn = "crtn.o", | ||
| 864 | }, | ||
| 865 | .dynamic_pie => .{ | ||
| 866 | .crt0 = "crt0.o", | ||
| 867 | .crti = "crti.o", | ||
| 868 | .crtbegin = "crtbeginS.o", | ||
| 869 | .crtend = "crtendS.o", | ||
| 870 | .crtn = "crtn.o", | ||
| 871 | }, | ||
| 872 | .static_exe => .{ | ||
| 873 | .crt0 = "crt0.o", | ||
| 874 | .crti = "crti.o", | ||
| 875 | .crtbegin = "crtbeginT.o", | ||
| 876 | .crtend = "crtend.o", | ||
| 877 | .crtn = "crtn.o", | ||
| 878 | }, | ||
| 879 | .static_pie => .{ | ||
| 880 | .crt0 = "crt0.o", | ||
| 881 | .crti = "crti.o", | ||
| 882 | .crtbegin = "crtbeginT.o", | ||
| 883 | .crtend = "crtendS.o", | ||
| 884 | .crtn = "crtn.o", | ||
| 885 | }, | ||
| 886 | }, | ||
| 887 | .openbsd => switch (mode) { | ||
| 888 | .dynamic_lib => .{ | ||
| 889 | .crtbegin = "crtbeginS.o", | ||
| 890 | .crtend = "crtendS.o", | ||
| 891 | }, | ||
| 892 | .dynamic_exe, .dynamic_pie => .{ | ||
| 893 | .crt0 = "crt0.o", | ||
| 894 | .crtbegin = "crtbegin.o", | ||
| 895 | .crtend = "crtend.o", | ||
| 896 | }, | ||
| 897 | .static_exe, .static_pie => .{ | ||
| 898 | .crt0 = "rcrt0.o", | ||
| 899 | .crtbegin = "crtbegin.o", | ||
| 900 | .crtend = "crtend.o", | ||
| 901 | }, | ||
| 902 | }, | ||
| 903 | .haiku => switch (mode) { | ||
| 904 | .dynamic_lib => .{ | ||
| 905 | .crti = "crti.o", | ||
| 906 | .crtbegin = "crtbeginS.o", | ||
| 907 | .crtend = "crtendS.o", | ||
| 908 | .crtn = "crtn.o", | ||
| 909 | }, | ||
| 910 | .dynamic_exe => .{ | ||
| 911 | .crt0 = "start_dyn.o", | ||
| 912 | .crti = "crti.o", | ||
| 913 | .crtbegin = "crtbegin.o", | ||
| 914 | .crtend = "crtend.o", | ||
| 915 | .crtn = "crtn.o", | ||
| 916 | }, | ||
| 917 | .dynamic_pie => .{ | ||
| 918 | .crt0 = "start_dyn.o", | ||
| 919 | .crti = "crti.o", | ||
| 920 | .crtbegin = "crtbeginS.o", | ||
| 921 | .crtend = "crtendS.o", | ||
| 922 | .crtn = "crtn.o", | ||
| 923 | }, | ||
| 924 | .static_exe => .{ | ||
| 925 | .crt0 = "start_dyn.o", | ||
| 926 | .crti = "crti.o", | ||
| 927 | .crtbegin = "crtbegin.o", | ||
| 928 | .crtend = "crtend.o", | ||
| 929 | .crtn = "crtn.o", | ||
| 930 | }, | ||
| 931 | .static_pie => .{ | ||
| 932 | .crt0 = "start_dyn.o", | ||
| 933 | .crti = "crti.o", | ||
| 934 | .crtbegin = "crtbeginS.o", | ||
| 935 | .crtend = "crtendS.o", | ||
| 936 | .crtn = "crtn.o", | ||
| 937 | }, | ||
| 938 | }, | ||
| 939 | .solaris, .illumos => switch (mode) { | ||
| 940 | .dynamic_lib => .{ | ||
| 941 | .crti = "crti.o", | ||
| 942 | .crtn = "crtn.o", | ||
| 943 | }, | ||
| 944 | .dynamic_exe, .dynamic_pie => .{ | ||
| 945 | .crt0 = "crt1.o", | ||
| 946 | .crti = "crti.o", | ||
| 947 | .crtn = "crtn.o", | ||
| 948 | }, | ||
| 949 | .static_exe, .static_pie => .{}, | ||
| 950 | }, | ||
| 951 | else => .{}, | ||
| 952 | }; | ||
| 953 | } | ||
| 954 | }; | ||
| 955 | |||
| 956 | pub const CrtPaths = struct { | ||
| 957 | crt0: ?Path = null, | ||
| 958 | crti: ?Path = null, | ||
| 959 | crtbegin: ?Path = null, | ||
| 960 | crtend: ?Path = null, | ||
| 961 | crtn: ?Path = null, | ||
| 962 | }; | ||
| 963 | |||
| 964 | pub fn resolveCrtPaths( | ||
| 965 | lci: LibCInstallation, | ||
| 966 | arena: Allocator, | ||
| 967 | crt_basenames: CrtBasenames, | ||
| 968 | target: std.Target, | ||
| 969 | ) error{ OutOfMemory, LibCInstallationMissingCrtDir }!CrtPaths { | ||
| 970 | const crt_dir_path: Path = .{ | ||
| 971 | .root_dir = std.Build.Cache.Directory.cwd(), | ||
| 972 | .sub_path = lci.crt_dir orelse return error.LibCInstallationMissingCrtDir, | ||
| 973 | }; | ||
| 974 | switch (target.os.tag) { | ||
| 975 | .dragonfly => { | ||
| 976 | const gccv: []const u8 = if (target.os.version_range.semver.isAtLeast(.{ | ||
| 977 | .major = 5, | ||
| 978 | .minor = 4, | ||
| 979 | .patch = 0, | ||
| 980 | }) orelse true) "gcc80" else "gcc54"; | ||
| 981 | return .{ | ||
| 982 | .crt0 = if (crt_basenames.crt0) |basename| try crt_dir_path.join(arena, basename) else null, | ||
| 983 | .crti = if (crt_basenames.crti) |basename| try crt_dir_path.join(arena, basename) else null, | ||
| 984 | .crtbegin = if (crt_basenames.crtbegin) |basename| .{ | ||
| 985 | .root_dir = crt_dir_path.root_dir, | ||
| 986 | .sub_path = try fs.path.join(arena, &.{ crt_dir_path.sub_path, gccv, basename }), | ||
| 987 | } else null, | ||
| 988 | .crtend = if (crt_basenames.crtend) |basename| .{ | ||
| 989 | .root_dir = crt_dir_path.root_dir, | ||
| 990 | .sub_path = try fs.path.join(arena, &.{ crt_dir_path.sub_path, gccv, basename }), | ||
| 991 | } else null, | ||
| 992 | .crtn = if (crt_basenames.crtn) |basename| try crt_dir_path.join(arena, basename) else null, | ||
| 993 | }; | ||
| 994 | }, | ||
| 995 | .haiku => { | ||
| 996 | const gcc_dir_path: Path = .{ | ||
| 997 | .root_dir = std.Build.Cache.Directory.cwd(), | ||
| 998 | .sub_path = lci.gcc_dir orelse return error.LibCInstallationMissingCrtDir, | ||
| 999 | }; | ||
| 1000 | return .{ | ||
| 1001 | .crt0 = if (crt_basenames.crt0) |basename| try crt_dir_path.join(arena, basename) else null, | ||
| 1002 | .crti = if (crt_basenames.crti) |basename| try crt_dir_path.join(arena, basename) else null, | ||
| 1003 | .crtbegin = if (crt_basenames.crtbegin) |basename| try gcc_dir_path.join(arena, basename) else null, | ||
| 1004 | .crtend = if (crt_basenames.crtend) |basename| try gcc_dir_path.join(arena, basename) else null, | ||
| 1005 | .crtn = if (crt_basenames.crtn) |basename| try crt_dir_path.join(arena, basename) else null, | ||
| 1006 | }; | ||
| 1007 | }, | ||
| 1008 | else => { | ||
| 1009 | return .{ | ||
| 1010 | .crt0 = if (crt_basenames.crt0) |basename| try crt_dir_path.join(arena, basename) else null, | ||
| 1011 | .crti = if (crt_basenames.crti) |basename| try crt_dir_path.join(arena, basename) else null, | ||
| 1012 | .crtbegin = if (crt_basenames.crtbegin) |basename| try crt_dir_path.join(arena, basename) else null, | ||
| 1013 | .crtend = if (crt_basenames.crtend) |basename| try crt_dir_path.join(arena, basename) else null, | ||
| 1014 | .crtn = if (crt_basenames.crtn) |basename| try crt_dir_path.join(arena, basename) else null, | ||
| 1015 | }; | ||
| 1016 | }, | ||
| 1017 | } | ||
| 1018 | } | ||
| 1019 | |||
| 693 | const LibCInstallation = @This(); | 1020 | const LibCInstallation = @This(); |
| 694 | const std = @import("std"); | 1021 | const std = @import("std"); |
| 695 | const builtin = @import("builtin"); | 1022 | const builtin = @import("builtin"); |
| 696 | const Target = std.Target; | 1023 | const Target = std.Target; |
| 697 | const fs = std.fs; | 1024 | const fs = std.fs; |
| 698 | const Allocator = std.mem.Allocator; | 1025 | const Allocator = std.mem.Allocator; |
| 1026 | const Path = std.Build.Cache.Path; | ||
| 699 | 1027 | ||
| 700 | const is_darwin = builtin.target.isDarwin(); | 1028 | const is_darwin = builtin.target.isDarwin(); |
| 701 | const is_windows = builtin.target.os.tag == .windows; | 1029 | const is_windows = builtin.target.os.tag == .windows; |
src/Compilation.zig+102-63| ... | @@ -217,37 +217,37 @@ thread_pool: *ThreadPool, | ... | @@ -217,37 +217,37 @@ thread_pool: *ThreadPool, |
| 217 | 217 | ||
| 218 | /// Populated when we build the libc++ static library. A Job to build this is placed in the queue | 218 | /// Populated when we build the libc++ static library. A Job to build this is placed in the queue |
| 219 | /// and resolved before calling linker.flush(). | 219 | /// and resolved before calling linker.flush(). |
| 220 | libcxx_static_lib: ?CRTFile = null, | 220 | libcxx_static_lib: ?CrtFile = null, |
| 221 | /// Populated when we build the libc++abi static library. A Job to build this is placed in the queue | 221 | /// Populated when we build the libc++abi static library. A Job to build this is placed in the queue |
| 222 | /// and resolved before calling linker.flush(). | 222 | /// and resolved before calling linker.flush(). |
| 223 | libcxxabi_static_lib: ?CRTFile = null, | 223 | libcxxabi_static_lib: ?CrtFile = null, |
| 224 | /// Populated when we build the libunwind static library. A Job to build this is placed in the queue | 224 | /// Populated when we build the libunwind static library. A Job to build this is placed in the queue |
| 225 | /// and resolved before calling linker.flush(). | 225 | /// and resolved before calling linker.flush(). |
| 226 | libunwind_static_lib: ?CRTFile = null, | 226 | libunwind_static_lib: ?CrtFile = null, |
| 227 | /// Populated when we build the TSAN library. A Job to build this is placed in the queue | 227 | /// Populated when we build the TSAN library. A Job to build this is placed in the queue |
| 228 | /// and resolved before calling linker.flush(). | 228 | /// and resolved before calling linker.flush(). |
| 229 | tsan_lib: ?CRTFile = null, | 229 | tsan_lib: ?CrtFile = null, |
| 230 | /// Populated when we build the libc static library. A Job to build this is placed in the queue | 230 | /// Populated when we build the libc static library. A Job to build this is placed in the queue |
| 231 | /// and resolved before calling linker.flush(). | 231 | /// and resolved before calling linker.flush(). |
| 232 | libc_static_lib: ?CRTFile = null, | 232 | libc_static_lib: ?CrtFile = null, |
| 233 | /// Populated when we build the libcompiler_rt static library. A Job to build this is indicated | 233 | /// Populated when we build the libcompiler_rt static library. A Job to build this is indicated |
| 234 | /// by setting `job_queued_compiler_rt_lib` and resolved before calling linker.flush(). | 234 | /// by setting `job_queued_compiler_rt_lib` and resolved before calling linker.flush(). |
| 235 | compiler_rt_lib: ?CRTFile = null, | 235 | compiler_rt_lib: ?CrtFile = null, |
| 236 | /// Populated when we build the compiler_rt_obj object. A Job to build this is indicated | 236 | /// Populated when we build the compiler_rt_obj object. A Job to build this is indicated |
| 237 | /// by setting `job_queued_compiler_rt_obj` and resolved before calling linker.flush(). | 237 | /// by setting `job_queued_compiler_rt_obj` and resolved before calling linker.flush(). |
| 238 | compiler_rt_obj: ?CRTFile = null, | 238 | compiler_rt_obj: ?CrtFile = null, |
| 239 | /// Populated when we build the libfuzzer static library. A Job to build this | 239 | /// Populated when we build the libfuzzer static library. A Job to build this |
| 240 | /// is indicated by setting `job_queued_fuzzer_lib` and resolved before | 240 | /// is indicated by setting `job_queued_fuzzer_lib` and resolved before |
| 241 | /// calling linker.flush(). | 241 | /// calling linker.flush(). |
| 242 | fuzzer_lib: ?CRTFile = null, | 242 | fuzzer_lib: ?CrtFile = null, |
| 243 | 243 | ||
| 244 | glibc_so_files: ?glibc.BuiltSharedObjects = null, | 244 | glibc_so_files: ?glibc.BuiltSharedObjects = null, |
| 245 | wasi_emulated_libs: []const wasi_libc.CRTFile, | 245 | wasi_emulated_libs: []const wasi_libc.CrtFile, |
| 246 | 246 | ||
| 247 | /// For example `Scrt1.o` and `libc_nonshared.a`. These are populated after building libc from source, | 247 | /// For example `Scrt1.o` and `libc_nonshared.a`. These are populated after building libc from source, |
| 248 | /// The set of needed CRT (C runtime) files differs depending on the target and compilation settings. | 248 | /// The set of needed CRT (C runtime) files differs depending on the target and compilation settings. |
| 249 | /// The key is the basename, and the value is the absolute path to the completed build artifact. | 249 | /// The key is the basename, and the value is the absolute path to the completed build artifact. |
| 250 | crt_files: std.StringHashMapUnmanaged(CRTFile) = .empty, | 250 | crt_files: std.StringHashMapUnmanaged(CrtFile) = .empty, |
| 251 | 251 | ||
| 252 | /// How many lines of reference trace should be included per compile error. | 252 | /// How many lines of reference trace should be included per compile error. |
| 253 | /// Null means only show snippet on first error. | 253 | /// Null means only show snippet on first error. |
| ... | @@ -276,20 +276,20 @@ digest: ?[Cache.bin_digest_len]u8 = null, | ... | @@ -276,20 +276,20 @@ digest: ?[Cache.bin_digest_len]u8 = null, |
| 276 | pub const default_stack_protector_buffer_size = target_util.default_stack_protector_buffer_size; | 276 | pub const default_stack_protector_buffer_size = target_util.default_stack_protector_buffer_size; |
| 277 | pub const SemaError = Zcu.SemaError; | 277 | pub const SemaError = Zcu.SemaError; |
| 278 | 278 | ||
| 279 | pub const CRTFile = struct { | 279 | pub const CrtFile = struct { |
| 280 | lock: Cache.Lock, | 280 | lock: Cache.Lock, |
| 281 | full_object_path: []const u8, | 281 | full_object_path: Path, |
| 282 | 282 | ||
| 283 | pub fn isObject(cf: CRTFile) bool { | 283 | pub fn isObject(cf: CrtFile) bool { |
| 284 | return switch (classifyFileExt(cf.full_object_path)) { | 284 | return switch (classifyFileExt(cf.full_object_path.sub_path)) { |
| 285 | .object => true, | 285 | .object => true, |
| 286 | else => false, | 286 | else => false, |
| 287 | }; | 287 | }; |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | pub fn deinit(self: *CRTFile, gpa: Allocator) void { | 290 | pub fn deinit(self: *CrtFile, gpa: Allocator) void { |
| 291 | self.lock.release(); | 291 | self.lock.release(); |
| 292 | gpa.free(self.full_object_path); | 292 | gpa.free(self.full_object_path.sub_path); |
| 293 | self.* = undefined; | 293 | self.* = undefined; |
| 294 | } | 294 | } |
| 295 | }; | 295 | }; |
| ... | @@ -369,13 +369,13 @@ const Job = union(enum) { | ... | @@ -369,13 +369,13 @@ const Job = union(enum) { |
| 369 | resolve_type_fully: InternPool.Index, | 369 | resolve_type_fully: InternPool.Index, |
| 370 | 370 | ||
| 371 | /// one of the glibc static objects | 371 | /// one of the glibc static objects |
| 372 | glibc_crt_file: glibc.CRTFile, | 372 | glibc_crt_file: glibc.CrtFile, |
| 373 | /// all of the glibc shared objects | 373 | /// all of the glibc shared objects |
| 374 | glibc_shared_objects, | 374 | glibc_shared_objects, |
| 375 | /// one of the musl static objects | 375 | /// one of the musl static objects |
| 376 | musl_crt_file: musl.CRTFile, | 376 | musl_crt_file: musl.CrtFile, |
| 377 | /// one of the mingw-w64 static objects | 377 | /// one of the mingw-w64 static objects |
| 378 | mingw_crt_file: mingw.CRTFile, | 378 | mingw_crt_file: mingw.CrtFile, |
| 379 | /// libunwind.a, usually needed when linking libc | 379 | /// libunwind.a, usually needed when linking libc |
| 380 | libunwind: void, | 380 | libunwind: void, |
| 381 | libcxx: void, | 381 | libcxx: void, |
| ... | @@ -385,7 +385,7 @@ const Job = union(enum) { | ... | @@ -385,7 +385,7 @@ const Job = union(enum) { |
| 385 | /// calls to, for example, memcpy and memset. | 385 | /// calls to, for example, memcpy and memset. |
| 386 | zig_libc: void, | 386 | zig_libc: void, |
| 387 | /// one of WASI libc static objects | 387 | /// one of WASI libc static objects |
| 388 | wasi_libc_crt_file: wasi_libc.CRTFile, | 388 | wasi_libc_crt_file: wasi_libc.CrtFile, |
| 389 | 389 | ||
| 390 | /// The value is the index into `system_libs`. | 390 | /// The value is the index into `system_libs`. |
| 391 | windows_import_lib: usize, | 391 | windows_import_lib: usize, |
| ... | @@ -422,8 +422,8 @@ pub const CObject = struct { | ... | @@ -422,8 +422,8 @@ pub const CObject = struct { |
| 422 | status: union(enum) { | 422 | status: union(enum) { |
| 423 | new, | 423 | new, |
| 424 | success: struct { | 424 | success: struct { |
| 425 | /// The outputted result. Owned by gpa. | 425 | /// The outputted result. `sub_path` owned by gpa. |
| 426 | object_path: []u8, | 426 | object_path: Path, |
| 427 | /// This is a file system lock on the cache hash manifest representing this | 427 | /// This is a file system lock on the cache hash manifest representing this |
| 428 | /// object. It prevents other invocations of the Zig compiler from interfering | 428 | /// object. It prevents other invocations of the Zig compiler from interfering |
| 429 | /// with this object until released. | 429 | /// with this object until released. |
| ... | @@ -719,7 +719,7 @@ pub const CObject = struct { | ... | @@ -719,7 +719,7 @@ pub const CObject = struct { |
| 719 | return true; | 719 | return true; |
| 720 | }, | 720 | }, |
| 721 | .success => |*success| { | 721 | .success => |*success| { |
| 722 | gpa.free(success.object_path); | 722 | gpa.free(success.object_path.sub_path); |
| 723 | success.lock.release(); | 723 | success.lock.release(); |
| 724 | self.status = .new; | 724 | self.status = .new; |
| 725 | return false; | 725 | return false; |
| ... | @@ -1018,7 +1018,7 @@ const CacheUse = union(CacheMode) { | ... | @@ -1018,7 +1018,7 @@ const CacheUse = union(CacheMode) { |
| 1018 | }; | 1018 | }; |
| 1019 | 1019 | ||
| 1020 | pub const LinkObject = struct { | 1020 | pub const LinkObject = struct { |
| 1021 | path: []const u8, | 1021 | path: Path, |
| 1022 | must_link: bool = false, | 1022 | must_link: bool = false, |
| 1023 | // When the library is passed via a positional argument, it will be | 1023 | // When the library is passed via a positional argument, it will be |
| 1024 | // added as a full path. If it's `-l<lib>`, then just the basename. | 1024 | // added as a full path. If it's `-l<lib>`, then just the basename. |
| ... | @@ -1027,7 +1027,7 @@ pub const LinkObject = struct { | ... | @@ -1027,7 +1027,7 @@ pub const LinkObject = struct { |
| 1027 | loption: bool = false, | 1027 | loption: bool = false, |
| 1028 | 1028 | ||
| 1029 | pub fn isObject(lo: LinkObject) bool { | 1029 | pub fn isObject(lo: LinkObject) bool { |
| 1030 | return switch (classifyFileExt(lo.path)) { | 1030 | return switch (classifyFileExt(lo.path.sub_path)) { |
| 1031 | .object => true, | 1031 | .object => true, |
| 1032 | else => false, | 1032 | else => false, |
| 1033 | }; | 1033 | }; |
| ... | @@ -1095,7 +1095,7 @@ pub const CreateOptions = struct { | ... | @@ -1095,7 +1095,7 @@ pub const CreateOptions = struct { |
| 1095 | /// * getpid | 1095 | /// * getpid |
| 1096 | /// * mman | 1096 | /// * mman |
| 1097 | /// * signal | 1097 | /// * signal |
| 1098 | wasi_emulated_libs: []const wasi_libc.CRTFile = &.{}, | 1098 | wasi_emulated_libs: []const wasi_libc.CrtFile = &.{}, |
| 1099 | /// This means that if the output mode is an executable it will be a | 1099 | /// This means that if the output mode is an executable it will be a |
| 1100 | /// Position Independent Executable. If the output mode is not an | 1100 | /// Position Independent Executable. If the output mode is not an |
| 1101 | /// executable this field is ignored. | 1101 | /// executable this field is ignored. |
| ... | @@ -2302,7 +2302,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { | ... | @@ -2302,7 +2302,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2302 | try pt.processExports(); | 2302 | try pt.processExports(); |
| 2303 | } | 2303 | } |
| 2304 | 2304 | ||
| 2305 | if (try comp.totalErrorCount() != 0) { | 2305 | if (anyErrors(comp)) { |
| 2306 | // Skip flushing and keep source files loaded for error reporting. | 2306 | // Skip flushing and keep source files loaded for error reporting. |
| 2307 | comp.link_error_flags = .{}; | 2307 | comp.link_error_flags = .{}; |
| 2308 | return; | 2308 | return; |
| ... | @@ -2392,6 +2392,10 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { | ... | @@ -2392,6 +2392,10 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2392 | .sub_path = o_sub_path, | 2392 | .sub_path = o_sub_path, |
| 2393 | }, .main, main_progress_node); | 2393 | }, .main, main_progress_node); |
| 2394 | 2394 | ||
| 2395 | // Calling `flush` may have produced errors, in which case the | ||
| 2396 | // cache manifest must not be written. | ||
| 2397 | if (anyErrors(comp)) return; | ||
| 2398 | |||
| 2395 | // Failure here only means an unnecessary cache miss. | 2399 | // Failure here only means an unnecessary cache miss. |
| 2396 | man.writeManifest() catch |err| { | 2400 | man.writeManifest() catch |err| { |
| 2397 | log.warn("failed to write cache manifest: {s}", .{@errorName(err)}); | 2401 | log.warn("failed to write cache manifest: {s}", .{@errorName(err)}); |
| ... | @@ -2578,7 +2582,7 @@ fn addNonIncrementalStuffToCacheManifest( | ... | @@ -2578,7 +2582,7 @@ fn addNonIncrementalStuffToCacheManifest( |
| 2578 | } | 2582 | } |
| 2579 | 2583 | ||
| 2580 | for (comp.objects) |obj| { | 2584 | for (comp.objects) |obj| { |
| 2581 | _ = try man.addFile(obj.path, null); | 2585 | _ = try man.addFilePath(obj.path, null); |
| 2582 | man.hash.add(obj.must_link); | 2586 | man.hash.add(obj.must_link); |
| 2583 | man.hash.add(obj.loption); | 2587 | man.hash.add(obj.loption); |
| 2584 | } | 2588 | } |
| ... | @@ -2703,9 +2707,8 @@ fn emitOthers(comp: *Compilation) void { | ... | @@ -2703,9 +2707,8 @@ fn emitOthers(comp: *Compilation) void { |
| 2703 | return; | 2707 | return; |
| 2704 | } | 2708 | } |
| 2705 | const obj_path = comp.c_object_table.keys()[0].status.success.object_path; | 2709 | const obj_path = comp.c_object_table.keys()[0].status.success.object_path; |
| 2706 | const cwd = std.fs.cwd(); | 2710 | const ext = std.fs.path.extension(obj_path.sub_path); |
| 2707 | const ext = std.fs.path.extension(obj_path); | 2711 | const dirname = obj_path.sub_path[0 .. obj_path.sub_path.len - ext.len]; |
| 2708 | const basename = obj_path[0 .. obj_path.len - ext.len]; | ||
| 2709 | // This obj path always ends with the object file extension, but if we change the | 2712 | // This obj path always ends with the object file extension, but if we change the |
| 2710 | // extension to .ll, .bc, or .s, then it will be the path to those things. | 2713 | // extension to .ll, .bc, or .s, then it will be the path to those things. |
| 2711 | const outs = [_]struct { | 2714 | const outs = [_]struct { |
| ... | @@ -2720,13 +2723,13 @@ fn emitOthers(comp: *Compilation) void { | ... | @@ -2720,13 +2723,13 @@ fn emitOthers(comp: *Compilation) void { |
| 2720 | if (out.emit) |loc| { | 2723 | if (out.emit) |loc| { |
| 2721 | if (loc.directory) |directory| { | 2724 | if (loc.directory) |directory| { |
| 2722 | const src_path = std.fmt.allocPrint(comp.gpa, "{s}{s}", .{ | 2725 | const src_path = std.fmt.allocPrint(comp.gpa, "{s}{s}", .{ |
| 2723 | basename, out.ext, | 2726 | dirname, out.ext, |
| 2724 | }) catch |err| { | 2727 | }) catch |err| { |
| 2725 | log.err("unable to copy {s}{s}: {s}", .{ basename, out.ext, @errorName(err) }); | 2728 | log.err("unable to copy {s}{s}: {s}", .{ dirname, out.ext, @errorName(err) }); |
| 2726 | continue; | 2729 | continue; |
| 2727 | }; | 2730 | }; |
| 2728 | defer comp.gpa.free(src_path); | 2731 | defer comp.gpa.free(src_path); |
| 2729 | cwd.copyFile(src_path, directory.handle, loc.basename, .{}) catch |err| { | 2732 | obj_path.root_dir.handle.copyFile(src_path, directory.handle, loc.basename, .{}) catch |err| { |
| 2730 | log.err("unable to copy {s}: {s}", .{ src_path, @errorName(err) }); | 2733 | log.err("unable to copy {s}: {s}", .{ src_path, @errorName(err) }); |
| 2731 | }; | 2734 | }; |
| 2732 | } | 2735 | } |
| ... | @@ -3292,6 +3295,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { | ... | @@ -3292,6 +3295,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3292 | return bundle.toOwnedBundle(compile_log_text); | 3295 | return bundle.toOwnedBundle(compile_log_text); |
| 3293 | } | 3296 | } |
| 3294 | 3297 | ||
| 3298 | fn anyErrors(comp: *Compilation) bool { | ||
| 3299 | return (totalErrorCount(comp) catch return true) != 0; | ||
| 3300 | } | ||
| 3301 | |||
| 3295 | fn totalErrorCount(comp: *Compilation) !u32 { | 3302 | fn totalErrorCount(comp: *Compilation) !u32 { |
| 3296 | var errors = try comp.getAllErrorsAlloc(); | 3303 | var errors = try comp.getAllErrorsAlloc(); |
| 3297 | defer errors.deinit(comp.gpa); | 3304 | defer errors.deinit(comp.gpa); |
| ... | @@ -3774,7 +3781,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre | ... | @@ -3774,7 +3781,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre |
| 3774 | const named_frame = tracy.namedFrame("glibc_crt_file"); | 3781 | const named_frame = tracy.namedFrame("glibc_crt_file"); |
| 3775 | defer named_frame.end(); | 3782 | defer named_frame.end(); |
| 3776 | 3783 | ||
| 3777 | glibc.buildCRTFile(comp, crt_file, prog_node) catch |err| { | 3784 | glibc.buildCrtFile(comp, crt_file, prog_node) catch |err| { |
| 3778 | // TODO Surface more error details. | 3785 | // TODO Surface more error details. |
| 3779 | comp.lockAndSetMiscFailure(.glibc_crt_file, "unable to build glibc CRT file: {s}", .{ | 3786 | comp.lockAndSetMiscFailure(.glibc_crt_file, "unable to build glibc CRT file: {s}", .{ |
| 3780 | @errorName(err), | 3787 | @errorName(err), |
| ... | @@ -3798,7 +3805,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre | ... | @@ -3798,7 +3805,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre |
| 3798 | const named_frame = tracy.namedFrame("musl_crt_file"); | 3805 | const named_frame = tracy.namedFrame("musl_crt_file"); |
| 3799 | defer named_frame.end(); | 3806 | defer named_frame.end(); |
| 3800 | 3807 | ||
| 3801 | musl.buildCRTFile(comp, crt_file, prog_node) catch |err| { | 3808 | musl.buildCrtFile(comp, crt_file, prog_node) catch |err| { |
| 3802 | // TODO Surface more error details. | 3809 | // TODO Surface more error details. |
| 3803 | comp.lockAndSetMiscFailure( | 3810 | comp.lockAndSetMiscFailure( |
| 3804 | .musl_crt_file, | 3811 | .musl_crt_file, |
| ... | @@ -3811,7 +3818,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre | ... | @@ -3811,7 +3818,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre |
| 3811 | const named_frame = tracy.namedFrame("mingw_crt_file"); | 3818 | const named_frame = tracy.namedFrame("mingw_crt_file"); |
| 3812 | defer named_frame.end(); | 3819 | defer named_frame.end(); |
| 3813 | 3820 | ||
| 3814 | mingw.buildCRTFile(comp, crt_file, prog_node) catch |err| { | 3821 | mingw.buildCrtFile(comp, crt_file, prog_node) catch |err| { |
| 3815 | // TODO Surface more error details. | 3822 | // TODO Surface more error details. |
| 3816 | comp.lockAndSetMiscFailure( | 3823 | comp.lockAndSetMiscFailure( |
| 3817 | .mingw_crt_file, | 3824 | .mingw_crt_file, |
| ... | @@ -3894,7 +3901,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre | ... | @@ -3894,7 +3901,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre |
| 3894 | const named_frame = tracy.namedFrame("wasi_libc_crt_file"); | 3901 | const named_frame = tracy.namedFrame("wasi_libc_crt_file"); |
| 3895 | defer named_frame.end(); | 3902 | defer named_frame.end(); |
| 3896 | 3903 | ||
| 3897 | wasi_libc.buildCRTFile(comp, crt_file, prog_node) catch |err| { | 3904 | wasi_libc.buildCrtFile(comp, crt_file, prog_node) catch |err| { |
| 3898 | // TODO Surface more error details. | 3905 | // TODO Surface more error details. |
| 3899 | comp.lockAndSetMiscFailure( | 3906 | comp.lockAndSetMiscFailure( |
| 3900 | .wasi_libc_crt_file, | 3907 | .wasi_libc_crt_file, |
| ... | @@ -4602,7 +4609,7 @@ fn buildRt( | ... | @@ -4602,7 +4609,7 @@ fn buildRt( |
| 4602 | root_source_name: []const u8, | 4609 | root_source_name: []const u8, |
| 4603 | misc_task: MiscTask, | 4610 | misc_task: MiscTask, |
| 4604 | output_mode: std.builtin.OutputMode, | 4611 | output_mode: std.builtin.OutputMode, |
| 4605 | out: *?CRTFile, | 4612 | out: *?CrtFile, |
| 4606 | prog_node: std.Progress.Node, | 4613 | prog_node: std.Progress.Node, |
| 4607 | ) void { | 4614 | ) void { |
| 4608 | comp.buildOutputFromZig( | 4615 | comp.buildOutputFromZig( |
| ... | @@ -4703,7 +4710,9 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr | ... | @@ -4703,7 +4710,9 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr |
| 4703 | 4710 | ||
| 4704 | log.debug("updating C object: {s}", .{c_object.src.src_path}); | 4711 | log.debug("updating C object: {s}", .{c_object.src.src_path}); |
| 4705 | 4712 | ||
| 4706 | if (c_object.clearStatus(comp.gpa)) { | 4713 | const gpa = comp.gpa; |
| 4714 | |||
| 4715 | if (c_object.clearStatus(gpa)) { | ||
| 4707 | // There was previous failure. | 4716 | // There was previous failure. |
| 4708 | comp.mutex.lock(); | 4717 | comp.mutex.lock(); |
| 4709 | defer comp.mutex.unlock(); | 4718 | defer comp.mutex.unlock(); |
| ... | @@ -4722,7 +4731,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr | ... | @@ -4722,7 +4731,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr |
| 4722 | 4731 | ||
| 4723 | try cache_helpers.hashCSource(&man, c_object.src); | 4732 | try cache_helpers.hashCSource(&man, c_object.src); |
| 4724 | 4733 | ||
| 4725 | var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); | 4734 | var arena_allocator = std.heap.ArenaAllocator.init(gpa); |
| 4726 | defer arena_allocator.deinit(); | 4735 | defer arena_allocator.deinit(); |
| 4727 | const arena = arena_allocator.allocator(); | 4736 | const arena = arena_allocator.allocator(); |
| 4728 | 4737 | ||
| ... | @@ -4744,7 +4753,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr | ... | @@ -4744,7 +4753,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr |
| 4744 | const target = comp.getTarget(); | 4753 | const target = comp.getTarget(); |
| 4745 | const o_ext = target.ofmt.fileExt(target.cpu.arch); | 4754 | const o_ext = target.ofmt.fileExt(target.cpu.arch); |
| 4746 | const digest = if (!comp.disable_c_depfile and try man.hit()) man.final() else blk: { | 4755 | const digest = if (!comp.disable_c_depfile and try man.hit()) man.final() else blk: { |
| 4747 | var argv = std.ArrayList([]const u8).init(comp.gpa); | 4756 | var argv = std.ArrayList([]const u8).init(gpa); |
| 4748 | defer argv.deinit(); | 4757 | defer argv.deinit(); |
| 4749 | 4758 | ||
| 4750 | // In case we are doing passthrough mode, we need to detect -S and -emit-llvm. | 4759 | // In case we are doing passthrough mode, we need to detect -S and -emit-llvm. |
| ... | @@ -4908,7 +4917,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr | ... | @@ -4908,7 +4917,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr |
| 4908 | 4917 | ||
| 4909 | switch (term) { | 4918 | switch (term) { |
| 4910 | .Exited => |code| if (code != 0) if (out_diag_path) |diag_file_path| { | 4919 | .Exited => |code| if (code != 0) if (out_diag_path) |diag_file_path| { |
| 4911 | const bundle = CObject.Diag.Bundle.parse(comp.gpa, diag_file_path) catch |err| { | 4920 | const bundle = CObject.Diag.Bundle.parse(gpa, diag_file_path) catch |err| { |
| 4912 | log.err("{}: failed to parse clang diagnostics: {s}", .{ err, stderr }); | 4921 | log.err("{}: failed to parse clang diagnostics: {s}", .{ err, stderr }); |
| 4913 | return comp.failCObj(c_object, "clang exited with code {d}", .{code}); | 4922 | return comp.failCObj(c_object, "clang exited with code {d}", .{code}); |
| 4914 | }; | 4923 | }; |
| ... | @@ -4982,9 +4991,10 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr | ... | @@ -4982,9 +4991,10 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr |
| 4982 | 4991 | ||
| 4983 | c_object.status = .{ | 4992 | c_object.status = .{ |
| 4984 | .success = .{ | 4993 | .success = .{ |
| 4985 | .object_path = try comp.local_cache_directory.join(comp.gpa, &[_][]const u8{ | 4994 | .object_path = .{ |
| 4986 | "o", &digest, o_basename, | 4995 | .root_dir = comp.local_cache_directory, |
| 4987 | }), | 4996 | .sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, o_basename }), |
| 4997 | }, | ||
| 4988 | .lock = man.toOwnedLock(), | 4998 | .lock = man.toOwnedLock(), |
| 4989 | }, | 4999 | }, |
| 4990 | }; | 5000 | }; |
| ... | @@ -6092,18 +6102,23 @@ test "classifyFileExt" { | ... | @@ -6092,18 +6102,23 @@ test "classifyFileExt" { |
| 6092 | try std.testing.expectEqual(FileExt.zig, classifyFileExt("foo.zig")); | 6102 | try std.testing.expectEqual(FileExt.zig, classifyFileExt("foo.zig")); |
| 6093 | } | 6103 | } |
| 6094 | 6104 | ||
| 6095 | pub fn get_libc_crt_file(comp: *Compilation, arena: Allocator, basename: []const u8) ![]const u8 { | 6105 | pub fn get_libc_crt_file(comp: *Compilation, arena: Allocator, basename: []const u8) !Path { |
| 6096 | if (comp.wantBuildGLibCFromSource() or | 6106 | return (try crtFilePath(comp, basename)) orelse { |
| 6097 | comp.wantBuildMuslFromSource() or | 6107 | const lci = comp.libc_installation orelse return error.LibCInstallationNotAvailable; |
| 6098 | comp.wantBuildMinGWFromSource() or | 6108 | const crt_dir_path = lci.crt_dir orelse return error.LibCInstallationMissingCrtDir; |
| 6099 | comp.wantBuildWasiLibcFromSource()) | 6109 | const full_path = try std.fs.path.join(arena, &[_][]const u8{ crt_dir_path, basename }); |
| 6100 | { | 6110 | return Path.initCwd(full_path); |
| 6101 | return comp.crt_files.get(basename).?.full_object_path; | 6111 | }; |
| 6102 | } | 6112 | } |
| 6103 | const lci = comp.libc_installation orelse return error.LibCInstallationNotAvailable; | 6113 | |
| 6104 | const crt_dir_path = lci.crt_dir orelse return error.LibCInstallationMissingCRTDir; | 6114 | pub fn crtFileAsString(comp: *Compilation, arena: Allocator, basename: []const u8) ![]const u8 { |
| 6105 | const full_path = try std.fs.path.join(arena, &[_][]const u8{ crt_dir_path, basename }); | 6115 | const path = try get_libc_crt_file(comp, arena, basename); |
| 6106 | return full_path; | 6116 | return path.toString(arena); |
| 6117 | } | ||
| 6118 | |||
| 6119 | pub fn crtFilePath(comp: *Compilation, basename: []const u8) Allocator.Error!?Path { | ||
| 6120 | const crt_file = comp.crt_files.get(basename) orelse return null; | ||
| 6121 | return crt_file.full_object_path; | ||
| 6107 | } | 6122 | } |
| 6108 | 6123 | ||
| 6109 | fn wantBuildLibCFromSource(comp: Compilation) bool { | 6124 | fn wantBuildLibCFromSource(comp: Compilation) bool { |
| ... | @@ -6314,7 +6329,7 @@ fn buildOutputFromZig( | ... | @@ -6314,7 +6329,7 @@ fn buildOutputFromZig( |
| 6314 | comp: *Compilation, | 6329 | comp: *Compilation, |
| 6315 | src_basename: []const u8, | 6330 | src_basename: []const u8, |
| 6316 | output_mode: std.builtin.OutputMode, | 6331 | output_mode: std.builtin.OutputMode, |
| 6317 | out: *?CRTFile, | 6332 | out: *?CrtFile, |
| 6318 | misc_task_tag: MiscTask, | 6333 | misc_task_tag: MiscTask, |
| 6319 | prog_node: std.Progress.Node, | 6334 | prog_node: std.Progress.Node, |
| 6320 | ) !void { | 6335 | ) !void { |
| ... | @@ -6542,15 +6557,39 @@ pub fn build_crt_file( | ... | @@ -6542,15 +6557,39 @@ pub fn build_crt_file( |
| 6542 | comp.crt_files.putAssumeCapacityNoClobber(basename, try sub_compilation.toCrtFile()); | 6557 | comp.crt_files.putAssumeCapacityNoClobber(basename, try sub_compilation.toCrtFile()); |
| 6543 | } | 6558 | } |
| 6544 | 6559 | ||
| 6545 | pub fn toCrtFile(comp: *Compilation) Allocator.Error!CRTFile { | 6560 | pub fn toCrtFile(comp: *Compilation) Allocator.Error!CrtFile { |
| 6546 | return .{ | 6561 | return .{ |
| 6547 | .full_object_path = try comp.local_cache_directory.join(comp.gpa, &.{ | 6562 | .full_object_path = .{ |
| 6548 | comp.cache_use.whole.bin_sub_path.?, | 6563 | .root_dir = comp.local_cache_directory, |
| 6549 | }), | 6564 | .sub_path = try comp.gpa.dupe(u8, comp.cache_use.whole.bin_sub_path.?), |
| 6565 | }, | ||
| 6550 | .lock = comp.cache_use.whole.moveLock(), | 6566 | .lock = comp.cache_use.whole.moveLock(), |
| 6551 | }; | 6567 | }; |
| 6552 | } | 6568 | } |
| 6553 | 6569 | ||
| 6570 | pub fn getCrtPaths( | ||
| 6571 | comp: *Compilation, | ||
| 6572 | arena: Allocator, | ||
| 6573 | ) error{ OutOfMemory, LibCInstallationMissingCrtDir }!LibCInstallation.CrtPaths { | ||
| 6574 | const target = comp.root_mod.resolved_target.result; | ||
| 6575 | const basenames = LibCInstallation.CrtBasenames.get(.{ | ||
| 6576 | .target = target, | ||
| 6577 | .link_libc = comp.config.link_libc, | ||
| 6578 | .output_mode = comp.config.output_mode, | ||
| 6579 | .link_mode = comp.config.link_mode, | ||
| 6580 | .pie = comp.config.pie, | ||
| 6581 | }); | ||
| 6582 | if (comp.libc_installation) |lci| return lci.resolveCrtPaths(arena, basenames, target); | ||
| 6583 | |||
| 6584 | return .{ | ||
| 6585 | .crt0 = if (basenames.crt0) |basename| try comp.crtFilePath(basename) else null, | ||
| 6586 | .crti = if (basenames.crti) |basename| try comp.crtFilePath(basename) else null, | ||
| 6587 | .crtbegin = if (basenames.crtbegin) |basename| try comp.crtFilePath(basename) else null, | ||
| 6588 | .crtend = if (basenames.crtend) |basename| try comp.crtFilePath(basename) else null, | ||
| 6589 | .crtn = if (basenames.crtn) |basename| try comp.crtFilePath(basename) else null, | ||
| 6590 | }; | ||
| 6591 | } | ||
| 6592 | |||
| 6554 | pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void { | 6593 | pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void { |
| 6555 | // Avoid deadlocking on building import libs such as kernel32.lib | 6594 | // Avoid deadlocking on building import libs such as kernel32.lib |
| 6556 | // This can happen when the user uses `build-exe foo.obj -lkernel32` and | 6595 | // This can happen when the user uses `build-exe foo.obj -lkernel32` and |
src/glibc.zig+4-3| ... | @@ -169,14 +169,14 @@ fn useElfInitFini(target: std.Target) bool { | ... | @@ -169,14 +169,14 @@ fn useElfInitFini(target: std.Target) bool { |
| 169 | }; | 169 | }; |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | pub const CRTFile = enum { | 172 | pub const CrtFile = enum { |
| 173 | crti_o, | 173 | crti_o, |
| 174 | crtn_o, | 174 | crtn_o, |
| 175 | scrt1_o, | 175 | scrt1_o, |
| 176 | libc_nonshared_a, | 176 | libc_nonshared_a, |
| 177 | }; | 177 | }; |
| 178 | 178 | ||
| 179 | pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: std.Progress.Node) !void { | 179 | pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progress.Node) !void { |
| 180 | if (!build_options.have_llvm) { | 180 | if (!build_options.have_llvm) { |
| 181 | return error.ZigCompilerNotBuiltWithLLVMExtensions; | 181 | return error.ZigCompilerNotBuiltWithLLVMExtensions; |
| 182 | } | 182 | } |
| ... | @@ -292,7 +292,8 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: std.Progre | ... | @@ -292,7 +292,8 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: std.Progre |
| 292 | .owner = undefined, | 292 | .owner = undefined, |
| 293 | }; | 293 | }; |
| 294 | var files = [_]Compilation.CSourceFile{ start_o, abi_note_o, init_o }; | 294 | var files = [_]Compilation.CSourceFile{ start_o, abi_note_o, init_o }; |
| 295 | return comp.build_crt_file("Scrt1", .Obj, .@"glibc Scrt1.o", prog_node, &files); | 295 | const basename = if (comp.config.output_mode == .Exe and !comp.config.pie) "crt1" else "Scrt1"; |
| 296 | return comp.build_crt_file(basename, .Obj, .@"glibc Scrt1.o", prog_node, &files); | ||
| 296 | }, | 297 | }, |
| 297 | .libc_nonshared_a => { | 298 | .libc_nonshared_a => { |
| 298 | const s = path.sep_str; | 299 | const s = path.sep_str; |
src/link.zig+12-15| ... | @@ -11,7 +11,7 @@ const wasi_libc = @import("wasi_libc.zig"); | ... | @@ -11,7 +11,7 @@ const wasi_libc = @import("wasi_libc.zig"); |
| 11 | const Air = @import("Air.zig"); | 11 | const Air = @import("Air.zig"); |
| 12 | const Allocator = std.mem.Allocator; | 12 | const Allocator = std.mem.Allocator; |
| 13 | const Cache = std.Build.Cache; | 13 | const Cache = std.Build.Cache; |
| 14 | const Path = Cache.Path; | 14 | const Path = std.Build.Cache.Path; |
| 15 | const Compilation = @import("Compilation.zig"); | 15 | const Compilation = @import("Compilation.zig"); |
| 16 | const LibCInstallation = std.zig.LibCInstallation; | 16 | const LibCInstallation = std.zig.LibCInstallation; |
| 17 | const Liveness = @import("Liveness.zig"); | 17 | const Liveness = @import("Liveness.zig"); |
| ... | @@ -34,7 +34,7 @@ pub const SystemLib = struct { | ... | @@ -34,7 +34,7 @@ pub const SystemLib = struct { |
| 34 | /// 1. Windows DLLs that zig ships such as advapi32. | 34 | /// 1. Windows DLLs that zig ships such as advapi32. |
| 35 | /// 2. extern "foo" fn declarations where we find out about libraries too late | 35 | /// 2. extern "foo" fn declarations where we find out about libraries too late |
| 36 | /// TODO: make this non-optional and resolve those two cases somehow. | 36 | /// TODO: make this non-optional and resolve those two cases somehow. |
| 37 | path: ?[]const u8, | 37 | path: ?Path, |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | pub fn hashAddSystemLibs( | 40 | pub fn hashAddSystemLibs( |
| ... | @@ -46,7 +46,7 @@ pub fn hashAddSystemLibs( | ... | @@ -46,7 +46,7 @@ pub fn hashAddSystemLibs( |
| 46 | for (hm.values()) |value| { | 46 | for (hm.values()) |value| { |
| 47 | man.hash.add(value.needed); | 47 | man.hash.add(value.needed); |
| 48 | man.hash.add(value.weak); | 48 | man.hash.add(value.weak); |
| 49 | if (value.path) |p| _ = try man.addFile(p, null); | 49 | if (value.path) |p| _ = try man.addFilePath(p, null); |
| 50 | } | 50 | } |
| 51 | } | 51 | } |
| 52 | 52 | ||
| ... | @@ -551,7 +551,7 @@ pub const File = struct { | ... | @@ -551,7 +551,7 @@ pub const File = struct { |
| 551 | LLDCrashed, | 551 | LLDCrashed, |
| 552 | LLDReportedFailure, | 552 | LLDReportedFailure, |
| 553 | LLD_LinkingIsTODO_ForSpirV, | 553 | LLD_LinkingIsTODO_ForSpirV, |
| 554 | LibCInstallationMissingCRTDir, | 554 | LibCInstallationMissingCrtDir, |
| 555 | LibCInstallationNotAvailable, | 555 | LibCInstallationNotAvailable, |
| 556 | LinkingWithoutZigSourceUnimplemented, | 556 | LinkingWithoutZigSourceUnimplemented, |
| 557 | MalformedArchive, | 557 | MalformedArchive, |
| ... | @@ -606,18 +606,15 @@ pub const File = struct { | ... | @@ -606,18 +606,15 @@ pub const File = struct { |
| 606 | const comp = base.comp; | 606 | const comp = base.comp; |
| 607 | if (comp.clang_preprocessor_mode == .yes or comp.clang_preprocessor_mode == .pch) { | 607 | if (comp.clang_preprocessor_mode == .yes or comp.clang_preprocessor_mode == .pch) { |
| 608 | dev.check(.clang_command); | 608 | dev.check(.clang_command); |
| 609 | const gpa = comp.gpa; | ||
| 610 | const emit = base.emit; | 609 | const emit = base.emit; |
| 611 | // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case) | 610 | // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case) |
| 612 | // Until then, we do `lld -r -o output.o input.o` even though the output is the same | 611 | // Until then, we do `lld -r -o output.o input.o` even though the output is the same |
| 613 | // as the input. For the preprocessing case (`zig cc -E -o foo`) we copy the file | 612 | // as the input. For the preprocessing case (`zig cc -E -o foo`) we copy the file |
| 614 | // to the final location. See also the corresponding TODO in Coff linking. | 613 | // to the final location. See also the corresponding TODO in Coff linking. |
| 615 | const full_out_path = try emit.root_dir.join(gpa, &[_][]const u8{emit.sub_path}); | ||
| 616 | defer gpa.free(full_out_path); | ||
| 617 | assert(comp.c_object_table.count() == 1); | 614 | assert(comp.c_object_table.count() == 1); |
| 618 | const the_key = comp.c_object_table.keys()[0]; | 615 | const the_key = comp.c_object_table.keys()[0]; |
| 619 | const cached_pp_file_path = the_key.status.success.object_path; | 616 | const cached_pp_file_path = the_key.status.success.object_path; |
| 620 | try fs.cwd().copyFile(cached_pp_file_path, fs.cwd(), full_out_path, .{}); | 617 | try cached_pp_file_path.root_dir.handle.copyFile(cached_pp_file_path.sub_path, emit.root_dir.handle, emit.sub_path, .{}); |
| 621 | return; | 618 | return; |
| 622 | } | 619 | } |
| 623 | 620 | ||
| ... | @@ -781,7 +778,7 @@ pub const File = struct { | ... | @@ -781,7 +778,7 @@ pub const File = struct { |
| 781 | 778 | ||
| 782 | log.debug("zcu_obj_path={s}", .{if (zcu_obj_path) |s| s else "(null)"}); | 779 | log.debug("zcu_obj_path={s}", .{if (zcu_obj_path) |s| s else "(null)"}); |
| 783 | 780 | ||
| 784 | const compiler_rt_path: ?[]const u8 = if (comp.include_compiler_rt) | 781 | const compiler_rt_path: ?Path = if (comp.include_compiler_rt) |
| 785 | comp.compiler_rt_obj.?.full_object_path | 782 | comp.compiler_rt_obj.?.full_object_path |
| 786 | else | 783 | else |
| 787 | null; | 784 | null; |
| ... | @@ -806,18 +803,18 @@ pub const File = struct { | ... | @@ -806,18 +803,18 @@ pub const File = struct { |
| 806 | base.releaseLock(); | 803 | base.releaseLock(); |
| 807 | 804 | ||
| 808 | for (objects) |obj| { | 805 | for (objects) |obj| { |
| 809 | _ = try man.addFile(obj.path, null); | 806 | _ = try man.addFilePath(obj.path, null); |
| 810 | man.hash.add(obj.must_link); | 807 | man.hash.add(obj.must_link); |
| 811 | man.hash.add(obj.loption); | 808 | man.hash.add(obj.loption); |
| 812 | } | 809 | } |
| 813 | for (comp.c_object_table.keys()) |key| { | 810 | for (comp.c_object_table.keys()) |key| { |
| 814 | _ = try man.addFile(key.status.success.object_path, null); | 811 | _ = try man.addFilePath(key.status.success.object_path, null); |
| 815 | } | 812 | } |
| 816 | for (comp.win32_resource_table.keys()) |key| { | 813 | for (comp.win32_resource_table.keys()) |key| { |
| 817 | _ = try man.addFile(key.status.success.res_path, null); | 814 | _ = try man.addFile(key.status.success.res_path, null); |
| 818 | } | 815 | } |
| 819 | try man.addOptionalFile(zcu_obj_path); | 816 | try man.addOptionalFile(zcu_obj_path); |
| 820 | try man.addOptionalFile(compiler_rt_path); | 817 | try man.addOptionalFilePath(compiler_rt_path); |
| 821 | 818 | ||
| 822 | // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. | 819 | // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. |
| 823 | _ = try man.hit(); | 820 | _ = try man.hit(); |
| ... | @@ -851,10 +848,10 @@ pub const File = struct { | ... | @@ -851,10 +848,10 @@ pub const File = struct { |
| 851 | defer object_files.deinit(); | 848 | defer object_files.deinit(); |
| 852 | 849 | ||
| 853 | for (objects) |obj| { | 850 | for (objects) |obj| { |
| 854 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, obj.path)); | 851 | object_files.appendAssumeCapacity(try obj.path.toStringZ(arena)); |
| 855 | } | 852 | } |
| 856 | for (comp.c_object_table.keys()) |key| { | 853 | for (comp.c_object_table.keys()) |key| { |
| 857 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.object_path)); | 854 | object_files.appendAssumeCapacity(try key.status.success.object_path.toStringZ(arena)); |
| 858 | } | 855 | } |
| 859 | for (comp.win32_resource_table.keys()) |key| { | 856 | for (comp.win32_resource_table.keys()) |key| { |
| 860 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.res_path)); | 857 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.res_path)); |
| ... | @@ -863,7 +860,7 @@ pub const File = struct { | ... | @@ -863,7 +860,7 @@ pub const File = struct { |
| 863 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); | 860 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); |
| 864 | } | 861 | } |
| 865 | if (compiler_rt_path) |p| { | 862 | if (compiler_rt_path) |p| { |
| 866 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); | 863 | object_files.appendAssumeCapacity(try p.toStringZ(arena)); |
| 867 | } | 864 | } |
| 868 | 865 | ||
| 869 | if (comp.verbose_link) { | 866 | if (comp.verbose_link) { |
src/link/Coff/lld.zig+25-22| ... | @@ -7,6 +7,7 @@ const fs = std.fs; | ... | @@ -7,6 +7,7 @@ const fs = std.fs; |
| 7 | const log = std.log.scoped(.link); | 7 | const log = std.log.scoped(.link); |
| 8 | const mem = std.mem; | 8 | const mem = std.mem; |
| 9 | const Cache = std.Build.Cache; | 9 | const Cache = std.Build.Cache; |
| 10 | const Path = std.Build.Cache.Path; | ||
| 10 | 11 | ||
| 11 | const mingw = @import("../../mingw.zig"); | 12 | const mingw = @import("../../mingw.zig"); |
| 12 | const link = @import("../../link.zig"); | 13 | const link = @import("../../link.zig"); |
| ... | @@ -74,11 +75,11 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no | ... | @@ -74,11 +75,11 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no |
| 74 | comptime assert(Compilation.link_hash_implementation_version == 14); | 75 | comptime assert(Compilation.link_hash_implementation_version == 14); |
| 75 | 76 | ||
| 76 | for (comp.objects) |obj| { | 77 | for (comp.objects) |obj| { |
| 77 | _ = try man.addFile(obj.path, null); | 78 | _ = try man.addFilePath(obj.path, null); |
| 78 | man.hash.add(obj.must_link); | 79 | man.hash.add(obj.must_link); |
| 79 | } | 80 | } |
| 80 | for (comp.c_object_table.keys()) |key| { | 81 | for (comp.c_object_table.keys()) |key| { |
| 81 | _ = try man.addFile(key.status.success.object_path, null); | 82 | _ = try man.addFilePath(key.status.success.object_path, null); |
| 82 | } | 83 | } |
| 83 | for (comp.win32_resource_table.keys()) |key| { | 84 | for (comp.win32_resource_table.keys()) |key| { |
| 84 | _ = try man.addFile(key.status.success.res_path, null); | 85 | _ = try man.addFile(key.status.success.res_path, null); |
| ... | @@ -154,17 +155,19 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no | ... | @@ -154,17 +155,19 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no |
| 154 | break :blk comp.c_object_table.keys()[0].status.success.object_path; | 155 | break :blk comp.c_object_table.keys()[0].status.success.object_path; |
| 155 | 156 | ||
| 156 | if (module_obj_path) |p| | 157 | if (module_obj_path) |p| |
| 157 | break :blk p; | 158 | break :blk Path.initCwd(p); |
| 158 | 159 | ||
| 159 | // TODO I think this is unreachable. Audit this situation when solving the above TODO | 160 | // TODO I think this is unreachable. Audit this situation when solving the above TODO |
| 160 | // regarding eliding redundant object -> object transformations. | 161 | // regarding eliding redundant object -> object transformations. |
| 161 | return error.NoObjectsToLink; | 162 | return error.NoObjectsToLink; |
| 162 | }; | 163 | }; |
| 163 | // This can happen when using --enable-cache and using the stage1 backend. In this case | 164 | try std.fs.Dir.copyFile( |
| 164 | // we can skip the file copy. | 165 | the_object_path.root_dir.handle, |
| 165 | if (!mem.eql(u8, the_object_path, full_out_path)) { | 166 | the_object_path.sub_path, |
| 166 | try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{}); | 167 | directory.handle, |
| 167 | } | 168 | self.base.emit.sub_path, |
| 169 | .{}, | ||
| 170 | ); | ||
| 168 | } else { | 171 | } else { |
| 169 | // Create an LLD command line and invoke it. | 172 | // Create an LLD command line and invoke it. |
| 170 | var argv = std.ArrayList([]const u8).init(gpa); | 173 | var argv = std.ArrayList([]const u8).init(gpa); |
| ... | @@ -270,14 +273,14 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no | ... | @@ -270,14 +273,14 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no |
| 270 | try argv.ensureUnusedCapacity(comp.objects.len); | 273 | try argv.ensureUnusedCapacity(comp.objects.len); |
| 271 | for (comp.objects) |obj| { | 274 | for (comp.objects) |obj| { |
| 272 | if (obj.must_link) { | 275 | if (obj.must_link) { |
| 273 | argv.appendAssumeCapacity(try allocPrint(arena, "-WHOLEARCHIVE:{s}", .{obj.path})); | 276 | argv.appendAssumeCapacity(try allocPrint(arena, "-WHOLEARCHIVE:{}", .{@as(Path, obj.path)})); |
| 274 | } else { | 277 | } else { |
| 275 | argv.appendAssumeCapacity(obj.path); | 278 | argv.appendAssumeCapacity(try obj.path.toString(arena)); |
| 276 | } | 279 | } |
| 277 | } | 280 | } |
| 278 | 281 | ||
| 279 | for (comp.c_object_table.keys()) |key| { | 282 | for (comp.c_object_table.keys()) |key| { |
| 280 | try argv.append(key.status.success.object_path); | 283 | try argv.append(try key.status.success.object_path.toString(arena)); |
| 281 | } | 284 | } |
| 282 | 285 | ||
| 283 | for (comp.win32_resource_table.keys()) |key| { | 286 | for (comp.win32_resource_table.keys()) |key| { |
| ... | @@ -401,17 +404,17 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no | ... | @@ -401,17 +404,17 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no |
| 401 | } | 404 | } |
| 402 | 405 | ||
| 403 | if (is_dyn_lib) { | 406 | if (is_dyn_lib) { |
| 404 | try argv.append(try comp.get_libc_crt_file(arena, "dllcrt2.obj")); | 407 | try argv.append(try comp.crtFileAsString(arena, "dllcrt2.obj")); |
| 405 | if (target.cpu.arch == .x86) { | 408 | if (target.cpu.arch == .x86) { |
| 406 | try argv.append("-ALTERNATENAME:__DllMainCRTStartup@12=_DllMainCRTStartup@12"); | 409 | try argv.append("-ALTERNATENAME:__DllMainCRTStartup@12=_DllMainCRTStartup@12"); |
| 407 | } else { | 410 | } else { |
| 408 | try argv.append("-ALTERNATENAME:_DllMainCRTStartup=DllMainCRTStartup"); | 411 | try argv.append("-ALTERNATENAME:_DllMainCRTStartup=DllMainCRTStartup"); |
| 409 | } | 412 | } |
| 410 | } else { | 413 | } else { |
| 411 | try argv.append(try comp.get_libc_crt_file(arena, "crt2.obj")); | 414 | try argv.append(try comp.crtFileAsString(arena, "crt2.obj")); |
| 412 | } | 415 | } |
| 413 | 416 | ||
| 414 | try argv.append(try comp.get_libc_crt_file(arena, "mingw32.lib")); | 417 | try argv.append(try comp.crtFileAsString(arena, "mingw32.lib")); |
| 415 | } else { | 418 | } else { |
| 416 | const lib_str = switch (comp.config.link_mode) { | 419 | const lib_str = switch (comp.config.link_mode) { |
| 417 | .dynamic => "", | 420 | .dynamic => "", |
| ... | @@ -456,36 +459,36 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no | ... | @@ -456,36 +459,36 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no |
| 456 | 459 | ||
| 457 | // libc++ dep | 460 | // libc++ dep |
| 458 | if (comp.config.link_libcpp) { | 461 | if (comp.config.link_libcpp) { |
| 459 | try argv.append(comp.libcxxabi_static_lib.?.full_object_path); | 462 | try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena)); |
| 460 | try argv.append(comp.libcxx_static_lib.?.full_object_path); | 463 | try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena)); |
| 461 | } | 464 | } |
| 462 | 465 | ||
| 463 | // libunwind dep | 466 | // libunwind dep |
| 464 | if (comp.config.link_libunwind) { | 467 | if (comp.config.link_libunwind) { |
| 465 | try argv.append(comp.libunwind_static_lib.?.full_object_path); | 468 | try argv.append(try comp.libunwind_static_lib.?.full_object_path.toString(arena)); |
| 466 | } | 469 | } |
| 467 | 470 | ||
| 468 | if (comp.config.any_fuzz) { | 471 | if (comp.config.any_fuzz) { |
| 469 | try argv.append(comp.fuzzer_lib.?.full_object_path); | 472 | try argv.append(try comp.fuzzer_lib.?.full_object_path.toString(arena)); |
| 470 | } | 473 | } |
| 471 | 474 | ||
| 472 | if (is_exe_or_dyn_lib and !comp.skip_linker_dependencies) { | 475 | if (is_exe_or_dyn_lib and !comp.skip_linker_dependencies) { |
| 473 | if (!comp.config.link_libc) { | 476 | if (!comp.config.link_libc) { |
| 474 | if (comp.libc_static_lib) |lib| { | 477 | if (comp.libc_static_lib) |lib| { |
| 475 | try argv.append(lib.full_object_path); | 478 | try argv.append(try lib.full_object_path.toString(arena)); |
| 476 | } | 479 | } |
| 477 | } | 480 | } |
| 478 | // MSVC compiler_rt is missing some stuff, so we build it unconditionally but | 481 | // MSVC compiler_rt is missing some stuff, so we build it unconditionally but |
| 479 | // and rely on weak linkage to allow MSVC compiler_rt functions to override ours. | 482 | // and rely on weak linkage to allow MSVC compiler_rt functions to override ours. |
| 480 | if (comp.compiler_rt_obj) |obj| try argv.append(obj.full_object_path); | 483 | if (comp.compiler_rt_obj) |obj| try argv.append(try obj.full_object_path.toString(arena)); |
| 481 | if (comp.compiler_rt_lib) |lib| try argv.append(lib.full_object_path); | 484 | if (comp.compiler_rt_lib) |lib| try argv.append(try lib.full_object_path.toString(arena)); |
| 482 | } | 485 | } |
| 483 | 486 | ||
| 484 | try argv.ensureUnusedCapacity(comp.system_libs.count()); | 487 | try argv.ensureUnusedCapacity(comp.system_libs.count()); |
| 485 | for (comp.system_libs.keys()) |key| { | 488 | for (comp.system_libs.keys()) |key| { |
| 486 | const lib_basename = try allocPrint(arena, "{s}.lib", .{key}); | 489 | const lib_basename = try allocPrint(arena, "{s}.lib", .{key}); |
| 487 | if (comp.crt_files.get(lib_basename)) |crt_file| { | 490 | if (comp.crt_files.get(lib_basename)) |crt_file| { |
| 488 | argv.appendAssumeCapacity(crt_file.full_object_path); | 491 | argv.appendAssumeCapacity(try crt_file.full_object_path.toString(arena)); |
| 489 | continue; | 492 | continue; |
| 490 | } | 493 | } |
| 491 | if (try findLib(arena, lib_basename, self.lib_dirs)) |full_path| { | 494 | if (try findLib(arena, lib_basename, self.lib_dirs)) |full_path| { |
src/link/Elf.zig+118-325| ... | @@ -383,9 +383,9 @@ pub fn createEmpty( | ... | @@ -383,9 +383,9 @@ pub fn createEmpty( |
| 383 | const index: File.Index = @intCast(try self.files.addOne(gpa)); | 383 | const index: File.Index = @intCast(try self.files.addOne(gpa)); |
| 384 | self.files.set(index, .{ .zig_object = .{ | 384 | self.files.set(index, .{ .zig_object = .{ |
| 385 | .index = index, | 385 | .index = index, |
| 386 | .path = try std.fmt.allocPrint(arena, "{s}.o", .{fs.path.stem( | 386 | .basename = try std.fmt.allocPrint(arena, "{s}.o", .{ |
| 387 | zcu.main_mod.root_src_path, | 387 | fs.path.stem(zcu.main_mod.root_src_path), |
| 388 | )}), | 388 | }), |
| 389 | } }); | 389 | } }); |
| 390 | self.zig_object_index = index; | 390 | self.zig_object_index = index; |
| 391 | try self.zigObjectPtr().?.init(self, .{ | 391 | try self.zigObjectPtr().?.init(self, .{ |
| ... | @@ -742,13 +742,12 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -742,13 +742,12 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 742 | const target = self.getTarget(); | 742 | const target = self.getTarget(); |
| 743 | const link_mode = comp.config.link_mode; | 743 | const link_mode = comp.config.link_mode; |
| 744 | const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type. | 744 | const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type. |
| 745 | const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: { | 745 | const module_obj_path: ?Path = if (self.base.zcu_object_sub_path) |path| .{ |
| 746 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); | 746 | .root_dir = directory, |
| 747 | if (fs.path.dirname(full_out_path)) |dirname| { | 747 | .sub_path = if (fs.path.dirname(self.base.emit.sub_path)) |dirname| |
| 748 | break :blk try fs.path.join(arena, &.{ dirname, path }); | 748 | try fs.path.join(arena, &.{ dirname, path }) |
| 749 | } else { | 749 | else |
| 750 | break :blk path; | 750 | path, |
| 751 | } | ||
| 752 | } else null; | 751 | } else null; |
| 753 | 752 | ||
| 754 | // --verbose-link | 753 | // --verbose-link |
| ... | @@ -758,7 +757,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -758,7 +757,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 758 | if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, module_obj_path); | 757 | if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, module_obj_path); |
| 759 | if (self.base.isObject()) return relocatable.flushObject(self, comp, module_obj_path); | 758 | if (self.base.isObject()) return relocatable.flushObject(self, comp, module_obj_path); |
| 760 | 759 | ||
| 761 | const csu = try CsuObjects.init(arena, comp); | 760 | const csu = try comp.getCrtPaths(arena); |
| 762 | 761 | ||
| 763 | // csu prelude | 762 | // csu prelude |
| 764 | if (csu.crt0) |path| try parseObjectReportingFailure(self, path); | 763 | if (csu.crt0) |path| try parseObjectReportingFailure(self, path); |
| ... | @@ -790,23 +789,22 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -790,23 +789,22 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 790 | if (comp.libc_static_lib) |lib| try parseCrtFileReportingFailure(self, lib); | 789 | if (comp.libc_static_lib) |lib| try parseCrtFileReportingFailure(self, lib); |
| 791 | } | 790 | } |
| 792 | 791 | ||
| 793 | var system_libs = std.ArrayList(SystemLib).init(arena); | ||
| 794 | |||
| 795 | try system_libs.ensureUnusedCapacity(comp.system_libs.values().len); | ||
| 796 | for (comp.system_libs.values()) |lib_info| { | 792 | for (comp.system_libs.values()) |lib_info| { |
| 797 | system_libs.appendAssumeCapacity(.{ .needed = lib_info.needed, .path = lib_info.path.? }); | 793 | try self.parseLibraryReportingFailure(.{ |
| 794 | .needed = lib_info.needed, | ||
| 795 | .path = lib_info.path.?, | ||
| 796 | }, false); | ||
| 798 | } | 797 | } |
| 799 | 798 | ||
| 800 | // libc++ dep | 799 | // libc++ dep |
| 801 | if (comp.config.link_libcpp) { | 800 | if (comp.config.link_libcpp) { |
| 802 | try system_libs.ensureUnusedCapacity(2); | 801 | try self.parseLibraryReportingFailure(.{ .path = comp.libcxxabi_static_lib.?.full_object_path }, false); |
| 803 | system_libs.appendAssumeCapacity(.{ .path = comp.libcxxabi_static_lib.?.full_object_path }); | 802 | try self.parseLibraryReportingFailure(.{ .path = comp.libcxx_static_lib.?.full_object_path }, false); |
| 804 | system_libs.appendAssumeCapacity(.{ .path = comp.libcxx_static_lib.?.full_object_path }); | ||
| 805 | } | 803 | } |
| 806 | 804 | ||
| 807 | // libunwind dep | 805 | // libunwind dep |
| 808 | if (comp.config.link_libunwind) { | 806 | if (comp.config.link_libunwind) { |
| 809 | try system_libs.append(.{ .path = comp.libunwind_static_lib.?.full_object_path }); | 807 | try self.parseLibraryReportingFailure(.{ .path = comp.libunwind_static_lib.?.full_object_path }, false); |
| 810 | } | 808 | } |
| 811 | 809 | ||
| 812 | // libc dep | 810 | // libc dep |
| ... | @@ -814,7 +812,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -814,7 +812,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 814 | if (comp.config.link_libc) { | 812 | if (comp.config.link_libc) { |
| 815 | if (comp.libc_installation) |lc| { | 813 | if (comp.libc_installation) |lc| { |
| 816 | const flags = target_util.libcFullLinkFlags(target); | 814 | const flags = target_util.libcFullLinkFlags(target); |
| 817 | try system_libs.ensureUnusedCapacity(flags.len); | ||
| 818 | 815 | ||
| 819 | var test_path = std.ArrayList(u8).init(arena); | 816 | var test_path = std.ArrayList(u8).init(arena); |
| 820 | var checked_paths = std.ArrayList([]const u8).init(arena); | 817 | var checked_paths = std.ArrayList([]const u8).init(arena); |
| ... | @@ -840,39 +837,34 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -840,39 +837,34 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 840 | continue; | 837 | continue; |
| 841 | } | 838 | } |
| 842 | 839 | ||
| 843 | const resolved_path = try arena.dupe(u8, test_path.items); | 840 | const resolved_path = Path.initCwd(try arena.dupe(u8, test_path.items)); |
| 844 | system_libs.appendAssumeCapacity(.{ .path = resolved_path }); | 841 | try self.parseLibraryReportingFailure(.{ .path = resolved_path }, false); |
| 845 | } | 842 | } |
| 846 | } else if (target.isGnuLibC()) { | 843 | } else if (target.isGnuLibC()) { |
| 847 | try system_libs.ensureUnusedCapacity(glibc.libs.len + 1); | ||
| 848 | for (glibc.libs) |lib| { | 844 | for (glibc.libs) |lib| { |
| 849 | if (lib.removed_in) |rem_in| { | 845 | if (lib.removed_in) |rem_in| { |
| 850 | if (target.os.version_range.linux.glibc.order(rem_in) != .lt) continue; | 846 | if (target.os.version_range.linux.glibc.order(rem_in) != .lt) continue; |
| 851 | } | 847 | } |
| 852 | 848 | ||
| 853 | const lib_path = try std.fmt.allocPrint(arena, "{s}{c}lib{s}.so.{d}", .{ | 849 | const lib_path = Path.initCwd(try std.fmt.allocPrint(arena, "{s}{c}lib{s}.so.{d}", .{ |
| 854 | comp.glibc_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover, | 850 | comp.glibc_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover, |
| 855 | }); | 851 | })); |
| 856 | system_libs.appendAssumeCapacity(.{ .path = lib_path }); | 852 | try self.parseLibraryReportingFailure(.{ .path = lib_path }, false); |
| 857 | } | 853 | } |
| 858 | system_libs.appendAssumeCapacity(.{ | 854 | try self.parseLibraryReportingFailure(.{ |
| 859 | .path = try comp.get_libc_crt_file(arena, "libc_nonshared.a"), | 855 | .path = try comp.get_libc_crt_file(arena, "libc_nonshared.a"), |
| 860 | }); | 856 | }, false); |
| 861 | } else if (target.isMusl()) { | 857 | } else if (target.isMusl()) { |
| 862 | const path = try comp.get_libc_crt_file(arena, switch (link_mode) { | 858 | const path = try comp.get_libc_crt_file(arena, switch (link_mode) { |
| 863 | .static => "libc.a", | 859 | .static => "libc.a", |
| 864 | .dynamic => "libc.so", | 860 | .dynamic => "libc.so", |
| 865 | }); | 861 | }); |
| 866 | try system_libs.append(.{ .path = path }); | 862 | try self.parseLibraryReportingFailure(.{ .path = path }, false); |
| 867 | } else { | 863 | } else { |
| 868 | comp.link_error_flags.missing_libc = true; | 864 | comp.link_error_flags.missing_libc = true; |
| 869 | } | 865 | } |
| 870 | } | 866 | } |
| 871 | 867 | ||
| 872 | for (system_libs.items) |lib| { | ||
| 873 | try self.parseLibraryReportingFailure(lib, false); | ||
| 874 | } | ||
| 875 | |||
| 876 | // Finally, as the last input objects we add compiler_rt and CSU postlude (if any). | 868 | // Finally, as the last input objects we add compiler_rt and CSU postlude (if any). |
| 877 | 869 | ||
| 878 | // compiler-rt. Since compiler_rt exports symbols like `memset`, it needs | 870 | // compiler-rt. Since compiler_rt exports symbols like `memset`, it needs |
| ... | @@ -1066,10 +1058,10 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { | ... | @@ -1066,10 +1058,10 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1066 | } | 1058 | } |
| 1067 | } else null; | 1059 | } else null; |
| 1068 | 1060 | ||
| 1069 | const csu = try CsuObjects.init(arena, comp); | 1061 | const csu = try comp.getCrtPaths(arena); |
| 1070 | const compiler_rt_path: ?[]const u8 = blk: { | 1062 | const compiler_rt_path: ?[]const u8 = blk: { |
| 1071 | if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; | 1063 | if (comp.compiler_rt_lib) |x| break :blk try x.full_object_path.toString(arena); |
| 1072 | if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; | 1064 | if (comp.compiler_rt_obj) |x| break :blk try x.full_object_path.toString(arena); |
| 1073 | break :blk null; | 1065 | break :blk null; |
| 1074 | }; | 1066 | }; |
| 1075 | 1067 | ||
| ... | @@ -1092,11 +1084,11 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { | ... | @@ -1092,11 +1084,11 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1092 | 1084 | ||
| 1093 | if (self.base.isRelocatable()) { | 1085 | if (self.base.isRelocatable()) { |
| 1094 | for (comp.objects) |obj| { | 1086 | for (comp.objects) |obj| { |
| 1095 | try argv.append(obj.path); | 1087 | try argv.append(try obj.path.toString(arena)); |
| 1096 | } | 1088 | } |
| 1097 | 1089 | ||
| 1098 | for (comp.c_object_table.keys()) |key| { | 1090 | for (comp.c_object_table.keys()) |key| { |
| 1099 | try argv.append(key.status.success.object_path); | 1091 | try argv.append(try key.status.success.object_path.toString(arena)); |
| 1100 | } | 1092 | } |
| 1101 | 1093 | ||
| 1102 | if (module_obj_path) |p| { | 1094 | if (module_obj_path) |p| { |
| ... | @@ -1178,9 +1170,9 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { | ... | @@ -1178,9 +1170,9 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1178 | } | 1170 | } |
| 1179 | 1171 | ||
| 1180 | // csu prelude | 1172 | // csu prelude |
| 1181 | if (csu.crt0) |v| try argv.append(v); | 1173 | if (csu.crt0) |path| try argv.append(try path.toString(arena)); |
| 1182 | if (csu.crti) |v| try argv.append(v); | 1174 | if (csu.crti) |path| try argv.append(try path.toString(arena)); |
| 1183 | if (csu.crtbegin) |v| try argv.append(v); | 1175 | if (csu.crtbegin) |path| try argv.append(try path.toString(arena)); |
| 1184 | 1176 | ||
| 1185 | for (self.lib_dirs) |lib_dir| { | 1177 | for (self.lib_dirs) |lib_dir| { |
| 1186 | try argv.append("-L"); | 1178 | try argv.append("-L"); |
| ... | @@ -1205,10 +1197,9 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { | ... | @@ -1205,10 +1197,9 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1205 | } | 1197 | } |
| 1206 | 1198 | ||
| 1207 | if (obj.loption) { | 1199 | if (obj.loption) { |
| 1208 | assert(obj.path[0] == ':'); | ||
| 1209 | try argv.append("-l"); | 1200 | try argv.append("-l"); |
| 1210 | } | 1201 | } |
| 1211 | try argv.append(obj.path); | 1202 | try argv.append(try obj.path.toString(arena)); |
| 1212 | } | 1203 | } |
| 1213 | if (whole_archive) { | 1204 | if (whole_archive) { |
| 1214 | try argv.append("-no-whole-archive"); | 1205 | try argv.append("-no-whole-archive"); |
| ... | @@ -1216,7 +1207,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { | ... | @@ -1216,7 +1207,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1216 | } | 1207 | } |
| 1217 | 1208 | ||
| 1218 | for (comp.c_object_table.keys()) |key| { | 1209 | for (comp.c_object_table.keys()) |key| { |
| 1219 | try argv.append(key.status.success.object_path); | 1210 | try argv.append(try key.status.success.object_path.toString(arena)); |
| 1220 | } | 1211 | } |
| 1221 | 1212 | ||
| 1222 | if (module_obj_path) |p| { | 1213 | if (module_obj_path) |p| { |
| ... | @@ -1224,17 +1215,17 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { | ... | @@ -1224,17 +1215,17 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1224 | } | 1215 | } |
| 1225 | 1216 | ||
| 1226 | if (comp.config.any_sanitize_thread) { | 1217 | if (comp.config.any_sanitize_thread) { |
| 1227 | try argv.append(comp.tsan_lib.?.full_object_path); | 1218 | try argv.append(try comp.tsan_lib.?.full_object_path.toString(arena)); |
| 1228 | } | 1219 | } |
| 1229 | 1220 | ||
| 1230 | if (comp.config.any_fuzz) { | 1221 | if (comp.config.any_fuzz) { |
| 1231 | try argv.append(comp.fuzzer_lib.?.full_object_path); | 1222 | try argv.append(try comp.fuzzer_lib.?.full_object_path.toString(arena)); |
| 1232 | } | 1223 | } |
| 1233 | 1224 | ||
| 1234 | // libc | 1225 | // libc |
| 1235 | if (!comp.skip_linker_dependencies and !comp.config.link_libc) { | 1226 | if (!comp.skip_linker_dependencies and !comp.config.link_libc) { |
| 1236 | if (comp.libc_static_lib) |lib| { | 1227 | if (comp.libc_static_lib) |lib| { |
| 1237 | try argv.append(lib.full_object_path); | 1228 | try argv.append(try lib.full_object_path.toString(arena)); |
| 1238 | } | 1229 | } |
| 1239 | } | 1230 | } |
| 1240 | 1231 | ||
| ... | @@ -1258,7 +1249,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { | ... | @@ -1258,7 +1249,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1258 | as_needed = true; | 1249 | as_needed = true; |
| 1259 | }, | 1250 | }, |
| 1260 | } | 1251 | } |
| 1261 | argv.appendAssumeCapacity(lib_info.path.?); | 1252 | argv.appendAssumeCapacity(try lib_info.path.?.toString(arena)); |
| 1262 | } | 1253 | } |
| 1263 | 1254 | ||
| 1264 | if (!as_needed) { | 1255 | if (!as_needed) { |
| ... | @@ -1268,13 +1259,13 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { | ... | @@ -1268,13 +1259,13 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1268 | 1259 | ||
| 1269 | // libc++ dep | 1260 | // libc++ dep |
| 1270 | if (comp.config.link_libcpp) { | 1261 | if (comp.config.link_libcpp) { |
| 1271 | try argv.append(comp.libcxxabi_static_lib.?.full_object_path); | 1262 | try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena)); |
| 1272 | try argv.append(comp.libcxx_static_lib.?.full_object_path); | 1263 | try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena)); |
| 1273 | } | 1264 | } |
| 1274 | 1265 | ||
| 1275 | // libunwind dep | 1266 | // libunwind dep |
| 1276 | if (comp.config.link_libunwind) { | 1267 | if (comp.config.link_libunwind) { |
| 1277 | try argv.append(comp.libunwind_static_lib.?.full_object_path); | 1268 | try argv.append(try comp.libunwind_static_lib.?.full_object_path.toString(arena)); |
| 1278 | } | 1269 | } |
| 1279 | 1270 | ||
| 1280 | // libc dep | 1271 | // libc dep |
| ... | @@ -1295,9 +1286,9 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { | ... | @@ -1295,9 +1286,9 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1295 | }); | 1286 | }); |
| 1296 | try argv.append(lib_path); | 1287 | try argv.append(lib_path); |
| 1297 | } | 1288 | } |
| 1298 | try argv.append(try comp.get_libc_crt_file(arena, "libc_nonshared.a")); | 1289 | try argv.append(try comp.crtFileAsString(arena, "libc_nonshared.a")); |
| 1299 | } else if (target.isMusl()) { | 1290 | } else if (target.isMusl()) { |
| 1300 | try argv.append(try comp.get_libc_crt_file(arena, switch (link_mode) { | 1291 | try argv.append(try comp.crtFileAsString(arena, switch (link_mode) { |
| 1301 | .static => "libc.a", | 1292 | .static => "libc.a", |
| 1302 | .dynamic => "libc.so", | 1293 | .dynamic => "libc.so", |
| 1303 | })); | 1294 | })); |
| ... | @@ -1310,8 +1301,8 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { | ... | @@ -1310,8 +1301,8 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1310 | } | 1301 | } |
| 1311 | 1302 | ||
| 1312 | // crt postlude | 1303 | // crt postlude |
| 1313 | if (csu.crtend) |v| try argv.append(v); | 1304 | if (csu.crtend) |path| try argv.append(try path.toString(arena)); |
| 1314 | if (csu.crtn) |v| try argv.append(v); | 1305 | if (csu.crtn) |path| try argv.append(try path.toString(arena)); |
| 1315 | } | 1306 | } |
| 1316 | 1307 | ||
| 1317 | Compilation.dump_argv(argv.items); | 1308 | Compilation.dump_argv(argv.items); |
| ... | @@ -1331,7 +1322,7 @@ pub const ParseError = error{ | ... | @@ -1331,7 +1322,7 @@ pub const ParseError = error{ |
| 1331 | UnknownFileType, | 1322 | UnknownFileType, |
| 1332 | } || LdScript.Error || fs.Dir.AccessError || fs.File.SeekError || fs.File.OpenError || fs.File.ReadError; | 1323 | } || LdScript.Error || fs.Dir.AccessError || fs.File.SeekError || fs.File.OpenError || fs.File.ReadError; |
| 1333 | 1324 | ||
| 1334 | fn parseCrtFileReportingFailure(self: *Elf, crt_file: Compilation.CRTFile) error{OutOfMemory}!void { | 1325 | fn parseCrtFileReportingFailure(self: *Elf, crt_file: Compilation.CrtFile) error{OutOfMemory}!void { |
| 1335 | if (crt_file.isObject()) { | 1326 | if (crt_file.isObject()) { |
| 1336 | try parseObjectReportingFailure(self, crt_file.full_object_path); | 1327 | try parseObjectReportingFailure(self, crt_file.full_object_path); |
| 1337 | } else { | 1328 | } else { |
| ... | @@ -1339,7 +1330,7 @@ fn parseCrtFileReportingFailure(self: *Elf, crt_file: Compilation.CRTFile) error | ... | @@ -1339,7 +1330,7 @@ fn parseCrtFileReportingFailure(self: *Elf, crt_file: Compilation.CRTFile) error |
| 1339 | } | 1330 | } |
| 1340 | } | 1331 | } |
| 1341 | 1332 | ||
| 1342 | pub fn parseObjectReportingFailure(self: *Elf, path: []const u8) error{OutOfMemory}!void { | 1333 | pub fn parseObjectReportingFailure(self: *Elf, path: Path) error{OutOfMemory}!void { |
| 1343 | self.parseObject(path) catch |err| switch (err) { | 1334 | self.parseObject(path) catch |err| switch (err) { |
| 1344 | error.LinkFailure => return, // already reported | 1335 | error.LinkFailure => return, // already reported |
| 1345 | error.OutOfMemory => return error.OutOfMemory, | 1336 | error.OutOfMemory => return error.OutOfMemory, |
| ... | @@ -1367,17 +1358,20 @@ fn parseLibrary(self: *Elf, lib: SystemLib, must_link: bool) ParseError!void { | ... | @@ -1367,17 +1358,20 @@ fn parseLibrary(self: *Elf, lib: SystemLib, must_link: bool) ParseError!void { |
| 1367 | } | 1358 | } |
| 1368 | } | 1359 | } |
| 1369 | 1360 | ||
| 1370 | fn parseObject(self: *Elf, path: []const u8) ParseError!void { | 1361 | fn parseObject(self: *Elf, path: Path) ParseError!void { |
| 1371 | const tracy = trace(@src()); | 1362 | const tracy = trace(@src()); |
| 1372 | defer tracy.end(); | 1363 | defer tracy.end(); |
| 1373 | 1364 | ||
| 1374 | const gpa = self.base.comp.gpa; | 1365 | const gpa = self.base.comp.gpa; |
| 1375 | const handle = try fs.cwd().openFile(path, .{}); | 1366 | const handle = try path.root_dir.handle.openFile(path.sub_path, .{}); |
| 1376 | const fh = try self.addFileHandle(handle); | 1367 | const fh = try self.addFileHandle(handle); |
| 1377 | 1368 | ||
| 1378 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); | 1369 | const index: File.Index = @intCast(try self.files.addOne(gpa)); |
| 1379 | self.files.set(index, .{ .object = .{ | 1370 | self.files.set(index, .{ .object = .{ |
| 1380 | .path = try gpa.dupe(u8, path), | 1371 | .path = .{ |
| 1372 | .root_dir = path.root_dir, | ||
| 1373 | .sub_path = try gpa.dupe(u8, path.sub_path), | ||
| 1374 | }, | ||
| 1381 | .file_handle = fh, | 1375 | .file_handle = fh, |
| 1382 | .index = index, | 1376 | .index = index, |
| 1383 | } }); | 1377 | } }); |
| ... | @@ -1387,15 +1381,15 @@ fn parseObject(self: *Elf, path: []const u8) ParseError!void { | ... | @@ -1387,15 +1381,15 @@ fn parseObject(self: *Elf, path: []const u8) ParseError!void { |
| 1387 | try object.parse(self); | 1381 | try object.parse(self); |
| 1388 | } | 1382 | } |
| 1389 | 1383 | ||
| 1390 | fn parseArchive(self: *Elf, path: []const u8, must_link: bool) ParseError!void { | 1384 | fn parseArchive(self: *Elf, path: Path, must_link: bool) ParseError!void { |
| 1391 | const tracy = trace(@src()); | 1385 | const tracy = trace(@src()); |
| 1392 | defer tracy.end(); | 1386 | defer tracy.end(); |
| 1393 | 1387 | ||
| 1394 | const gpa = self.base.comp.gpa; | 1388 | const gpa = self.base.comp.gpa; |
| 1395 | const handle = try fs.cwd().openFile(path, .{}); | 1389 | const handle = try path.root_dir.handle.openFile(path.sub_path, .{}); |
| 1396 | const fh = try self.addFileHandle(handle); | 1390 | const fh = try self.addFileHandle(handle); |
| 1397 | 1391 | ||
| 1398 | var archive = Archive{}; | 1392 | var archive: Archive = .{}; |
| 1399 | defer archive.deinit(gpa); | 1393 | defer archive.deinit(gpa); |
| 1400 | try archive.parse(self, path, fh); | 1394 | try archive.parse(self, path, fh); |
| 1401 | 1395 | ||
| ... | @@ -1403,7 +1397,7 @@ fn parseArchive(self: *Elf, path: []const u8, must_link: bool) ParseError!void { | ... | @@ -1403,7 +1397,7 @@ fn parseArchive(self: *Elf, path: []const u8, must_link: bool) ParseError!void { |
| 1403 | defer gpa.free(objects); | 1397 | defer gpa.free(objects); |
| 1404 | 1398 | ||
| 1405 | for (objects) |extracted| { | 1399 | for (objects) |extracted| { |
| 1406 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); | 1400 | const index: File.Index = @intCast(try self.files.addOne(gpa)); |
| 1407 | self.files.set(index, .{ .object = extracted }); | 1401 | self.files.set(index, .{ .object = extracted }); |
| 1408 | const object = &self.files.items(.data)[index].object; | 1402 | const object = &self.files.items(.data)[index].object; |
| 1409 | object.index = index; | 1403 | object.index = index; |
| ... | @@ -1418,12 +1412,15 @@ fn parseSharedObject(self: *Elf, lib: SystemLib) ParseError!void { | ... | @@ -1418,12 +1412,15 @@ fn parseSharedObject(self: *Elf, lib: SystemLib) ParseError!void { |
| 1418 | defer tracy.end(); | 1412 | defer tracy.end(); |
| 1419 | 1413 | ||
| 1420 | const gpa = self.base.comp.gpa; | 1414 | const gpa = self.base.comp.gpa; |
| 1421 | const handle = try fs.cwd().openFile(lib.path, .{}); | 1415 | const handle = try lib.path.root_dir.handle.openFile(lib.path.sub_path, .{}); |
| 1422 | defer handle.close(); | 1416 | defer handle.close(); |
| 1423 | 1417 | ||
| 1424 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); | 1418 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); |
| 1425 | self.files.set(index, .{ .shared_object = .{ | 1419 | self.files.set(index, .{ .shared_object = .{ |
| 1426 | .path = try gpa.dupe(u8, lib.path), | 1420 | .path = .{ |
| 1421 | .root_dir = lib.path.root_dir, | ||
| 1422 | .sub_path = try gpa.dupe(u8, lib.path.sub_path), | ||
| 1423 | }, | ||
| 1427 | .index = index, | 1424 | .index = index, |
| 1428 | .needed = lib.needed, | 1425 | .needed = lib.needed, |
| 1429 | .alive = lib.needed, | 1426 | .alive = lib.needed, |
| ... | @@ -1439,12 +1436,12 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { | ... | @@ -1439,12 +1436,12 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { |
| 1439 | defer tracy.end(); | 1436 | defer tracy.end(); |
| 1440 | 1437 | ||
| 1441 | const gpa = self.base.comp.gpa; | 1438 | const gpa = self.base.comp.gpa; |
| 1442 | const in_file = try fs.cwd().openFile(lib.path, .{}); | 1439 | const in_file = try lib.path.root_dir.handle.openFile(lib.path.sub_path, .{}); |
| 1443 | defer in_file.close(); | 1440 | defer in_file.close(); |
| 1444 | const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32)); | 1441 | const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32)); |
| 1445 | defer gpa.free(data); | 1442 | defer gpa.free(data); |
| 1446 | 1443 | ||
| 1447 | var script = LdScript{ .path = lib.path }; | 1444 | var script: LdScript = .{ .path = lib.path }; |
| 1448 | defer script.deinit(gpa); | 1445 | defer script.deinit(gpa); |
| 1449 | try script.parse(data, self); | 1446 | try script.parse(data, self); |
| 1450 | 1447 | ||
| ... | @@ -1455,12 +1452,12 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { | ... | @@ -1455,12 +1452,12 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { |
| 1455 | var test_path = std.ArrayList(u8).init(arena); | 1452 | var test_path = std.ArrayList(u8).init(arena); |
| 1456 | var checked_paths = std.ArrayList([]const u8).init(arena); | 1453 | var checked_paths = std.ArrayList([]const u8).init(arena); |
| 1457 | 1454 | ||
| 1458 | for (script.args.items) |scr_obj| { | 1455 | for (script.args.items) |script_arg| { |
| 1459 | checked_paths.clearRetainingCapacity(); | 1456 | checked_paths.clearRetainingCapacity(); |
| 1460 | 1457 | ||
| 1461 | success: { | 1458 | success: { |
| 1462 | if (mem.startsWith(u8, scr_obj.path, "-l")) { | 1459 | if (mem.startsWith(u8, script_arg.path, "-l")) { |
| 1463 | const lib_name = scr_obj.path["-l".len..]; | 1460 | const lib_name = script_arg.path["-l".len..]; |
| 1464 | 1461 | ||
| 1465 | // TODO I think technically we should re-use the mechanism used by the frontend here. | 1462 | // TODO I think technically we should re-use the mechanism used by the frontend here. |
| 1466 | // Maybe we should hoist search-strategy all the way here? | 1463 | // Maybe we should hoist search-strategy all the way here? |
| ... | @@ -1474,33 +1471,30 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { | ... | @@ -1474,33 +1471,30 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { |
| 1474 | } | 1471 | } |
| 1475 | } else { | 1472 | } else { |
| 1476 | var buffer: [fs.max_path_bytes]u8 = undefined; | 1473 | var buffer: [fs.max_path_bytes]u8 = undefined; |
| 1477 | if (fs.realpath(scr_obj.path, &buffer)) |path| { | 1474 | if (fs.realpath(script_arg.path, &buffer)) |path| { |
| 1478 | test_path.clearRetainingCapacity(); | 1475 | test_path.clearRetainingCapacity(); |
| 1479 | try test_path.writer().writeAll(path); | 1476 | try test_path.writer().writeAll(path); |
| 1480 | break :success; | 1477 | break :success; |
| 1481 | } else |_| {} | 1478 | } else |_| {} |
| 1482 | 1479 | ||
| 1483 | try checked_paths.append(try arena.dupe(u8, scr_obj.path)); | 1480 | try checked_paths.append(try arena.dupe(u8, script_arg.path)); |
| 1484 | for (self.lib_dirs) |lib_dir| { | 1481 | for (self.lib_dirs) |lib_dir| { |
| 1485 | if (try self.accessLibPath(arena, &test_path, &checked_paths, lib_dir, scr_obj.path, null)) | 1482 | if (try self.accessLibPath(arena, &test_path, &checked_paths, lib_dir, script_arg.path, null)) |
| 1486 | break :success; | 1483 | break :success; |
| 1487 | } | 1484 | } |
| 1488 | } | 1485 | } |
| 1489 | 1486 | ||
| 1490 | try self.reportMissingLibraryError( | 1487 | try self.reportMissingLibraryError( |
| 1491 | checked_paths.items, | 1488 | checked_paths.items, |
| 1492 | "missing library dependency: GNU ld script '{s}' requires '{s}', but file not found", | 1489 | "missing library dependency: GNU ld script '{}' requires '{s}', but file not found", |
| 1493 | .{ | 1490 | .{ @as(Path, lib.path), script_arg.path }, |
| 1494 | lib.path, | ||
| 1495 | scr_obj.path, | ||
| 1496 | }, | ||
| 1497 | ); | 1491 | ); |
| 1498 | continue; | 1492 | continue; |
| 1499 | } | 1493 | } |
| 1500 | 1494 | ||
| 1501 | const full_path = test_path.items; | 1495 | const full_path = Path.initCwd(test_path.items); |
| 1502 | self.parseLibrary(.{ | 1496 | self.parseLibrary(.{ |
| 1503 | .needed = scr_obj.needed, | 1497 | .needed = script_arg.needed, |
| 1504 | .path = full_path, | 1498 | .path = full_path, |
| 1505 | }, false) catch |err| switch (err) { | 1499 | }, false) catch |err| switch (err) { |
| 1506 | error.LinkFailure => continue, // already reported | 1500 | error.LinkFailure => continue, // already reported |
| ... | @@ -1841,7 +1835,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s | ... | @@ -1841,7 +1835,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 1841 | const have_dynamic_linker = comp.config.link_libc and | 1835 | const have_dynamic_linker = comp.config.link_libc and |
| 1842 | link_mode == .dynamic and is_exe_or_dyn_lib; | 1836 | link_mode == .dynamic and is_exe_or_dyn_lib; |
| 1843 | const target = self.getTarget(); | 1837 | const target = self.getTarget(); |
| 1844 | const compiler_rt_path: ?[]const u8 = blk: { | 1838 | const compiler_rt_path: ?Path = blk: { |
| 1845 | if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; | 1839 | if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; |
| 1846 | if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; | 1840 | if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; |
| 1847 | break :blk null; | 1841 | break :blk null; |
| ... | @@ -1875,17 +1869,17 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s | ... | @@ -1875,17 +1869,17 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 1875 | man.hash.add(self.allow_undefined_version); | 1869 | man.hash.add(self.allow_undefined_version); |
| 1876 | man.hash.addOptional(self.enable_new_dtags); | 1870 | man.hash.addOptional(self.enable_new_dtags); |
| 1877 | for (comp.objects) |obj| { | 1871 | for (comp.objects) |obj| { |
| 1878 | _ = try man.addFile(obj.path, null); | 1872 | _ = try man.addFilePath(obj.path, null); |
| 1879 | man.hash.add(obj.must_link); | 1873 | man.hash.add(obj.must_link); |
| 1880 | man.hash.add(obj.loption); | 1874 | man.hash.add(obj.loption); |
| 1881 | } | 1875 | } |
| 1882 | for (comp.c_object_table.keys()) |key| { | 1876 | for (comp.c_object_table.keys()) |key| { |
| 1883 | _ = try man.addFile(key.status.success.object_path, null); | 1877 | _ = try man.addFilePath(key.status.success.object_path, null); |
| 1884 | } | 1878 | } |
| 1885 | try man.addOptionalFile(module_obj_path); | 1879 | try man.addOptionalFile(module_obj_path); |
| 1886 | try man.addOptionalFile(compiler_rt_path); | 1880 | try man.addOptionalFilePath(compiler_rt_path); |
| 1887 | try man.addOptionalFile(if (comp.tsan_lib) |l| l.full_object_path else null); | 1881 | try man.addOptionalFilePath(if (comp.tsan_lib) |l| l.full_object_path else null); |
| 1888 | try man.addOptionalFile(if (comp.fuzzer_lib) |l| l.full_object_path else null); | 1882 | try man.addOptionalFilePath(if (comp.fuzzer_lib) |l| l.full_object_path else null); |
| 1889 | 1883 | ||
| 1890 | // We can skip hashing libc and libc++ components that we are in charge of building from Zig | 1884 | // We can skip hashing libc and libc++ components that we are in charge of building from Zig |
| 1891 | // installation sources because they are always a product of the compiler version + target information. | 1885 | // installation sources because they are always a product of the compiler version + target information. |
| ... | @@ -1982,17 +1976,19 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s | ... | @@ -1982,17 +1976,19 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 1982 | break :blk comp.c_object_table.keys()[0].status.success.object_path; | 1976 | break :blk comp.c_object_table.keys()[0].status.success.object_path; |
| 1983 | 1977 | ||
| 1984 | if (module_obj_path) |p| | 1978 | if (module_obj_path) |p| |
| 1985 | break :blk p; | 1979 | break :blk Path.initCwd(p); |
| 1986 | 1980 | ||
| 1987 | // TODO I think this is unreachable. Audit this situation when solving the above TODO | 1981 | // TODO I think this is unreachable. Audit this situation when solving the above TODO |
| 1988 | // regarding eliding redundant object -> object transformations. | 1982 | // regarding eliding redundant object -> object transformations. |
| 1989 | return error.NoObjectsToLink; | 1983 | return error.NoObjectsToLink; |
| 1990 | }; | 1984 | }; |
| 1991 | // This can happen when using --enable-cache and using the stage1 backend. In this case | 1985 | try std.fs.Dir.copyFile( |
| 1992 | // we can skip the file copy. | 1986 | the_object_path.root_dir.handle, |
| 1993 | if (!mem.eql(u8, the_object_path, full_out_path)) { | 1987 | the_object_path.sub_path, |
| 1994 | try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{}); | 1988 | directory.handle, |
| 1995 | } | 1989 | self.base.emit.sub_path, |
| 1990 | .{}, | ||
| 1991 | ); | ||
| 1996 | } else { | 1992 | } else { |
| 1997 | // Create an LLD command line and invoke it. | 1993 | // Create an LLD command line and invoke it. |
| 1998 | var argv = std.ArrayList([]const u8).init(gpa); | 1994 | var argv = std.ArrayList([]const u8).init(gpa); |
| ... | @@ -2177,10 +2173,10 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s | ... | @@ -2177,10 +2173,10 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2177 | try argv.append(full_out_path); | 2173 | try argv.append(full_out_path); |
| 2178 | 2174 | ||
| 2179 | // csu prelude | 2175 | // csu prelude |
| 2180 | const csu = try CsuObjects.init(arena, comp); | 2176 | const csu = try comp.getCrtPaths(arena); |
| 2181 | if (csu.crt0) |v| try argv.append(v); | 2177 | if (csu.crt0) |p| try argv.append(try p.toString(arena)); |
| 2182 | if (csu.crti) |v| try argv.append(v); | 2178 | if (csu.crti) |p| try argv.append(try p.toString(arena)); |
| 2183 | if (csu.crtbegin) |v| try argv.append(v); | 2179 | if (csu.crtbegin) |p| try argv.append(try p.toString(arena)); |
| 2184 | 2180 | ||
| 2185 | for (self.rpath_table.keys()) |rpath| { | 2181 | for (self.rpath_table.keys()) |rpath| { |
| 2186 | try argv.appendSlice(&.{ "-rpath", rpath }); | 2182 | try argv.appendSlice(&.{ "-rpath", rpath }); |
| ... | @@ -2244,10 +2240,10 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s | ... | @@ -2244,10 +2240,10 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2244 | } | 2240 | } |
| 2245 | 2241 | ||
| 2246 | if (obj.loption) { | 2242 | if (obj.loption) { |
| 2247 | assert(obj.path[0] == ':'); | 2243 | assert(obj.path.sub_path[0] == ':'); |
| 2248 | try argv.append("-l"); | 2244 | try argv.append("-l"); |
| 2249 | } | 2245 | } |
| 2250 | try argv.append(obj.path); | 2246 | try argv.append(try obj.path.toString(arena)); |
| 2251 | } | 2247 | } |
| 2252 | if (whole_archive) { | 2248 | if (whole_archive) { |
| 2253 | try argv.append("-no-whole-archive"); | 2249 | try argv.append("-no-whole-archive"); |
| ... | @@ -2255,7 +2251,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s | ... | @@ -2255,7 +2251,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2255 | } | 2251 | } |
| 2256 | 2252 | ||
| 2257 | for (comp.c_object_table.keys()) |key| { | 2253 | for (comp.c_object_table.keys()) |key| { |
| 2258 | try argv.append(key.status.success.object_path); | 2254 | try argv.append(try key.status.success.object_path.toString(arena)); |
| 2259 | } | 2255 | } |
| 2260 | 2256 | ||
| 2261 | if (module_obj_path) |p| { | 2257 | if (module_obj_path) |p| { |
| ... | @@ -2264,12 +2260,12 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s | ... | @@ -2264,12 +2260,12 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2264 | 2260 | ||
| 2265 | if (comp.tsan_lib) |lib| { | 2261 | if (comp.tsan_lib) |lib| { |
| 2266 | assert(comp.config.any_sanitize_thread); | 2262 | assert(comp.config.any_sanitize_thread); |
| 2267 | try argv.append(lib.full_object_path); | 2263 | try argv.append(try lib.full_object_path.toString(arena)); |
| 2268 | } | 2264 | } |
| 2269 | 2265 | ||
| 2270 | if (comp.fuzzer_lib) |lib| { | 2266 | if (comp.fuzzer_lib) |lib| { |
| 2271 | assert(comp.config.any_fuzz); | 2267 | assert(comp.config.any_fuzz); |
| 2272 | try argv.append(lib.full_object_path); | 2268 | try argv.append(try lib.full_object_path.toString(arena)); |
| 2273 | } | 2269 | } |
| 2274 | 2270 | ||
| 2275 | // libc | 2271 | // libc |
| ... | @@ -2278,7 +2274,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s | ... | @@ -2278,7 +2274,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2278 | !comp.config.link_libc) | 2274 | !comp.config.link_libc) |
| 2279 | { | 2275 | { |
| 2280 | if (comp.libc_static_lib) |lib| { | 2276 | if (comp.libc_static_lib) |lib| { |
| 2281 | try argv.append(lib.full_object_path); | 2277 | try argv.append(try lib.full_object_path.toString(arena)); |
| 2282 | } | 2278 | } |
| 2283 | } | 2279 | } |
| 2284 | 2280 | ||
| ... | @@ -2311,7 +2307,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s | ... | @@ -2311,7 +2307,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2311 | // libraries and not static libraries (the check for that needs to be earlier), | 2307 | // libraries and not static libraries (the check for that needs to be earlier), |
| 2312 | // but they could be full paths to .so files, in which case we | 2308 | // but they could be full paths to .so files, in which case we |
| 2313 | // want to avoid prepending "-l". | 2309 | // want to avoid prepending "-l". |
| 2314 | argv.appendAssumeCapacity(lib_info.path.?); | 2310 | argv.appendAssumeCapacity(try lib_info.path.?.toString(arena)); |
| 2315 | } | 2311 | } |
| 2316 | 2312 | ||
| 2317 | if (!as_needed) { | 2313 | if (!as_needed) { |
| ... | @@ -2321,13 +2317,13 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s | ... | @@ -2321,13 +2317,13 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2321 | 2317 | ||
| 2322 | // libc++ dep | 2318 | // libc++ dep |
| 2323 | if (comp.config.link_libcpp) { | 2319 | if (comp.config.link_libcpp) { |
| 2324 | try argv.append(comp.libcxxabi_static_lib.?.full_object_path); | 2320 | try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena)); |
| 2325 | try argv.append(comp.libcxx_static_lib.?.full_object_path); | 2321 | try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena)); |
| 2326 | } | 2322 | } |
| 2327 | 2323 | ||
| 2328 | // libunwind dep | 2324 | // libunwind dep |
| 2329 | if (comp.config.link_libunwind) { | 2325 | if (comp.config.link_libunwind) { |
| 2330 | try argv.append(comp.libunwind_static_lib.?.full_object_path); | 2326 | try argv.append(try comp.libunwind_static_lib.?.full_object_path.toString(arena)); |
| 2331 | } | 2327 | } |
| 2332 | 2328 | ||
| 2333 | // libc dep | 2329 | // libc dep |
| ... | @@ -2349,9 +2345,9 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s | ... | @@ -2349,9 +2345,9 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2349 | }); | 2345 | }); |
| 2350 | try argv.append(lib_path); | 2346 | try argv.append(lib_path); |
| 2351 | } | 2347 | } |
| 2352 | try argv.append(try comp.get_libc_crt_file(arena, "libc_nonshared.a")); | 2348 | try argv.append(try comp.crtFileAsString(arena, "libc_nonshared.a")); |
| 2353 | } else if (target.isMusl()) { | 2349 | } else if (target.isMusl()) { |
| 2354 | try argv.append(try comp.get_libc_crt_file(arena, switch (link_mode) { | 2350 | try argv.append(try comp.crtFileAsString(arena, switch (link_mode) { |
| 2355 | .static => "libc.a", | 2351 | .static => "libc.a", |
| 2356 | .dynamic => "libc.so", | 2352 | .dynamic => "libc.so", |
| 2357 | })); | 2353 | })); |
| ... | @@ -2365,12 +2361,12 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s | ... | @@ -2365,12 +2361,12 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2365 | // to be after the shared libraries, so they are picked up from the shared | 2361 | // to be after the shared libraries, so they are picked up from the shared |
| 2366 | // libraries, not libcompiler_rt. | 2362 | // libraries, not libcompiler_rt. |
| 2367 | if (compiler_rt_path) |p| { | 2363 | if (compiler_rt_path) |p| { |
| 2368 | try argv.append(p); | 2364 | try argv.append(try p.toString(arena)); |
| 2369 | } | 2365 | } |
| 2370 | 2366 | ||
| 2371 | // crt postlude | 2367 | // crt postlude |
| 2372 | if (csu.crtend) |v| try argv.append(v); | 2368 | if (csu.crtend) |p| try argv.append(try p.toString(arena)); |
| 2373 | if (csu.crtn) |v| try argv.append(v); | 2369 | if (csu.crtn) |p| try argv.append(try p.toString(arena)); |
| 2374 | 2370 | ||
| 2375 | if (self.base.allow_shlib_undefined) { | 2371 | if (self.base.allow_shlib_undefined) { |
| 2376 | try argv.append("--allow-shlib-undefined"); | 2372 | try argv.append("--allow-shlib-undefined"); |
| ... | @@ -3183,8 +3179,9 @@ fn sortInitFini(self: *Elf) !void { | ... | @@ -3183,8 +3179,9 @@ fn sortInitFini(self: *Elf) !void { |
| 3183 | const object = atom_ptr.file(self).?.object; | 3179 | const object = atom_ptr.file(self).?.object; |
| 3184 | const priority = blk: { | 3180 | const priority = blk: { |
| 3185 | if (is_ctor_dtor) { | 3181 | if (is_ctor_dtor) { |
| 3186 | if (mem.indexOf(u8, object.path, "crtbegin") != null) break :blk std.math.minInt(i32); | 3182 | const basename = object.path.basename(); |
| 3187 | if (mem.indexOf(u8, object.path, "crtend") != null) break :blk std.math.maxInt(i32); | 3183 | if (mem.eql(u8, basename, "crtbegin.o")) break :blk std.math.minInt(i32); |
| 3184 | if (mem.eql(u8, basename, "crtend.o")) break :blk std.math.maxInt(i32); | ||
| 3188 | } | 3185 | } |
| 3189 | const default: i32 = if (is_ctor_dtor) -1 else std.math.maxInt(i32); | 3186 | const default: i32 = if (is_ctor_dtor) -1 else std.math.maxInt(i32); |
| 3190 | const name = atom_ptr.name(self); | 3187 | const name = atom_ptr.name(self); |
| ... | @@ -4472,210 +4469,6 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { | ... | @@ -4472,210 +4469,6 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
| 4472 | return actual_size +| (actual_size / ideal_factor); | 4469 | return actual_size +| (actual_size / ideal_factor); |
| 4473 | } | 4470 | } |
| 4474 | 4471 | ||
| 4475 | // Provide a blueprint of csu (c-runtime startup) objects for supported | ||
| 4476 | // link modes. | ||
| 4477 | // | ||
| 4478 | // This is for cross-mode targets only. For host-mode targets the system | ||
| 4479 | // compiler can be probed to produce a robust blueprint. | ||
| 4480 | // | ||
| 4481 | // Targets requiring a libc for which zig does not bundle a libc are | ||
| 4482 | // host-mode targets. Unfortunately, host-mode probes are not yet | ||
| 4483 | // implemented. For now the data is hard-coded here. Such targets are | ||
| 4484 | // { freebsd, netbsd, openbsd, dragonfly }. | ||
| 4485 | const CsuObjects = struct { | ||
| 4486 | crt0: ?[]const u8 = null, | ||
| 4487 | crti: ?[]const u8 = null, | ||
| 4488 | crtbegin: ?[]const u8 = null, | ||
| 4489 | crtend: ?[]const u8 = null, | ||
| 4490 | crtn: ?[]const u8 = null, | ||
| 4491 | |||
| 4492 | const InitArgs = struct {}; | ||
| 4493 | |||
| 4494 | fn init(arena: Allocator, comp: *const Compilation) !CsuObjects { | ||
| 4495 | // crt objects are only required for libc. | ||
| 4496 | if (!comp.config.link_libc) return .{}; | ||
| 4497 | |||
| 4498 | var result: CsuObjects = .{}; | ||
| 4499 | |||
| 4500 | // Flatten crt cases. | ||
| 4501 | const mode: enum { | ||
| 4502 | dynamic_lib, | ||
| 4503 | dynamic_exe, | ||
| 4504 | dynamic_pie, | ||
| 4505 | static_exe, | ||
| 4506 | static_pie, | ||
| 4507 | } = switch (comp.config.output_mode) { | ||
| 4508 | .Obj => return CsuObjects{}, | ||
| 4509 | .Lib => switch (comp.config.link_mode) { | ||
| 4510 | .dynamic => .dynamic_lib, | ||
| 4511 | .static => return CsuObjects{}, | ||
| 4512 | }, | ||
| 4513 | .Exe => switch (comp.config.link_mode) { | ||
| 4514 | .dynamic => if (comp.config.pie) .dynamic_pie else .dynamic_exe, | ||
| 4515 | .static => if (comp.config.pie) .static_pie else .static_exe, | ||
| 4516 | }, | ||
| 4517 | }; | ||
| 4518 | |||
| 4519 | const target = comp.root_mod.resolved_target.result; | ||
| 4520 | |||
| 4521 | if (target.isAndroid()) { | ||
| 4522 | switch (mode) { | ||
| 4523 | // zig fmt: off | ||
| 4524 | .dynamic_lib => result.set( null, null, "crtbegin_so.o", "crtend_so.o", null ), | ||
| 4525 | .dynamic_exe, | ||
| 4526 | .dynamic_pie => result.set( null, null, "crtbegin_dynamic.o", "crtend_android.o", null ), | ||
| 4527 | .static_exe, | ||
| 4528 | .static_pie => result.set( null, null, "crtbegin_static.o", "crtend_android.o", null ), | ||
| 4529 | // zig fmt: on | ||
| 4530 | } | ||
| 4531 | } else { | ||
| 4532 | switch (target.os.tag) { | ||
| 4533 | .linux => { | ||
| 4534 | switch (mode) { | ||
| 4535 | // zig fmt: off | ||
| 4536 | .dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 4537 | .dynamic_exe => result.set( "crt1.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), | ||
| 4538 | .dynamic_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 4539 | .static_exe => result.set( "crt1.o", "crti.o", "crtbeginT.o", "crtend.o", "crtn.o" ), | ||
| 4540 | .static_pie => result.set( "rcrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 4541 | // zig fmt: on | ||
| 4542 | } | ||
| 4543 | if (comp.libc_installation) |_| { | ||
| 4544 | // hosted-glibc provides crtbegin/end objects in platform/compiler-specific dirs | ||
| 4545 | // and they are not known at comptime. For now null-out crtbegin/end objects; | ||
| 4546 | // there is no feature loss, zig has never linked those objects in before. | ||
| 4547 | result.crtbegin = null; | ||
| 4548 | result.crtend = null; | ||
| 4549 | } else { | ||
| 4550 | // Bundled glibc only has Scrt1.o . | ||
| 4551 | if (result.crt0 != null and target.isGnuLibC()) result.crt0 = "Scrt1.o"; | ||
| 4552 | } | ||
| 4553 | }, | ||
| 4554 | .dragonfly => switch (mode) { | ||
| 4555 | // zig fmt: off | ||
| 4556 | .dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 4557 | .dynamic_exe => result.set( "crt1.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), | ||
| 4558 | .dynamic_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 4559 | .static_exe => result.set( "crt1.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), | ||
| 4560 | .static_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 4561 | // zig fmt: on | ||
| 4562 | }, | ||
| 4563 | .freebsd => switch (mode) { | ||
| 4564 | // zig fmt: off | ||
| 4565 | .dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 4566 | .dynamic_exe => result.set( "crt1.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), | ||
| 4567 | .dynamic_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 4568 | .static_exe => result.set( "crt1.o", "crti.o", "crtbeginT.o", "crtend.o", "crtn.o" ), | ||
| 4569 | .static_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 4570 | // zig fmt: on | ||
| 4571 | }, | ||
| 4572 | .netbsd => switch (mode) { | ||
| 4573 | // zig fmt: off | ||
| 4574 | .dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 4575 | .dynamic_exe => result.set( "crt0.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), | ||
| 4576 | .dynamic_pie => result.set( "crt0.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 4577 | .static_exe => result.set( "crt0.o", "crti.o", "crtbeginT.o", "crtend.o", "crtn.o" ), | ||
| 4578 | .static_pie => result.set( "crt0.o", "crti.o", "crtbeginT.o", "crtendS.o", "crtn.o" ), | ||
| 4579 | // zig fmt: on | ||
| 4580 | }, | ||
| 4581 | .openbsd => switch (mode) { | ||
| 4582 | // zig fmt: off | ||
| 4583 | .dynamic_lib => result.set( null, null, "crtbeginS.o", "crtendS.o", null ), | ||
| 4584 | .dynamic_exe, | ||
| 4585 | .dynamic_pie => result.set( "crt0.o", null, "crtbegin.o", "crtend.o", null ), | ||
| 4586 | .static_exe, | ||
| 4587 | .static_pie => result.set( "rcrt0.o", null, "crtbegin.o", "crtend.o", null ), | ||
| 4588 | // zig fmt: on | ||
| 4589 | }, | ||
| 4590 | .haiku => switch (mode) { | ||
| 4591 | // zig fmt: off | ||
| 4592 | .dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 4593 | .dynamic_exe => result.set( "start_dyn.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), | ||
| 4594 | .dynamic_pie => result.set( "start_dyn.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 4595 | .static_exe => result.set( "start_dyn.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), | ||
| 4596 | .static_pie => result.set( "start_dyn.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 4597 | // zig fmt: on | ||
| 4598 | }, | ||
| 4599 | .solaris, .illumos => switch (mode) { | ||
| 4600 | // zig fmt: off | ||
| 4601 | .dynamic_lib => result.set( null, "crti.o", null, null, "crtn.o" ), | ||
| 4602 | .dynamic_exe, | ||
| 4603 | .dynamic_pie => result.set( "crt1.o", "crti.o", null, null, "crtn.o" ), | ||
| 4604 | .static_exe, | ||
| 4605 | .static_pie => result.set( null, null, null, null, null ), | ||
| 4606 | // zig fmt: on | ||
| 4607 | }, | ||
| 4608 | else => {}, | ||
| 4609 | } | ||
| 4610 | } | ||
| 4611 | |||
| 4612 | // Convert each object to a full pathname. | ||
| 4613 | if (comp.libc_installation) |lci| { | ||
| 4614 | const crt_dir_path = lci.crt_dir orelse return error.LibCInstallationMissingCRTDir; | ||
| 4615 | switch (target.os.tag) { | ||
| 4616 | .dragonfly => { | ||
| 4617 | if (result.crt0) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); | ||
| 4618 | if (result.crti) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); | ||
| 4619 | if (result.crtn) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); | ||
| 4620 | |||
| 4621 | var gccv: []const u8 = undefined; | ||
| 4622 | if (target.os.version_range.semver.isAtLeast(.{ .major = 5, .minor = 4, .patch = 0 }) orelse true) { | ||
| 4623 | gccv = "gcc80"; | ||
| 4624 | } else { | ||
| 4625 | gccv = "gcc54"; | ||
| 4626 | } | ||
| 4627 | |||
| 4628 | if (result.crtbegin) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, gccv, obj.* }); | ||
| 4629 | if (result.crtend) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, gccv, obj.* }); | ||
| 4630 | }, | ||
| 4631 | .haiku => { | ||
| 4632 | const gcc_dir_path = lci.gcc_dir orelse return error.LibCInstallationMissingCRTDir; | ||
| 4633 | if (result.crt0) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); | ||
| 4634 | if (result.crti) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); | ||
| 4635 | if (result.crtn) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); | ||
| 4636 | |||
| 4637 | if (result.crtbegin) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ gcc_dir_path, obj.* }); | ||
| 4638 | if (result.crtend) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ gcc_dir_path, obj.* }); | ||
| 4639 | }, | ||
| 4640 | else => { | ||
| 4641 | inline for (std.meta.fields(@TypeOf(result))) |f| { | ||
| 4642 | if (@field(result, f.name)) |*obj| { | ||
| 4643 | obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); | ||
| 4644 | } | ||
| 4645 | } | ||
| 4646 | }, | ||
| 4647 | } | ||
| 4648 | } else { | ||
| 4649 | inline for (std.meta.fields(@TypeOf(result))) |f| { | ||
| 4650 | if (@field(result, f.name)) |*obj| { | ||
| 4651 | if (comp.crt_files.get(obj.*)) |crtf| { | ||
| 4652 | obj.* = crtf.full_object_path; | ||
| 4653 | } else { | ||
| 4654 | @field(result, f.name) = null; | ||
| 4655 | } | ||
| 4656 | } | ||
| 4657 | } | ||
| 4658 | } | ||
| 4659 | |||
| 4660 | return result; | ||
| 4661 | } | ||
| 4662 | |||
| 4663 | fn set( | ||
| 4664 | self: *CsuObjects, | ||
| 4665 | crt0: ?[]const u8, | ||
| 4666 | crti: ?[]const u8, | ||
| 4667 | crtbegin: ?[]const u8, | ||
| 4668 | crtend: ?[]const u8, | ||
| 4669 | crtn: ?[]const u8, | ||
| 4670 | ) void { | ||
| 4671 | self.crt0 = crt0; | ||
| 4672 | self.crti = crti; | ||
| 4673 | self.crtbegin = crtbegin; | ||
| 4674 | self.crtend = crtend; | ||
| 4675 | self.crtn = crtn; | ||
| 4676 | } | ||
| 4677 | }; | ||
| 4678 | |||
| 4679 | /// If a target compiles other output modes as dynamic libraries, | 4472 | /// If a target compiles other output modes as dynamic libraries, |
| 4680 | /// this function returns true for those too. | 4473 | /// this function returns true for those too. |
| 4681 | pub fn isEffectivelyDynLib(self: Elf) bool { | 4474 | pub fn isEffectivelyDynLib(self: Elf) bool { |
| ... | @@ -5089,13 +4882,13 @@ fn reportUnsupportedCpuArch(self: *Elf) error{OutOfMemory}!void { | ... | @@ -5089,13 +4882,13 @@ fn reportUnsupportedCpuArch(self: *Elf) error{OutOfMemory}!void { |
| 5089 | 4882 | ||
| 5090 | pub fn addParseError( | 4883 | pub fn addParseError( |
| 5091 | self: *Elf, | 4884 | self: *Elf, |
| 5092 | path: []const u8, | 4885 | path: Path, |
| 5093 | comptime format: []const u8, | 4886 | comptime format: []const u8, |
| 5094 | args: anytype, | 4887 | args: anytype, |
| 5095 | ) error{OutOfMemory}!void { | 4888 | ) error{OutOfMemory}!void { |
| 5096 | var err = try self.base.addErrorWithNotes(1); | 4889 | var err = try self.base.addErrorWithNotes(1); |
| 5097 | try err.addMsg(format, args); | 4890 | try err.addMsg(format, args); |
| 5098 | try err.addNote("while parsing {s}", .{path}); | 4891 | try err.addNote("while parsing {}", .{path}); |
| 5099 | } | 4892 | } |
| 5100 | 4893 | ||
| 5101 | pub fn addFileError( | 4894 | pub fn addFileError( |
| ... | @@ -5121,7 +4914,7 @@ pub fn failFile( | ... | @@ -5121,7 +4914,7 @@ pub fn failFile( |
| 5121 | 4914 | ||
| 5122 | pub fn failParse( | 4915 | pub fn failParse( |
| 5123 | self: *Elf, | 4916 | self: *Elf, |
| 5124 | path: []const u8, | 4917 | path: Path, |
| 5125 | comptime format: []const u8, | 4918 | comptime format: []const u8, |
| 5126 | args: anytype, | 4919 | args: anytype, |
| 5127 | ) error{ OutOfMemory, LinkFailure } { | 4920 | ) error{ OutOfMemory, LinkFailure } { |
| ... | @@ -5274,7 +5067,7 @@ fn fmtDumpState( | ... | @@ -5274,7 +5067,7 @@ fn fmtDumpState( |
| 5274 | _ = options; | 5067 | _ = options; |
| 5275 | 5068 | ||
| 5276 | if (self.zigObjectPtr()) |zig_object| { | 5069 | if (self.zigObjectPtr()) |zig_object| { |
| 5277 | try writer.print("zig_object({d}) : {s}\n", .{ zig_object.index, zig_object.path }); | 5070 | try writer.print("zig_object({d}) : {s}\n", .{ zig_object.index, zig_object.basename }); |
| 5278 | try writer.print("{}{}", .{ | 5071 | try writer.print("{}{}", .{ |
| 5279 | zig_object.fmtAtoms(self), | 5072 | zig_object.fmtAtoms(self), |
| 5280 | zig_object.fmtSymtab(self), | 5073 | zig_object.fmtSymtab(self), |
| ... | @@ -5299,7 +5092,7 @@ fn fmtDumpState( | ... | @@ -5299,7 +5092,7 @@ fn fmtDumpState( |
| 5299 | for (self.shared_objects.items) |index| { | 5092 | for (self.shared_objects.items) |index| { |
| 5300 | const shared_object = self.file(index).?.shared_object; | 5093 | const shared_object = self.file(index).?.shared_object; |
| 5301 | try writer.print("shared_object({d}) : ", .{index}); | 5094 | try writer.print("shared_object({d}) : ", .{index}); |
| 5302 | try writer.print("{s}", .{shared_object.path}); | 5095 | try writer.print("{}", .{shared_object.path}); |
| 5303 | try writer.print(" : needed({})", .{shared_object.needed}); | 5096 | try writer.print(" : needed({})", .{shared_object.needed}); |
| 5304 | if (!shared_object.alive) try writer.writeAll(" : [*]"); | 5097 | if (!shared_object.alive) try writer.writeAll(" : [*]"); |
| 5305 | try writer.writeByte('\n'); | 5098 | try writer.writeByte('\n'); |
| ... | @@ -5482,7 +5275,7 @@ pub const null_shdr = elf.Elf64_Shdr{ | ... | @@ -5482,7 +5275,7 @@ pub const null_shdr = elf.Elf64_Shdr{ |
| 5482 | 5275 | ||
| 5483 | pub const SystemLib = struct { | 5276 | pub const SystemLib = struct { |
| 5484 | needed: bool = false, | 5277 | needed: bool = false, |
| 5485 | path: []const u8, | 5278 | path: Path, |
| 5486 | }; | 5279 | }; |
| 5487 | 5280 | ||
| 5488 | pub const Ref = struct { | 5281 | pub const Ref = struct { |
src/link/Elf/Archive.zig+13-7| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | objects: std.ArrayListUnmanaged(Object) = .empty, | 1 | objects: std.ArrayListUnmanaged(Object) = .empty, |
| 2 | strtab: std.ArrayListUnmanaged(u8) = .empty, | 2 | strtab: std.ArrayListUnmanaged(u8) = .empty, |
| 3 | 3 | ||
| 4 | pub fn isArchive(path: []const u8) !bool { | 4 | pub fn isArchive(path: Path) !bool { |
| 5 | const file = try std.fs.cwd().openFile(path, .{}); | 5 | const file = try path.root_dir.handle.openFile(path.sub_path, .{}); |
| 6 | defer file.close(); | 6 | defer file.close(); |
| 7 | const reader = file.reader(); | 7 | const reader = file.reader(); |
| 8 | const magic = reader.readBytesNoEof(elf.ARMAG.len) catch return false; | 8 | const magic = reader.readBytesNoEof(elf.ARMAG.len) catch return false; |
| ... | @@ -15,7 +15,7 @@ pub fn deinit(self: *Archive, allocator: Allocator) void { | ... | @@ -15,7 +15,7 @@ pub fn deinit(self: *Archive, allocator: Allocator) void { |
| 15 | self.strtab.deinit(allocator); | 15 | self.strtab.deinit(allocator); |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | pub fn parse(self: *Archive, elf_file: *Elf, path: []const u8, handle_index: File.HandleIndex) !void { | 18 | pub fn parse(self: *Archive, elf_file: *Elf, path: Path, handle_index: File.HandleIndex) !void { |
| 19 | const comp = elf_file.base.comp; | 19 | const comp = elf_file.base.comp; |
| 20 | const gpa = comp.gpa; | 20 | const gpa = comp.gpa; |
| 21 | const handle = elf_file.fileHandle(handle_index); | 21 | const handle = elf_file.fileHandle(handle_index); |
| ... | @@ -59,19 +59,24 @@ pub fn parse(self: *Archive, elf_file: *Elf, path: []const u8, handle_index: Fil | ... | @@ -59,19 +59,24 @@ pub fn parse(self: *Archive, elf_file: *Elf, path: []const u8, handle_index: Fil |
| 59 | else | 59 | else |
| 60 | unreachable; | 60 | unreachable; |
| 61 | 61 | ||
| 62 | const object = Object{ | 62 | const object: Object = .{ |
| 63 | .archive = .{ | 63 | .archive = .{ |
| 64 | .path = try gpa.dupe(u8, path), | 64 | .path = .{ |
| 65 | .root_dir = path.root_dir, | ||
| 66 | .sub_path = try gpa.dupe(u8, path.sub_path), | ||
| 67 | }, | ||
| 65 | .offset = pos, | 68 | .offset = pos, |
| 66 | .size = obj_size, | 69 | .size = obj_size, |
| 67 | }, | 70 | }, |
| 68 | .path = try gpa.dupe(u8, name), | 71 | .path = Path.initCwd(try gpa.dupe(u8, name)), |
| 69 | .file_handle = handle_index, | 72 | .file_handle = handle_index, |
| 70 | .index = undefined, | 73 | .index = undefined, |
| 71 | .alive = false, | 74 | .alive = false, |
| 72 | }; | 75 | }; |
| 73 | 76 | ||
| 74 | log.debug("extracting object '{s}' from archive '{s}'", .{ object.path, path }); | 77 | log.debug("extracting object '{}' from archive '{}'", .{ |
| 78 | @as(Path, object.path), @as(Path, path), | ||
| 79 | }); | ||
| 75 | 80 | ||
| 76 | try self.objects.append(gpa, object); | 81 | try self.objects.append(gpa, object); |
| 77 | } | 82 | } |
| ... | @@ -292,6 +297,7 @@ const elf = std.elf; | ... | @@ -292,6 +297,7 @@ const elf = std.elf; |
| 292 | const fs = std.fs; | 297 | const fs = std.fs; |
| 293 | const log = std.log.scoped(.link); | 298 | const log = std.log.scoped(.link); |
| 294 | const mem = std.mem; | 299 | const mem = std.mem; |
| 300 | const Path = std.Build.Cache.Path; | ||
| 295 | 301 | ||
| 296 | const Allocator = mem.Allocator; | 302 | const Allocator = mem.Allocator; |
| 297 | const Archive = @This(); | 303 | const Archive = @This(); |
src/link/Elf/LdScript.zig+16-10| ... | @@ -1,6 +1,11 @@ | ... | @@ -1,6 +1,11 @@ |
| 1 | path: []const u8, | 1 | path: Path, |
| 2 | cpu_arch: ?std.Target.Cpu.Arch = null, | 2 | cpu_arch: ?std.Target.Cpu.Arch = null, |
| 3 | args: std.ArrayListUnmanaged(Elf.SystemLib) = .empty, | 3 | args: std.ArrayListUnmanaged(Arg) = .empty, |
| 4 | |||
| 5 | pub const Arg = struct { | ||
| 6 | needed: bool = false, | ||
| 7 | path: []const u8, | ||
| 8 | }; | ||
| 4 | 9 | ||
| 5 | pub fn deinit(scr: *LdScript, allocator: Allocator) void { | 10 | pub fn deinit(scr: *LdScript, allocator: Allocator) void { |
| 6 | scr.args.deinit(allocator); | 11 | scr.args.deinit(allocator); |
| ... | @@ -47,7 +52,7 @@ pub fn parse(scr: *LdScript, data: []const u8, elf_file: *Elf) Error!void { | ... | @@ -47,7 +52,7 @@ pub fn parse(scr: *LdScript, data: []const u8, elf_file: *Elf) Error!void { |
| 47 | 52 | ||
| 48 | var it = TokenIterator{ .tokens = tokens.items }; | 53 | var it = TokenIterator{ .tokens = tokens.items }; |
| 49 | var parser = Parser{ .source = data, .it = &it }; | 54 | var parser = Parser{ .source = data, .it = &it }; |
| 50 | var args = std.ArrayList(Elf.SystemLib).init(gpa); | 55 | var args = std.ArrayList(Arg).init(gpa); |
| 51 | scr.doParse(.{ | 56 | scr.doParse(.{ |
| 52 | .parser = &parser, | 57 | .parser = &parser, |
| 53 | .args = &args, | 58 | .args = &args, |
| ... | @@ -70,7 +75,7 @@ pub fn parse(scr: *LdScript, data: []const u8, elf_file: *Elf) Error!void { | ... | @@ -70,7 +75,7 @@ pub fn parse(scr: *LdScript, data: []const u8, elf_file: *Elf) Error!void { |
| 70 | 75 | ||
| 71 | fn doParse(scr: *LdScript, ctx: struct { | 76 | fn doParse(scr: *LdScript, ctx: struct { |
| 72 | parser: *Parser, | 77 | parser: *Parser, |
| 73 | args: *std.ArrayList(Elf.SystemLib), | 78 | args: *std.ArrayList(Arg), |
| 74 | }) !void { | 79 | }) !void { |
| 75 | while (true) { | 80 | while (true) { |
| 76 | ctx.parser.skipAny(&.{ .comment, .new_line }); | 81 | ctx.parser.skipAny(&.{ .comment, .new_line }); |
| ... | @@ -142,7 +147,7 @@ const Parser = struct { | ... | @@ -142,7 +147,7 @@ const Parser = struct { |
| 142 | return error.UnknownCpuArch; | 147 | return error.UnknownCpuArch; |
| 143 | } | 148 | } |
| 144 | 149 | ||
| 145 | fn group(p: *Parser, args: *std.ArrayList(Elf.SystemLib)) !void { | 150 | fn group(p: *Parser, args: *std.ArrayList(Arg)) !void { |
| 146 | if (!p.skip(&.{.lparen})) return error.UnexpectedToken; | 151 | if (!p.skip(&.{.lparen})) return error.UnexpectedToken; |
| 147 | 152 | ||
| 148 | while (true) { | 153 | while (true) { |
| ... | @@ -162,7 +167,7 @@ const Parser = struct { | ... | @@ -162,7 +167,7 @@ const Parser = struct { |
| 162 | _ = try p.require(.rparen); | 167 | _ = try p.require(.rparen); |
| 163 | } | 168 | } |
| 164 | 169 | ||
| 165 | fn asNeeded(p: *Parser, args: *std.ArrayList(Elf.SystemLib)) !void { | 170 | fn asNeeded(p: *Parser, args: *std.ArrayList(Arg)) !void { |
| 166 | if (!p.skip(&.{.lparen})) return error.UnexpectedToken; | 171 | if (!p.skip(&.{.lparen})) return error.UnexpectedToken; |
| 167 | 172 | ||
| 168 | while (p.maybe(.literal)) |tok_id| { | 173 | while (p.maybe(.literal)) |tok_id| { |
| ... | @@ -239,7 +244,7 @@ const Token = struct { | ... | @@ -239,7 +244,7 @@ const Token = struct { |
| 239 | 244 | ||
| 240 | const Index = usize; | 245 | const Index = usize; |
| 241 | 246 | ||
| 242 | inline fn get(tok: Token, source: []const u8) []const u8 { | 247 | fn get(tok: Token, source: []const u8) []const u8 { |
| 243 | return source[tok.start..tok.end]; | 248 | return source[tok.start..tok.end]; |
| 244 | } | 249 | } |
| 245 | }; | 250 | }; |
| ... | @@ -399,11 +404,11 @@ const TokenIterator = struct { | ... | @@ -399,11 +404,11 @@ const TokenIterator = struct { |
| 399 | return it.tokens[it.pos]; | 404 | return it.tokens[it.pos]; |
| 400 | } | 405 | } |
| 401 | 406 | ||
| 402 | inline fn reset(it: *TokenIterator) void { | 407 | fn reset(it: *TokenIterator) void { |
| 403 | it.pos = 0; | 408 | it.pos = 0; |
| 404 | } | 409 | } |
| 405 | 410 | ||
| 406 | inline fn seekTo(it: *TokenIterator, pos: Token.Index) void { | 411 | fn seekTo(it: *TokenIterator, pos: Token.Index) void { |
| 407 | it.pos = pos; | 412 | it.pos = pos; |
| 408 | } | 413 | } |
| 409 | 414 | ||
| ... | @@ -416,7 +421,7 @@ const TokenIterator = struct { | ... | @@ -416,7 +421,7 @@ const TokenIterator = struct { |
| 416 | } | 421 | } |
| 417 | } | 422 | } |
| 418 | 423 | ||
| 419 | inline fn get(it: *TokenIterator, pos: Token.Index) Token { | 424 | fn get(it: *TokenIterator, pos: Token.Index) Token { |
| 420 | assert(pos < it.tokens.len); | 425 | assert(pos < it.tokens.len); |
| 421 | return it.tokens[pos]; | 426 | return it.tokens[pos]; |
| 422 | } | 427 | } |
| ... | @@ -426,6 +431,7 @@ const LdScript = @This(); | ... | @@ -426,6 +431,7 @@ const LdScript = @This(); |
| 426 | 431 | ||
| 427 | const std = @import("std"); | 432 | const std = @import("std"); |
| 428 | const assert = std.debug.assert; | 433 | const assert = std.debug.assert; |
| 434 | const Path = std.Build.Cache.Path; | ||
| 429 | 435 | ||
| 430 | const Allocator = std.mem.Allocator; | 436 | const Allocator = std.mem.Allocator; |
| 431 | const Elf = @import("../Elf.zig"); | 437 | const Elf = @import("../Elf.zig"); |
src/link/Elf/Object.zig+14-13| ... | @@ -1,5 +1,7 @@ | ... | @@ -1,5 +1,7 @@ |
| 1 | archive: ?InArchive = null, | 1 | archive: ?InArchive = null, |
| 2 | path: []const u8, | 2 | /// Archive files cannot contain subdirectories, so only the basename is needed |
| 3 | /// for output. However, the full path is kept for error reporting. | ||
| 4 | path: Path, | ||
| 3 | file_handle: File.HandleIndex, | 5 | file_handle: File.HandleIndex, |
| 4 | index: File.Index, | 6 | index: File.Index, |
| 5 | 7 | ||
| ... | @@ -36,8 +38,8 @@ output_symtab_ctx: Elf.SymtabCtx = .{}, | ... | @@ -36,8 +38,8 @@ output_symtab_ctx: Elf.SymtabCtx = .{}, |
| 36 | output_ar_state: Archive.ArState = .{}, | 38 | output_ar_state: Archive.ArState = .{}, |
| 37 | 39 | ||
| 38 | pub fn deinit(self: *Object, allocator: Allocator) void { | 40 | pub fn deinit(self: *Object, allocator: Allocator) void { |
| 39 | if (self.archive) |*ar| allocator.free(ar.path); | 41 | if (self.archive) |*ar| allocator.free(ar.path.sub_path); |
| 40 | allocator.free(self.path); | 42 | allocator.free(self.path.sub_path); |
| 41 | self.shdrs.deinit(allocator); | 43 | self.shdrs.deinit(allocator); |
| 42 | self.symtab.deinit(allocator); | 44 | self.symtab.deinit(allocator); |
| 43 | self.strtab.deinit(allocator); | 45 | self.strtab.deinit(allocator); |
| ... | @@ -474,8 +476,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void { | ... | @@ -474,8 +476,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void { |
| 474 | if (sym.type(elf_file) != elf.STT_FUNC) | 476 | if (sym.type(elf_file) != elf.STT_FUNC) |
| 475 | // TODO convert into an error | 477 | // TODO convert into an error |
| 476 | log.debug("{s}: {s}: CIE referencing external data reference", .{ | 478 | log.debug("{s}: {s}: CIE referencing external data reference", .{ |
| 477 | self.fmtPath(), | 479 | self.fmtPath(), sym.name(elf_file), |
| 478 | sym.name(elf_file), | ||
| 479 | }); | 480 | }); |
| 480 | sym.flags.needs_plt = true; | 481 | sym.flags.needs_plt = true; |
| 481 | } | 482 | } |
| ... | @@ -996,7 +997,7 @@ pub fn updateArSize(self: *Object, elf_file: *Elf) !void { | ... | @@ -996,7 +997,7 @@ pub fn updateArSize(self: *Object, elf_file: *Elf) !void { |
| 996 | pub fn writeAr(self: Object, elf_file: *Elf, writer: anytype) !void { | 997 | pub fn writeAr(self: Object, elf_file: *Elf, writer: anytype) !void { |
| 997 | const size = std.math.cast(usize, self.output_ar_state.size) orelse return error.Overflow; | 998 | const size = std.math.cast(usize, self.output_ar_state.size) orelse return error.Overflow; |
| 998 | const offset: u64 = if (self.archive) |ar| ar.offset else 0; | 999 | const offset: u64 = if (self.archive) |ar| ar.offset else 0; |
| 999 | const name = self.path; | 1000 | const name = std.fs.path.basename(self.path.sub_path); |
| 1000 | const hdr = Archive.setArHdr(.{ | 1001 | const hdr = Archive.setArHdr(.{ |
| 1001 | .name = if (name.len <= Archive.max_member_name_len) | 1002 | .name = if (name.len <= Archive.max_member_name_len) |
| 1002 | .{ .name = name } | 1003 | .{ .name = name } |
| ... | @@ -1489,15 +1490,14 @@ fn formatPath( | ... | @@ -1489,15 +1490,14 @@ fn formatPath( |
| 1489 | _ = unused_fmt_string; | 1490 | _ = unused_fmt_string; |
| 1490 | _ = options; | 1491 | _ = options; |
| 1491 | if (object.archive) |ar| { | 1492 | if (object.archive) |ar| { |
| 1492 | try writer.writeAll(ar.path); | 1493 | try writer.print("{}({})", .{ ar.path, object.path }); |
| 1493 | try writer.writeByte('('); | 1494 | } else { |
| 1494 | try writer.writeAll(object.path); | 1495 | try writer.print("{}", .{object.path}); |
| 1495 | try writer.writeByte(')'); | 1496 | } |
| 1496 | } else try writer.writeAll(object.path); | ||
| 1497 | } | 1497 | } |
| 1498 | 1498 | ||
| 1499 | const InArchive = struct { | 1499 | const InArchive = struct { |
| 1500 | path: []const u8, | 1500 | path: Path, |
| 1501 | offset: u64, | 1501 | offset: u64, |
| 1502 | size: u32, | 1502 | size: u32, |
| 1503 | }; | 1503 | }; |
| ... | @@ -1512,8 +1512,9 @@ const fs = std.fs; | ... | @@ -1512,8 +1512,9 @@ const fs = std.fs; |
| 1512 | const log = std.log.scoped(.link); | 1512 | const log = std.log.scoped(.link); |
| 1513 | const math = std.math; | 1513 | const math = std.math; |
| 1514 | const mem = std.mem; | 1514 | const mem = std.mem; |
| 1515 | 1515 | const Path = std.Build.Cache.Path; | |
| 1516 | const Allocator = mem.Allocator; | 1516 | const Allocator = mem.Allocator; |
| 1517 | |||
| 1517 | const Archive = @import("Archive.zig"); | 1518 | const Archive = @import("Archive.zig"); |
| 1518 | const Atom = @import("Atom.zig"); | 1519 | const Atom = @import("Atom.zig"); |
| 1519 | const AtomList = @import("AtomList.zig"); | 1520 | const AtomList = @import("AtomList.zig"); |
src/link/Elf/SharedObject.zig+8-7| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | path: []const u8, | 1 | path: Path, |
| 2 | index: File.Index, | 2 | index: File.Index, |
| 3 | 3 | ||
| 4 | header: ?elf.Elf64_Ehdr = null, | 4 | header: ?elf.Elf64_Ehdr = null, |
| ... | @@ -22,8 +22,8 @@ alive: bool, | ... | @@ -22,8 +22,8 @@ alive: bool, |
| 22 | 22 | ||
| 23 | output_symtab_ctx: Elf.SymtabCtx = .{}, | 23 | output_symtab_ctx: Elf.SymtabCtx = .{}, |
| 24 | 24 | ||
| 25 | pub fn isSharedObject(path: []const u8) !bool { | 25 | pub fn isSharedObject(path: Path) !bool { |
| 26 | const file = try std.fs.cwd().openFile(path, .{}); | 26 | const file = try path.root_dir.handle.openFile(path.sub_path, .{}); |
| 27 | defer file.close(); | 27 | defer file.close(); |
| 28 | const reader = file.reader(); | 28 | const reader = file.reader(); |
| 29 | const header = reader.readStruct(elf.Elf64_Ehdr) catch return false; | 29 | const header = reader.readStruct(elf.Elf64_Ehdr) catch return false; |
| ... | @@ -34,7 +34,7 @@ pub fn isSharedObject(path: []const u8) !bool { | ... | @@ -34,7 +34,7 @@ pub fn isSharedObject(path: []const u8) !bool { |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | pub fn deinit(self: *SharedObject, allocator: Allocator) void { | 36 | pub fn deinit(self: *SharedObject, allocator: Allocator) void { |
| 37 | allocator.free(self.path); | 37 | allocator.free(self.path.sub_path); |
| 38 | self.shdrs.deinit(allocator); | 38 | self.shdrs.deinit(allocator); |
| 39 | self.symtab.deinit(allocator); | 39 | self.symtab.deinit(allocator); |
| 40 | self.strtab.deinit(allocator); | 40 | self.strtab.deinit(allocator); |
| ... | @@ -319,7 +319,7 @@ pub fn asFile(self: *SharedObject) File { | ... | @@ -319,7 +319,7 @@ pub fn asFile(self: *SharedObject) File { |
| 319 | 319 | ||
| 320 | fn verdefNum(self: *SharedObject) u32 { | 320 | fn verdefNum(self: *SharedObject) u32 { |
| 321 | for (self.dynamic_table.items) |entry| switch (entry.d_tag) { | 321 | for (self.dynamic_table.items) |entry| switch (entry.d_tag) { |
| 322 | elf.DT_VERDEFNUM => return @as(u32, @intCast(entry.d_val)), | 322 | elf.DT_VERDEFNUM => return @intCast(entry.d_val), |
| 323 | else => {}, | 323 | else => {}, |
| 324 | }; | 324 | }; |
| 325 | return 0; | 325 | return 0; |
| ... | @@ -327,10 +327,10 @@ fn verdefNum(self: *SharedObject) u32 { | ... | @@ -327,10 +327,10 @@ fn verdefNum(self: *SharedObject) u32 { |
| 327 | 327 | ||
| 328 | pub fn soname(self: *SharedObject) []const u8 { | 328 | pub fn soname(self: *SharedObject) []const u8 { |
| 329 | for (self.dynamic_table.items) |entry| switch (entry.d_tag) { | 329 | for (self.dynamic_table.items) |entry| switch (entry.d_tag) { |
| 330 | elf.DT_SONAME => return self.getString(@as(u32, @intCast(entry.d_val))), | 330 | elf.DT_SONAME => return self.getString(@intCast(entry.d_val)), |
| 331 | else => {}, | 331 | else => {}, |
| 332 | }; | 332 | }; |
| 333 | return std.fs.path.basename(self.path); | 333 | return std.fs.path.basename(self.path.sub_path); |
| 334 | } | 334 | } |
| 335 | 335 | ||
| 336 | pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void { | 336 | pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void { |
| ... | @@ -508,6 +508,7 @@ const assert = std.debug.assert; | ... | @@ -508,6 +508,7 @@ const assert = std.debug.assert; |
| 508 | const elf = std.elf; | 508 | const elf = std.elf; |
| 509 | const log = std.log.scoped(.elf); | 509 | const log = std.log.scoped(.elf); |
| 510 | const mem = std.mem; | 510 | const mem = std.mem; |
| 511 | const Path = std.Build.Cache.Path; | ||
| 511 | 512 | ||
| 512 | const Allocator = mem.Allocator; | 513 | const Allocator = mem.Allocator; |
| 513 | const Elf = @import("../Elf.zig"); | 514 | const Elf = @import("../Elf.zig"); |
src/link/Elf/ZigObject.zig+4-4| ... | @@ -5,7 +5,7 @@ | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | ||
| 6 | data: std.ArrayListUnmanaged(u8) = .empty, | 6 | data: std.ArrayListUnmanaged(u8) = .empty, |
| 7 | /// Externally owned memory. | 7 | /// Externally owned memory. |
| 8 | path: []const u8, | 8 | basename: []const u8, |
| 9 | index: File.Index, | 9 | index: File.Index, |
| 10 | 10 | ||
| 11 | symtab: std.MultiArrayList(ElfSym) = .{}, | 11 | symtab: std.MultiArrayList(ElfSym) = .{}, |
| ... | @@ -88,7 +88,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { | ... | @@ -88,7 +88,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { |
| 88 | try self.strtab.buffer.append(gpa, 0); | 88 | try self.strtab.buffer.append(gpa, 0); |
| 89 | 89 | ||
| 90 | { | 90 | { |
| 91 | const name_off = try self.strtab.insert(gpa, self.path); | 91 | const name_off = try self.strtab.insert(gpa, self.basename); |
| 92 | const symbol_index = try self.newLocalSymbol(gpa, name_off); | 92 | const symbol_index = try self.newLocalSymbol(gpa, name_off); |
| 93 | const sym = self.symbol(symbol_index); | 93 | const sym = self.symbol(symbol_index); |
| 94 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; | 94 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; |
| ... | @@ -774,7 +774,7 @@ pub fn updateArSize(self: *ZigObject) void { | ... | @@ -774,7 +774,7 @@ pub fn updateArSize(self: *ZigObject) void { |
| 774 | } | 774 | } |
| 775 | 775 | ||
| 776 | pub fn writeAr(self: ZigObject, writer: anytype) !void { | 776 | pub fn writeAr(self: ZigObject, writer: anytype) !void { |
| 777 | const name = self.path; | 777 | const name = self.basename; |
| 778 | const hdr = Archive.setArHdr(.{ | 778 | const hdr = Archive.setArHdr(.{ |
| 779 | .name = if (name.len <= Archive.max_member_name_len) | 779 | .name = if (name.len <= Archive.max_member_name_len) |
| 780 | .{ .name = name } | 780 | .{ .name = name } |
| ... | @@ -2384,9 +2384,9 @@ const relocation = @import("relocation.zig"); | ... | @@ -2384,9 +2384,9 @@ const relocation = @import("relocation.zig"); |
| 2384 | const target_util = @import("../../target.zig"); | 2384 | const target_util = @import("../../target.zig"); |
| 2385 | const trace = @import("../../tracy.zig").trace; | 2385 | const trace = @import("../../tracy.zig").trace; |
| 2386 | const std = @import("std"); | 2386 | const std = @import("std"); |
| 2387 | const Allocator = std.mem.Allocator; | ||
| 2387 | 2388 | ||
| 2388 | const Air = @import("../../Air.zig"); | 2389 | const Air = @import("../../Air.zig"); |
| 2389 | const Allocator = std.mem.Allocator; | ||
| 2390 | const Archive = @import("Archive.zig"); | 2390 | const Archive = @import("Archive.zig"); |
| 2391 | const Atom = @import("Atom.zig"); | 2391 | const Atom = @import("Atom.zig"); |
| 2392 | const Dwarf = @import("../Dwarf.zig"); | 2392 | const Dwarf = @import("../Dwarf.zig"); |
src/link/Elf/file.zig+20-18| ... | @@ -23,10 +23,10 @@ pub const File = union(enum) { | ... | @@ -23,10 +23,10 @@ pub const File = union(enum) { |
| 23 | _ = unused_fmt_string; | 23 | _ = unused_fmt_string; |
| 24 | _ = options; | 24 | _ = options; |
| 25 | switch (file) { | 25 | switch (file) { |
| 26 | .zig_object => |x| try writer.print("{s}", .{x.path}), | 26 | .zig_object => |zo| try writer.writeAll(zo.basename), |
| 27 | .linker_defined => try writer.writeAll("(linker defined)"), | 27 | .linker_defined => try writer.writeAll("(linker defined)"), |
| 28 | .object => |x| try writer.print("{}", .{x.fmtPath()}), | 28 | .object => |x| try writer.print("{}", .{x.fmtPath()}), |
| 29 | .shared_object => |x| try writer.writeAll(x.path), | 29 | .shared_object => |x| try writer.print("{}", .{@as(Path, x.path)}), |
| 30 | } | 30 | } |
| 31 | } | 31 | } |
| 32 | 32 | ||
| ... | @@ -240,30 +240,31 @@ pub const File = union(enum) { | ... | @@ -240,30 +240,31 @@ pub const File = union(enum) { |
| 240 | return switch (file) { | 240 | return switch (file) { |
| 241 | .zig_object => |x| x.updateArSymtab(ar_symtab, elf_file), | 241 | .zig_object => |x| x.updateArSymtab(ar_symtab, elf_file), |
| 242 | .object => |x| x.updateArSymtab(ar_symtab, elf_file), | 242 | .object => |x| x.updateArSymtab(ar_symtab, elf_file), |
| 243 | inline else => unreachable, | 243 | else => unreachable, |
| 244 | }; | 244 | }; |
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | pub fn updateArStrtab(file: File, allocator: Allocator, ar_strtab: *Archive.ArStrtab) !void { | 247 | pub fn updateArStrtab(file: File, allocator: Allocator, ar_strtab: *Archive.ArStrtab) !void { |
| 248 | const path = switch (file) { | 248 | switch (file) { |
| 249 | .zig_object => |x| x.path, | 249 | .zig_object => |zo| { |
| 250 | .object => |x| x.path, | 250 | const basename = zo.basename; |
| 251 | inline else => unreachable, | 251 | if (basename.len <= Archive.max_member_name_len) return; |
| 252 | }; | 252 | zo.output_ar_state.name_off = try ar_strtab.insert(allocator, basename); |
| 253 | const state = switch (file) { | 253 | }, |
| 254 | .zig_object => |x| &x.output_ar_state, | 254 | .object => |o| { |
| 255 | .object => |x| &x.output_ar_state, | 255 | const basename = std.fs.path.basename(o.path.sub_path); |
| 256 | inline else => unreachable, | 256 | if (basename.len <= Archive.max_member_name_len) return; |
| 257 | }; | 257 | o.output_ar_state.name_off = try ar_strtab.insert(allocator, basename); |
| 258 | if (path.len <= Archive.max_member_name_len) return; | 258 | }, |
| 259 | state.name_off = try ar_strtab.insert(allocator, path); | 259 | else => unreachable, |
| 260 | } | ||
| 260 | } | 261 | } |
| 261 | 262 | ||
| 262 | pub fn updateArSize(file: File, elf_file: *Elf) !void { | 263 | pub fn updateArSize(file: File, elf_file: *Elf) !void { |
| 263 | return switch (file) { | 264 | return switch (file) { |
| 264 | .zig_object => |x| x.updateArSize(), | 265 | .zig_object => |x| x.updateArSize(), |
| 265 | .object => |x| x.updateArSize(elf_file), | 266 | .object => |x| x.updateArSize(elf_file), |
| 266 | inline else => unreachable, | 267 | else => unreachable, |
| 267 | }; | 268 | }; |
| 268 | } | 269 | } |
| 269 | 270 | ||
| ... | @@ -271,7 +272,7 @@ pub const File = union(enum) { | ... | @@ -271,7 +272,7 @@ pub const File = union(enum) { |
| 271 | return switch (file) { | 272 | return switch (file) { |
| 272 | .zig_object => |x| x.writeAr(writer), | 273 | .zig_object => |x| x.writeAr(writer), |
| 273 | .object => |x| x.writeAr(elf_file, writer), | 274 | .object => |x| x.writeAr(elf_file, writer), |
| 274 | inline else => unreachable, | 275 | else => unreachable, |
| 275 | }; | 276 | }; |
| 276 | } | 277 | } |
| 277 | 278 | ||
| ... | @@ -292,8 +293,9 @@ pub const File = union(enum) { | ... | @@ -292,8 +293,9 @@ pub const File = union(enum) { |
| 292 | const std = @import("std"); | 293 | const std = @import("std"); |
| 293 | const elf = std.elf; | 294 | const elf = std.elf; |
| 294 | const log = std.log.scoped(.link); | 295 | const log = std.log.scoped(.link); |
| 295 | 296 | const Path = std.Build.Cache.Path; | |
| 296 | const Allocator = std.mem.Allocator; | 297 | const Allocator = std.mem.Allocator; |
| 298 | |||
| 297 | const Archive = @import("Archive.zig"); | 299 | const Archive = @import("Archive.zig"); |
| 298 | const Atom = @import("Atom.zig"); | 300 | const Atom = @import("Atom.zig"); |
| 299 | const Cie = @import("eh_frame.zig").Cie; | 301 | const Cie = @import("eh_frame.zig").Cie; |
src/link/Elf/relocatable.zig+15-11| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { | 1 | pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path) link.File.FlushError!void { |
| 2 | const gpa = comp.gpa; | 2 | const gpa = comp.gpa; |
| 3 | 3 | ||
| 4 | for (comp.objects) |obj| { | 4 | for (comp.objects) |obj| { |
| 5 | switch (Compilation.classifyFileExt(obj.path)) { | 5 | switch (Compilation.classifyFileExt(obj.path.sub_path)) { |
| 6 | .object => try parseObjectStaticLibReportingFailure(elf_file, obj.path), | 6 | .object => try parseObjectStaticLibReportingFailure(elf_file, obj.path), |
| 7 | .static_library => try parseArchiveStaticLibReportingFailure(elf_file, obj.path), | 7 | .static_library => try parseArchiveStaticLibReportingFailure(elf_file, obj.path), |
| 8 | else => try elf_file.addParseError(obj.path, "unrecognized file extension", .{}), | 8 | else => try elf_file.addParseError(obj.path, "unrecognized file extension", .{}), |
| ... | @@ -140,7 +140,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co | ... | @@ -140,7 +140,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co |
| 140 | if (elf_file.base.hasErrors()) return error.FlushFailure; | 140 | if (elf_file.base.hasErrors()) return error.FlushFailure; |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { | 143 | pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path) link.File.FlushError!void { |
| 144 | for (comp.objects) |obj| { | 144 | for (comp.objects) |obj| { |
| 145 | if (obj.isObject()) { | 145 | if (obj.isObject()) { |
| 146 | try elf_file.parseObjectReportingFailure(obj.path); | 146 | try elf_file.parseObjectReportingFailure(obj.path); |
| ... | @@ -198,7 +198,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const | ... | @@ -198,7 +198,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 198 | if (elf_file.base.hasErrors()) return error.FlushFailure; | 198 | if (elf_file.base.hasErrors()) return error.FlushFailure; |
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | fn parseObjectStaticLibReportingFailure(elf_file: *Elf, path: []const u8) error{OutOfMemory}!void { | 201 | fn parseObjectStaticLibReportingFailure(elf_file: *Elf, path: Path) error{OutOfMemory}!void { |
| 202 | parseObjectStaticLib(elf_file, path) catch |err| switch (err) { | 202 | parseObjectStaticLib(elf_file, path) catch |err| switch (err) { |
| 203 | error.LinkFailure => return, | 203 | error.LinkFailure => return, |
| 204 | error.OutOfMemory => return error.OutOfMemory, | 204 | error.OutOfMemory => return error.OutOfMemory, |
| ... | @@ -206,7 +206,7 @@ fn parseObjectStaticLibReportingFailure(elf_file: *Elf, path: []const u8) error{ | ... | @@ -206,7 +206,7 @@ fn parseObjectStaticLibReportingFailure(elf_file: *Elf, path: []const u8) error{ |
| 206 | }; | 206 | }; |
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | fn parseArchiveStaticLibReportingFailure(elf_file: *Elf, path: []const u8) error{OutOfMemory}!void { | 209 | fn parseArchiveStaticLibReportingFailure(elf_file: *Elf, path: Path) error{OutOfMemory}!void { |
| 210 | parseArchiveStaticLib(elf_file, path) catch |err| switch (err) { | 210 | parseArchiveStaticLib(elf_file, path) catch |err| switch (err) { |
| 211 | error.LinkFailure => return, | 211 | error.LinkFailure => return, |
| 212 | error.OutOfMemory => return error.OutOfMemory, | 212 | error.OutOfMemory => return error.OutOfMemory, |
| ... | @@ -214,14 +214,17 @@ fn parseArchiveStaticLibReportingFailure(elf_file: *Elf, path: []const u8) error | ... | @@ -214,14 +214,17 @@ fn parseArchiveStaticLibReportingFailure(elf_file: *Elf, path: []const u8) error |
| 214 | }; | 214 | }; |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | fn parseObjectStaticLib(elf_file: *Elf, path: []const u8) Elf.ParseError!void { | 217 | fn parseObjectStaticLib(elf_file: *Elf, path: Path) Elf.ParseError!void { |
| 218 | const gpa = elf_file.base.comp.gpa; | 218 | const gpa = elf_file.base.comp.gpa; |
| 219 | const handle = try std.fs.cwd().openFile(path, .{}); | 219 | const handle = try path.root_dir.handle.openFile(path.sub_path, .{}); |
| 220 | const fh = try elf_file.addFileHandle(handle); | 220 | const fh = try elf_file.addFileHandle(handle); |
| 221 | 221 | ||
| 222 | const index = @as(File.Index, @intCast(try elf_file.files.addOne(gpa))); | 222 | const index: File.Index = @intCast(try elf_file.files.addOne(gpa)); |
| 223 | elf_file.files.set(index, .{ .object = .{ | 223 | elf_file.files.set(index, .{ .object = .{ |
| 224 | .path = try gpa.dupe(u8, path), | 224 | .path = .{ |
| 225 | .root_dir = path.root_dir, | ||
| 226 | .sub_path = try gpa.dupe(u8, path.sub_path), | ||
| 227 | }, | ||
| 225 | .file_handle = fh, | 228 | .file_handle = fh, |
| 226 | .index = index, | 229 | .index = index, |
| 227 | } }); | 230 | } }); |
| ... | @@ -231,9 +234,9 @@ fn parseObjectStaticLib(elf_file: *Elf, path: []const u8) Elf.ParseError!void { | ... | @@ -231,9 +234,9 @@ fn parseObjectStaticLib(elf_file: *Elf, path: []const u8) Elf.ParseError!void { |
| 231 | try object.parseAr(elf_file); | 234 | try object.parseAr(elf_file); |
| 232 | } | 235 | } |
| 233 | 236 | ||
| 234 | fn parseArchiveStaticLib(elf_file: *Elf, path: []const u8) Elf.ParseError!void { | 237 | fn parseArchiveStaticLib(elf_file: *Elf, path: Path) Elf.ParseError!void { |
| 235 | const gpa = elf_file.base.comp.gpa; | 238 | const gpa = elf_file.base.comp.gpa; |
| 236 | const handle = try std.fs.cwd().openFile(path, .{}); | 239 | const handle = try path.root_dir.handle.openFile(path.sub_path, .{}); |
| 237 | const fh = try elf_file.addFileHandle(handle); | 240 | const fh = try elf_file.addFileHandle(handle); |
| 238 | 241 | ||
| 239 | var archive = Archive{}; | 242 | var archive = Archive{}; |
| ... | @@ -531,6 +534,7 @@ const log = std.log.scoped(.link); | ... | @@ -531,6 +534,7 @@ const log = std.log.scoped(.link); |
| 531 | const math = std.math; | 534 | const math = std.math; |
| 532 | const mem = std.mem; | 535 | const mem = std.mem; |
| 533 | const state_log = std.log.scoped(.link_state); | 536 | const state_log = std.log.scoped(.link_state); |
| 537 | const Path = std.Build.Cache.Path; | ||
| 534 | const std = @import("std"); | 538 | const std = @import("std"); |
| 535 | 539 | ||
| 536 | const Archive = @import("Archive.zig"); | 540 | const Archive = @import("Archive.zig"); |
src/link/MachO.zig+57-47| ... | @@ -144,14 +144,14 @@ hot_state: if (is_hot_update_compatible) HotUpdateState else struct {} = .{}, | ... | @@ -144,14 +144,14 @@ hot_state: if (is_hot_update_compatible) HotUpdateState else struct {} = .{}, |
| 144 | pub const Framework = struct { | 144 | pub const Framework = struct { |
| 145 | needed: bool = false, | 145 | needed: bool = false, |
| 146 | weak: bool = false, | 146 | weak: bool = false, |
| 147 | path: []const u8, | 147 | path: Path, |
| 148 | }; | 148 | }; |
| 149 | 149 | ||
| 150 | pub fn hashAddFrameworks(man: *Cache.Manifest, hm: []const Framework) !void { | 150 | pub fn hashAddFrameworks(man: *Cache.Manifest, hm: []const Framework) !void { |
| 151 | for (hm) |value| { | 151 | for (hm) |value| { |
| 152 | man.hash.add(value.needed); | 152 | man.hash.add(value.needed); |
| 153 | man.hash.add(value.weak); | 153 | man.hash.add(value.weak); |
| 154 | _ = try man.addFile(value.path, null); | 154 | _ = try man.addFilePath(value.path, null); |
| 155 | } | 155 | } |
| 156 | } | 156 | } |
| 157 | 157 | ||
| ... | @@ -239,9 +239,9 @@ pub fn createEmpty( | ... | @@ -239,9 +239,9 @@ pub fn createEmpty( |
| 239 | const index: File.Index = @intCast(try self.files.addOne(gpa)); | 239 | const index: File.Index = @intCast(try self.files.addOne(gpa)); |
| 240 | self.files.set(index, .{ .zig_object = .{ | 240 | self.files.set(index, .{ .zig_object = .{ |
| 241 | .index = index, | 241 | .index = index, |
| 242 | .path = try std.fmt.allocPrint(arena, "{s}.o", .{fs.path.stem( | 242 | .basename = try std.fmt.allocPrint(arena, "{s}.o", .{ |
| 243 | zcu.main_mod.root_src_path, | 243 | fs.path.stem(zcu.main_mod.root_src_path), |
| 244 | )}), | 244 | }), |
| 245 | } }); | 245 | } }); |
| 246 | self.zig_object = index; | 246 | self.zig_object = index; |
| 247 | const zo = self.getZigObject().?; | 247 | const zo = self.getZigObject().?; |
| ... | @@ -356,13 +356,12 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n | ... | @@ -356,13 +356,12 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 356 | defer sub_prog_node.end(); | 356 | defer sub_prog_node.end(); |
| 357 | 357 | ||
| 358 | const directory = self.base.emit.root_dir; | 358 | const directory = self.base.emit.root_dir; |
| 359 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); | 359 | const module_obj_path: ?Path = if (self.base.zcu_object_sub_path) |path| .{ |
| 360 | const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: { | 360 | .root_dir = directory, |
| 361 | if (fs.path.dirname(full_out_path)) |dirname| { | 361 | .sub_path = if (fs.path.dirname(self.base.emit.sub_path)) |dirname| |
| 362 | break :blk try fs.path.join(arena, &.{ dirname, path }); | 362 | try fs.path.join(arena, &.{ dirname, path }) |
| 363 | } else { | 363 | else |
| 364 | break :blk path; | 364 | path, |
| 365 | } | ||
| 366 | } else null; | 365 | } else null; |
| 367 | 366 | ||
| 368 | // --verbose-link | 367 | // --verbose-link |
| ... | @@ -455,7 +454,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n | ... | @@ -455,7 +454,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 455 | } | 454 | } |
| 456 | 455 | ||
| 457 | // Finally, link against compiler_rt. | 456 | // Finally, link against compiler_rt. |
| 458 | const compiler_rt_path: ?[]const u8 = blk: { | 457 | const compiler_rt_path: ?Path = blk: { |
| 459 | if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; | 458 | if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; |
| 460 | if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; | 459 | if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; |
| 461 | break :blk null; | 460 | break :blk null; |
| ... | @@ -567,7 +566,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n | ... | @@ -567,7 +566,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 567 | // The most important here is to have the correct vm and filesize of the __LINKEDIT segment | 566 | // The most important here is to have the correct vm and filesize of the __LINKEDIT segment |
| 568 | // where the code signature goes into. | 567 | // where the code signature goes into. |
| 569 | var codesig = CodeSignature.init(self.getPageSize()); | 568 | var codesig = CodeSignature.init(self.getPageSize()); |
| 570 | codesig.code_directory.ident = fs.path.basename(full_out_path); | 569 | codesig.code_directory.ident = fs.path.basename(self.base.emit.sub_path); |
| 571 | if (self.entitlements) |path| try codesig.addEntitlements(gpa, path); | 570 | if (self.entitlements) |path| try codesig.addEntitlements(gpa, path); |
| 572 | try self.writeCodeSignaturePadding(&codesig); | 571 | try self.writeCodeSignaturePadding(&codesig); |
| 573 | break :blk codesig; | 572 | break :blk codesig; |
| ... | @@ -625,11 +624,11 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { | ... | @@ -625,11 +624,11 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 625 | 624 | ||
| 626 | if (self.base.isRelocatable()) { | 625 | if (self.base.isRelocatable()) { |
| 627 | for (comp.objects) |obj| { | 626 | for (comp.objects) |obj| { |
| 628 | try argv.append(obj.path); | 627 | try argv.append(try obj.path.toString(arena)); |
| 629 | } | 628 | } |
| 630 | 629 | ||
| 631 | for (comp.c_object_table.keys()) |key| { | 630 | for (comp.c_object_table.keys()) |key| { |
| 632 | try argv.append(key.status.success.object_path); | 631 | try argv.append(try key.status.success.object_path.toString(arena)); |
| 633 | } | 632 | } |
| 634 | 633 | ||
| 635 | if (module_obj_path) |p| { | 634 | if (module_obj_path) |p| { |
| ... | @@ -711,11 +710,11 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { | ... | @@ -711,11 +710,11 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 711 | if (obj.must_link) { | 710 | if (obj.must_link) { |
| 712 | try argv.append("-force_load"); | 711 | try argv.append("-force_load"); |
| 713 | } | 712 | } |
| 714 | try argv.append(obj.path); | 713 | try argv.append(try obj.path.toString(arena)); |
| 715 | } | 714 | } |
| 716 | 715 | ||
| 717 | for (comp.c_object_table.keys()) |key| { | 716 | for (comp.c_object_table.keys()) |key| { |
| 718 | try argv.append(key.status.success.object_path); | 717 | try argv.append(try key.status.success.object_path.toString(arena)); |
| 719 | } | 718 | } |
| 720 | 719 | ||
| 721 | if (module_obj_path) |p| { | 720 | if (module_obj_path) |p| { |
| ... | @@ -723,13 +722,12 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { | ... | @@ -723,13 +722,12 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 723 | } | 722 | } |
| 724 | 723 | ||
| 725 | if (comp.config.any_sanitize_thread) { | 724 | if (comp.config.any_sanitize_thread) { |
| 726 | const path = comp.tsan_lib.?.full_object_path; | 725 | const path = try comp.tsan_lib.?.full_object_path.toString(arena); |
| 727 | try argv.append(path); | 726 | try argv.appendSlice(&.{ path, "-rpath", std.fs.path.dirname(path) orelse "." }); |
| 728 | try argv.appendSlice(&.{ "-rpath", std.fs.path.dirname(path) orelse "." }); | ||
| 729 | } | 727 | } |
| 730 | 728 | ||
| 731 | if (comp.config.any_fuzz) { | 729 | if (comp.config.any_fuzz) { |
| 732 | try argv.append(comp.fuzzer_lib.?.full_object_path); | 730 | try argv.append(try comp.fuzzer_lib.?.full_object_path.toString(arena)); |
| 733 | } | 731 | } |
| 734 | 732 | ||
| 735 | for (self.lib_dirs) |lib_dir| { | 733 | for (self.lib_dirs) |lib_dir| { |
| ... | @@ -754,7 +752,7 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { | ... | @@ -754,7 +752,7 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 754 | } | 752 | } |
| 755 | 753 | ||
| 756 | for (self.frameworks) |framework| { | 754 | for (self.frameworks) |framework| { |
| 757 | const name = fs.path.stem(framework.path); | 755 | const name = framework.path.stem(); |
| 758 | const arg = if (framework.needed) | 756 | const arg = if (framework.needed) |
| 759 | try std.fmt.allocPrint(arena, "-needed_framework {s}", .{name}) | 757 | try std.fmt.allocPrint(arena, "-needed_framework {s}", .{name}) |
| 760 | else if (framework.weak) | 758 | else if (framework.weak) |
| ... | @@ -765,14 +763,16 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { | ... | @@ -765,14 +763,16 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 765 | } | 763 | } |
| 766 | 764 | ||
| 767 | if (comp.config.link_libcpp) { | 765 | if (comp.config.link_libcpp) { |
| 768 | try argv.append(comp.libcxxabi_static_lib.?.full_object_path); | 766 | try argv.appendSlice(&.{ |
| 769 | try argv.append(comp.libcxx_static_lib.?.full_object_path); | 767 | try comp.libcxxabi_static_lib.?.full_object_path.toString(arena), |
| 768 | try comp.libcxx_static_lib.?.full_object_path.toString(arena), | ||
| 769 | }); | ||
| 770 | } | 770 | } |
| 771 | 771 | ||
| 772 | try argv.append("-lSystem"); | 772 | try argv.append("-lSystem"); |
| 773 | 773 | ||
| 774 | if (comp.compiler_rt_lib) |lib| try argv.append(lib.full_object_path); | 774 | if (comp.compiler_rt_lib) |lib| try argv.append(try lib.full_object_path.toString(arena)); |
| 775 | if (comp.compiler_rt_obj) |obj| try argv.append(obj.full_object_path); | 775 | if (comp.compiler_rt_obj) |obj| try argv.append(try obj.full_object_path.toString(arena)); |
| 776 | } | 776 | } |
| 777 | 777 | ||
| 778 | Compilation.dump_argv(argv.items); | 778 | Compilation.dump_argv(argv.items); |
| ... | @@ -807,20 +807,20 @@ pub fn resolveLibSystem( | ... | @@ -807,20 +807,20 @@ pub fn resolveLibSystem( |
| 807 | return error.MissingLibSystem; | 807 | return error.MissingLibSystem; |
| 808 | } | 808 | } |
| 809 | 809 | ||
| 810 | const libsystem_path = try arena.dupe(u8, test_path.items); | 810 | const libsystem_path = Path.initCwd(try arena.dupe(u8, test_path.items)); |
| 811 | try out_libs.append(.{ | 811 | try out_libs.append(.{ |
| 812 | .needed = true, | 812 | .needed = true, |
| 813 | .path = libsystem_path, | 813 | .path = libsystem_path, |
| 814 | }); | 814 | }); |
| 815 | } | 815 | } |
| 816 | 816 | ||
| 817 | pub fn classifyInputFile(self: *MachO, path: []const u8, lib: SystemLib, must_link: bool) !void { | 817 | pub fn classifyInputFile(self: *MachO, path: Path, lib: SystemLib, must_link: bool) !void { |
| 818 | const tracy = trace(@src()); | 818 | const tracy = trace(@src()); |
| 819 | defer tracy.end(); | 819 | defer tracy.end(); |
| 820 | 820 | ||
| 821 | log.debug("classifying input file {s}", .{path}); | 821 | log.debug("classifying input file {}", .{path}); |
| 822 | 822 | ||
| 823 | const file = try std.fs.cwd().openFile(path, .{}); | 823 | const file = try path.root_dir.handle.openFile(path.sub_path, .{}); |
| 824 | const fh = try self.addFileHandle(file); | 824 | const fh = try self.addFileHandle(file); |
| 825 | var buffer: [Archive.SARMAG]u8 = undefined; | 825 | var buffer: [Archive.SARMAG]u8 = undefined; |
| 826 | 826 | ||
| ... | @@ -844,7 +844,7 @@ pub fn classifyInputFile(self: *MachO, path: []const u8, lib: SystemLib, must_li | ... | @@ -844,7 +844,7 @@ pub fn classifyInputFile(self: *MachO, path: []const u8, lib: SystemLib, must_li |
| 844 | _ = try self.addTbd(lib, true, fh); | 844 | _ = try self.addTbd(lib, true, fh); |
| 845 | } | 845 | } |
| 846 | 846 | ||
| 847 | fn parseFatFile(self: *MachO, file: std.fs.File, path: []const u8) !?fat.Arch { | 847 | fn parseFatFile(self: *MachO, file: std.fs.File, path: Path) !?fat.Arch { |
| 848 | const fat_h = fat.readFatHeader(file) catch return null; | 848 | const fat_h = fat.readFatHeader(file) catch return null; |
| 849 | if (fat_h.magic != macho.FAT_MAGIC and fat_h.magic != macho.FAT_MAGIC_64) return null; | 849 | if (fat_h.magic != macho.FAT_MAGIC and fat_h.magic != macho.FAT_MAGIC_64) return null; |
| 850 | var fat_archs_buffer: [2]fat.Arch = undefined; | 850 | var fat_archs_buffer: [2]fat.Arch = undefined; |
| ... | @@ -873,7 +873,7 @@ pub fn readArMagic(file: std.fs.File, offset: usize, buffer: *[Archive.SARMAG]u8 | ... | @@ -873,7 +873,7 @@ pub fn readArMagic(file: std.fs.File, offset: usize, buffer: *[Archive.SARMAG]u8 |
| 873 | return buffer[0..Archive.SARMAG]; | 873 | return buffer[0..Archive.SARMAG]; |
| 874 | } | 874 | } |
| 875 | 875 | ||
| 876 | fn addObject(self: *MachO, path: []const u8, handle: File.HandleIndex, offset: u64) !void { | 876 | fn addObject(self: *MachO, path: Path, handle: File.HandleIndex, offset: u64) !void { |
| 877 | const tracy = trace(@src()); | 877 | const tracy = trace(@src()); |
| 878 | defer tracy.end(); | 878 | defer tracy.end(); |
| 879 | 879 | ||
| ... | @@ -886,7 +886,10 @@ fn addObject(self: *MachO, path: []const u8, handle: File.HandleIndex, offset: u | ... | @@ -886,7 +886,10 @@ fn addObject(self: *MachO, path: []const u8, handle: File.HandleIndex, offset: u |
| 886 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); | 886 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); |
| 887 | self.files.set(index, .{ .object = .{ | 887 | self.files.set(index, .{ .object = .{ |
| 888 | .offset = offset, | 888 | .offset = offset, |
| 889 | .path = try gpa.dupe(u8, path), | 889 | .path = .{ |
| 890 | .root_dir = path.root_dir, | ||
| 891 | .sub_path = try gpa.dupe(u8, path.sub_path), | ||
| 892 | }, | ||
| 890 | .file_handle = handle, | 893 | .file_handle = handle, |
| 891 | .mtime = mtime, | 894 | .mtime = mtime, |
| 892 | .index = index, | 895 | .index = index, |
| ... | @@ -937,7 +940,7 @@ fn addArchive(self: *MachO, lib: SystemLib, must_link: bool, handle: File.Handle | ... | @@ -937,7 +940,7 @@ fn addArchive(self: *MachO, lib: SystemLib, must_link: bool, handle: File.Handle |
| 937 | 940 | ||
| 938 | const gpa = self.base.comp.gpa; | 941 | const gpa = self.base.comp.gpa; |
| 939 | 942 | ||
| 940 | var archive = Archive{}; | 943 | var archive: Archive = .{}; |
| 941 | defer archive.deinit(gpa); | 944 | defer archive.deinit(gpa); |
| 942 | try archive.unpack(self, lib.path, handle, fat_arch); | 945 | try archive.unpack(self, lib.path, handle, fat_arch); |
| 943 | 946 | ||
| ... | @@ -963,7 +966,10 @@ fn addDylib(self: *MachO, lib: SystemLib, explicit: bool, handle: File.HandleInd | ... | @@ -963,7 +966,10 @@ fn addDylib(self: *MachO, lib: SystemLib, explicit: bool, handle: File.HandleInd |
| 963 | .offset = offset, | 966 | .offset = offset, |
| 964 | .file_handle = handle, | 967 | .file_handle = handle, |
| 965 | .tag = .dylib, | 968 | .tag = .dylib, |
| 966 | .path = try gpa.dupe(u8, lib.path), | 969 | .path = .{ |
| 970 | .root_dir = lib.path.root_dir, | ||
| 971 | .sub_path = try gpa.dupe(u8, lib.path.sub_path), | ||
| 972 | }, | ||
| 967 | .index = index, | 973 | .index = index, |
| 968 | .needed = lib.needed, | 974 | .needed = lib.needed, |
| 969 | .weak = lib.weak, | 975 | .weak = lib.weak, |
| ... | @@ -986,7 +992,10 @@ fn addTbd(self: *MachO, lib: SystemLib, explicit: bool, handle: File.HandleIndex | ... | @@ -986,7 +992,10 @@ fn addTbd(self: *MachO, lib: SystemLib, explicit: bool, handle: File.HandleIndex |
| 986 | .offset = 0, | 992 | .offset = 0, |
| 987 | .file_handle = handle, | 993 | .file_handle = handle, |
| 988 | .tag = .tbd, | 994 | .tag = .tbd, |
| 989 | .path = try gpa.dupe(u8, lib.path), | 995 | .path = .{ |
| 996 | .root_dir = lib.path.root_dir, | ||
| 997 | .sub_path = try gpa.dupe(u8, lib.path.sub_path), | ||
| 998 | }, | ||
| 990 | .index = index, | 999 | .index = index, |
| 991 | .needed = lib.needed, | 1000 | .needed = lib.needed, |
| 992 | .weak = lib.weak, | 1001 | .weak = lib.weak, |
| ... | @@ -1175,11 +1184,11 @@ fn parseDependentDylibs(self: *MachO) !void { | ... | @@ -1175,11 +1184,11 @@ fn parseDependentDylibs(self: *MachO) !void { |
| 1175 | continue; | 1184 | continue; |
| 1176 | } | 1185 | } |
| 1177 | }; | 1186 | }; |
| 1178 | const lib = SystemLib{ | 1187 | const lib: SystemLib = .{ |
| 1179 | .path = full_path, | 1188 | .path = Path.initCwd(full_path), |
| 1180 | .weak = is_weak, | 1189 | .weak = is_weak, |
| 1181 | }; | 1190 | }; |
| 1182 | const file = try std.fs.cwd().openFile(lib.path, .{}); | 1191 | const file = try lib.path.root_dir.handle.openFile(lib.path.sub_path, .{}); |
| 1183 | const fh = try self.addFileHandle(file); | 1192 | const fh = try self.addFileHandle(file); |
| 1184 | const fat_arch = try self.parseFatFile(file, lib.path); | 1193 | const fat_arch = try self.parseFatFile(file, lib.path); |
| 1185 | const offset = if (fat_arch) |fa| fa.offset else 0; | 1194 | const offset = if (fat_arch) |fa| fa.offset else 0; |
| ... | @@ -2865,7 +2874,8 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { | ... | @@ -2865,7 +2874,8 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { |
| 2865 | ncmds += 1; | 2874 | ncmds += 1; |
| 2866 | } | 2875 | } |
| 2867 | if (comp.config.any_sanitize_thread) { | 2876 | if (comp.config.any_sanitize_thread) { |
| 2868 | const path = comp.tsan_lib.?.full_object_path; | 2877 | const path = try comp.tsan_lib.?.full_object_path.toString(gpa); |
| 2878 | defer gpa.free(path); | ||
| 2869 | const rpath = std.fs.path.dirname(path) orelse "."; | 2879 | const rpath = std.fs.path.dirname(path) orelse "."; |
| 2870 | try load_commands.writeRpathLC(rpath, writer); | 2880 | try load_commands.writeRpathLC(rpath, writer); |
| 2871 | ncmds += 1; | 2881 | ncmds += 1; |
| ... | @@ -3758,13 +3768,13 @@ pub fn eatPrefix(path: []const u8, prefix: []const u8) ?[]const u8 { | ... | @@ -3758,13 +3768,13 @@ pub fn eatPrefix(path: []const u8, prefix: []const u8) ?[]const u8 { |
| 3758 | 3768 | ||
| 3759 | pub fn reportParseError( | 3769 | pub fn reportParseError( |
| 3760 | self: *MachO, | 3770 | self: *MachO, |
| 3761 | path: []const u8, | 3771 | path: Path, |
| 3762 | comptime format: []const u8, | 3772 | comptime format: []const u8, |
| 3763 | args: anytype, | 3773 | args: anytype, |
| 3764 | ) error{OutOfMemory}!void { | 3774 | ) error{OutOfMemory}!void { |
| 3765 | var err = try self.base.addErrorWithNotes(1); | 3775 | var err = try self.base.addErrorWithNotes(1); |
| 3766 | try err.addMsg(format, args); | 3776 | try err.addMsg(format, args); |
| 3767 | try err.addNote("while parsing {s}", .{path}); | 3777 | try err.addNote("while parsing {}", .{path}); |
| 3768 | } | 3778 | } |
| 3769 | 3779 | ||
| 3770 | pub fn reportParseError2( | 3780 | pub fn reportParseError2( |
| ... | @@ -3913,7 +3923,7 @@ fn fmtDumpState( | ... | @@ -3913,7 +3923,7 @@ fn fmtDumpState( |
| 3913 | _ = options; | 3923 | _ = options; |
| 3914 | _ = unused_fmt_string; | 3924 | _ = unused_fmt_string; |
| 3915 | if (self.getZigObject()) |zo| { | 3925 | if (self.getZigObject()) |zo| { |
| 3916 | try writer.print("zig_object({d}) : {s}\n", .{ zo.index, zo.path }); | 3926 | try writer.print("zig_object({d}) : {s}\n", .{ zo.index, zo.basename }); |
| 3917 | try writer.print("{}{}\n", .{ | 3927 | try writer.print("{}{}\n", .{ |
| 3918 | zo.fmtAtoms(self), | 3928 | zo.fmtAtoms(self), |
| 3919 | zo.fmtSymtab(self), | 3929 | zo.fmtSymtab(self), |
| ... | @@ -3938,9 +3948,9 @@ fn fmtDumpState( | ... | @@ -3938,9 +3948,9 @@ fn fmtDumpState( |
| 3938 | } | 3948 | } |
| 3939 | for (self.dylibs.items) |index| { | 3949 | for (self.dylibs.items) |index| { |
| 3940 | const dylib = self.getFile(index).?.dylib; | 3950 | const dylib = self.getFile(index).?.dylib; |
| 3941 | try writer.print("dylib({d}) : {s} : needed({}) : weak({})", .{ | 3951 | try writer.print("dylib({d}) : {} : needed({}) : weak({})", .{ |
| 3942 | index, | 3952 | index, |
| 3943 | dylib.path, | 3953 | @as(Path, dylib.path), |
| 3944 | dylib.needed, | 3954 | dylib.needed, |
| 3945 | dylib.weak, | 3955 | dylib.weak, |
| 3946 | }); | 3956 | }); |
| ... | @@ -4442,7 +4452,7 @@ pub const default_pagezero_size: u64 = 0x100000000; | ... | @@ -4442,7 +4452,7 @@ pub const default_pagezero_size: u64 = 0x100000000; |
| 4442 | pub const default_headerpad_size: u32 = 0x1000; | 4452 | pub const default_headerpad_size: u32 = 0x1000; |
| 4443 | 4453 | ||
| 4444 | const SystemLib = struct { | 4454 | const SystemLib = struct { |
| 4445 | path: []const u8, | 4455 | path: Path, |
| 4446 | needed: bool = false, | 4456 | needed: bool = false, |
| 4447 | weak: bool = false, | 4457 | weak: bool = false, |
| 4448 | hidden: bool = false, | 4458 | hidden: bool = false, |
src/link/MachO/Archive.zig+10-6| ... | @@ -4,7 +4,7 @@ pub fn deinit(self: *Archive, allocator: Allocator) void { | ... | @@ -4,7 +4,7 @@ pub fn deinit(self: *Archive, allocator: Allocator) void { |
| 4 | self.objects.deinit(allocator); | 4 | self.objects.deinit(allocator); |
| 5 | } | 5 | } |
| 6 | 6 | ||
| 7 | pub fn unpack(self: *Archive, macho_file: *MachO, path: []const u8, handle_index: File.HandleIndex, fat_arch: ?fat.Arch) !void { | 7 | pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File.HandleIndex, fat_arch: ?fat.Arch) !void { |
| 8 | const gpa = macho_file.base.comp.gpa; | 8 | const gpa = macho_file.base.comp.gpa; |
| 9 | 9 | ||
| 10 | var arena = std.heap.ArenaAllocator.init(gpa); | 10 | var arena = std.heap.ArenaAllocator.init(gpa); |
| ... | @@ -55,20 +55,23 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: []const u8, handle_index | ... | @@ -55,20 +55,23 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: []const u8, handle_index |
| 55 | mem.eql(u8, name, SYMDEF_SORTED) or | 55 | mem.eql(u8, name, SYMDEF_SORTED) or |
| 56 | mem.eql(u8, name, SYMDEF64_SORTED)) continue; | 56 | mem.eql(u8, name, SYMDEF64_SORTED)) continue; |
| 57 | 57 | ||
| 58 | const object = Object{ | 58 | const object: Object = .{ |
| 59 | .offset = pos, | 59 | .offset = pos, |
| 60 | .in_archive = .{ | 60 | .in_archive = .{ |
| 61 | .path = try gpa.dupe(u8, path), | 61 | .path = .{ |
| 62 | .root_dir = path.root_dir, | ||
| 63 | .sub_path = try gpa.dupe(u8, path.sub_path), | ||
| 64 | }, | ||
| 62 | .size = hdr_size, | 65 | .size = hdr_size, |
| 63 | }, | 66 | }, |
| 64 | .path = try gpa.dupe(u8, name), | 67 | .path = Path.initCwd(try gpa.dupe(u8, name)), |
| 65 | .file_handle = handle_index, | 68 | .file_handle = handle_index, |
| 66 | .index = undefined, | 69 | .index = undefined, |
| 67 | .alive = false, | 70 | .alive = false, |
| 68 | .mtime = hdr.date() catch 0, | 71 | .mtime = hdr.date() catch 0, |
| 69 | }; | 72 | }; |
| 70 | 73 | ||
| 71 | log.debug("extracting object '{s}' from archive '{s}'", .{ object.path, path }); | 74 | log.debug("extracting object '{}' from archive '{}'", .{ object.path, path }); |
| 72 | 75 | ||
| 73 | try self.objects.append(gpa, object); | 76 | try self.objects.append(gpa, object); |
| 74 | } | 77 | } |
| ... | @@ -301,8 +304,9 @@ const log = std.log.scoped(.link); | ... | @@ -301,8 +304,9 @@ const log = std.log.scoped(.link); |
| 301 | const macho = std.macho; | 304 | const macho = std.macho; |
| 302 | const mem = std.mem; | 305 | const mem = std.mem; |
| 303 | const std = @import("std"); | 306 | const std = @import("std"); |
| 304 | |||
| 305 | const Allocator = mem.Allocator; | 307 | const Allocator = mem.Allocator; |
| 308 | const Path = std.Build.Cache.Path; | ||
| 309 | |||
| 306 | const Archive = @This(); | 310 | const Archive = @This(); |
| 307 | const File = @import("file.zig").File; | 311 | const File = @import("file.zig").File; |
| 308 | const MachO = @import("../MachO.zig"); | 312 | const MachO = @import("../MachO.zig"); |
src/link/MachO/Dylib.zig+6-5| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | /// Non-zero for fat dylibs | 1 | /// Non-zero for fat dylibs |
| 2 | offset: u64, | 2 | offset: u64, |
| 3 | path: []const u8, | 3 | path: Path, |
| 4 | index: File.Index, | 4 | index: File.Index, |
| 5 | file_handle: File.HandleIndex, | 5 | file_handle: File.HandleIndex, |
| 6 | tag: enum { dylib, tbd }, | 6 | tag: enum { dylib, tbd }, |
| ... | @@ -28,7 +28,7 @@ referenced: bool = false, | ... | @@ -28,7 +28,7 @@ referenced: bool = false, |
| 28 | output_symtab_ctx: MachO.SymtabCtx = .{}, | 28 | output_symtab_ctx: MachO.SymtabCtx = .{}, |
| 29 | 29 | ||
| 30 | pub fn deinit(self: *Dylib, allocator: Allocator) void { | 30 | pub fn deinit(self: *Dylib, allocator: Allocator) void { |
| 31 | allocator.free(self.path); | 31 | allocator.free(self.path.sub_path); |
| 32 | self.exports.deinit(allocator); | 32 | self.exports.deinit(allocator); |
| 33 | self.strtab.deinit(allocator); | 33 | self.strtab.deinit(allocator); |
| 34 | if (self.id) |*id| id.deinit(allocator); | 34 | if (self.id) |*id| id.deinit(allocator); |
| ... | @@ -61,7 +61,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void { | ... | @@ -61,7 +61,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void { |
| 61 | const file = macho_file.getFileHandle(self.file_handle); | 61 | const file = macho_file.getFileHandle(self.file_handle); |
| 62 | const offset = self.offset; | 62 | const offset = self.offset; |
| 63 | 63 | ||
| 64 | log.debug("parsing dylib from binary: {s}", .{self.path}); | 64 | log.debug("parsing dylib from binary: {}", .{@as(Path, self.path)}); |
| 65 | 65 | ||
| 66 | var header_buffer: [@sizeOf(macho.mach_header_64)]u8 = undefined; | 66 | var header_buffer: [@sizeOf(macho.mach_header_64)]u8 = undefined; |
| 67 | { | 67 | { |
| ... | @@ -267,7 +267,7 @@ fn parseTbd(self: *Dylib, macho_file: *MachO) !void { | ... | @@ -267,7 +267,7 @@ fn parseTbd(self: *Dylib, macho_file: *MachO) !void { |
| 267 | 267 | ||
| 268 | const gpa = macho_file.base.comp.gpa; | 268 | const gpa = macho_file.base.comp.gpa; |
| 269 | 269 | ||
| 270 | log.debug("parsing dylib from stub: {s}", .{self.path}); | 270 | log.debug("parsing dylib from stub: {}", .{self.path}); |
| 271 | 271 | ||
| 272 | const file = macho_file.getFileHandle(self.file_handle); | 272 | const file = macho_file.getFileHandle(self.file_handle); |
| 273 | var lib_stub = LibStub.loadFromFile(gpa, file) catch |err| { | 273 | var lib_stub = LibStub.loadFromFile(gpa, file) catch |err| { |
| ... | @@ -959,8 +959,9 @@ const mem = std.mem; | ... | @@ -959,8 +959,9 @@ const mem = std.mem; |
| 959 | const tapi = @import("../tapi.zig"); | 959 | const tapi = @import("../tapi.zig"); |
| 960 | const trace = @import("../../tracy.zig").trace; | 960 | const trace = @import("../../tracy.zig").trace; |
| 961 | const std = @import("std"); | 961 | const std = @import("std"); |
| 962 | |||
| 963 | const Allocator = mem.Allocator; | 962 | const Allocator = mem.Allocator; |
| 963 | const Path = std.Build.Cache.Path; | ||
| 964 | |||
| 964 | const Dylib = @This(); | 965 | const Dylib = @This(); |
| 965 | const File = @import("file.zig").File; | 966 | const File = @import("file.zig").File; |
| 966 | const LibStub = tapi.LibStub; | 967 | const LibStub = tapi.LibStub; |
src/link/MachO/Object.zig+45-18| ... | @@ -1,6 +1,8 @@ | ... | @@ -1,6 +1,8 @@ |
| 1 | /// Non-zero for fat object files or archives | 1 | /// Non-zero for fat object files or archives |
| 2 | offset: u64, | 2 | offset: u64, |
| 3 | path: []const u8, | 3 | /// Archive files cannot contain subdirectories, so only the basename is needed |
| 4 | /// for output. However, the full path is kept for error reporting. | ||
| 5 | path: Path, | ||
| 4 | file_handle: File.HandleIndex, | 6 | file_handle: File.HandleIndex, |
| 5 | mtime: u64, | 7 | mtime: u64, |
| 6 | index: File.Index, | 8 | index: File.Index, |
| ... | @@ -39,8 +41,8 @@ output_symtab_ctx: MachO.SymtabCtx = .{}, | ... | @@ -39,8 +41,8 @@ output_symtab_ctx: MachO.SymtabCtx = .{}, |
| 39 | output_ar_state: Archive.ArState = .{}, | 41 | output_ar_state: Archive.ArState = .{}, |
| 40 | 42 | ||
| 41 | pub fn deinit(self: *Object, allocator: Allocator) void { | 43 | pub fn deinit(self: *Object, allocator: Allocator) void { |
| 42 | if (self.in_archive) |*ar| allocator.free(ar.path); | 44 | if (self.in_archive) |*ar| allocator.free(ar.path.sub_path); |
| 43 | allocator.free(self.path); | 45 | allocator.free(self.path.sub_path); |
| 44 | for (self.sections.items(.relocs), self.sections.items(.subsections)) |*relocs, *sub| { | 46 | for (self.sections.items(.relocs), self.sections.items(.subsections)) |*relocs, *sub| { |
| 45 | relocs.deinit(allocator); | 47 | relocs.deinit(allocator); |
| 46 | sub.deinit(allocator); | 48 | sub.deinit(allocator); |
| ... | @@ -1723,7 +1725,8 @@ pub fn updateArSize(self: *Object, macho_file: *MachO) !void { | ... | @@ -1723,7 +1725,8 @@ pub fn updateArSize(self: *Object, macho_file: *MachO) !void { |
| 1723 | pub fn writeAr(self: Object, ar_format: Archive.Format, macho_file: *MachO, writer: anytype) !void { | 1725 | pub fn writeAr(self: Object, ar_format: Archive.Format, macho_file: *MachO, writer: anytype) !void { |
| 1724 | // Header | 1726 | // Header |
| 1725 | const size = std.math.cast(usize, self.output_ar_state.size) orelse return error.Overflow; | 1727 | const size = std.math.cast(usize, self.output_ar_state.size) orelse return error.Overflow; |
| 1726 | try Archive.writeHeader(self.path, size, ar_format, writer); | 1728 | const basename = std.fs.path.basename(self.path.sub_path); |
| 1729 | try Archive.writeHeader(basename, size, ar_format, writer); | ||
| 1727 | // Data | 1730 | // Data |
| 1728 | const file = macho_file.getFileHandle(self.file_handle); | 1731 | const file = macho_file.getFileHandle(self.file_handle); |
| 1729 | // TODO try using copyRangeAll | 1732 | // TODO try using copyRangeAll |
| ... | @@ -1774,6 +1777,11 @@ pub fn calcSymtabSize(self: *Object, macho_file: *MachO) void { | ... | @@ -1774,6 +1777,11 @@ pub fn calcSymtabSize(self: *Object, macho_file: *MachO) void { |
| 1774 | self.calcStabsSize(macho_file); | 1777 | self.calcStabsSize(macho_file); |
| 1775 | } | 1778 | } |
| 1776 | 1779 | ||
| 1780 | fn pathLen(path: Path) usize { | ||
| 1781 | // +1 for the path separator | ||
| 1782 | return (if (path.root_dir.path) |p| p.len + @intFromBool(path.sub_path.len != 0) else 0) + path.sub_path.len; | ||
| 1783 | } | ||
| 1784 | |||
| 1777 | pub fn calcStabsSize(self: *Object, macho_file: *MachO) void { | 1785 | pub fn calcStabsSize(self: *Object, macho_file: *MachO) void { |
| 1778 | if (self.compile_unit) |cu| { | 1786 | if (self.compile_unit) |cu| { |
| 1779 | const comp_dir = cu.getCompDir(self.*); | 1787 | const comp_dir = cu.getCompDir(self.*); |
| ... | @@ -1784,9 +1792,9 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) void { | ... | @@ -1784,9 +1792,9 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) void { |
| 1784 | self.output_symtab_ctx.strsize += @as(u32, @intCast(tu_name.len + 1)); // tu_name | 1792 | self.output_symtab_ctx.strsize += @as(u32, @intCast(tu_name.len + 1)); // tu_name |
| 1785 | 1793 | ||
| 1786 | if (self.in_archive) |ar| { | 1794 | if (self.in_archive) |ar| { |
| 1787 | self.output_symtab_ctx.strsize += @as(u32, @intCast(ar.path.len + 1 + self.path.len + 1 + 1)); | 1795 | self.output_symtab_ctx.strsize += @intCast(pathLen(ar.path) + 1 + self.path.basename().len + 1 + 1); |
| 1788 | } else { | 1796 | } else { |
| 1789 | self.output_symtab_ctx.strsize += @as(u32, @intCast(self.path.len + 1)); | 1797 | self.output_symtab_ctx.strsize += @intCast(pathLen(self.path) + 1); |
| 1790 | } | 1798 | } |
| 1791 | 1799 | ||
| 1792 | for (self.symbols.items, 0..) |sym, i| { | 1800 | for (self.symbols.items, 0..) |sym, i| { |
| ... | @@ -2118,19 +2126,36 @@ pub fn writeStabs(self: Object, stroff: u32, macho_file: *MachO, ctx: anytype) v | ... | @@ -2118,19 +2126,36 @@ pub fn writeStabs(self: Object, stroff: u32, macho_file: *MachO, ctx: anytype) v |
| 2118 | }; | 2126 | }; |
| 2119 | index += 1; | 2127 | index += 1; |
| 2120 | if (self.in_archive) |ar| { | 2128 | if (self.in_archive) |ar| { |
| 2121 | @memcpy(ctx.strtab.items[n_strx..][0..ar.path.len], ar.path); | 2129 | if (ar.path.root_dir.path) |p| { |
| 2122 | n_strx += @intCast(ar.path.len); | 2130 | @memcpy(ctx.strtab.items[n_strx..][0..p.len], p); |
| 2131 | n_strx += @intCast(p.len); | ||
| 2132 | if (ar.path.sub_path.len != 0) { | ||
| 2133 | ctx.strtab.items[n_strx] = '/'; | ||
| 2134 | n_strx += 1; | ||
| 2135 | } | ||
| 2136 | } | ||
| 2137 | @memcpy(ctx.strtab.items[n_strx..][0..ar.path.sub_path.len], ar.path.sub_path); | ||
| 2138 | n_strx += @intCast(ar.path.sub_path.len); | ||
| 2123 | ctx.strtab.items[n_strx] = '('; | 2139 | ctx.strtab.items[n_strx] = '('; |
| 2124 | n_strx += 1; | 2140 | n_strx += 1; |
| 2125 | @memcpy(ctx.strtab.items[n_strx..][0..self.path.len], self.path); | 2141 | const basename = self.path.basename(); |
| 2126 | n_strx += @intCast(self.path.len); | 2142 | @memcpy(ctx.strtab.items[n_strx..][0..basename.len], basename); |
| 2143 | n_strx += @intCast(basename.len); | ||
| 2127 | ctx.strtab.items[n_strx] = ')'; | 2144 | ctx.strtab.items[n_strx] = ')'; |
| 2128 | n_strx += 1; | 2145 | n_strx += 1; |
| 2129 | ctx.strtab.items[n_strx] = 0; | 2146 | ctx.strtab.items[n_strx] = 0; |
| 2130 | n_strx += 1; | 2147 | n_strx += 1; |
| 2131 | } else { | 2148 | } else { |
| 2132 | @memcpy(ctx.strtab.items[n_strx..][0..self.path.len], self.path); | 2149 | if (self.path.root_dir.path) |p| { |
| 2133 | n_strx += @intCast(self.path.len); | 2150 | @memcpy(ctx.strtab.items[n_strx..][0..p.len], p); |
| 2151 | n_strx += @intCast(p.len); | ||
| 2152 | if (self.path.sub_path.len != 0) { | ||
| 2153 | ctx.strtab.items[n_strx] = '/'; | ||
| 2154 | n_strx += 1; | ||
| 2155 | } | ||
| 2156 | } | ||
| 2157 | @memcpy(ctx.strtab.items[n_strx..][0..self.path.sub_path.len], self.path.sub_path); | ||
| 2158 | n_strx += @intCast(self.path.sub_path.len); | ||
| 2134 | ctx.strtab.items[n_strx] = 0; | 2159 | ctx.strtab.items[n_strx] = 0; |
| 2135 | n_strx += 1; | 2160 | n_strx += 1; |
| 2136 | } | 2161 | } |
| ... | @@ -2666,11 +2691,12 @@ fn formatPath( | ... | @@ -2666,11 +2691,12 @@ fn formatPath( |
| 2666 | _ = unused_fmt_string; | 2691 | _ = unused_fmt_string; |
| 2667 | _ = options; | 2692 | _ = options; |
| 2668 | if (object.in_archive) |ar| { | 2693 | if (object.in_archive) |ar| { |
| 2669 | try writer.writeAll(ar.path); | 2694 | try writer.print("{}({s})", .{ |
| 2670 | try writer.writeByte('('); | 2695 | @as(Path, ar.path), object.path.basename(), |
| 2671 | try writer.writeAll(object.path); | 2696 | }); |
| 2672 | try writer.writeByte(')'); | 2697 | } else { |
| 2673 | } else try writer.writeAll(object.path); | 2698 | try writer.print("{}", .{@as(Path, object.path)}); |
| 2699 | } | ||
| 2674 | } | 2700 | } |
| 2675 | 2701 | ||
| 2676 | const Section = struct { | 2702 | const Section = struct { |
| ... | @@ -2777,7 +2803,7 @@ const CompileUnit = struct { | ... | @@ -2777,7 +2803,7 @@ const CompileUnit = struct { |
| 2777 | }; | 2803 | }; |
| 2778 | 2804 | ||
| 2779 | const InArchive = struct { | 2805 | const InArchive = struct { |
| 2780 | path: []const u8, | 2806 | path: Path, |
| 2781 | size: u32, | 2807 | size: u32, |
| 2782 | }; | 2808 | }; |
| 2783 | 2809 | ||
| ... | @@ -3170,6 +3196,7 @@ const math = std.math; | ... | @@ -3170,6 +3196,7 @@ const math = std.math; |
| 3170 | const mem = std.mem; | 3196 | const mem = std.mem; |
| 3171 | const trace = @import("../../tracy.zig").trace; | 3197 | const trace = @import("../../tracy.zig").trace; |
| 3172 | const std = @import("std"); | 3198 | const std = @import("std"); |
| 3199 | const Path = std.Build.Cache.Path; | ||
| 3173 | 3200 | ||
| 3174 | const Allocator = mem.Allocator; | 3201 | const Allocator = mem.Allocator; |
| 3175 | const Archive = @import("Archive.zig"); | 3202 | const Archive = @import("Archive.zig"); |
src/link/MachO/ZigObject.zig+2-2| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | data: std.ArrayListUnmanaged(u8) = .empty, | 1 | data: std.ArrayListUnmanaged(u8) = .empty, |
| 2 | /// Externally owned memory. | 2 | /// Externally owned memory. |
| 3 | path: []const u8, | 3 | basename: []const u8, |
| 4 | index: File.Index, | 4 | index: File.Index, |
| 5 | 5 | ||
| 6 | symtab: std.MultiArrayList(Nlist) = .{}, | 6 | symtab: std.MultiArrayList(Nlist) = .{}, |
| ... | @@ -317,7 +317,7 @@ pub fn updateArSize(self: *ZigObject) void { | ... | @@ -317,7 +317,7 @@ pub fn updateArSize(self: *ZigObject) void { |
| 317 | pub fn writeAr(self: ZigObject, ar_format: Archive.Format, writer: anytype) !void { | 317 | pub fn writeAr(self: ZigObject, ar_format: Archive.Format, writer: anytype) !void { |
| 318 | // Header | 318 | // Header |
| 319 | const size = std.math.cast(usize, self.output_ar_state.size) orelse return error.Overflow; | 319 | const size = std.math.cast(usize, self.output_ar_state.size) orelse return error.Overflow; |
| 320 | try Archive.writeHeader(self.path, size, ar_format, writer); | 320 | try Archive.writeHeader(self.basename, size, ar_format, writer); |
| 321 | // Data | 321 | // Data |
| 322 | try writer.writeAll(self.data.items); | 322 | try writer.writeAll(self.data.items); |
| 323 | } | 323 | } |
src/link/MachO/file.zig+6-5| ... | @@ -23,10 +23,10 @@ pub const File = union(enum) { | ... | @@ -23,10 +23,10 @@ pub const File = union(enum) { |
| 23 | _ = unused_fmt_string; | 23 | _ = unused_fmt_string; |
| 24 | _ = options; | 24 | _ = options; |
| 25 | switch (file) { | 25 | switch (file) { |
| 26 | .zig_object => |x| try writer.writeAll(x.path), | 26 | .zig_object => |zo| try writer.writeAll(zo.basename), |
| 27 | .internal => try writer.writeAll("internal"), | 27 | .internal => try writer.writeAll("internal"), |
| 28 | .object => |x| try writer.print("{}", .{x.fmtPath()}), | 28 | .object => |x| try writer.print("{}", .{x.fmtPath()}), |
| 29 | .dylib => |x| try writer.writeAll(x.path), | 29 | .dylib => |dl| try writer.print("{}", .{@as(Path, dl.path)}), |
| 30 | } | 30 | } |
| 31 | } | 31 | } |
| 32 | 32 | ||
| ... | @@ -373,13 +373,14 @@ pub const File = union(enum) { | ... | @@ -373,13 +373,14 @@ pub const File = union(enum) { |
| 373 | pub const HandleIndex = Index; | 373 | pub const HandleIndex = Index; |
| 374 | }; | 374 | }; |
| 375 | 375 | ||
| 376 | const std = @import("std"); | ||
| 376 | const assert = std.debug.assert; | 377 | const assert = std.debug.assert; |
| 377 | const log = std.log.scoped(.link); | 378 | const log = std.log.scoped(.link); |
| 378 | const macho = std.macho; | 379 | const macho = std.macho; |
| 379 | const std = @import("std"); | ||
| 380 | const trace = @import("../../tracy.zig").trace; | ||
| 381 | |||
| 382 | const Allocator = std.mem.Allocator; | 380 | const Allocator = std.mem.Allocator; |
| 381 | const Path = std.Build.Cache.Path; | ||
| 382 | |||
| 383 | const trace = @import("../../tracy.zig").trace; | ||
| 383 | const Archive = @import("Archive.zig"); | 384 | const Archive = @import("Archive.zig"); |
| 384 | const Atom = @import("Atom.zig"); | 385 | const Atom = @import("Atom.zig"); |
| 385 | const InternalObject = @import("InternalObject.zig"); | 386 | const InternalObject = @import("InternalObject.zig"); |
src/link/MachO/load_commands.zig+2-1| ... | @@ -72,7 +72,8 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) !u32 | ... | @@ -72,7 +72,8 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) !u32 |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | if (comp.config.any_sanitize_thread) { | 74 | if (comp.config.any_sanitize_thread) { |
| 75 | const path = comp.tsan_lib.?.full_object_path; | 75 | const path = try comp.tsan_lib.?.full_object_path.toString(gpa); |
| 76 | defer gpa.free(path); | ||
| 76 | const rpath = std.fs.path.dirname(path) orelse "."; | 77 | const rpath = std.fs.path.dirname(path) orelse "."; |
| 77 | sizeofcmds += calcInstallNameLen( | 78 | sizeofcmds += calcInstallNameLen( |
| 78 | @sizeOf(macho.rpath_command), | 79 | @sizeOf(macho.rpath_command), |
src/link/MachO/relocatable.zig+23-17| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { | 1 | pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Path) link.File.FlushError!void { |
| 2 | const gpa = macho_file.base.comp.gpa; | 2 | const gpa = macho_file.base.comp.gpa; |
| 3 | 3 | ||
| 4 | // TODO: "positional arguments" is a CLI concept, not a linker concept. Delete this unnecessary array list. | ||
| 4 | var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); | 5 | var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); |
| 5 | defer positionals.deinit(); | 6 | defer positionals.deinit(); |
| 6 | try positionals.ensureUnusedCapacity(comp.objects.len); | 7 | try positionals.ensureUnusedCapacity(comp.objects.len); |
| ... | @@ -19,7 +20,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]c | ... | @@ -19,7 +20,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]c |
| 19 | // TODO: in the future, when we implement `dsymutil` alternative directly in the Zig | 20 | // TODO: in the future, when we implement `dsymutil` alternative directly in the Zig |
| 20 | // compiler, investigate if we can get rid of this `if` prong here. | 21 | // compiler, investigate if we can get rid of this `if` prong here. |
| 21 | const path = positionals.items[0].path; | 22 | const path = positionals.items[0].path; |
| 22 | const in_file = try std.fs.cwd().openFile(path, .{}); | 23 | const in_file = try path.root_dir.handle.openFile(path.sub_path, .{}); |
| 23 | const stat = try in_file.stat(); | 24 | const stat = try in_file.stat(); |
| 24 | const amt = try in_file.copyRangeAll(0, macho_file.base.file.?, 0, stat.size); | 25 | const amt = try in_file.copyRangeAll(0, macho_file.base.file.?, 0, stat.size); |
| 25 | if (amt != stat.size) return error.InputOutput; // TODO: report an actual user error | 26 | if (amt != stat.size) return error.InputOutput; // TODO: report an actual user error |
| ... | @@ -72,7 +73,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]c | ... | @@ -72,7 +73,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]c |
| 72 | try writeHeader(macho_file, ncmds, sizeofcmds); | 73 | try writeHeader(macho_file, ncmds, sizeofcmds); |
| 73 | } | 74 | } |
| 74 | 75 | ||
| 75 | pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { | 76 | pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Path) link.File.FlushError!void { |
| 76 | const gpa = comp.gpa; | 77 | const gpa = comp.gpa; |
| 77 | 78 | ||
| 78 | var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); | 79 | var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); |
| ... | @@ -173,21 +174,25 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? | ... | @@ -173,21 +174,25 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? |
| 173 | 174 | ||
| 174 | for (files.items) |index| { | 175 | for (files.items) |index| { |
| 175 | const file = macho_file.getFile(index).?; | 176 | const file = macho_file.getFile(index).?; |
| 176 | const state = switch (file) { | 177 | switch (file) { |
| 177 | .zig_object => |x| &x.output_ar_state, | 178 | .zig_object => |zo| { |
| 178 | .object => |x| &x.output_ar_state, | 179 | const state = &zo.output_ar_state; |
| 180 | pos = mem.alignForward(usize, pos, 2); | ||
| 181 | state.file_off = pos; | ||
| 182 | pos += @sizeOf(Archive.ar_hdr); | ||
| 183 | pos += mem.alignForward(usize, zo.basename.len + 1, ptr_width); | ||
| 184 | pos += math.cast(usize, state.size) orelse return error.Overflow; | ||
| 185 | }, | ||
| 186 | .object => |o| { | ||
| 187 | const state = &o.output_ar_state; | ||
| 188 | pos = mem.alignForward(usize, pos, 2); | ||
| 189 | state.file_off = pos; | ||
| 190 | pos += @sizeOf(Archive.ar_hdr); | ||
| 191 | pos += mem.alignForward(usize, o.path.basename().len + 1, ptr_width); | ||
| 192 | pos += math.cast(usize, state.size) orelse return error.Overflow; | ||
| 193 | }, | ||
| 179 | else => unreachable, | 194 | else => unreachable, |
| 180 | }; | 195 | } |
| 181 | const path = switch (file) { | ||
| 182 | .zig_object => |x| x.path, | ||
| 183 | .object => |x| x.path, | ||
| 184 | else => unreachable, | ||
| 185 | }; | ||
| 186 | pos = mem.alignForward(usize, pos, 2); | ||
| 187 | state.file_off = pos; | ||
| 188 | pos += @sizeOf(Archive.ar_hdr); | ||
| 189 | pos += mem.alignForward(usize, path.len + 1, ptr_width); | ||
| 190 | pos += math.cast(usize, state.size) orelse return error.Overflow; | ||
| 191 | } | 196 | } |
| 192 | 197 | ||
| 193 | break :blk pos; | 198 | break :blk pos; |
| ... | @@ -777,6 +782,7 @@ const mem = std.mem; | ... | @@ -777,6 +782,7 @@ const mem = std.mem; |
| 777 | const state_log = std.log.scoped(.link_state); | 782 | const state_log = std.log.scoped(.link_state); |
| 778 | const std = @import("std"); | 783 | const std = @import("std"); |
| 779 | const trace = @import("../../tracy.zig").trace; | 784 | const trace = @import("../../tracy.zig").trace; |
| 785 | const Path = std.Build.Cache.Path; | ||
| 780 | 786 | ||
| 781 | const Archive = @import("Archive.zig"); | 787 | const Archive = @import("Archive.zig"); |
| 782 | const Atom = @import("Atom.zig"); | 788 | const Atom = @import("Atom.zig"); |
src/link/StringTable.zig+1-1| ... | @@ -15,7 +15,7 @@ pub fn insert(self: *Self, gpa: Allocator, string: []const u8) !u32 { | ... | @@ -15,7 +15,7 @@ pub fn insert(self: *Self, gpa: Allocator, string: []const u8) !u32 { |
| 15 | if (gop.found_existing) return gop.key_ptr.*; | 15 | if (gop.found_existing) return gop.key_ptr.*; |
| 16 | 16 | ||
| 17 | try self.buffer.ensureUnusedCapacity(gpa, string.len + 1); | 17 | try self.buffer.ensureUnusedCapacity(gpa, string.len + 1); |
| 18 | const new_off = @as(u32, @intCast(self.buffer.items.len)); | 18 | const new_off: u32 = @intCast(self.buffer.items.len); |
| 19 | 19 | ||
| 20 | self.buffer.appendSliceAssumeCapacity(string); | 20 | self.buffer.appendSliceAssumeCapacity(string); |
| 21 | self.buffer.appendAssumeCapacity(0); | 21 | self.buffer.appendAssumeCapacity(0); |
src/link/Wasm.zig+31-28| ... | @@ -2507,6 +2507,7 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_no | ... | @@ -2507,6 +2507,7 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_no |
| 2507 | } else null; | 2507 | } else null; |
| 2508 | 2508 | ||
| 2509 | // Positional arguments to the linker such as object files and static archives. | 2509 | // Positional arguments to the linker such as object files and static archives. |
| 2510 | // TODO: "positional arguments" is a CLI concept, not a linker concept. Delete this unnecessary array list. | ||
| 2510 | var positionals = std.ArrayList([]const u8).init(arena); | 2511 | var positionals = std.ArrayList([]const u8).init(arena); |
| 2511 | try positionals.ensureUnusedCapacity(comp.objects.len); | 2512 | try positionals.ensureUnusedCapacity(comp.objects.len); |
| 2512 | 2513 | ||
| ... | @@ -2527,23 +2528,23 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_no | ... | @@ -2527,23 +2528,23 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_no |
| 2527 | (output_mode == .Lib and link_mode == .dynamic); | 2528 | (output_mode == .Lib and link_mode == .dynamic); |
| 2528 | if (is_exe_or_dyn_lib) { | 2529 | if (is_exe_or_dyn_lib) { |
| 2529 | for (comp.wasi_emulated_libs) |crt_file| { | 2530 | for (comp.wasi_emulated_libs) |crt_file| { |
| 2530 | try positionals.append(try comp.get_libc_crt_file( | 2531 | try positionals.append(try comp.crtFileAsString( |
| 2531 | arena, | 2532 | arena, |
| 2532 | wasi_libc.emulatedLibCRFileLibName(crt_file), | 2533 | wasi_libc.emulatedLibCRFileLibName(crt_file), |
| 2533 | )); | 2534 | )); |
| 2534 | } | 2535 | } |
| 2535 | 2536 | ||
| 2536 | if (link_libc) { | 2537 | if (link_libc) { |
| 2537 | try positionals.append(try comp.get_libc_crt_file( | 2538 | try positionals.append(try comp.crtFileAsString( |
| 2538 | arena, | 2539 | arena, |
| 2539 | wasi_libc.execModelCrtFileFullName(wasi_exec_model), | 2540 | wasi_libc.execModelCrtFileFullName(wasi_exec_model), |
| 2540 | )); | 2541 | )); |
| 2541 | try positionals.append(try comp.get_libc_crt_file(arena, "libc.a")); | 2542 | try positionals.append(try comp.crtFileAsString(arena, "libc.a")); |
| 2542 | } | 2543 | } |
| 2543 | 2544 | ||
| 2544 | if (link_libcpp) { | 2545 | if (link_libcpp) { |
| 2545 | try positionals.append(comp.libcxx_static_lib.?.full_object_path); | 2546 | try positionals.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena)); |
| 2546 | try positionals.append(comp.libcxxabi_static_lib.?.full_object_path); | 2547 | try positionals.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena)); |
| 2547 | } | 2548 | } |
| 2548 | } | 2549 | } |
| 2549 | } | 2550 | } |
| ... | @@ -2553,15 +2554,15 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_no | ... | @@ -2553,15 +2554,15 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_no |
| 2553 | } | 2554 | } |
| 2554 | 2555 | ||
| 2555 | for (comp.objects) |object| { | 2556 | for (comp.objects) |object| { |
| 2556 | try positionals.append(object.path); | 2557 | try positionals.append(try object.path.toString(arena)); |
| 2557 | } | 2558 | } |
| 2558 | 2559 | ||
| 2559 | for (comp.c_object_table.keys()) |c_object| { | 2560 | for (comp.c_object_table.keys()) |c_object| { |
| 2560 | try positionals.append(c_object.status.success.object_path); | 2561 | try positionals.append(try c_object.status.success.object_path.toString(arena)); |
| 2561 | } | 2562 | } |
| 2562 | 2563 | ||
| 2563 | if (comp.compiler_rt_lib) |lib| try positionals.append(lib.full_object_path); | 2564 | if (comp.compiler_rt_lib) |lib| try positionals.append(try lib.full_object_path.toString(arena)); |
| 2564 | if (comp.compiler_rt_obj) |obj| try positionals.append(obj.full_object_path); | 2565 | if (comp.compiler_rt_obj) |obj| try positionals.append(try obj.full_object_path.toString(arena)); |
| 2565 | 2566 | ||
| 2566 | try wasm.parseInputFiles(positionals.items); | 2567 | try wasm.parseInputFiles(positionals.items); |
| 2567 | 2568 | ||
| ... | @@ -3365,7 +3366,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: | ... | @@ -3365,7 +3366,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: |
| 3365 | defer sub_prog_node.end(); | 3366 | defer sub_prog_node.end(); |
| 3366 | 3367 | ||
| 3367 | const is_obj = comp.config.output_mode == .Obj; | 3368 | const is_obj = comp.config.output_mode == .Obj; |
| 3368 | const compiler_rt_path: ?[]const u8 = blk: { | 3369 | const compiler_rt_path: ?Path = blk: { |
| 3369 | if (comp.compiler_rt_lib) |lib| break :blk lib.full_object_path; | 3370 | if (comp.compiler_rt_lib) |lib| break :blk lib.full_object_path; |
| 3370 | if (comp.compiler_rt_obj) |obj| break :blk obj.full_object_path; | 3371 | if (comp.compiler_rt_obj) |obj| break :blk obj.full_object_path; |
| 3371 | break :blk null; | 3372 | break :blk null; |
| ... | @@ -3387,14 +3388,14 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: | ... | @@ -3387,14 +3388,14 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: |
| 3387 | comptime assert(Compilation.link_hash_implementation_version == 14); | 3388 | comptime assert(Compilation.link_hash_implementation_version == 14); |
| 3388 | 3389 | ||
| 3389 | for (comp.objects) |obj| { | 3390 | for (comp.objects) |obj| { |
| 3390 | _ = try man.addFile(obj.path, null); | 3391 | _ = try man.addFilePath(obj.path, null); |
| 3391 | man.hash.add(obj.must_link); | 3392 | man.hash.add(obj.must_link); |
| 3392 | } | 3393 | } |
| 3393 | for (comp.c_object_table.keys()) |key| { | 3394 | for (comp.c_object_table.keys()) |key| { |
| 3394 | _ = try man.addFile(key.status.success.object_path, null); | 3395 | _ = try man.addFilePath(key.status.success.object_path, null); |
| 3395 | } | 3396 | } |
| 3396 | try man.addOptionalFile(module_obj_path); | 3397 | try man.addOptionalFile(module_obj_path); |
| 3397 | try man.addOptionalFile(compiler_rt_path); | 3398 | try man.addOptionalFilePath(compiler_rt_path); |
| 3398 | man.hash.addOptionalBytes(wasm.entry_name); | 3399 | man.hash.addOptionalBytes(wasm.entry_name); |
| 3399 | man.hash.add(wasm.base.stack_size); | 3400 | man.hash.add(wasm.base.stack_size); |
| 3400 | man.hash.add(wasm.base.build_id); | 3401 | man.hash.add(wasm.base.build_id); |
| ... | @@ -3450,17 +3451,19 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: | ... | @@ -3450,17 +3451,19 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: |
| 3450 | break :blk comp.c_object_table.keys()[0].status.success.object_path; | 3451 | break :blk comp.c_object_table.keys()[0].status.success.object_path; |
| 3451 | 3452 | ||
| 3452 | if (module_obj_path) |p| | 3453 | if (module_obj_path) |p| |
| 3453 | break :blk p; | 3454 | break :blk Path.initCwd(p); |
| 3454 | 3455 | ||
| 3455 | // TODO I think this is unreachable. Audit this situation when solving the above TODO | 3456 | // TODO I think this is unreachable. Audit this situation when solving the above TODO |
| 3456 | // regarding eliding redundant object -> object transformations. | 3457 | // regarding eliding redundant object -> object transformations. |
| 3457 | return error.NoObjectsToLink; | 3458 | return error.NoObjectsToLink; |
| 3458 | }; | 3459 | }; |
| 3459 | // This can happen when using --enable-cache and using the stage1 backend. In this case | 3460 | try std.fs.Dir.copyFile( |
| 3460 | // we can skip the file copy. | 3461 | the_object_path.root_dir.handle, |
| 3461 | if (!mem.eql(u8, the_object_path, full_out_path)) { | 3462 | the_object_path.sub_path, |
| 3462 | try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{}); | 3463 | directory.handle, |
| 3463 | } | 3464 | wasm.base.emit.sub_path, |
| 3465 | .{}, | ||
| 3466 | ); | ||
| 3464 | } else { | 3467 | } else { |
| 3465 | // Create an LLD command line and invoke it. | 3468 | // Create an LLD command line and invoke it. |
| 3466 | var argv = std.ArrayList([]const u8).init(gpa); | 3469 | var argv = std.ArrayList([]const u8).init(gpa); |
| ... | @@ -3581,23 +3584,23 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: | ... | @@ -3581,23 +3584,23 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: |
| 3581 | (comp.config.output_mode == .Lib and comp.config.link_mode == .dynamic); | 3584 | (comp.config.output_mode == .Lib and comp.config.link_mode == .dynamic); |
| 3582 | if (is_exe_or_dyn_lib) { | 3585 | if (is_exe_or_dyn_lib) { |
| 3583 | for (comp.wasi_emulated_libs) |crt_file| { | 3586 | for (comp.wasi_emulated_libs) |crt_file| { |
| 3584 | try argv.append(try comp.get_libc_crt_file( | 3587 | try argv.append(try comp.crtFileAsString( |
| 3585 | arena, | 3588 | arena, |
| 3586 | wasi_libc.emulatedLibCRFileLibName(crt_file), | 3589 | wasi_libc.emulatedLibCRFileLibName(crt_file), |
| 3587 | )); | 3590 | )); |
| 3588 | } | 3591 | } |
| 3589 | 3592 | ||
| 3590 | if (comp.config.link_libc) { | 3593 | if (comp.config.link_libc) { |
| 3591 | try argv.append(try comp.get_libc_crt_file( | 3594 | try argv.append(try comp.crtFileAsString( |
| 3592 | arena, | 3595 | arena, |
| 3593 | wasi_libc.execModelCrtFileFullName(comp.config.wasi_exec_model), | 3596 | wasi_libc.execModelCrtFileFullName(comp.config.wasi_exec_model), |
| 3594 | )); | 3597 | )); |
| 3595 | try argv.append(try comp.get_libc_crt_file(arena, "libc.a")); | 3598 | try argv.append(try comp.crtFileAsString(arena, "libc.a")); |
| 3596 | } | 3599 | } |
| 3597 | 3600 | ||
| 3598 | if (comp.config.link_libcpp) { | 3601 | if (comp.config.link_libcpp) { |
| 3599 | try argv.append(comp.libcxx_static_lib.?.full_object_path); | 3602 | try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena)); |
| 3600 | try argv.append(comp.libcxxabi_static_lib.?.full_object_path); | 3603 | try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena)); |
| 3601 | } | 3604 | } |
| 3602 | } | 3605 | } |
| 3603 | } | 3606 | } |
| ... | @@ -3612,7 +3615,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: | ... | @@ -3612,7 +3615,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: |
| 3612 | try argv.append("-no-whole-archive"); | 3615 | try argv.append("-no-whole-archive"); |
| 3613 | whole_archive = false; | 3616 | whole_archive = false; |
| 3614 | } | 3617 | } |
| 3615 | try argv.append(obj.path); | 3618 | try argv.append(try obj.path.toString(arena)); |
| 3616 | } | 3619 | } |
| 3617 | if (whole_archive) { | 3620 | if (whole_archive) { |
| 3618 | try argv.append("-no-whole-archive"); | 3621 | try argv.append("-no-whole-archive"); |
| ... | @@ -3620,7 +3623,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: | ... | @@ -3620,7 +3623,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: |
| 3620 | } | 3623 | } |
| 3621 | 3624 | ||
| 3622 | for (comp.c_object_table.keys()) |key| { | 3625 | for (comp.c_object_table.keys()) |key| { |
| 3623 | try argv.append(key.status.success.object_path); | 3626 | try argv.append(try key.status.success.object_path.toString(arena)); |
| 3624 | } | 3627 | } |
| 3625 | if (module_obj_path) |p| { | 3628 | if (module_obj_path) |p| { |
| 3626 | try argv.append(p); | 3629 | try argv.append(p); |
| ... | @@ -3630,11 +3633,11 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: | ... | @@ -3630,11 +3633,11 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: |
| 3630 | !comp.skip_linker_dependencies and | 3633 | !comp.skip_linker_dependencies and |
| 3631 | !comp.config.link_libc) | 3634 | !comp.config.link_libc) |
| 3632 | { | 3635 | { |
| 3633 | try argv.append(comp.libc_static_lib.?.full_object_path); | 3636 | try argv.append(try comp.libc_static_lib.?.full_object_path.toString(arena)); |
| 3634 | } | 3637 | } |
| 3635 | 3638 | ||
| 3636 | if (compiler_rt_path) |p| { | 3639 | if (compiler_rt_path) |p| { |
| 3637 | try argv.append(p); | 3640 | try argv.append(try p.toString(arena)); |
| 3638 | } | 3641 | } |
| 3639 | 3642 | ||
| 3640 | if (comp.verbose_link) { | 3643 | if (comp.verbose_link) { |
src/main.zig+24-23| ... | @@ -13,6 +13,12 @@ const warn = std.log.warn; | ... | @@ -13,6 +13,12 @@ const warn = std.log.warn; |
| 13 | const ThreadPool = std.Thread.Pool; | 13 | const ThreadPool = std.Thread.Pool; |
| 14 | const cleanExit = std.process.cleanExit; | 14 | const cleanExit = std.process.cleanExit; |
| 15 | const native_os = builtin.os.tag; | 15 | const native_os = builtin.os.tag; |
| 16 | const Cache = std.Build.Cache; | ||
| 17 | const Path = std.Build.Cache.Path; | ||
| 18 | const EnvVar = std.zig.EnvVar; | ||
| 19 | const LibCInstallation = std.zig.LibCInstallation; | ||
| 20 | const AstGen = std.zig.AstGen; | ||
| 21 | const Server = std.zig.Server; | ||
| 16 | 22 | ||
| 17 | const tracy = @import("tracy.zig"); | 23 | const tracy = @import("tracy.zig"); |
| 18 | const Compilation = @import("Compilation.zig"); | 24 | const Compilation = @import("Compilation.zig"); |
| ... | @@ -20,16 +26,11 @@ const link = @import("link.zig"); | ... | @@ -20,16 +26,11 @@ const link = @import("link.zig"); |
| 20 | const Package = @import("Package.zig"); | 26 | const Package = @import("Package.zig"); |
| 21 | const build_options = @import("build_options"); | 27 | const build_options = @import("build_options"); |
| 22 | const introspect = @import("introspect.zig"); | 28 | const introspect = @import("introspect.zig"); |
| 23 | const EnvVar = std.zig.EnvVar; | ||
| 24 | const LibCInstallation = std.zig.LibCInstallation; | ||
| 25 | const wasi_libc = @import("wasi_libc.zig"); | 29 | const wasi_libc = @import("wasi_libc.zig"); |
| 26 | const Cache = std.Build.Cache; | ||
| 27 | const target_util = @import("target.zig"); | 30 | const target_util = @import("target.zig"); |
| 28 | const crash_report = @import("crash_report.zig"); | 31 | const crash_report = @import("crash_report.zig"); |
| 29 | const Zcu = @import("Zcu.zig"); | 32 | const Zcu = @import("Zcu.zig"); |
| 30 | const AstGen = std.zig.AstGen; | ||
| 31 | const mingw = @import("mingw.zig"); | 33 | const mingw = @import("mingw.zig"); |
| 32 | const Server = std.zig.Server; | ||
| 33 | const dev = @import("dev.zig"); | 34 | const dev = @import("dev.zig"); |
| 34 | 35 | ||
| 35 | pub const std_options = .{ | 36 | pub const std_options = .{ |
| ... | @@ -1724,14 +1725,14 @@ fn buildOutputType( | ... | @@ -1724,14 +1725,14 @@ fn buildOutputType( |
| 1724 | } | 1725 | } |
| 1725 | } else switch (file_ext orelse Compilation.classifyFileExt(arg)) { | 1726 | } else switch (file_ext orelse Compilation.classifyFileExt(arg)) { |
| 1726 | .shared_library => { | 1727 | .shared_library => { |
| 1727 | try create_module.link_objects.append(arena, .{ .path = arg }); | 1728 | try create_module.link_objects.append(arena, .{ .path = Path.initCwd(arg) }); |
| 1728 | create_module.opts.any_dyn_libs = true; | 1729 | create_module.opts.any_dyn_libs = true; |
| 1729 | }, | 1730 | }, |
| 1730 | .object, .static_library => { | 1731 | .object, .static_library => { |
| 1731 | try create_module.link_objects.append(arena, .{ .path = arg }); | 1732 | try create_module.link_objects.append(arena, .{ .path = Path.initCwd(arg) }); |
| 1732 | }, | 1733 | }, |
| 1733 | .res => { | 1734 | .res => { |
| 1734 | try create_module.link_objects.append(arena, .{ .path = arg }); | 1735 | try create_module.link_objects.append(arena, .{ .path = Path.initCwd(arg) }); |
| 1735 | contains_res_file = true; | 1736 | contains_res_file = true; |
| 1736 | }, | 1737 | }, |
| 1737 | .manifest => { | 1738 | .manifest => { |
| ... | @@ -1845,20 +1846,20 @@ fn buildOutputType( | ... | @@ -1845,20 +1846,20 @@ fn buildOutputType( |
| 1845 | }, | 1846 | }, |
| 1846 | .shared_library => { | 1847 | .shared_library => { |
| 1847 | try create_module.link_objects.append(arena, .{ | 1848 | try create_module.link_objects.append(arena, .{ |
| 1848 | .path = it.only_arg, | 1849 | .path = Path.initCwd(it.only_arg), |
| 1849 | .must_link = must_link, | 1850 | .must_link = must_link, |
| 1850 | }); | 1851 | }); |
| 1851 | create_module.opts.any_dyn_libs = true; | 1852 | create_module.opts.any_dyn_libs = true; |
| 1852 | }, | 1853 | }, |
| 1853 | .unknown, .object, .static_library => { | 1854 | .unknown, .object, .static_library => { |
| 1854 | try create_module.link_objects.append(arena, .{ | 1855 | try create_module.link_objects.append(arena, .{ |
| 1855 | .path = it.only_arg, | 1856 | .path = Path.initCwd(it.only_arg), |
| 1856 | .must_link = must_link, | 1857 | .must_link = must_link, |
| 1857 | }); | 1858 | }); |
| 1858 | }, | 1859 | }, |
| 1859 | .res => { | 1860 | .res => { |
| 1860 | try create_module.link_objects.append(arena, .{ | 1861 | try create_module.link_objects.append(arena, .{ |
| 1861 | .path = it.only_arg, | 1862 | .path = Path.initCwd(it.only_arg), |
| 1862 | .must_link = must_link, | 1863 | .must_link = must_link, |
| 1863 | }); | 1864 | }); |
| 1864 | contains_res_file = true; | 1865 | contains_res_file = true; |
| ... | @@ -1894,7 +1895,7 @@ fn buildOutputType( | ... | @@ -1894,7 +1895,7 @@ fn buildOutputType( |
| 1894 | // binary: no extra rpaths and DSO filename exactly | 1895 | // binary: no extra rpaths and DSO filename exactly |
| 1895 | // as provided. Hello, Go. | 1896 | // as provided. Hello, Go. |
| 1896 | try create_module.link_objects.append(arena, .{ | 1897 | try create_module.link_objects.append(arena, .{ |
| 1897 | .path = it.only_arg, | 1898 | .path = Path.initCwd(it.only_arg), |
| 1898 | .must_link = must_link, | 1899 | .must_link = must_link, |
| 1899 | .loption = true, | 1900 | .loption = true, |
| 1900 | }); | 1901 | }); |
| ... | @@ -2532,7 +2533,7 @@ fn buildOutputType( | ... | @@ -2532,7 +2533,7 @@ fn buildOutputType( |
| 2532 | install_name = linker_args_it.nextOrFatal(); | 2533 | install_name = linker_args_it.nextOrFatal(); |
| 2533 | } else if (mem.eql(u8, arg, "-force_load")) { | 2534 | } else if (mem.eql(u8, arg, "-force_load")) { |
| 2534 | try create_module.link_objects.append(arena, .{ | 2535 | try create_module.link_objects.append(arena, .{ |
| 2535 | .path = linker_args_it.nextOrFatal(), | 2536 | .path = Path.initCwd(linker_args_it.nextOrFatal()), |
| 2536 | .must_link = true, | 2537 | .must_link = true, |
| 2537 | }); | 2538 | }); |
| 2538 | } else if (mem.eql(u8, arg, "-hash-style") or | 2539 | } else if (mem.eql(u8, arg, "-hash-style") or |
| ... | @@ -2707,7 +2708,7 @@ fn buildOutputType( | ... | @@ -2707,7 +2708,7 @@ fn buildOutputType( |
| 2707 | break :b create_module.c_source_files.items[0].src_path; | 2708 | break :b create_module.c_source_files.items[0].src_path; |
| 2708 | 2709 | ||
| 2709 | if (create_module.link_objects.items.len >= 1) | 2710 | if (create_module.link_objects.items.len >= 1) |
| 2710 | break :b create_module.link_objects.items[0].path; | 2711 | break :b create_module.link_objects.items[0].path.sub_path; |
| 2711 | 2712 | ||
| 2712 | if (emit_bin == .yes) | 2713 | if (emit_bin == .yes) |
| 2713 | break :b emit_bin.yes; | 2714 | break :b emit_bin.yes; |
| ... | @@ -2963,7 +2964,7 @@ fn buildOutputType( | ... | @@ -2963,7 +2964,7 @@ fn buildOutputType( |
| 2963 | framework_dir_path, | 2964 | framework_dir_path, |
| 2964 | framework_name, | 2965 | framework_name, |
| 2965 | )) { | 2966 | )) { |
| 2966 | const path = try arena.dupe(u8, test_path.items); | 2967 | const path = Path.initCwd(try arena.dupe(u8, test_path.items)); |
| 2967 | try resolved_frameworks.append(.{ | 2968 | try resolved_frameworks.append(.{ |
| 2968 | .needed = info.needed, | 2969 | .needed = info.needed, |
| 2969 | .weak = info.weak, | 2970 | .weak = info.weak, |
| ... | @@ -3635,7 +3636,7 @@ const CreateModule = struct { | ... | @@ -3635,7 +3636,7 @@ const CreateModule = struct { |
| 3635 | name: []const u8, | 3636 | name: []const u8, |
| 3636 | lib: Compilation.SystemLib, | 3637 | lib: Compilation.SystemLib, |
| 3637 | }), | 3638 | }), |
| 3638 | wasi_emulated_libs: std.ArrayListUnmanaged(wasi_libc.CRTFile), | 3639 | wasi_emulated_libs: std.ArrayListUnmanaged(wasi_libc.CrtFile), |
| 3639 | 3640 | ||
| 3640 | c_source_files: std.ArrayListUnmanaged(Compilation.CSourceFile), | 3641 | c_source_files: std.ArrayListUnmanaged(Compilation.CSourceFile), |
| 3641 | rc_source_files: std.ArrayListUnmanaged(Compilation.RcSourceFile), | 3642 | rc_source_files: std.ArrayListUnmanaged(Compilation.RcSourceFile), |
| ... | @@ -3808,7 +3809,7 @@ fn createModule( | ... | @@ -3808,7 +3809,7 @@ fn createModule( |
| 3808 | } | 3809 | } |
| 3809 | 3810 | ||
| 3810 | if (target.os.tag == .wasi) { | 3811 | if (target.os.tag == .wasi) { |
| 3811 | if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| { | 3812 | if (wasi_libc.getEmulatedLibCrtFile(lib_name)) |crt_file| { |
| 3812 | try create_module.wasi_emulated_libs.append(arena, crt_file); | 3813 | try create_module.wasi_emulated_libs.append(arena, crt_file); |
| 3813 | continue; | 3814 | continue; |
| 3814 | } | 3815 | } |
| ... | @@ -3929,7 +3930,7 @@ fn createModule( | ... | @@ -3929,7 +3930,7 @@ fn createModule( |
| 3929 | target, | 3930 | target, |
| 3930 | info.preferred_mode, | 3931 | info.preferred_mode, |
| 3931 | )) { | 3932 | )) { |
| 3932 | const path = try arena.dupe(u8, test_path.items); | 3933 | const path = Path.initCwd(try arena.dupe(u8, test_path.items)); |
| 3933 | switch (info.preferred_mode) { | 3934 | switch (info.preferred_mode) { |
| 3934 | .static => try create_module.link_objects.append(arena, .{ .path = path }), | 3935 | .static => try create_module.link_objects.append(arena, .{ .path = path }), |
| 3935 | .dynamic => try create_module.resolved_system_libs.append(arena, .{ | 3936 | .dynamic => try create_module.resolved_system_libs.append(arena, .{ |
| ... | @@ -3963,7 +3964,7 @@ fn createModule( | ... | @@ -3963,7 +3964,7 @@ fn createModule( |
| 3963 | target, | 3964 | target, |
| 3964 | info.fallbackMode(), | 3965 | info.fallbackMode(), |
| 3965 | )) { | 3966 | )) { |
| 3966 | const path = try arena.dupe(u8, test_path.items); | 3967 | const path = Path.initCwd(try arena.dupe(u8, test_path.items)); |
| 3967 | switch (info.fallbackMode()) { | 3968 | switch (info.fallbackMode()) { |
| 3968 | .static => try create_module.link_objects.append(arena, .{ .path = path }), | 3969 | .static => try create_module.link_objects.append(arena, .{ .path = path }), |
| 3969 | .dynamic => try create_module.resolved_system_libs.append(arena, .{ | 3970 | .dynamic => try create_module.resolved_system_libs.append(arena, .{ |
| ... | @@ -3997,7 +3998,7 @@ fn createModule( | ... | @@ -3997,7 +3998,7 @@ fn createModule( |
| 3997 | target, | 3998 | target, |
| 3998 | info.preferred_mode, | 3999 | info.preferred_mode, |
| 3999 | )) { | 4000 | )) { |
| 4000 | const path = try arena.dupe(u8, test_path.items); | 4001 | const path = Path.initCwd(try arena.dupe(u8, test_path.items)); |
| 4001 | switch (info.preferred_mode) { | 4002 | switch (info.preferred_mode) { |
| 4002 | .static => try create_module.link_objects.append(arena, .{ .path = path }), | 4003 | .static => try create_module.link_objects.append(arena, .{ .path = path }), |
| 4003 | .dynamic => try create_module.resolved_system_libs.append(arena, .{ | 4004 | .dynamic => try create_module.resolved_system_libs.append(arena, .{ |
| ... | @@ -4021,7 +4022,7 @@ fn createModule( | ... | @@ -4021,7 +4022,7 @@ fn createModule( |
| 4021 | target, | 4022 | target, |
| 4022 | info.fallbackMode(), | 4023 | info.fallbackMode(), |
| 4023 | )) { | 4024 | )) { |
| 4024 | const path = try arena.dupe(u8, test_path.items); | 4025 | const path = Path.initCwd(try arena.dupe(u8, test_path.items)); |
| 4025 | switch (info.fallbackMode()) { | 4026 | switch (info.fallbackMode()) { |
| 4026 | .static => try create_module.link_objects.append(arena, .{ .path = path }), | 4027 | .static => try create_module.link_objects.append(arena, .{ .path = path }), |
| 4027 | .dynamic => try create_module.resolved_system_libs.append(arena, .{ | 4028 | .dynamic => try create_module.resolved_system_libs.append(arena, .{ |
| ... | @@ -6163,7 +6164,7 @@ fn cmdAstCheck( | ... | @@ -6163,7 +6164,7 @@ fn cmdAstCheck( |
| 6163 | } | 6164 | } |
| 6164 | 6165 | ||
| 6165 | file.mod = try Package.Module.createLimited(arena, .{ | 6166 | file.mod = try Package.Module.createLimited(arena, .{ |
| 6166 | .root = Cache.Path.cwd(), | 6167 | .root = Path.cwd(), |
| 6167 | .root_src_path = file.sub_file_path, | 6168 | .root_src_path = file.sub_file_path, |
| 6168 | .fully_qualified_name = "root", | 6169 | .fully_qualified_name = "root", |
| 6169 | }); | 6170 | }); |
| ... | @@ -6523,7 +6524,7 @@ fn cmdChangelist( | ... | @@ -6523,7 +6524,7 @@ fn cmdChangelist( |
| 6523 | }; | 6524 | }; |
| 6524 | 6525 | ||
| 6525 | file.mod = try Package.Module.createLimited(arena, .{ | 6526 | file.mod = try Package.Module.createLimited(arena, .{ |
| 6526 | .root = Cache.Path.cwd(), | 6527 | .root = Path.cwd(), |
| 6527 | .root_src_path = file.sub_file_path, | 6528 | .root_src_path = file.sub_file_path, |
| 6528 | .fully_qualified_name = "root", | 6529 | .fully_qualified_name = "root", |
| 6529 | }); | 6530 | }); |
src/mingw.zig+23-19| ... | @@ -11,13 +11,13 @@ const build_options = @import("build_options"); | ... | @@ -11,13 +11,13 @@ const build_options = @import("build_options"); |
| 11 | const Cache = std.Build.Cache; | 11 | const Cache = std.Build.Cache; |
| 12 | const dev = @import("dev.zig"); | 12 | const dev = @import("dev.zig"); |
| 13 | 13 | ||
| 14 | pub const CRTFile = enum { | 14 | pub const CrtFile = enum { |
| 15 | crt2_o, | 15 | crt2_o, |
| 16 | dllcrt2_o, | 16 | dllcrt2_o, |
| 17 | mingw32_lib, | 17 | mingw32_lib, |
| 18 | }; | 18 | }; |
| 19 | 19 | ||
| 20 | pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: std.Progress.Node) !void { | 20 | pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progress.Node) !void { |
| 21 | if (!build_options.have_llvm) { | 21 | if (!build_options.have_llvm) { |
| 22 | return error.ZigCompilerNotBuiltWithLLVMExtensions; | 22 | return error.ZigCompilerNotBuiltWithLLVMExtensions; |
| 23 | } | 23 | } |
| ... | @@ -160,7 +160,9 @@ fn add_cc_args( | ... | @@ -160,7 +160,9 @@ fn add_cc_args( |
| 160 | pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { | 160 | pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { |
| 161 | dev.check(.build_import_lib); | 161 | dev.check(.build_import_lib); |
| 162 | 162 | ||
| 163 | var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); | 163 | const gpa = comp.gpa; |
| 164 | |||
| 165 | var arena_allocator = std.heap.ArenaAllocator.init(gpa); | ||
| 164 | defer arena_allocator.deinit(); | 166 | defer arena_allocator.deinit(); |
| 165 | const arena = arena_allocator.allocator(); | 167 | const arena = arena_allocator.allocator(); |
| 166 | 168 | ||
| ... | @@ -178,7 +180,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { | ... | @@ -178,7 +180,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { |
| 178 | 180 | ||
| 179 | // Use the global cache directory. | 181 | // Use the global cache directory. |
| 180 | var cache: Cache = .{ | 182 | var cache: Cache = .{ |
| 181 | .gpa = comp.gpa, | 183 | .gpa = gpa, |
| 182 | .manifest_dir = try comp.global_cache_directory.handle.makeOpenPath("h", .{}), | 184 | .manifest_dir = try comp.global_cache_directory.handle.makeOpenPath("h", .{}), |
| 183 | }; | 185 | }; |
| 184 | cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() }); | 186 | cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() }); |
| ... | @@ -195,17 +197,18 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { | ... | @@ -195,17 +197,18 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { |
| 195 | 197 | ||
| 196 | _ = try man.addFile(def_file_path, null); | 198 | _ = try man.addFile(def_file_path, null); |
| 197 | 199 | ||
| 198 | const final_lib_basename = try std.fmt.allocPrint(comp.gpa, "{s}.lib", .{lib_name}); | 200 | const final_lib_basename = try std.fmt.allocPrint(gpa, "{s}.lib", .{lib_name}); |
| 199 | errdefer comp.gpa.free(final_lib_basename); | 201 | errdefer gpa.free(final_lib_basename); |
| 200 | 202 | ||
| 201 | if (try man.hit()) { | 203 | if (try man.hit()) { |
| 202 | const digest = man.final(); | 204 | const digest = man.final(); |
| 203 | 205 | ||
| 204 | try comp.crt_files.ensureUnusedCapacity(comp.gpa, 1); | 206 | try comp.crt_files.ensureUnusedCapacity(gpa, 1); |
| 205 | comp.crt_files.putAssumeCapacityNoClobber(final_lib_basename, .{ | 207 | comp.crt_files.putAssumeCapacityNoClobber(final_lib_basename, .{ |
| 206 | .full_object_path = try comp.global_cache_directory.join(comp.gpa, &[_][]const u8{ | 208 | .full_object_path = .{ |
| 207 | "o", &digest, final_lib_basename, | 209 | .root_dir = comp.global_cache_directory, |
| 208 | }), | 210 | .sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename }), |
| 211 | }, | ||
| 209 | .lock = man.toOwnedLock(), | 212 | .lock = man.toOwnedLock(), |
| 210 | }); | 213 | }); |
| 211 | return; | 214 | return; |
| ... | @@ -230,7 +233,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { | ... | @@ -230,7 +233,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { |
| 230 | }; | 233 | }; |
| 231 | 234 | ||
| 232 | const aro = @import("aro"); | 235 | const aro = @import("aro"); |
| 233 | var aro_comp = aro.Compilation.init(comp.gpa, std.fs.cwd()); | 236 | var aro_comp = aro.Compilation.init(gpa, std.fs.cwd()); |
| 234 | defer aro_comp.deinit(); | 237 | defer aro_comp.deinit(); |
| 235 | 238 | ||
| 236 | const include_dir = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "def-include" }); | 239 | const include_dir = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "def-include" }); |
| ... | @@ -244,7 +247,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { | ... | @@ -244,7 +247,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { |
| 244 | nosuspend stderr.print("output path: {s}\n", .{def_final_path}) catch break :print; | 247 | nosuspend stderr.print("output path: {s}\n", .{def_final_path}) catch break :print; |
| 245 | } | 248 | } |
| 246 | 249 | ||
| 247 | try aro_comp.include_dirs.append(comp.gpa, include_dir); | 250 | try aro_comp.include_dirs.append(gpa, include_dir); |
| 248 | 251 | ||
| 249 | const builtin_macros = try aro_comp.generateBuiltinMacros(.include_system_defines); | 252 | const builtin_macros = try aro_comp.generateBuiltinMacros(.include_system_defines); |
| 250 | const user_macros = try aro_comp.addSourceFromBuffer("<command line>", target_defines); | 253 | const user_macros = try aro_comp.addSourceFromBuffer("<command line>", target_defines); |
| ... | @@ -271,17 +274,15 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { | ... | @@ -271,17 +274,15 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { |
| 271 | try pp.prettyPrintTokens(def_final_file.writer(), .result_only); | 274 | try pp.prettyPrintTokens(def_final_file.writer(), .result_only); |
| 272 | } | 275 | } |
| 273 | 276 | ||
| 274 | const lib_final_path = try comp.global_cache_directory.join(comp.gpa, &[_][]const u8{ | 277 | const lib_final_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename }); |
| 275 | "o", &digest, final_lib_basename, | 278 | errdefer gpa.free(lib_final_path); |
| 276 | }); | ||
| 277 | errdefer comp.gpa.free(lib_final_path); | ||
| 278 | 279 | ||
| 279 | if (!build_options.have_llvm) return error.ZigCompilerNotBuiltWithLLVMExtensions; | 280 | if (!build_options.have_llvm) return error.ZigCompilerNotBuiltWithLLVMExtensions; |
| 280 | const llvm_bindings = @import("codegen/llvm/bindings.zig"); | 281 | const llvm_bindings = @import("codegen/llvm/bindings.zig"); |
| 281 | const llvm = @import("codegen/llvm.zig"); | 282 | const llvm = @import("codegen/llvm.zig"); |
| 282 | const arch_tag = llvm.targetArch(target.cpu.arch); | 283 | const arch_tag = llvm.targetArch(target.cpu.arch); |
| 283 | const def_final_path_z = try arena.dupeZ(u8, def_final_path); | 284 | const def_final_path_z = try arena.dupeZ(u8, def_final_path); |
| 284 | const lib_final_path_z = try arena.dupeZ(u8, lib_final_path); | 285 | const lib_final_path_z = try comp.global_cache_directory.joinZ(arena, &.{lib_final_path}); |
| 285 | if (llvm_bindings.WriteImportLibrary(def_final_path_z.ptr, arch_tag, lib_final_path_z.ptr, true)) { | 286 | if (llvm_bindings.WriteImportLibrary(def_final_path_z.ptr, arch_tag, lib_final_path_z.ptr, true)) { |
| 286 | // TODO surface a proper error here | 287 | // TODO surface a proper error here |
| 287 | log.err("unable to turn {s}.def into {s}.lib", .{ lib_name, lib_name }); | 288 | log.err("unable to turn {s}.def into {s}.lib", .{ lib_name, lib_name }); |
| ... | @@ -292,8 +293,11 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { | ... | @@ -292,8 +293,11 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { |
| 292 | log.warn("failed to write cache manifest for DLL import {s}.lib: {s}", .{ lib_name, @errorName(err) }); | 293 | log.warn("failed to write cache manifest for DLL import {s}.lib: {s}", .{ lib_name, @errorName(err) }); |
| 293 | }; | 294 | }; |
| 294 | 295 | ||
| 295 | try comp.crt_files.putNoClobber(comp.gpa, final_lib_basename, .{ | 296 | try comp.crt_files.putNoClobber(gpa, final_lib_basename, .{ |
| 296 | .full_object_path = lib_final_path, | 297 | .full_object_path = .{ |
| 298 | .root_dir = comp.global_cache_directory, | ||
| 299 | .sub_path = lib_final_path, | ||
| 300 | }, | ||
| 297 | .lock = man.toOwnedLock(), | 301 | .lock = man.toOwnedLock(), |
| 298 | }); | 302 | }); |
| 299 | } | 303 | } |
src/musl.zig+2-2| ... | @@ -9,7 +9,7 @@ const archName = std.zig.target.muslArchName; | ... | @@ -9,7 +9,7 @@ const archName = std.zig.target.muslArchName; |
| 9 | const Compilation = @import("Compilation.zig"); | 9 | const Compilation = @import("Compilation.zig"); |
| 10 | const build_options = @import("build_options"); | 10 | const build_options = @import("build_options"); |
| 11 | 11 | ||
| 12 | pub const CRTFile = enum { | 12 | pub const CrtFile = enum { |
| 13 | crti_o, | 13 | crti_o, |
| 14 | crtn_o, | 14 | crtn_o, |
| 15 | crt1_o, | 15 | crt1_o, |
| ... | @@ -19,7 +19,7 @@ pub const CRTFile = enum { | ... | @@ -19,7 +19,7 @@ pub const CRTFile = enum { |
| 19 | libc_so, | 19 | libc_so, |
| 20 | }; | 20 | }; |
| 21 | 21 | ||
| 22 | pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: std.Progress.Node) !void { | 22 | pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progress.Node) !void { |
| 23 | if (!build_options.have_llvm) { | 23 | if (!build_options.have_llvm) { |
| 24 | return error.ZigCompilerNotBuiltWithLLVMExtensions; | 24 | return error.ZigCompilerNotBuiltWithLLVMExtensions; |
| 25 | } | 25 | } |
src/wasi_libc.zig+7-7| ... | @@ -6,7 +6,7 @@ const Allocator = std.mem.Allocator; | ... | @@ -6,7 +6,7 @@ const Allocator = std.mem.Allocator; |
| 6 | const Compilation = @import("Compilation.zig"); | 6 | const Compilation = @import("Compilation.zig"); |
| 7 | const build_options = @import("build_options"); | 7 | const build_options = @import("build_options"); |
| 8 | 8 | ||
| 9 | pub const CRTFile = enum { | 9 | pub const CrtFile = enum { |
| 10 | crt1_reactor_o, | 10 | crt1_reactor_o, |
| 11 | crt1_command_o, | 11 | crt1_command_o, |
| 12 | libc_a, | 12 | libc_a, |
| ... | @@ -16,7 +16,7 @@ pub const CRTFile = enum { | ... | @@ -16,7 +16,7 @@ pub const CRTFile = enum { |
| 16 | libwasi_emulated_signal_a, | 16 | libwasi_emulated_signal_a, |
| 17 | }; | 17 | }; |
| 18 | 18 | ||
| 19 | pub fn getEmulatedLibCRTFile(lib_name: []const u8) ?CRTFile { | 19 | pub fn getEmulatedLibCrtFile(lib_name: []const u8) ?CrtFile { |
| 20 | if (mem.eql(u8, lib_name, "wasi-emulated-process-clocks")) { | 20 | if (mem.eql(u8, lib_name, "wasi-emulated-process-clocks")) { |
| 21 | return .libwasi_emulated_process_clocks_a; | 21 | return .libwasi_emulated_process_clocks_a; |
| 22 | } | 22 | } |
| ... | @@ -32,7 +32,7 @@ pub fn getEmulatedLibCRTFile(lib_name: []const u8) ?CRTFile { | ... | @@ -32,7 +32,7 @@ pub fn getEmulatedLibCRTFile(lib_name: []const u8) ?CRTFile { |
| 32 | return null; | 32 | return null; |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | pub fn emulatedLibCRFileLibName(crt_file: CRTFile) []const u8 { | 35 | pub fn emulatedLibCRFileLibName(crt_file: CrtFile) []const u8 { |
| 36 | return switch (crt_file) { | 36 | return switch (crt_file) { |
| 37 | .libwasi_emulated_process_clocks_a => "libwasi-emulated-process-clocks.a", | 37 | .libwasi_emulated_process_clocks_a => "libwasi-emulated-process-clocks.a", |
| 38 | .libwasi_emulated_getpid_a => "libwasi-emulated-getpid.a", | 38 | .libwasi_emulated_getpid_a => "libwasi-emulated-getpid.a", |
| ... | @@ -42,10 +42,10 @@ pub fn emulatedLibCRFileLibName(crt_file: CRTFile) []const u8 { | ... | @@ -42,10 +42,10 @@ pub fn emulatedLibCRFileLibName(crt_file: CRTFile) []const u8 { |
| 42 | }; | 42 | }; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | pub fn execModelCrtFile(wasi_exec_model: std.builtin.WasiExecModel) CRTFile { | 45 | pub fn execModelCrtFile(wasi_exec_model: std.builtin.WasiExecModel) CrtFile { |
| 46 | return switch (wasi_exec_model) { | 46 | return switch (wasi_exec_model) { |
| 47 | .reactor => CRTFile.crt1_reactor_o, | 47 | .reactor => CrtFile.crt1_reactor_o, |
| 48 | .command => CRTFile.crt1_command_o, | 48 | .command => CrtFile.crt1_command_o, |
| 49 | }; | 49 | }; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| ... | @@ -57,7 +57,7 @@ pub fn execModelCrtFileFullName(wasi_exec_model: std.builtin.WasiExecModel) []co | ... | @@ -57,7 +57,7 @@ pub fn execModelCrtFileFullName(wasi_exec_model: std.builtin.WasiExecModel) []co |
| 57 | }; | 57 | }; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: std.Progress.Node) !void { | 60 | pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progress.Node) !void { |
| 61 | if (!build_options.have_llvm) { | 61 | if (!build_options.have_llvm) { |
| 62 | return error.ZigCompilerNotBuiltWithLLVMExtensions; | 62 | return error.ZigCompilerNotBuiltWithLLVMExtensions; |
| 63 | } | 63 | } |
test/link/elf.zig+7-7| ... | @@ -952,25 +952,25 @@ fn testEmitStaticLib(b: *Build, opts: Options) *Step { | ... | @@ -952,25 +952,25 @@ fn testEmitStaticLib(b: *Build, opts: Options) *Step { |
| 952 | 952 | ||
| 953 | const check = lib.checkObject(); | 953 | const check = lib.checkObject(); |
| 954 | check.checkInArchiveSymtab(); | 954 | check.checkInArchiveSymtab(); |
| 955 | check.checkExactPath("in object", obj1.getEmittedBin()); | 955 | check.checkExact("in object obj1.o"); |
| 956 | check.checkExact("foo"); | 956 | check.checkExact("foo"); |
| 957 | check.checkInArchiveSymtab(); | 957 | check.checkInArchiveSymtab(); |
| 958 | check.checkExactPath("in object", obj1.getEmittedBin()); | 958 | check.checkExact("in object obj1.o"); |
| 959 | check.checkExact("bar"); | 959 | check.checkExact("bar"); |
| 960 | check.checkInArchiveSymtab(); | 960 | check.checkInArchiveSymtab(); |
| 961 | check.checkExactPath("in object", obj1.getEmittedBin()); | 961 | check.checkExact("in object obj1.o"); |
| 962 | check.checkExact("fooBar"); | 962 | check.checkExact("fooBar"); |
| 963 | check.checkInArchiveSymtab(); | 963 | check.checkInArchiveSymtab(); |
| 964 | check.checkExactPath("in object", obj2.getEmittedBin()); | 964 | check.checkExact("in object obj2.o"); |
| 965 | check.checkExact("tentative"); | 965 | check.checkExact("tentative"); |
| 966 | check.checkInArchiveSymtab(); | 966 | check.checkInArchiveSymtab(); |
| 967 | check.checkExactPath("in object", obj3.getEmittedBin()); | 967 | check.checkExact("in object a_very_long_file_name_so_that_it_ends_up_in_strtab.o"); |
| 968 | check.checkExact("weakFoo"); | 968 | check.checkExact("weakFoo"); |
| 969 | check.checkInArchiveSymtab(); | 969 | check.checkInArchiveSymtab(); |
| 970 | check.checkExactPath("in object", obj3.getEmittedBin()); | 970 | check.checkExact("in object a_very_long_file_name_so_that_it_ends_up_in_strtab.o"); |
| 971 | check.checkExact("strongBar"); | 971 | check.checkExact("strongBar"); |
| 972 | check.checkInArchiveSymtab(); | 972 | check.checkInArchiveSymtab(); |
| 973 | check.checkExactPath("in object", obj3.getEmittedBin()); | 973 | check.checkExact("in object a_very_long_file_name_so_that_it_ends_up_in_strtab.o"); |
| 974 | check.checkExact("strongBarAlias"); | 974 | check.checkExact("strongBarAlias"); |
| 975 | test_step.dependOn(&check.step); | 975 | test_step.dependOn(&check.step); |
| 976 | 976 |
test/link/link.zig+1-1| ... | @@ -74,8 +74,8 @@ fn addCompileStep( | ... | @@ -74,8 +74,8 @@ fn addCompileStep( |
| 74 | .target = base.target, | 74 | .target = base.target, |
| 75 | .optimize = base.optimize, | 75 | .optimize = base.optimize, |
| 76 | .root_source_file = rsf: { | 76 | .root_source_file = rsf: { |
| 77 | const name = b.fmt("{s}.zig", .{overlay.name}); | ||
| 78 | const bytes = overlay.zig_source_bytes orelse break :rsf null; | 77 | const bytes = overlay.zig_source_bytes orelse break :rsf null; |
| 78 | const name = b.fmt("{s}.zig", .{overlay.name}); | ||
| 79 | break :rsf b.addWriteFiles().add(name, bytes); | 79 | break :rsf b.addWriteFiles().add(name, bytes); |
| 80 | }, | 80 | }, |
| 81 | .pic = overlay.pic, | 81 | .pic = overlay.pic, |