| 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 | 398 | return gop.index; |
| 399 | 399 | } |
| 400 | 400 | |
| 401 | /// Deprecated, use `addOptionalFilePath`. | |
| 401 | 402 | pub fn addOptionalFile(self: *Manifest, optional_file_path: ?[]const u8) !void { |
| 402 | 403 | self.hash.add(optional_file_path != null); |
| 403 | 404 | const file_path = optional_file_path orelse return; |
| 404 | 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 | 414 | pub fn addListOfFiles(self: *Manifest, list_of_files: []const []const u8) !void { |
| 408 | 415 | self.hash.add(list_of_files.len); |
| 409 | 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 | 11 | } |
| 12 | 12 | |
| 13 | 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 | 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 | 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 | 141 | pub fn format( |
| 130 | 142 | self: Path, |
| 131 | 143 | comptime fmt_string: []const u8, |
| ... | ... | @@ -137,7 +149,7 @@ pub fn format( |
| 137 | 149 | const stringEscape = std.zig.stringEscape; |
| 138 | 150 | const f = switch (fmt_string[0]) { |
| 139 | 151 | 'q' => "", |
| 140 | '\'' => '\'', | |
| 152 | '\'' => "\'", | |
| 141 | 153 | else => @compileError("unsupported format string: " ++ fmt_string), |
| 142 | 154 | }; |
| 143 | 155 | if (self.root_dir.path) |p| { |
| ... | ... | @@ -182,6 +194,14 @@ pub fn subPathOrDot(self: Path) []const u8 { |
| 182 | 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 | 205 | /// Useful to make `Path` a key in `std.ArrayHashMap`. |
| 186 | 206 | pub const TableAdapter = struct { |
| 187 | 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 | 557 | const check_object: *CheckObject = @fieldParentPtr("step", step); |
| 558 | 558 | try step.singleUnchangingWatchInput(check_object.source); |
| 559 | 559 | |
| 560 | const src_path = check_object.source.getPath2(b, step); | |
| 561 | const contents = fs.cwd().readFileAllocOptions( | |
| 560 | const src_path = check_object.source.getPath3(b, step); | |
| 561 | const contents = src_path.root_dir.handle.readFileAllocOptions( | |
| 562 | 562 | gpa, |
| 563 | src_path, | |
| 563 | src_path.sub_path, | |
| 564 | 564 | check_object.max_bytes, |
| 565 | 565 | null, |
| 566 | 566 | @alignOf(u64), |
| 567 | 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 | 570 | var vars = std.StringHashMap(u64).init(gpa); |
| 571 | 571 | for (check_object.checks.items) |chk| { |
| ... | ... | @@ -640,8 +640,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { |
| 640 | 640 | \\{s} |
| 641 | 641 | \\========= but parsed file does not contain it: ======= |
| 642 | 642 | \\{s} |
| 643 | \\====================================================== | |
| 644 | , .{ fmtMessageString(chk.kind, act.phrase.resolve(b, step)), fmtMessageString(chk.kind, output) }); | |
| 643 | \\========= file path: ================================= | |
| 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 | 660 | \\*{s}* |
| 656 | 661 | \\========= but parsed file does not contain it: ======= |
| 657 | 662 | \\{s} |
| 658 | \\====================================================== | |
| 659 | , .{ fmtMessageString(chk.kind, act.phrase.resolve(b, step)), fmtMessageString(chk.kind, output) }); | |
| 663 | \\========= file path: ================================= | |
| 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 | 679 | \\{s} |
| 670 | 680 | \\========= but parsed file does contain it: ======== |
| 671 | 681 | \\{s} |
| 672 | \\=================================================== | |
| 673 | , .{ fmtMessageString(chk.kind, act.phrase.resolve(b, step)), fmtMessageString(chk.kind, output) }); | |
| 682 | \\========= file path: ============================== | |
| 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 | 699 | \\{s} |
| 685 | 700 | \\========= but parsed file does not contain it: ======= |
| 686 | 701 | \\{s} |
| 687 | \\====================================================== | |
| 688 | , .{ act.phrase.resolve(b, step), fmtMessageString(chk.kind, output) }); | |
| 702 | \\========= file path: ============================== | |
| 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 | 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 | 1020 | const LibCInstallation = @This(); |
| 694 | 1021 | const std = @import("std"); |
| 695 | 1022 | const builtin = @import("builtin"); |
| 696 | 1023 | const Target = std.Target; |
| 697 | 1024 | const fs = std.fs; |
| 698 | 1025 | const Allocator = std.mem.Allocator; |
| 1026 | const Path = std.Build.Cache.Path; | |
| 699 | 1027 | |
| 700 | 1028 | const is_darwin = builtin.target.isDarwin(); |
| 701 | 1029 | const is_windows = builtin.target.os.tag == .windows; |
src/Compilation.zig+102-63| ... | ... | @@ -217,37 +217,37 @@ thread_pool: *ThreadPool, |
| 217 | 217 | |
| 218 | 218 | /// Populated when we build the libc++ static library. A Job to build this is placed in the queue |
| 219 | 219 | /// and resolved before calling linker.flush(). |
| 220 | libcxx_static_lib: ?CRTFile = null, | |
| 220 | libcxx_static_lib: ?CrtFile = null, | |
| 221 | 221 | /// Populated when we build the libc++abi static library. A Job to build this is placed in the queue |
| 222 | 222 | /// and resolved before calling linker.flush(). |
| 223 | libcxxabi_static_lib: ?CRTFile = null, | |
| 223 | libcxxabi_static_lib: ?CrtFile = null, | |
| 224 | 224 | /// Populated when we build the libunwind static library. A Job to build this is placed in the queue |
| 225 | 225 | /// and resolved before calling linker.flush(). |
| 226 | libunwind_static_lib: ?CRTFile = null, | |
| 226 | libunwind_static_lib: ?CrtFile = null, | |
| 227 | 227 | /// Populated when we build the TSAN library. A Job to build this is placed in the queue |
| 228 | 228 | /// and resolved before calling linker.flush(). |
| 229 | tsan_lib: ?CRTFile = null, | |
| 229 | tsan_lib: ?CrtFile = null, | |
| 230 | 230 | /// Populated when we build the libc static library. A Job to build this is placed in the queue |
| 231 | 231 | /// and resolved before calling linker.flush(). |
| 232 | libc_static_lib: ?CRTFile = null, | |
| 232 | libc_static_lib: ?CrtFile = null, | |
| 233 | 233 | /// Populated when we build the libcompiler_rt static library. A Job to build this is indicated |
| 234 | 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 | 236 | /// Populated when we build the compiler_rt_obj object. A Job to build this is indicated |
| 237 | 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 | 239 | /// Populated when we build the libfuzzer static library. A Job to build this |
| 240 | 240 | /// is indicated by setting `job_queued_fuzzer_lib` and resolved before |
| 241 | 241 | /// calling linker.flush(). |
| 242 | fuzzer_lib: ?CRTFile = null, | |
| 242 | fuzzer_lib: ?CrtFile = null, | |
| 243 | 243 | |
| 244 | 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 | 247 | /// For example `Scrt1.o` and `libc_nonshared.a`. These are populated after building libc from source, |
| 248 | 248 | /// The set of needed CRT (C runtime) files differs depending on the target and compilation settings. |
| 249 | 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 | 252 | /// How many lines of reference trace should be included per compile error. |
| 253 | 253 | /// Null means only show snippet on first error. |
| ... | ... | @@ -276,20 +276,20 @@ digest: ?[Cache.bin_digest_len]u8 = null, |
| 276 | 276 | pub const default_stack_protector_buffer_size = target_util.default_stack_protector_buffer_size; |
| 277 | 277 | pub const SemaError = Zcu.SemaError; |
| 278 | 278 | |
| 279 | pub const CRTFile = struct { | |
| 279 | pub const CrtFile = struct { | |
| 280 | 280 | lock: Cache.Lock, |
| 281 | full_object_path: []const u8, | |
| 281 | full_object_path: Path, | |
| 282 | 282 | |
| 283 | pub fn isObject(cf: CRTFile) bool { | |
| 284 | return switch (classifyFileExt(cf.full_object_path)) { | |
| 283 | pub fn isObject(cf: CrtFile) bool { | |
| 284 | return switch (classifyFileExt(cf.full_object_path.sub_path)) { | |
| 285 | 285 | .object => true, |
| 286 | 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 | 291 | self.lock.release(); |
| 292 | gpa.free(self.full_object_path); | |
| 292 | gpa.free(self.full_object_path.sub_path); | |
| 293 | 293 | self.* = undefined; |
| 294 | 294 | } |
| 295 | 295 | }; |
| ... | ... | @@ -369,13 +369,13 @@ const Job = union(enum) { |
| 369 | 369 | resolve_type_fully: InternPool.Index, |
| 370 | 370 | |
| 371 | 371 | /// one of the glibc static objects |
| 372 | glibc_crt_file: glibc.CRTFile, | |
| 372 | glibc_crt_file: glibc.CrtFile, | |
| 373 | 373 | /// all of the glibc shared objects |
| 374 | 374 | glibc_shared_objects, |
| 375 | 375 | /// one of the musl static objects |
| 376 | musl_crt_file: musl.CRTFile, | |
| 376 | musl_crt_file: musl.CrtFile, | |
| 377 | 377 | /// one of the mingw-w64 static objects |
| 378 | mingw_crt_file: mingw.CRTFile, | |
| 378 | mingw_crt_file: mingw.CrtFile, | |
| 379 | 379 | /// libunwind.a, usually needed when linking libc |
| 380 | 380 | libunwind: void, |
| 381 | 381 | libcxx: void, |
| ... | ... | @@ -385,7 +385,7 @@ const Job = union(enum) { |
| 385 | 385 | /// calls to, for example, memcpy and memset. |
| 386 | 386 | zig_libc: void, |
| 387 | 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 | 390 | /// The value is the index into `system_libs`. |
| 391 | 391 | windows_import_lib: usize, |
| ... | ... | @@ -422,8 +422,8 @@ pub const CObject = struct { |
| 422 | 422 | status: union(enum) { |
| 423 | 423 | new, |
| 424 | 424 | success: struct { |
| 425 | /// The outputted result. Owned by gpa. | |
| 426 | object_path: []u8, | |
| 425 | /// The outputted result. `sub_path` owned by gpa. | |
| 426 | object_path: Path, | |
| 427 | 427 | /// This is a file system lock on the cache hash manifest representing this |
| 428 | 428 | /// object. It prevents other invocations of the Zig compiler from interfering |
| 429 | 429 | /// with this object until released. |
| ... | ... | @@ -719,7 +719,7 @@ pub const CObject = struct { |
| 719 | 719 | return true; |
| 720 | 720 | }, |
| 721 | 721 | .success => |*success| { |
| 722 | gpa.free(success.object_path); | |
| 722 | gpa.free(success.object_path.sub_path); | |
| 723 | 723 | success.lock.release(); |
| 724 | 724 | self.status = .new; |
| 725 | 725 | return false; |
| ... | ... | @@ -1018,7 +1018,7 @@ const CacheUse = union(CacheMode) { |
| 1018 | 1018 | }; |
| 1019 | 1019 | |
| 1020 | 1020 | pub const LinkObject = struct { |
| 1021 | path: []const u8, | |
| 1021 | path: Path, | |
| 1022 | 1022 | must_link: bool = false, |
| 1023 | 1023 | // When the library is passed via a positional argument, it will be |
| 1024 | 1024 | // added as a full path. If it's `-l<lib>`, then just the basename. |
| ... | ... | @@ -1027,7 +1027,7 @@ pub const LinkObject = struct { |
| 1027 | 1027 | loption: bool = false, |
| 1028 | 1028 | |
| 1029 | 1029 | pub fn isObject(lo: LinkObject) bool { |
| 1030 | return switch (classifyFileExt(lo.path)) { | |
| 1030 | return switch (classifyFileExt(lo.path.sub_path)) { | |
| 1031 | 1031 | .object => true, |
| 1032 | 1032 | else => false, |
| 1033 | 1033 | }; |
| ... | ... | @@ -1095,7 +1095,7 @@ pub const CreateOptions = struct { |
| 1095 | 1095 | /// * getpid |
| 1096 | 1096 | /// * mman |
| 1097 | 1097 | /// * signal |
| 1098 | wasi_emulated_libs: []const wasi_libc.CRTFile = &.{}, | |
| 1098 | wasi_emulated_libs: []const wasi_libc.CrtFile = &.{}, | |
| 1099 | 1099 | /// This means that if the output mode is an executable it will be a |
| 1100 | 1100 | /// Position Independent Executable. If the output mode is not an |
| 1101 | 1101 | /// executable this field is ignored. |
| ... | ... | @@ -2302,7 +2302,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2302 | 2302 | try pt.processExports(); |
| 2303 | 2303 | } |
| 2304 | 2304 | |
| 2305 | if (try comp.totalErrorCount() != 0) { | |
| 2305 | if (anyErrors(comp)) { | |
| 2306 | 2306 | // Skip flushing and keep source files loaded for error reporting. |
| 2307 | 2307 | comp.link_error_flags = .{}; |
| 2308 | 2308 | return; |
| ... | ... | @@ -2392,6 +2392,10 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2392 | 2392 | .sub_path = o_sub_path, |
| 2393 | 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 | 2399 | // Failure here only means an unnecessary cache miss. |
| 2396 | 2400 | man.writeManifest() catch |err| { |
| 2397 | 2401 | log.warn("failed to write cache manifest: {s}", .{@errorName(err)}); |
| ... | ... | @@ -2578,7 +2582,7 @@ fn addNonIncrementalStuffToCacheManifest( |
| 2578 | 2582 | } |
| 2579 | 2583 | |
| 2580 | 2584 | for (comp.objects) |obj| { |
| 2581 | _ = try man.addFile(obj.path, null); | |
| 2585 | _ = try man.addFilePath(obj.path, null); | |
| 2582 | 2586 | man.hash.add(obj.must_link); |
| 2583 | 2587 | man.hash.add(obj.loption); |
| 2584 | 2588 | } |
| ... | ... | @@ -2703,9 +2707,8 @@ fn emitOthers(comp: *Compilation) void { |
| 2703 | 2707 | return; |
| 2704 | 2708 | } |
| 2705 | 2709 | const obj_path = comp.c_object_table.keys()[0].status.success.object_path; |
| 2706 | const cwd = std.fs.cwd(); | |
| 2707 | const ext = std.fs.path.extension(obj_path); | |
| 2708 | const basename = obj_path[0 .. obj_path.len - ext.len]; | |
| 2710 | const ext = std.fs.path.extension(obj_path.sub_path); | |
| 2711 | const dirname = obj_path.sub_path[0 .. obj_path.sub_path.len - ext.len]; | |
| 2709 | 2712 | // This obj path always ends with the object file extension, but if we change the |
| 2710 | 2713 | // extension to .ll, .bc, or .s, then it will be the path to those things. |
| 2711 | 2714 | const outs = [_]struct { |
| ... | ... | @@ -2720,13 +2723,13 @@ fn emitOthers(comp: *Compilation) void { |
| 2720 | 2723 | if (out.emit) |loc| { |
| 2721 | 2724 | if (loc.directory) |directory| { |
| 2722 | 2725 | const src_path = std.fmt.allocPrint(comp.gpa, "{s}{s}", .{ |
| 2723 | basename, out.ext, | |
| 2726 | dirname, out.ext, | |
| 2724 | 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 | 2729 | continue; |
| 2727 | 2730 | }; |
| 2728 | 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 | 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 | 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 | 3302 | fn totalErrorCount(comp: *Compilation) !u32 { |
| 3296 | 3303 | var errors = try comp.getAllErrorsAlloc(); |
| 3297 | 3304 | defer errors.deinit(comp.gpa); |
| ... | ... | @@ -3774,7 +3781,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre |
| 3774 | 3781 | const named_frame = tracy.namedFrame("glibc_crt_file"); |
| 3775 | 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 | 3785 | // TODO Surface more error details. |
| 3779 | 3786 | comp.lockAndSetMiscFailure(.glibc_crt_file, "unable to build glibc CRT file: {s}", .{ |
| 3780 | 3787 | @errorName(err), |
| ... | ... | @@ -3798,7 +3805,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre |
| 3798 | 3805 | const named_frame = tracy.namedFrame("musl_crt_file"); |
| 3799 | 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 | 3809 | // TODO Surface more error details. |
| 3803 | 3810 | comp.lockAndSetMiscFailure( |
| 3804 | 3811 | .musl_crt_file, |
| ... | ... | @@ -3811,7 +3818,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre |
| 3811 | 3818 | const named_frame = tracy.namedFrame("mingw_crt_file"); |
| 3812 | 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 | 3822 | // TODO Surface more error details. |
| 3816 | 3823 | comp.lockAndSetMiscFailure( |
| 3817 | 3824 | .mingw_crt_file, |
| ... | ... | @@ -3894,7 +3901,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre |
| 3894 | 3901 | const named_frame = tracy.namedFrame("wasi_libc_crt_file"); |
| 3895 | 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 | 3905 | // TODO Surface more error details. |
| 3899 | 3906 | comp.lockAndSetMiscFailure( |
| 3900 | 3907 | .wasi_libc_crt_file, |
| ... | ... | @@ -4602,7 +4609,7 @@ fn buildRt( |
| 4602 | 4609 | root_source_name: []const u8, |
| 4603 | 4610 | misc_task: MiscTask, |
| 4604 | 4611 | output_mode: std.builtin.OutputMode, |
| 4605 | out: *?CRTFile, | |
| 4612 | out: *?CrtFile, | |
| 4606 | 4613 | prog_node: std.Progress.Node, |
| 4607 | 4614 | ) void { |
| 4608 | 4615 | comp.buildOutputFromZig( |
| ... | ... | @@ -4703,7 +4710,9 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr |
| 4703 | 4710 | |
| 4704 | 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 | 4716 | // There was previous failure. |
| 4708 | 4717 | comp.mutex.lock(); |
| 4709 | 4718 | defer comp.mutex.unlock(); |
| ... | ... | @@ -4722,7 +4731,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr |
| 4722 | 4731 | |
| 4723 | 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 | 4735 | defer arena_allocator.deinit(); |
| 4727 | 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 | 4753 | const target = comp.getTarget(); |
| 4745 | 4754 | const o_ext = target.ofmt.fileExt(target.cpu.arch); |
| 4746 | 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 | 4757 | defer argv.deinit(); |
| 4749 | 4758 | |
| 4750 | 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 | 4917 | |
| 4909 | 4918 | switch (term) { |
| 4910 | 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 | 4921 | log.err("{}: failed to parse clang diagnostics: {s}", .{ err, stderr }); |
| 4913 | 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 | 4991 | |
| 4983 | 4992 | c_object.status = .{ |
| 4984 | 4993 | .success = .{ |
| 4985 | .object_path = try comp.local_cache_directory.join(comp.gpa, &[_][]const u8{ | |
| 4986 | "o", &digest, o_basename, | |
| 4987 | }), | |
| 4994 | .object_path = .{ | |
| 4995 | .root_dir = comp.local_cache_directory, | |
| 4996 | .sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, o_basename }), | |
| 4997 | }, | |
| 4988 | 4998 | .lock = man.toOwnedLock(), |
| 4989 | 4999 | }, |
| 4990 | 5000 | }; |
| ... | ... | @@ -6092,18 +6102,23 @@ test "classifyFileExt" { |
| 6092 | 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 { | |
| 6096 | if (comp.wantBuildGLibCFromSource() or | |
| 6097 | comp.wantBuildMuslFromSource() or | |
| 6098 | comp.wantBuildMinGWFromSource() or | |
| 6099 | comp.wantBuildWasiLibcFromSource()) | |
| 6100 | { | |
| 6101 | return comp.crt_files.get(basename).?.full_object_path; | |
| 6102 | } | |
| 6103 | const lci = comp.libc_installation orelse return error.LibCInstallationNotAvailable; | |
| 6104 | const crt_dir_path = lci.crt_dir orelse return error.LibCInstallationMissingCRTDir; | |
| 6105 | const full_path = try std.fs.path.join(arena, &[_][]const u8{ crt_dir_path, basename }); | |
| 6106 | return full_path; | |
| 6105 | pub fn get_libc_crt_file(comp: *Compilation, arena: Allocator, basename: []const u8) !Path { | |
| 6106 | return (try crtFilePath(comp, basename)) orelse { | |
| 6107 | const lci = comp.libc_installation orelse return error.LibCInstallationNotAvailable; | |
| 6108 | const crt_dir_path = lci.crt_dir orelse return error.LibCInstallationMissingCrtDir; | |
| 6109 | const full_path = try std.fs.path.join(arena, &[_][]const u8{ crt_dir_path, basename }); | |
| 6110 | return Path.initCwd(full_path); | |
| 6111 | }; | |
| 6112 | } | |
| 6113 | ||
| 6114 | pub fn crtFileAsString(comp: *Compilation, arena: Allocator, basename: []const u8) ![]const u8 { | |
| 6115 | const path = try get_libc_crt_file(comp, arena, basename); | |
| 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 | 6124 | fn wantBuildLibCFromSource(comp: Compilation) bool { |
| ... | ... | @@ -6314,7 +6329,7 @@ fn buildOutputFromZig( |
| 6314 | 6329 | comp: *Compilation, |
| 6315 | 6330 | src_basename: []const u8, |
| 6316 | 6331 | output_mode: std.builtin.OutputMode, |
| 6317 | out: *?CRTFile, | |
| 6332 | out: *?CrtFile, | |
| 6318 | 6333 | misc_task_tag: MiscTask, |
| 6319 | 6334 | prog_node: std.Progress.Node, |
| 6320 | 6335 | ) !void { |
| ... | ... | @@ -6542,15 +6557,39 @@ pub fn build_crt_file( |
| 6542 | 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 | 6561 | return .{ |
| 6547 | .full_object_path = try comp.local_cache_directory.join(comp.gpa, &.{ | |
| 6548 | comp.cache_use.whole.bin_sub_path.?, | |
| 6549 | }), | |
| 6562 | .full_object_path = .{ | |
| 6563 | .root_dir = comp.local_cache_directory, | |
| 6564 | .sub_path = try comp.gpa.dupe(u8, comp.cache_use.whole.bin_sub_path.?), | |
| 6565 | }, | |
| 6550 | 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 | 6593 | pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void { |
| 6555 | 6594 | // Avoid deadlocking on building import libs such as kernel32.lib |
| 6556 | 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 | 169 | }; |
| 170 | 170 | } |
| 171 | 171 | |
| 172 | pub const CRTFile = enum { | |
| 172 | pub const CrtFile = enum { | |
| 173 | 173 | crti_o, |
| 174 | 174 | crtn_o, |
| 175 | 175 | scrt1_o, |
| 176 | 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 | 180 | if (!build_options.have_llvm) { |
| 181 | 181 | return error.ZigCompilerNotBuiltWithLLVMExtensions; |
| 182 | 182 | } |
| ... | ... | @@ -292,7 +292,8 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: std.Progre |
| 292 | 292 | .owner = undefined, |
| 293 | 293 | }; |
| 294 | 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 | 298 | .libc_nonshared_a => { |
| 298 | 299 | const s = path.sep_str; |
src/link.zig+12-15| ... | ... | @@ -11,7 +11,7 @@ const wasi_libc = @import("wasi_libc.zig"); |
| 11 | 11 | const Air = @import("Air.zig"); |
| 12 | 12 | const Allocator = std.mem.Allocator; |
| 13 | 13 | const Cache = std.Build.Cache; |
| 14 | const Path = Cache.Path; | |
| 14 | const Path = std.Build.Cache.Path; | |
| 15 | 15 | const Compilation = @import("Compilation.zig"); |
| 16 | 16 | const LibCInstallation = std.zig.LibCInstallation; |
| 17 | 17 | const Liveness = @import("Liveness.zig"); |
| ... | ... | @@ -34,7 +34,7 @@ pub const SystemLib = struct { |
| 34 | 34 | /// 1. Windows DLLs that zig ships such as advapi32. |
| 35 | 35 | /// 2. extern "foo" fn declarations where we find out about libraries too late |
| 36 | 36 | /// TODO: make this non-optional and resolve those two cases somehow. |
| 37 | path: ?[]const u8, | |
| 37 | path: ?Path, | |
| 38 | 38 | }; |
| 39 | 39 | |
| 40 | 40 | pub fn hashAddSystemLibs( |
| ... | ... | @@ -46,7 +46,7 @@ pub fn hashAddSystemLibs( |
| 46 | 46 | for (hm.values()) |value| { |
| 47 | 47 | man.hash.add(value.needed); |
| 48 | 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 | 551 | LLDCrashed, |
| 552 | 552 | LLDReportedFailure, |
| 553 | 553 | LLD_LinkingIsTODO_ForSpirV, |
| 554 | LibCInstallationMissingCRTDir, | |
| 554 | LibCInstallationMissingCrtDir, | |
| 555 | 555 | LibCInstallationNotAvailable, |
| 556 | 556 | LinkingWithoutZigSourceUnimplemented, |
| 557 | 557 | MalformedArchive, |
| ... | ... | @@ -606,18 +606,15 @@ pub const File = struct { |
| 606 | 606 | const comp = base.comp; |
| 607 | 607 | if (comp.clang_preprocessor_mode == .yes or comp.clang_preprocessor_mode == .pch) { |
| 608 | 608 | dev.check(.clang_command); |
| 609 | const gpa = comp.gpa; | |
| 610 | 609 | const emit = base.emit; |
| 611 | 610 | // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case) |
| 612 | 611 | // Until then, we do `lld -r -o output.o input.o` even though the output is the same |
| 613 | 612 | // as the input. For the preprocessing case (`zig cc -E -o foo`) we copy the file |
| 614 | 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 | 614 | assert(comp.c_object_table.count() == 1); |
| 618 | 615 | const the_key = comp.c_object_table.keys()[0]; |
| 619 | 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 | 618 | return; |
| 622 | 619 | } |
| 623 | 620 | |
| ... | ... | @@ -781,7 +778,7 @@ pub const File = struct { |
| 781 | 778 | |
| 782 | 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 | 782 | comp.compiler_rt_obj.?.full_object_path |
| 786 | 783 | else |
| 787 | 784 | null; |
| ... | ... | @@ -806,18 +803,18 @@ pub const File = struct { |
| 806 | 803 | base.releaseLock(); |
| 807 | 804 | |
| 808 | 805 | for (objects) |obj| { |
| 809 | _ = try man.addFile(obj.path, null); | |
| 806 | _ = try man.addFilePath(obj.path, null); | |
| 810 | 807 | man.hash.add(obj.must_link); |
| 811 | 808 | man.hash.add(obj.loption); |
| 812 | 809 | } |
| 813 | 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 | 813 | for (comp.win32_resource_table.keys()) |key| { |
| 817 | 814 | _ = try man.addFile(key.status.success.res_path, null); |
| 818 | 815 | } |
| 819 | 816 | try man.addOptionalFile(zcu_obj_path); |
| 820 | try man.addOptionalFile(compiler_rt_path); | |
| 817 | try man.addOptionalFilePath(compiler_rt_path); | |
| 821 | 818 | |
| 822 | 819 | // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. |
| 823 | 820 | _ = try man.hit(); |
| ... | ... | @@ -851,10 +848,10 @@ pub const File = struct { |
| 851 | 848 | defer object_files.deinit(); |
| 852 | 849 | |
| 853 | 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 | 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 | 856 | for (comp.win32_resource_table.keys()) |key| { |
| 860 | 857 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.res_path)); |
| ... | ... | @@ -863,7 +860,7 @@ pub const File = struct { |
| 863 | 860 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); |
| 864 | 861 | } |
| 865 | 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 | 866 | if (comp.verbose_link) { |
src/link/Coff/lld.zig+25-22| ... | ... | @@ -7,6 +7,7 @@ const fs = std.fs; |
| 7 | 7 | const log = std.log.scoped(.link); |
| 8 | 8 | const mem = std.mem; |
| 9 | 9 | const Cache = std.Build.Cache; |
| 10 | const Path = std.Build.Cache.Path; | |
| 10 | 11 | |
| 11 | 12 | const mingw = @import("../../mingw.zig"); |
| 12 | 13 | const link = @import("../../link.zig"); |
| ... | ... | @@ -74,11 +75,11 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no |
| 74 | 75 | comptime assert(Compilation.link_hash_implementation_version == 14); |
| 75 | 76 | |
| 76 | 77 | for (comp.objects) |obj| { |
| 77 | _ = try man.addFile(obj.path, null); | |
| 78 | _ = try man.addFilePath(obj.path, null); | |
| 78 | 79 | man.hash.add(obj.must_link); |
| 79 | 80 | } |
| 80 | 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 | 84 | for (comp.win32_resource_table.keys()) |key| { |
| 84 | 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 | 155 | break :blk comp.c_object_table.keys()[0].status.success.object_path; |
| 155 | 156 | |
| 156 | 157 | if (module_obj_path) |p| |
| 157 | break :blk p; | |
| 158 | break :blk Path.initCwd(p); | |
| 158 | 159 | |
| 159 | 160 | // TODO I think this is unreachable. Audit this situation when solving the above TODO |
| 160 | 161 | // regarding eliding redundant object -> object transformations. |
| 161 | 162 | return error.NoObjectsToLink; |
| 162 | 163 | }; |
| 163 | // This can happen when using --enable-cache and using the stage1 backend. In this case | |
| 164 | // we can skip the file copy. | |
| 165 | if (!mem.eql(u8, the_object_path, full_out_path)) { | |
| 166 | try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{}); | |
| 167 | } | |
| 164 | try std.fs.Dir.copyFile( | |
| 165 | the_object_path.root_dir.handle, | |
| 166 | the_object_path.sub_path, | |
| 167 | directory.handle, | |
| 168 | self.base.emit.sub_path, | |
| 169 | .{}, | |
| 170 | ); | |
| 168 | 171 | } else { |
| 169 | 172 | // Create an LLD command line and invoke it. |
| 170 | 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 | 273 | try argv.ensureUnusedCapacity(comp.objects.len); |
| 271 | 274 | for (comp.objects) |obj| { |
| 272 | 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 | 277 | } else { |
| 275 | argv.appendAssumeCapacity(obj.path); | |
| 278 | argv.appendAssumeCapacity(try obj.path.toString(arena)); | |
| 276 | 279 | } |
| 277 | 280 | } |
| 278 | 281 | |
| 279 | 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 | 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 | 404 | } |
| 402 | 405 | |
| 403 | 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 | 408 | if (target.cpu.arch == .x86) { |
| 406 | 409 | try argv.append("-ALTERNATENAME:__DllMainCRTStartup@12=_DllMainCRTStartup@12"); |
| 407 | 410 | } else { |
| 408 | 411 | try argv.append("-ALTERNATENAME:_DllMainCRTStartup=DllMainCRTStartup"); |
| 409 | 412 | } |
| 410 | 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 | 418 | } else { |
| 416 | 419 | const lib_str = switch (comp.config.link_mode) { |
| 417 | 420 | .dynamic => "", |
| ... | ... | @@ -456,36 +459,36 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no |
| 456 | 459 | |
| 457 | 460 | // libc++ dep |
| 458 | 461 | if (comp.config.link_libcpp) { |
| 459 | try argv.append(comp.libcxxabi_static_lib.?.full_object_path); | |
| 460 | try argv.append(comp.libcxx_static_lib.?.full_object_path); | |
| 462 | try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena)); | |
| 463 | try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena)); | |
| 461 | 464 | } |
| 462 | 465 | |
| 463 | 466 | // libunwind dep |
| 464 | 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 | 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 | 475 | if (is_exe_or_dyn_lib and !comp.skip_linker_dependencies) { |
| 473 | 476 | if (!comp.config.link_libc) { |
| 474 | 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 | 481 | // MSVC compiler_rt is missing some stuff, so we build it unconditionally but |
| 479 | 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); | |
| 481 | if (comp.compiler_rt_lib) |lib| try argv.append(lib.full_object_path); | |
| 483 | if (comp.compiler_rt_obj) |obj| try argv.append(try obj.full_object_path.toString(arena)); | |
| 484 | if (comp.compiler_rt_lib) |lib| try argv.append(try lib.full_object_path.toString(arena)); | |
| 482 | 485 | } |
| 483 | 486 | |
| 484 | 487 | try argv.ensureUnusedCapacity(comp.system_libs.count()); |
| 485 | 488 | for (comp.system_libs.keys()) |key| { |
| 486 | 489 | const lib_basename = try allocPrint(arena, "{s}.lib", .{key}); |
| 487 | 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 | 492 | continue; |
| 490 | 493 | } |
| 491 | 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 | 383 | const index: File.Index = @intCast(try self.files.addOne(gpa)); |
| 384 | 384 | self.files.set(index, .{ .zig_object = .{ |
| 385 | 385 | .index = index, |
| 386 | .path = try std.fmt.allocPrint(arena, "{s}.o", .{fs.path.stem( | |
| 387 | zcu.main_mod.root_src_path, | |
| 388 | )}), | |
| 386 | .basename = try std.fmt.allocPrint(arena, "{s}.o", .{ | |
| 387 | fs.path.stem(zcu.main_mod.root_src_path), | |
| 388 | }), | |
| 389 | 389 | } }); |
| 390 | 390 | self.zig_object_index = index; |
| 391 | 391 | try self.zigObjectPtr().?.init(self, .{ |
| ... | ... | @@ -742,13 +742,12 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 742 | 742 | const target = self.getTarget(); |
| 743 | 743 | const link_mode = comp.config.link_mode; |
| 744 | 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: { | |
| 746 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); | |
| 747 | if (fs.path.dirname(full_out_path)) |dirname| { | |
| 748 | break :blk try fs.path.join(arena, &.{ dirname, path }); | |
| 749 | } else { | |
| 750 | break :blk path; | |
| 751 | } | |
| 745 | const module_obj_path: ?Path = if (self.base.zcu_object_sub_path) |path| .{ | |
| 746 | .root_dir = directory, | |
| 747 | .sub_path = if (fs.path.dirname(self.base.emit.sub_path)) |dirname| | |
| 748 | try fs.path.join(arena, &.{ dirname, path }) | |
| 749 | else | |
| 750 | path, | |
| 752 | 751 | } else null; |
| 753 | 752 | |
| 754 | 753 | // --verbose-link |
| ... | ... | @@ -758,7 +757,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 758 | 757 | if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, module_obj_path); |
| 759 | 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 | 762 | // csu prelude |
| 764 | 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 | 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 | 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 | 799 | // libc++ dep |
| 801 | 800 | if (comp.config.link_libcpp) { |
| 802 | try system_libs.ensureUnusedCapacity(2); | |
| 803 | system_libs.appendAssumeCapacity(.{ .path = comp.libcxxabi_static_lib.?.full_object_path }); | |
| 804 | system_libs.appendAssumeCapacity(.{ .path = comp.libcxx_static_lib.?.full_object_path }); | |
| 801 | try self.parseLibraryReportingFailure(.{ .path = comp.libcxxabi_static_lib.?.full_object_path }, false); | |
| 802 | try self.parseLibraryReportingFailure(.{ .path = comp.libcxx_static_lib.?.full_object_path }, false); | |
| 805 | 803 | } |
| 806 | 804 | |
| 807 | 805 | // libunwind dep |
| 808 | 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 | 810 | // libc dep |
| ... | ... | @@ -814,7 +812,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 814 | 812 | if (comp.config.link_libc) { |
| 815 | 813 | if (comp.libc_installation) |lc| { |
| 816 | 814 | const flags = target_util.libcFullLinkFlags(target); |
| 817 | try system_libs.ensureUnusedCapacity(flags.len); | |
| 818 | 815 | |
| 819 | 816 | var test_path = std.ArrayList(u8).init(arena); |
| 820 | 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 | 837 | continue; |
| 841 | 838 | } |
| 842 | 839 | |
| 843 | const resolved_path = try arena.dupe(u8, test_path.items); | |
| 844 | system_libs.appendAssumeCapacity(.{ .path = resolved_path }); | |
| 840 | const resolved_path = Path.initCwd(try arena.dupe(u8, test_path.items)); | |
| 841 | try self.parseLibraryReportingFailure(.{ .path = resolved_path }, false); | |
| 845 | 842 | } |
| 846 | 843 | } else if (target.isGnuLibC()) { |
| 847 | try system_libs.ensureUnusedCapacity(glibc.libs.len + 1); | |
| 848 | 844 | for (glibc.libs) |lib| { |
| 849 | 845 | if (lib.removed_in) |rem_in| { |
| 850 | 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 | 850 | comp.glibc_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover, |
| 855 | }); | |
| 856 | system_libs.appendAssumeCapacity(.{ .path = lib_path }); | |
| 851 | })); | |
| 852 | try self.parseLibraryReportingFailure(.{ .path = lib_path }, false); | |
| 857 | 853 | } |
| 858 | system_libs.appendAssumeCapacity(.{ | |
| 854 | try self.parseLibraryReportingFailure(.{ | |
| 859 | 855 | .path = try comp.get_libc_crt_file(arena, "libc_nonshared.a"), |
| 860 | }); | |
| 856 | }, false); | |
| 861 | 857 | } else if (target.isMusl()) { |
| 862 | 858 | const path = try comp.get_libc_crt_file(arena, switch (link_mode) { |
| 863 | 859 | .static => "libc.a", |
| 864 | 860 | .dynamic => "libc.so", |
| 865 | 861 | }); |
| 866 | try system_libs.append(.{ .path = path }); | |
| 862 | try self.parseLibraryReportingFailure(.{ .path = path }, false); | |
| 867 | 863 | } else { |
| 868 | 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 | 868 | // Finally, as the last input objects we add compiler_rt and CSU postlude (if any). |
| 877 | 869 | |
| 878 | 870 | // compiler-rt. Since compiler_rt exports symbols like `memset`, it needs |
| ... | ... | @@ -1066,10 +1058,10 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1066 | 1058 | } |
| 1067 | 1059 | } else null; |
| 1068 | 1060 | |
| 1069 | const csu = try CsuObjects.init(arena, comp); | |
| 1061 | const csu = try comp.getCrtPaths(arena); | |
| 1070 | 1062 | const compiler_rt_path: ?[]const u8 = blk: { |
| 1071 | if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; | |
| 1072 | if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; | |
| 1063 | if (comp.compiler_rt_lib) |x| break :blk try x.full_object_path.toString(arena); | |
| 1064 | if (comp.compiler_rt_obj) |x| break :blk try x.full_object_path.toString(arena); | |
| 1073 | 1065 | break :blk null; |
| 1074 | 1066 | }; |
| 1075 | 1067 | |
| ... | ... | @@ -1092,11 +1084,11 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1092 | 1084 | |
| 1093 | 1085 | if (self.base.isRelocatable()) { |
| 1094 | 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 | 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 | 1094 | if (module_obj_path) |p| { |
| ... | ... | @@ -1178,9 +1170,9 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1178 | 1170 | } |
| 1179 | 1171 | |
| 1180 | 1172 | // csu prelude |
| 1181 | if (csu.crt0) |v| try argv.append(v); | |
| 1182 | if (csu.crti) |v| try argv.append(v); | |
| 1183 | if (csu.crtbegin) |v| try argv.append(v); | |
| 1173 | if (csu.crt0) |path| try argv.append(try path.toString(arena)); | |
| 1174 | if (csu.crti) |path| try argv.append(try path.toString(arena)); | |
| 1175 | if (csu.crtbegin) |path| try argv.append(try path.toString(arena)); | |
| 1184 | 1176 | |
| 1185 | 1177 | for (self.lib_dirs) |lib_dir| { |
| 1186 | 1178 | try argv.append("-L"); |
| ... | ... | @@ -1205,10 +1197,9 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1205 | 1197 | } |
| 1206 | 1198 | |
| 1207 | 1199 | if (obj.loption) { |
| 1208 | assert(obj.path[0] == ':'); | |
| 1209 | 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 | 1204 | if (whole_archive) { |
| 1214 | 1205 | try argv.append("-no-whole-archive"); |
| ... | ... | @@ -1216,7 +1207,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1216 | 1207 | } |
| 1217 | 1208 | |
| 1218 | 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 | 1213 | if (module_obj_path) |p| { |
| ... | ... | @@ -1224,17 +1215,17 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1224 | 1215 | } |
| 1225 | 1216 | |
| 1226 | 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 | 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 | 1225 | // libc |
| 1235 | 1226 | if (!comp.skip_linker_dependencies and !comp.config.link_libc) { |
| 1236 | 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 | 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 | 1255 | if (!as_needed) { |
| ... | ... | @@ -1268,13 +1259,13 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1268 | 1259 | |
| 1269 | 1260 | // libc++ dep |
| 1270 | 1261 | if (comp.config.link_libcpp) { |
| 1271 | try argv.append(comp.libcxxabi_static_lib.?.full_object_path); | |
| 1272 | try argv.append(comp.libcxx_static_lib.?.full_object_path); | |
| 1262 | try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena)); | |
| 1263 | try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena)); | |
| 1273 | 1264 | } |
| 1274 | 1265 | |
| 1275 | 1266 | // libunwind dep |
| 1276 | 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 | 1271 | // libc dep |
| ... | ... | @@ -1295,9 +1286,9 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1295 | 1286 | }); |
| 1296 | 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 | 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 | 1292 | .static => "libc.a", |
| 1302 | 1293 | .dynamic => "libc.so", |
| 1303 | 1294 | })); |
| ... | ... | @@ -1310,8 +1301,8 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1310 | 1301 | } |
| 1311 | 1302 | |
| 1312 | 1303 | // crt postlude |
| 1313 | if (csu.crtend) |v| try argv.append(v); | |
| 1314 | if (csu.crtn) |v| try argv.append(v); | |
| 1304 | if (csu.crtend) |path| try argv.append(try path.toString(arena)); | |
| 1305 | if (csu.crtn) |path| try argv.append(try path.toString(arena)); | |
| 1315 | 1306 | } |
| 1316 | 1307 | |
| 1317 | 1308 | Compilation.dump_argv(argv.items); |
| ... | ... | @@ -1331,7 +1322,7 @@ pub const ParseError = error{ |
| 1331 | 1322 | UnknownFileType, |
| 1332 | 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 | 1326 | if (crt_file.isObject()) { |
| 1336 | 1327 | try parseObjectReportingFailure(self, crt_file.full_object_path); |
| 1337 | 1328 | } else { |
| ... | ... | @@ -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 | 1334 | self.parseObject(path) catch |err| switch (err) { |
| 1344 | 1335 | error.LinkFailure => return, // already reported |
| 1345 | 1336 | error.OutOfMemory => return error.OutOfMemory, |
| ... | ... | @@ -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 | 1362 | const tracy = trace(@src()); |
| 1372 | 1363 | defer tracy.end(); |
| 1373 | 1364 | |
| 1374 | 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 | 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 | 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 | 1375 | .file_handle = fh, |
| 1382 | 1376 | .index = index, |
| 1383 | 1377 | } }); |
| ... | ... | @@ -1387,15 +1381,15 @@ fn parseObject(self: *Elf, path: []const u8) ParseError!void { |
| 1387 | 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 | 1385 | const tracy = trace(@src()); |
| 1392 | 1386 | defer tracy.end(); |
| 1393 | 1387 | |
| 1394 | 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 | 1390 | const fh = try self.addFileHandle(handle); |
| 1397 | 1391 | |
| 1398 | var archive = Archive{}; | |
| 1392 | var archive: Archive = .{}; | |
| 1399 | 1393 | defer archive.deinit(gpa); |
| 1400 | 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 | 1397 | defer gpa.free(objects); |
| 1404 | 1398 | |
| 1405 | 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 | 1401 | self.files.set(index, .{ .object = extracted }); |
| 1408 | 1402 | const object = &self.files.items(.data)[index].object; |
| 1409 | 1403 | object.index = index; |
| ... | ... | @@ -1418,12 +1412,15 @@ fn parseSharedObject(self: *Elf, lib: SystemLib) ParseError!void { |
| 1418 | 1412 | defer tracy.end(); |
| 1419 | 1413 | |
| 1420 | 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 | 1416 | defer handle.close(); |
| 1423 | 1417 | |
| 1424 | 1418 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); |
| 1425 | 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 | 1424 | .index = index, |
| 1428 | 1425 | .needed = lib.needed, |
| 1429 | 1426 | .alive = lib.needed, |
| ... | ... | @@ -1439,12 +1436,12 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { |
| 1439 | 1436 | defer tracy.end(); |
| 1440 | 1437 | |
| 1441 | 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 | 1440 | defer in_file.close(); |
| 1444 | 1441 | const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32)); |
| 1445 | 1442 | defer gpa.free(data); |
| 1446 | 1443 | |
| 1447 | var script = LdScript{ .path = lib.path }; | |
| 1444 | var script: LdScript = .{ .path = lib.path }; | |
| 1448 | 1445 | defer script.deinit(gpa); |
| 1449 | 1446 | try script.parse(data, self); |
| 1450 | 1447 | |
| ... | ... | @@ -1455,12 +1452,12 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { |
| 1455 | 1452 | var test_path = std.ArrayList(u8).init(arena); |
| 1456 | 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 | 1456 | checked_paths.clearRetainingCapacity(); |
| 1460 | 1457 | |
| 1461 | 1458 | success: { |
| 1462 | if (mem.startsWith(u8, scr_obj.path, "-l")) { | |
| 1463 | const lib_name = scr_obj.path["-l".len..]; | |
| 1459 | if (mem.startsWith(u8, script_arg.path, "-l")) { | |
| 1460 | const lib_name = script_arg.path["-l".len..]; | |
| 1464 | 1461 | |
| 1465 | 1462 | // TODO I think technically we should re-use the mechanism used by the frontend here. |
| 1466 | 1463 | // Maybe we should hoist search-strategy all the way here? |
| ... | ... | @@ -1474,33 +1471,30 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { |
| 1474 | 1471 | } |
| 1475 | 1472 | } else { |
| 1476 | 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 | 1475 | test_path.clearRetainingCapacity(); |
| 1479 | 1476 | try test_path.writer().writeAll(path); |
| 1480 | 1477 | break :success; |
| 1481 | 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 | 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 | 1483 | break :success; |
| 1487 | 1484 | } |
| 1488 | 1485 | } |
| 1489 | 1486 | |
| 1490 | 1487 | try self.reportMissingLibraryError( |
| 1491 | 1488 | checked_paths.items, |
| 1492 | "missing library dependency: GNU ld script '{s}' requires '{s}', but file not found", | |
| 1493 | .{ | |
| 1494 | lib.path, | |
| 1495 | scr_obj.path, | |
| 1496 | }, | |
| 1489 | "missing library dependency: GNU ld script '{}' requires '{s}', but file not found", | |
| 1490 | .{ @as(Path, lib.path), script_arg.path }, | |
| 1497 | 1491 | ); |
| 1498 | 1492 | continue; |
| 1499 | 1493 | } |
| 1500 | 1494 | |
| 1501 | const full_path = test_path.items; | |
| 1495 | const full_path = Path.initCwd(test_path.items); | |
| 1502 | 1496 | self.parseLibrary(.{ |
| 1503 | .needed = scr_obj.needed, | |
| 1497 | .needed = script_arg.needed, | |
| 1504 | 1498 | .path = full_path, |
| 1505 | 1499 | }, false) catch |err| switch (err) { |
| 1506 | 1500 | error.LinkFailure => continue, // already reported |
| ... | ... | @@ -1841,7 +1835,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 1841 | 1835 | const have_dynamic_linker = comp.config.link_libc and |
| 1842 | 1836 | link_mode == .dynamic and is_exe_or_dyn_lib; |
| 1843 | 1837 | const target = self.getTarget(); |
| 1844 | const compiler_rt_path: ?[]const u8 = blk: { | |
| 1838 | const compiler_rt_path: ?Path = blk: { | |
| 1845 | 1839 | if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; |
| 1846 | 1840 | if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; |
| 1847 | 1841 | break :blk null; |
| ... | ... | @@ -1875,17 +1869,17 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 1875 | 1869 | man.hash.add(self.allow_undefined_version); |
| 1876 | 1870 | man.hash.addOptional(self.enable_new_dtags); |
| 1877 | 1871 | for (comp.objects) |obj| { |
| 1878 | _ = try man.addFile(obj.path, null); | |
| 1872 | _ = try man.addFilePath(obj.path, null); | |
| 1879 | 1873 | man.hash.add(obj.must_link); |
| 1880 | 1874 | man.hash.add(obj.loption); |
| 1881 | 1875 | } |
| 1882 | 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 | 1879 | try man.addOptionalFile(module_obj_path); |
| 1886 | try man.addOptionalFile(compiler_rt_path); | |
| 1887 | try man.addOptionalFile(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); | |
| 1880 | try man.addOptionalFilePath(compiler_rt_path); | |
| 1881 | try man.addOptionalFilePath(if (comp.tsan_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 | 1884 | // We can skip hashing libc and libc++ components that we are in charge of building from Zig |
| 1891 | 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 | 1976 | break :blk comp.c_object_table.keys()[0].status.success.object_path; |
| 1983 | 1977 | |
| 1984 | 1978 | if (module_obj_path) |p| |
| 1985 | break :blk p; | |
| 1979 | break :blk Path.initCwd(p); | |
| 1986 | 1980 | |
| 1987 | 1981 | // TODO I think this is unreachable. Audit this situation when solving the above TODO |
| 1988 | 1982 | // regarding eliding redundant object -> object transformations. |
| 1989 | 1983 | return error.NoObjectsToLink; |
| 1990 | 1984 | }; |
| 1991 | // This can happen when using --enable-cache and using the stage1 backend. In this case | |
| 1992 | // we can skip the file copy. | |
| 1993 | if (!mem.eql(u8, the_object_path, full_out_path)) { | |
| 1994 | try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{}); | |
| 1995 | } | |
| 1985 | try std.fs.Dir.copyFile( | |
| 1986 | the_object_path.root_dir.handle, | |
| 1987 | the_object_path.sub_path, | |
| 1988 | directory.handle, | |
| 1989 | self.base.emit.sub_path, | |
| 1990 | .{}, | |
| 1991 | ); | |
| 1996 | 1992 | } else { |
| 1997 | 1993 | // Create an LLD command line and invoke it. |
| 1998 | 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 | 2173 | try argv.append(full_out_path); |
| 2178 | 2174 | |
| 2179 | 2175 | // csu prelude |
| 2180 | const csu = try CsuObjects.init(arena, comp); | |
| 2181 | if (csu.crt0) |v| try argv.append(v); | |
| 2182 | if (csu.crti) |v| try argv.append(v); | |
| 2183 | if (csu.crtbegin) |v| try argv.append(v); | |
| 2176 | const csu = try comp.getCrtPaths(arena); | |
| 2177 | if (csu.crt0) |p| try argv.append(try p.toString(arena)); | |
| 2178 | if (csu.crti) |p| try argv.append(try p.toString(arena)); | |
| 2179 | if (csu.crtbegin) |p| try argv.append(try p.toString(arena)); | |
| 2184 | 2180 | |
| 2185 | 2181 | for (self.rpath_table.keys()) |rpath| { |
| 2186 | 2182 | try argv.appendSlice(&.{ "-rpath", rpath }); |
| ... | ... | @@ -2244,10 +2240,10 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2244 | 2240 | } |
| 2245 | 2241 | |
| 2246 | 2242 | if (obj.loption) { |
| 2247 | assert(obj.path[0] == ':'); | |
| 2243 | assert(obj.path.sub_path[0] == ':'); | |
| 2248 | 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 | 2248 | if (whole_archive) { |
| 2253 | 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 | 2251 | } |
| 2256 | 2252 | |
| 2257 | 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 | 2257 | if (module_obj_path) |p| { |
| ... | ... | @@ -2264,12 +2260,12 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2264 | 2260 | |
| 2265 | 2261 | if (comp.tsan_lib) |lib| { |
| 2266 | 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 | 2266 | if (comp.fuzzer_lib) |lib| { |
| 2271 | 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 | 2271 | // libc |
| ... | ... | @@ -2278,7 +2274,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2278 | 2274 | !comp.config.link_libc) |
| 2279 | 2275 | { |
| 2280 | 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 | 2307 | // libraries and not static libraries (the check for that needs to be earlier), |
| 2312 | 2308 | // but they could be full paths to .so files, in which case we |
| 2313 | 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 | 2313 | if (!as_needed) { |
| ... | ... | @@ -2321,13 +2317,13 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2321 | 2317 | |
| 2322 | 2318 | // libc++ dep |
| 2323 | 2319 | if (comp.config.link_libcpp) { |
| 2324 | try argv.append(comp.libcxxabi_static_lib.?.full_object_path); | |
| 2325 | try argv.append(comp.libcxx_static_lib.?.full_object_path); | |
| 2320 | try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena)); | |
| 2321 | try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena)); | |
| 2326 | 2322 | } |
| 2327 | 2323 | |
| 2328 | 2324 | // libunwind dep |
| 2329 | 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 | 2329 | // libc dep |
| ... | ... | @@ -2349,9 +2345,9 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2349 | 2345 | }); |
| 2350 | 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 | 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 | 2351 | .static => "libc.a", |
| 2356 | 2352 | .dynamic => "libc.so", |
| 2357 | 2353 | })); |
| ... | ... | @@ -2365,12 +2361,12 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2365 | 2361 | // to be after the shared libraries, so they are picked up from the shared |
| 2366 | 2362 | // libraries, not libcompiler_rt. |
| 2367 | 2363 | if (compiler_rt_path) |p| { |
| 2368 | try argv.append(p); | |
| 2364 | try argv.append(try p.toString(arena)); | |
| 2369 | 2365 | } |
| 2370 | 2366 | |
| 2371 | 2367 | // crt postlude |
| 2372 | if (csu.crtend) |v| try argv.append(v); | |
| 2373 | if (csu.crtn) |v| try argv.append(v); | |
| 2368 | if (csu.crtend) |p| try argv.append(try p.toString(arena)); | |
| 2369 | if (csu.crtn) |p| try argv.append(try p.toString(arena)); | |
| 2374 | 2370 | |
| 2375 | 2371 | if (self.base.allow_shlib_undefined) { |
| 2376 | 2372 | try argv.append("--allow-shlib-undefined"); |
| ... | ... | @@ -3183,8 +3179,9 @@ fn sortInitFini(self: *Elf) !void { |
| 3183 | 3179 | const object = atom_ptr.file(self).?.object; |
| 3184 | 3180 | const priority = blk: { |
| 3185 | 3181 | if (is_ctor_dtor) { |
| 3186 | if (mem.indexOf(u8, object.path, "crtbegin") != null) break :blk std.math.minInt(i32); | |
| 3187 | if (mem.indexOf(u8, object.path, "crtend") != null) break :blk std.math.maxInt(i32); | |
| 3182 | const basename = object.path.basename(); | |
| 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 | 3186 | const default: i32 = if (is_ctor_dtor) -1 else std.math.maxInt(i32); |
| 3190 | 3187 | const name = atom_ptr.name(self); |
| ... | ... | @@ -4472,210 +4469,6 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
| 4472 | 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 | 4472 | /// If a target compiles other output modes as dynamic libraries, |
| 4680 | 4473 | /// this function returns true for those too. |
| 4681 | 4474 | pub fn isEffectivelyDynLib(self: Elf) bool { |
| ... | ... | @@ -5089,13 +4882,13 @@ fn reportUnsupportedCpuArch(self: *Elf) error{OutOfMemory}!void { |
| 5089 | 4882 | |
| 5090 | 4883 | pub fn addParseError( |
| 5091 | 4884 | self: *Elf, |
| 5092 | path: []const u8, | |
| 4885 | path: Path, | |
| 5093 | 4886 | comptime format: []const u8, |
| 5094 | 4887 | args: anytype, |
| 5095 | 4888 | ) error{OutOfMemory}!void { |
| 5096 | 4889 | var err = try self.base.addErrorWithNotes(1); |
| 5097 | 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 | 4894 | pub fn addFileError( |
| ... | ... | @@ -5121,7 +4914,7 @@ pub fn failFile( |
| 5121 | 4914 | |
| 5122 | 4915 | pub fn failParse( |
| 5123 | 4916 | self: *Elf, |
| 5124 | path: []const u8, | |
| 4917 | path: Path, | |
| 5125 | 4918 | comptime format: []const u8, |
| 5126 | 4919 | args: anytype, |
| 5127 | 4920 | ) error{ OutOfMemory, LinkFailure } { |
| ... | ... | @@ -5274,7 +5067,7 @@ fn fmtDumpState( |
| 5274 | 5067 | _ = options; |
| 5275 | 5068 | |
| 5276 | 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 | 5071 | try writer.print("{}{}", .{ |
| 5279 | 5072 | zig_object.fmtAtoms(self), |
| 5280 | 5073 | zig_object.fmtSymtab(self), |
| ... | ... | @@ -5299,7 +5092,7 @@ fn fmtDumpState( |
| 5299 | 5092 | for (self.shared_objects.items) |index| { |
| 5300 | 5093 | const shared_object = self.file(index).?.shared_object; |
| 5301 | 5094 | try writer.print("shared_object({d}) : ", .{index}); |
| 5302 | try writer.print("{s}", .{shared_object.path}); | |
| 5095 | try writer.print("{}", .{shared_object.path}); | |
| 5303 | 5096 | try writer.print(" : needed({})", .{shared_object.needed}); |
| 5304 | 5097 | if (!shared_object.alive) try writer.writeAll(" : [*]"); |
| 5305 | 5098 | try writer.writeByte('\n'); |
| ... | ... | @@ -5482,7 +5275,7 @@ pub const null_shdr = elf.Elf64_Shdr{ |
| 5482 | 5275 | |
| 5483 | 5276 | pub const SystemLib = struct { |
| 5484 | 5277 | needed: bool = false, |
| 5485 | path: []const u8, | |
| 5278 | path: Path, | |
| 5486 | 5279 | }; |
| 5487 | 5280 | |
| 5488 | 5281 | pub const Ref = struct { |
src/link/Elf/Archive.zig+13-7| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | objects: std.ArrayListUnmanaged(Object) = .empty, |
| 2 | 2 | strtab: std.ArrayListUnmanaged(u8) = .empty, |
| 3 | 3 | |
| 4 | pub fn isArchive(path: []const u8) !bool { | |
| 5 | const file = try std.fs.cwd().openFile(path, .{}); | |
| 4 | pub fn isArchive(path: Path) !bool { | |
| 5 | const file = try path.root_dir.handle.openFile(path.sub_path, .{}); | |
| 6 | 6 | defer file.close(); |
| 7 | 7 | const reader = file.reader(); |
| 8 | 8 | const magic = reader.readBytesNoEof(elf.ARMAG.len) catch return false; |
| ... | ... | @@ -15,7 +15,7 @@ pub fn deinit(self: *Archive, allocator: Allocator) void { |
| 15 | 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 | 19 | const comp = elf_file.base.comp; |
| 20 | 20 | const gpa = comp.gpa; |
| 21 | 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 | 59 | else |
| 60 | 60 | unreachable; |
| 61 | 61 | |
| 62 | const object = Object{ | |
| 62 | const object: Object = .{ | |
| 63 | 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 | 68 | .offset = pos, |
| 66 | 69 | .size = obj_size, |
| 67 | 70 | }, |
| 68 | .path = try gpa.dupe(u8, name), | |
| 71 | .path = Path.initCwd(try gpa.dupe(u8, name)), | |
| 69 | 72 | .file_handle = handle_index, |
| 70 | 73 | .index = undefined, |
| 71 | 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 | 81 | try self.objects.append(gpa, object); |
| 77 | 82 | } |
| ... | ... | @@ -292,6 +297,7 @@ const elf = std.elf; |
| 292 | 297 | const fs = std.fs; |
| 293 | 298 | const log = std.log.scoped(.link); |
| 294 | 299 | const mem = std.mem; |
| 300 | const Path = std.Build.Cache.Path; | |
| 295 | 301 | |
| 296 | 302 | const Allocator = mem.Allocator; |
| 297 | 303 | const Archive = @This(); |
src/link/Elf/LdScript.zig+16-10| ... | ... | @@ -1,6 +1,11 @@ |
| 1 | path: []const u8, | |
| 1 | path: Path, | |
| 2 | 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 | 10 | pub fn deinit(scr: *LdScript, allocator: Allocator) void { |
| 6 | 11 | scr.args.deinit(allocator); |
| ... | ... | @@ -47,7 +52,7 @@ pub fn parse(scr: *LdScript, data: []const u8, elf_file: *Elf) Error!void { |
| 47 | 52 | |
| 48 | 53 | var it = TokenIterator{ .tokens = tokens.items }; |
| 49 | 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 | 56 | scr.doParse(.{ |
| 52 | 57 | .parser = &parser, |
| 53 | 58 | .args = &args, |
| ... | ... | @@ -70,7 +75,7 @@ pub fn parse(scr: *LdScript, data: []const u8, elf_file: *Elf) Error!void { |
| 70 | 75 | |
| 71 | 76 | fn doParse(scr: *LdScript, ctx: struct { |
| 72 | 77 | parser: *Parser, |
| 73 | args: *std.ArrayList(Elf.SystemLib), | |
| 78 | args: *std.ArrayList(Arg), | |
| 74 | 79 | }) !void { |
| 75 | 80 | while (true) { |
| 76 | 81 | ctx.parser.skipAny(&.{ .comment, .new_line }); |
| ... | ... | @@ -142,7 +147,7 @@ const Parser = struct { |
| 142 | 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 | 151 | if (!p.skip(&.{.lparen})) return error.UnexpectedToken; |
| 147 | 152 | |
| 148 | 153 | while (true) { |
| ... | ... | @@ -162,7 +167,7 @@ const Parser = struct { |
| 162 | 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 | 171 | if (!p.skip(&.{.lparen})) return error.UnexpectedToken; |
| 167 | 172 | |
| 168 | 173 | while (p.maybe(.literal)) |tok_id| { |
| ... | ... | @@ -239,7 +244,7 @@ const Token = struct { |
| 239 | 244 | |
| 240 | 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 | 248 | return source[tok.start..tok.end]; |
| 244 | 249 | } |
| 245 | 250 | }; |
| ... | ... | @@ -399,11 +404,11 @@ const TokenIterator = struct { |
| 399 | 404 | return it.tokens[it.pos]; |
| 400 | 405 | } |
| 401 | 406 | |
| 402 | inline fn reset(it: *TokenIterator) void { | |
| 407 | fn reset(it: *TokenIterator) void { | |
| 403 | 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 | 412 | it.pos = pos; |
| 408 | 413 | } |
| 409 | 414 | |
| ... | ... | @@ -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 | 425 | assert(pos < it.tokens.len); |
| 421 | 426 | return it.tokens[pos]; |
| 422 | 427 | } |
| ... | ... | @@ -426,6 +431,7 @@ const LdScript = @This(); |
| 426 | 431 | |
| 427 | 432 | const std = @import("std"); |
| 428 | 433 | const assert = std.debug.assert; |
| 434 | const Path = std.Build.Cache.Path; | |
| 429 | 435 | |
| 430 | 436 | const Allocator = std.mem.Allocator; |
| 431 | 437 | const Elf = @import("../Elf.zig"); |
src/link/Elf/Object.zig+14-13| ... | ... | @@ -1,5 +1,7 @@ |
| 1 | 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 | 5 | file_handle: File.HandleIndex, |
| 4 | 6 | index: File.Index, |
| 5 | 7 | |
| ... | ... | @@ -36,8 +38,8 @@ output_symtab_ctx: Elf.SymtabCtx = .{}, |
| 36 | 38 | output_ar_state: Archive.ArState = .{}, |
| 37 | 39 | |
| 38 | 40 | pub fn deinit(self: *Object, allocator: Allocator) void { |
| 39 | if (self.archive) |*ar| allocator.free(ar.path); | |
| 40 | allocator.free(self.path); | |
| 41 | if (self.archive) |*ar| allocator.free(ar.path.sub_path); | |
| 42 | allocator.free(self.path.sub_path); | |
| 41 | 43 | self.shdrs.deinit(allocator); |
| 42 | 44 | self.symtab.deinit(allocator); |
| 43 | 45 | self.strtab.deinit(allocator); |
| ... | ... | @@ -474,8 +476,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void { |
| 474 | 476 | if (sym.type(elf_file) != elf.STT_FUNC) |
| 475 | 477 | // TODO convert into an error |
| 476 | 478 | log.debug("{s}: {s}: CIE referencing external data reference", .{ |
| 477 | self.fmtPath(), | |
| 478 | sym.name(elf_file), | |
| 479 | self.fmtPath(), sym.name(elf_file), | |
| 479 | 480 | }); |
| 480 | 481 | sym.flags.needs_plt = true; |
| 481 | 482 | } |
| ... | ... | @@ -996,7 +997,7 @@ pub fn updateArSize(self: *Object, elf_file: *Elf) !void { |
| 996 | 997 | pub fn writeAr(self: Object, elf_file: *Elf, writer: anytype) !void { |
| 997 | 998 | const size = std.math.cast(usize, self.output_ar_state.size) orelse return error.Overflow; |
| 998 | 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 | 1001 | const hdr = Archive.setArHdr(.{ |
| 1001 | 1002 | .name = if (name.len <= Archive.max_member_name_len) |
| 1002 | 1003 | .{ .name = name } |
| ... | ... | @@ -1489,15 +1490,14 @@ fn formatPath( |
| 1489 | 1490 | _ = unused_fmt_string; |
| 1490 | 1491 | _ = options; |
| 1491 | 1492 | if (object.archive) |ar| { |
| 1492 | try writer.writeAll(ar.path); | |
| 1493 | try writer.writeByte('('); | |
| 1494 | try writer.writeAll(object.path); | |
| 1495 | try writer.writeByte(')'); | |
| 1496 | } else try writer.writeAll(object.path); | |
| 1493 | try writer.print("{}({})", .{ ar.path, object.path }); | |
| 1494 | } else { | |
| 1495 | try writer.print("{}", .{object.path}); | |
| 1496 | } | |
| 1497 | 1497 | } |
| 1498 | 1498 | |
| 1499 | 1499 | const InArchive = struct { |
| 1500 | path: []const u8, | |
| 1500 | path: Path, | |
| 1501 | 1501 | offset: u64, |
| 1502 | 1502 | size: u32, |
| 1503 | 1503 | }; |
| ... | ... | @@ -1512,8 +1512,9 @@ const fs = std.fs; |
| 1512 | 1512 | const log = std.log.scoped(.link); |
| 1513 | 1513 | const math = std.math; |
| 1514 | 1514 | const mem = std.mem; |
| 1515 | ||
| 1515 | const Path = std.Build.Cache.Path; | |
| 1516 | 1516 | const Allocator = mem.Allocator; |
| 1517 | ||
| 1517 | 1518 | const Archive = @import("Archive.zig"); |
| 1518 | 1519 | const Atom = @import("Atom.zig"); |
| 1519 | 1520 | const AtomList = @import("AtomList.zig"); |
src/link/Elf/SharedObject.zig+8-7| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | path: []const u8, | |
| 1 | path: Path, | |
| 2 | 2 | index: File.Index, |
| 3 | 3 | |
| 4 | 4 | header: ?elf.Elf64_Ehdr = null, |
| ... | ... | @@ -22,8 +22,8 @@ alive: bool, |
| 22 | 22 | |
| 23 | 23 | output_symtab_ctx: Elf.SymtabCtx = .{}, |
| 24 | 24 | |
| 25 | pub fn isSharedObject(path: []const u8) !bool { | |
| 26 | const file = try std.fs.cwd().openFile(path, .{}); | |
| 25 | pub fn isSharedObject(path: Path) !bool { | |
| 26 | const file = try path.root_dir.handle.openFile(path.sub_path, .{}); | |
| 27 | 27 | defer file.close(); |
| 28 | 28 | const reader = file.reader(); |
| 29 | 29 | const header = reader.readStruct(elf.Elf64_Ehdr) catch return false; |
| ... | ... | @@ -34,7 +34,7 @@ pub fn isSharedObject(path: []const u8) !bool { |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | 36 | pub fn deinit(self: *SharedObject, allocator: Allocator) void { |
| 37 | allocator.free(self.path); | |
| 37 | allocator.free(self.path.sub_path); | |
| 38 | 38 | self.shdrs.deinit(allocator); |
| 39 | 39 | self.symtab.deinit(allocator); |
| 40 | 40 | self.strtab.deinit(allocator); |
| ... | ... | @@ -319,7 +319,7 @@ pub fn asFile(self: *SharedObject) File { |
| 319 | 319 | |
| 320 | 320 | fn verdefNum(self: *SharedObject) u32 { |
| 321 | 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 | 323 | else => {}, |
| 324 | 324 | }; |
| 325 | 325 | return 0; |
| ... | ... | @@ -327,10 +327,10 @@ fn verdefNum(self: *SharedObject) u32 { |
| 327 | 327 | |
| 328 | 328 | pub fn soname(self: *SharedObject) []const u8 { |
| 329 | 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 | 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 | 336 | pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void { |
| ... | ... | @@ -508,6 +508,7 @@ const assert = std.debug.assert; |
| 508 | 508 | const elf = std.elf; |
| 509 | 509 | const log = std.log.scoped(.elf); |
| 510 | 510 | const mem = std.mem; |
| 511 | const Path = std.Build.Cache.Path; | |
| 511 | 512 | |
| 512 | 513 | const Allocator = mem.Allocator; |
| 513 | 514 | const Elf = @import("../Elf.zig"); |
src/link/Elf/ZigObject.zig+4-4| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | |
| 6 | 6 | data: std.ArrayListUnmanaged(u8) = .empty, |
| 7 | 7 | /// Externally owned memory. |
| 8 | path: []const u8, | |
| 8 | basename: []const u8, | |
| 9 | 9 | index: File.Index, |
| 10 | 10 | |
| 11 | 11 | symtab: std.MultiArrayList(ElfSym) = .{}, |
| ... | ... | @@ -88,7 +88,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { |
| 88 | 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 | 92 | const symbol_index = try self.newLocalSymbol(gpa, name_off); |
| 93 | 93 | const sym = self.symbol(symbol_index); |
| 94 | 94 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; |
| ... | ... | @@ -774,7 +774,7 @@ pub fn updateArSize(self: *ZigObject) void { |
| 774 | 774 | } |
| 775 | 775 | |
| 776 | 776 | pub fn writeAr(self: ZigObject, writer: anytype) !void { |
| 777 | const name = self.path; | |
| 777 | const name = self.basename; | |
| 778 | 778 | const hdr = Archive.setArHdr(.{ |
| 779 | 779 | .name = if (name.len <= Archive.max_member_name_len) |
| 780 | 780 | .{ .name = name } |
| ... | ... | @@ -2384,9 +2384,9 @@ const relocation = @import("relocation.zig"); |
| 2384 | 2384 | const target_util = @import("../../target.zig"); |
| 2385 | 2385 | const trace = @import("../../tracy.zig").trace; |
| 2386 | 2386 | const std = @import("std"); |
| 2387 | const Allocator = std.mem.Allocator; | |
| 2387 | 2388 | |
| 2388 | 2389 | const Air = @import("../../Air.zig"); |
| 2389 | const Allocator = std.mem.Allocator; | |
| 2390 | 2390 | const Archive = @import("Archive.zig"); |
| 2391 | 2391 | const Atom = @import("Atom.zig"); |
| 2392 | 2392 | const Dwarf = @import("../Dwarf.zig"); |
src/link/Elf/file.zig+20-18| ... | ... | @@ -23,10 +23,10 @@ pub const File = union(enum) { |
| 23 | 23 | _ = unused_fmt_string; |
| 24 | 24 | _ = options; |
| 25 | 25 | switch (file) { |
| 26 | .zig_object => |x| try writer.print("{s}", .{x.path}), | |
| 26 | .zig_object => |zo| try writer.writeAll(zo.basename), | |
| 27 | 27 | .linker_defined => try writer.writeAll("(linker defined)"), |
| 28 | 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 | 240 | return switch (file) { |
| 241 | 241 | .zig_object => |x| x.updateArSymtab(ar_symtab, elf_file), |
| 242 | 242 | .object => |x| x.updateArSymtab(ar_symtab, elf_file), |
| 243 | inline else => unreachable, | |
| 243 | else => unreachable, | |
| 244 | 244 | }; |
| 245 | 245 | } |
| 246 | 246 | |
| 247 | 247 | pub fn updateArStrtab(file: File, allocator: Allocator, ar_strtab: *Archive.ArStrtab) !void { |
| 248 | const path = switch (file) { | |
| 249 | .zig_object => |x| x.path, | |
| 250 | .object => |x| x.path, | |
| 251 | inline else => unreachable, | |
| 252 | }; | |
| 253 | const state = switch (file) { | |
| 254 | .zig_object => |x| &x.output_ar_state, | |
| 255 | .object => |x| &x.output_ar_state, | |
| 256 | inline else => unreachable, | |
| 257 | }; | |
| 258 | if (path.len <= Archive.max_member_name_len) return; | |
| 259 | state.name_off = try ar_strtab.insert(allocator, path); | |
| 248 | switch (file) { | |
| 249 | .zig_object => |zo| { | |
| 250 | const basename = zo.basename; | |
| 251 | if (basename.len <= Archive.max_member_name_len) return; | |
| 252 | zo.output_ar_state.name_off = try ar_strtab.insert(allocator, basename); | |
| 253 | }, | |
| 254 | .object => |o| { | |
| 255 | const basename = std.fs.path.basename(o.path.sub_path); | |
| 256 | if (basename.len <= Archive.max_member_name_len) return; | |
| 257 | o.output_ar_state.name_off = try ar_strtab.insert(allocator, basename); | |
| 258 | }, | |
| 259 | else => unreachable, | |
| 260 | } | |
| 260 | 261 | } |
| 261 | 262 | |
| 262 | 263 | pub fn updateArSize(file: File, elf_file: *Elf) !void { |
| 263 | 264 | return switch (file) { |
| 264 | 265 | .zig_object => |x| x.updateArSize(), |
| 265 | 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 | 272 | return switch (file) { |
| 272 | 273 | .zig_object => |x| x.writeAr(writer), |
| 273 | 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 | 293 | const std = @import("std"); |
| 293 | 294 | const elf = std.elf; |
| 294 | 295 | const log = std.log.scoped(.link); |
| 295 | ||
| 296 | const Path = std.Build.Cache.Path; | |
| 296 | 297 | const Allocator = std.mem.Allocator; |
| 298 | ||
| 297 | 299 | const Archive = @import("Archive.zig"); |
| 298 | 300 | const Atom = @import("Atom.zig"); |
| 299 | 301 | const Cie = @import("eh_frame.zig").Cie; |
src/link/Elf/relocatable.zig+15-11| ... | ... | @@ -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 | 2 | const gpa = comp.gpa; |
| 3 | 3 | |
| 4 | 4 | for (comp.objects) |obj| { |
| 5 | switch (Compilation.classifyFileExt(obj.path)) { | |
| 5 | switch (Compilation.classifyFileExt(obj.path.sub_path)) { | |
| 6 | 6 | .object => try parseObjectStaticLibReportingFailure(elf_file, obj.path), |
| 7 | 7 | .static_library => try parseArchiveStaticLibReportingFailure(elf_file, obj.path), |
| 8 | 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 | 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 | 144 | for (comp.objects) |obj| { |
| 145 | 145 | if (obj.isObject()) { |
| 146 | 146 | try elf_file.parseObjectReportingFailure(obj.path); |
| ... | ... | @@ -198,7 +198,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 198 | 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 | 202 | parseObjectStaticLib(elf_file, path) catch |err| switch (err) { |
| 203 | 203 | error.LinkFailure => return, |
| 204 | 204 | error.OutOfMemory => return error.OutOfMemory, |
| ... | ... | @@ -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 | 210 | parseArchiveStaticLib(elf_file, path) catch |err| switch (err) { |
| 211 | 211 | error.LinkFailure => return, |
| 212 | 212 | error.OutOfMemory => return error.OutOfMemory, |
| ... | ... | @@ -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 | 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 | 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 | 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 | 228 | .file_handle = fh, |
| 226 | 229 | .index = index, |
| 227 | 230 | } }); |
| ... | ... | @@ -231,9 +234,9 @@ fn parseObjectStaticLib(elf_file: *Elf, path: []const u8) Elf.ParseError!void { |
| 231 | 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 | 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 | 240 | const fh = try elf_file.addFileHandle(handle); |
| 238 | 241 | |
| 239 | 242 | var archive = Archive{}; |
| ... | ... | @@ -531,6 +534,7 @@ const log = std.log.scoped(.link); |
| 531 | 534 | const math = std.math; |
| 532 | 535 | const mem = std.mem; |
| 533 | 536 | const state_log = std.log.scoped(.link_state); |
| 537 | const Path = std.Build.Cache.Path; | |
| 534 | 538 | const std = @import("std"); |
| 535 | 539 | |
| 536 | 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 | 144 | pub const Framework = struct { |
| 145 | 145 | needed: bool = false, |
| 146 | 146 | weak: bool = false, |
| 147 | path: []const u8, | |
| 147 | path: Path, | |
| 148 | 148 | }; |
| 149 | 149 | |
| 150 | 150 | pub fn hashAddFrameworks(man: *Cache.Manifest, hm: []const Framework) !void { |
| 151 | 151 | for (hm) |value| { |
| 152 | 152 | man.hash.add(value.needed); |
| 153 | 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 | 239 | const index: File.Index = @intCast(try self.files.addOne(gpa)); |
| 240 | 240 | self.files.set(index, .{ .zig_object = .{ |
| 241 | 241 | .index = index, |
| 242 | .path = try std.fmt.allocPrint(arena, "{s}.o", .{fs.path.stem( | |
| 243 | zcu.main_mod.root_src_path, | |
| 244 | )}), | |
| 242 | .basename = try std.fmt.allocPrint(arena, "{s}.o", .{ | |
| 243 | fs.path.stem(zcu.main_mod.root_src_path), | |
| 244 | }), | |
| 245 | 245 | } }); |
| 246 | 246 | self.zig_object = index; |
| 247 | 247 | const zo = self.getZigObject().?; |
| ... | ... | @@ -356,13 +356,12 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 356 | 356 | defer sub_prog_node.end(); |
| 357 | 357 | |
| 358 | 358 | const directory = self.base.emit.root_dir; |
| 359 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); | |
| 360 | const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: { | |
| 361 | if (fs.path.dirname(full_out_path)) |dirname| { | |
| 362 | break :blk try fs.path.join(arena, &.{ dirname, path }); | |
| 363 | } else { | |
| 364 | break :blk path; | |
| 365 | } | |
| 359 | const module_obj_path: ?Path = if (self.base.zcu_object_sub_path) |path| .{ | |
| 360 | .root_dir = directory, | |
| 361 | .sub_path = if (fs.path.dirname(self.base.emit.sub_path)) |dirname| | |
| 362 | try fs.path.join(arena, &.{ dirname, path }) | |
| 363 | else | |
| 364 | path, | |
| 366 | 365 | } else null; |
| 367 | 366 | |
| 368 | 367 | // --verbose-link |
| ... | ... | @@ -455,7 +454,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 455 | 454 | } |
| 456 | 455 | |
| 457 | 456 | // Finally, link against compiler_rt. |
| 458 | const compiler_rt_path: ?[]const u8 = blk: { | |
| 457 | const compiler_rt_path: ?Path = blk: { | |
| 459 | 458 | if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; |
| 460 | 459 | if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; |
| 461 | 460 | break :blk null; |
| ... | ... | @@ -567,7 +566,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 567 | 566 | // The most important here is to have the correct vm and filesize of the __LINKEDIT segment |
| 568 | 567 | // where the code signature goes into. |
| 569 | 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 | 570 | if (self.entitlements) |path| try codesig.addEntitlements(gpa, path); |
| 572 | 571 | try self.writeCodeSignaturePadding(&codesig); |
| 573 | 572 | break :blk codesig; |
| ... | ... | @@ -625,11 +624,11 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 625 | 624 | |
| 626 | 625 | if (self.base.isRelocatable()) { |
| 627 | 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 | 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 | 634 | if (module_obj_path) |p| { |
| ... | ... | @@ -711,11 +710,11 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 711 | 710 | if (obj.must_link) { |
| 712 | 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 | 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 | 720 | if (module_obj_path) |p| { |
| ... | ... | @@ -723,13 +722,12 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 723 | 722 | } |
| 724 | 723 | |
| 725 | 724 | if (comp.config.any_sanitize_thread) { |
| 726 | const path = comp.tsan_lib.?.full_object_path; | |
| 727 | try argv.append(path); | |
| 728 | try argv.appendSlice(&.{ "-rpath", std.fs.path.dirname(path) orelse "." }); | |
| 725 | const path = try comp.tsan_lib.?.full_object_path.toString(arena); | |
| 726 | try argv.appendSlice(&.{ path, "-rpath", std.fs.path.dirname(path) orelse "." }); | |
| 729 | 727 | } |
| 730 | 728 | |
| 731 | 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 | 733 | for (self.lib_dirs) |lib_dir| { |
| ... | ... | @@ -754,7 +752,7 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 754 | 752 | } |
| 755 | 753 | |
| 756 | 754 | for (self.frameworks) |framework| { |
| 757 | const name = fs.path.stem(framework.path); | |
| 755 | const name = framework.path.stem(); | |
| 758 | 756 | const arg = if (framework.needed) |
| 759 | 757 | try std.fmt.allocPrint(arena, "-needed_framework {s}", .{name}) |
| 760 | 758 | else if (framework.weak) |
| ... | ... | @@ -765,14 +763,16 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 765 | 763 | } |
| 766 | 764 | |
| 767 | 765 | if (comp.config.link_libcpp) { |
| 768 | try argv.append(comp.libcxxabi_static_lib.?.full_object_path); | |
| 769 | try argv.append(comp.libcxx_static_lib.?.full_object_path); | |
| 766 | try argv.appendSlice(&.{ | |
| 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 | 772 | try argv.append("-lSystem"); |
| 773 | 773 | |
| 774 | if (comp.compiler_rt_lib) |lib| try argv.append(lib.full_object_path); | |
| 775 | if (comp.compiler_rt_obj) |obj| try argv.append(obj.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(try obj.full_object_path.toString(arena)); | |
| 776 | 776 | } |
| 777 | 777 | |
| 778 | 778 | Compilation.dump_argv(argv.items); |
| ... | ... | @@ -807,20 +807,20 @@ pub fn resolveLibSystem( |
| 807 | 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 | 811 | try out_libs.append(.{ |
| 812 | 812 | .needed = true, |
| 813 | 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 | 818 | const tracy = trace(@src()); |
| 819 | 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 | 824 | const fh = try self.addFileHandle(file); |
| 825 | 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 | 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 | 848 | const fat_h = fat.readFatHeader(file) catch return null; |
| 849 | 849 | if (fat_h.magic != macho.FAT_MAGIC and fat_h.magic != macho.FAT_MAGIC_64) return null; |
| 850 | 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 | 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 | 877 | const tracy = trace(@src()); |
| 878 | 878 | defer tracy.end(); |
| 879 | 879 | |
| ... | ... | @@ -886,7 +886,10 @@ fn addObject(self: *MachO, path: []const u8, handle: File.HandleIndex, offset: u |
| 886 | 886 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); |
| 887 | 887 | self.files.set(index, .{ .object = .{ |
| 888 | 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 | 893 | .file_handle = handle, |
| 891 | 894 | .mtime = mtime, |
| 892 | 895 | .index = index, |
| ... | ... | @@ -937,7 +940,7 @@ fn addArchive(self: *MachO, lib: SystemLib, must_link: bool, handle: File.Handle |
| 937 | 940 | |
| 938 | 941 | const gpa = self.base.comp.gpa; |
| 939 | 942 | |
| 940 | var archive = Archive{}; | |
| 943 | var archive: Archive = .{}; | |
| 941 | 944 | defer archive.deinit(gpa); |
| 942 | 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 | 966 | .offset = offset, |
| 964 | 967 | .file_handle = handle, |
| 965 | 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 | 973 | .index = index, |
| 968 | 974 | .needed = lib.needed, |
| 969 | 975 | .weak = lib.weak, |
| ... | ... | @@ -986,7 +992,10 @@ fn addTbd(self: *MachO, lib: SystemLib, explicit: bool, handle: File.HandleIndex |
| 986 | 992 | .offset = 0, |
| 987 | 993 | .file_handle = handle, |
| 988 | 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 | 999 | .index = index, |
| 991 | 1000 | .needed = lib.needed, |
| 992 | 1001 | .weak = lib.weak, |
| ... | ... | @@ -1175,11 +1184,11 @@ fn parseDependentDylibs(self: *MachO) !void { |
| 1175 | 1184 | continue; |
| 1176 | 1185 | } |
| 1177 | 1186 | }; |
| 1178 | const lib = SystemLib{ | |
| 1179 | .path = full_path, | |
| 1187 | const lib: SystemLib = .{ | |
| 1188 | .path = Path.initCwd(full_path), | |
| 1180 | 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 | 1192 | const fh = try self.addFileHandle(file); |
| 1184 | 1193 | const fat_arch = try self.parseFatFile(file, lib.path); |
| 1185 | 1194 | const offset = if (fat_arch) |fa| fa.offset else 0; |
| ... | ... | @@ -2865,7 +2874,8 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { |
| 2865 | 2874 | ncmds += 1; |
| 2866 | 2875 | } |
| 2867 | 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 | 2879 | const rpath = std.fs.path.dirname(path) orelse "."; |
| 2870 | 2880 | try load_commands.writeRpathLC(rpath, writer); |
| 2871 | 2881 | ncmds += 1; |
| ... | ... | @@ -3758,13 +3768,13 @@ pub fn eatPrefix(path: []const u8, prefix: []const u8) ?[]const u8 { |
| 3758 | 3768 | |
| 3759 | 3769 | pub fn reportParseError( |
| 3760 | 3770 | self: *MachO, |
| 3761 | path: []const u8, | |
| 3771 | path: Path, | |
| 3762 | 3772 | comptime format: []const u8, |
| 3763 | 3773 | args: anytype, |
| 3764 | 3774 | ) error{OutOfMemory}!void { |
| 3765 | 3775 | var err = try self.base.addErrorWithNotes(1); |
| 3766 | 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 | 3780 | pub fn reportParseError2( |
| ... | ... | @@ -3913,7 +3923,7 @@ fn fmtDumpState( |
| 3913 | 3923 | _ = options; |
| 3914 | 3924 | _ = unused_fmt_string; |
| 3915 | 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 | 3927 | try writer.print("{}{}\n", .{ |
| 3918 | 3928 | zo.fmtAtoms(self), |
| 3919 | 3929 | zo.fmtSymtab(self), |
| ... | ... | @@ -3938,9 +3948,9 @@ fn fmtDumpState( |
| 3938 | 3948 | } |
| 3939 | 3949 | for (self.dylibs.items) |index| { |
| 3940 | 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 | 3952 | index, |
| 3943 | dylib.path, | |
| 3953 | @as(Path, dylib.path), | |
| 3944 | 3954 | dylib.needed, |
| 3945 | 3955 | dylib.weak, |
| 3946 | 3956 | }); |
| ... | ... | @@ -4442,7 +4452,7 @@ pub const default_pagezero_size: u64 = 0x100000000; |
| 4442 | 4452 | pub const default_headerpad_size: u32 = 0x1000; |
| 4443 | 4453 | |
| 4444 | 4454 | const SystemLib = struct { |
| 4445 | path: []const u8, | |
| 4455 | path: Path, | |
| 4446 | 4456 | needed: bool = false, |
| 4447 | 4457 | weak: bool = false, |
| 4448 | 4458 | hidden: bool = false, |
src/link/MachO/Archive.zig+10-6| ... | ... | @@ -4,7 +4,7 @@ pub fn deinit(self: *Archive, allocator: Allocator) void { |
| 4 | 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 | 8 | const gpa = macho_file.base.comp.gpa; |
| 9 | 9 | |
| 10 | 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 | 55 | mem.eql(u8, name, SYMDEF_SORTED) or |
| 56 | 56 | mem.eql(u8, name, SYMDEF64_SORTED)) continue; |
| 57 | 57 | |
| 58 | const object = Object{ | |
| 58 | const object: Object = .{ | |
| 59 | 59 | .offset = pos, |
| 60 | 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 | 65 | .size = hdr_size, |
| 63 | 66 | }, |
| 64 | .path = try gpa.dupe(u8, name), | |
| 67 | .path = Path.initCwd(try gpa.dupe(u8, name)), | |
| 65 | 68 | .file_handle = handle_index, |
| 66 | 69 | .index = undefined, |
| 67 | 70 | .alive = false, |
| 68 | 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 | 76 | try self.objects.append(gpa, object); |
| 74 | 77 | } |
| ... | ... | @@ -301,8 +304,9 @@ const log = std.log.scoped(.link); |
| 301 | 304 | const macho = std.macho; |
| 302 | 305 | const mem = std.mem; |
| 303 | 306 | const std = @import("std"); |
| 304 | ||
| 305 | 307 | const Allocator = mem.Allocator; |
| 308 | const Path = std.Build.Cache.Path; | |
| 309 | ||
| 306 | 310 | const Archive = @This(); |
| 307 | 311 | const File = @import("file.zig").File; |
| 308 | 312 | const MachO = @import("../MachO.zig"); |
src/link/MachO/Dylib.zig+6-5| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | /// Non-zero for fat dylibs |
| 2 | 2 | offset: u64, |
| 3 | path: []const u8, | |
| 3 | path: Path, | |
| 4 | 4 | index: File.Index, |
| 5 | 5 | file_handle: File.HandleIndex, |
| 6 | 6 | tag: enum { dylib, tbd }, |
| ... | ... | @@ -28,7 +28,7 @@ referenced: bool = false, |
| 28 | 28 | output_symtab_ctx: MachO.SymtabCtx = .{}, |
| 29 | 29 | |
| 30 | 30 | pub fn deinit(self: *Dylib, allocator: Allocator) void { |
| 31 | allocator.free(self.path); | |
| 31 | allocator.free(self.path.sub_path); | |
| 32 | 32 | self.exports.deinit(allocator); |
| 33 | 33 | self.strtab.deinit(allocator); |
| 34 | 34 | if (self.id) |*id| id.deinit(allocator); |
| ... | ... | @@ -61,7 +61,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void { |
| 61 | 61 | const file = macho_file.getFileHandle(self.file_handle); |
| 62 | 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 | 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 | 267 | |
| 268 | 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 | 272 | const file = macho_file.getFileHandle(self.file_handle); |
| 273 | 273 | var lib_stub = LibStub.loadFromFile(gpa, file) catch |err| { |
| ... | ... | @@ -959,8 +959,9 @@ const mem = std.mem; |
| 959 | 959 | const tapi = @import("../tapi.zig"); |
| 960 | 960 | const trace = @import("../../tracy.zig").trace; |
| 961 | 961 | const std = @import("std"); |
| 962 | ||
| 963 | 962 | const Allocator = mem.Allocator; |
| 963 | const Path = std.Build.Cache.Path; | |
| 964 | ||
| 964 | 965 | const Dylib = @This(); |
| 965 | 966 | const File = @import("file.zig").File; |
| 966 | 967 | const LibStub = tapi.LibStub; |
src/link/MachO/Object.zig+45-18| ... | ... | @@ -1,6 +1,8 @@ |
| 1 | 1 | /// Non-zero for fat object files or archives |
| 2 | 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 | 6 | file_handle: File.HandleIndex, |
| 5 | 7 | mtime: u64, |
| 6 | 8 | index: File.Index, |
| ... | ... | @@ -39,8 +41,8 @@ output_symtab_ctx: MachO.SymtabCtx = .{}, |
| 39 | 41 | output_ar_state: Archive.ArState = .{}, |
| 40 | 42 | |
| 41 | 43 | pub fn deinit(self: *Object, allocator: Allocator) void { |
| 42 | if (self.in_archive) |*ar| allocator.free(ar.path); | |
| 43 | allocator.free(self.path); | |
| 44 | if (self.in_archive) |*ar| allocator.free(ar.path.sub_path); | |
| 45 | allocator.free(self.path.sub_path); | |
| 44 | 46 | for (self.sections.items(.relocs), self.sections.items(.subsections)) |*relocs, *sub| { |
| 45 | 47 | relocs.deinit(allocator); |
| 46 | 48 | sub.deinit(allocator); |
| ... | ... | @@ -1723,7 +1725,8 @@ pub fn updateArSize(self: *Object, macho_file: *MachO) !void { |
| 1723 | 1725 | pub fn writeAr(self: Object, ar_format: Archive.Format, macho_file: *MachO, writer: anytype) !void { |
| 1724 | 1726 | // Header |
| 1725 | 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 | 1730 | // Data |
| 1728 | 1731 | const file = macho_file.getFileHandle(self.file_handle); |
| 1729 | 1732 | // TODO try using copyRangeAll |
| ... | ... | @@ -1774,6 +1777,11 @@ pub fn calcSymtabSize(self: *Object, macho_file: *MachO) void { |
| 1774 | 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 | 1785 | pub fn calcStabsSize(self: *Object, macho_file: *MachO) void { |
| 1778 | 1786 | if (self.compile_unit) |cu| { |
| 1779 | 1787 | const comp_dir = cu.getCompDir(self.*); |
| ... | ... | @@ -1784,9 +1792,9 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) void { |
| 1784 | 1792 | self.output_symtab_ctx.strsize += @as(u32, @intCast(tu_name.len + 1)); // tu_name |
| 1785 | 1793 | |
| 1786 | 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 | 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 | 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 | 2126 | }; |
| 2119 | 2127 | index += 1; |
| 2120 | 2128 | if (self.in_archive) |ar| { |
| 2121 | @memcpy(ctx.strtab.items[n_strx..][0..ar.path.len], ar.path); | |
| 2122 | n_strx += @intCast(ar.path.len); | |
| 2129 | if (ar.path.root_dir.path) |p| { | |
| 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 | 2139 | ctx.strtab.items[n_strx] = '('; |
| 2124 | 2140 | n_strx += 1; |
| 2125 | @memcpy(ctx.strtab.items[n_strx..][0..self.path.len], self.path); | |
| 2126 | n_strx += @intCast(self.path.len); | |
| 2141 | const basename = self.path.basename(); | |
| 2142 | @memcpy(ctx.strtab.items[n_strx..][0..basename.len], basename); | |
| 2143 | n_strx += @intCast(basename.len); | |
| 2127 | 2144 | ctx.strtab.items[n_strx] = ')'; |
| 2128 | 2145 | n_strx += 1; |
| 2129 | 2146 | ctx.strtab.items[n_strx] = 0; |
| 2130 | 2147 | n_strx += 1; |
| 2131 | 2148 | } else { |
| 2132 | @memcpy(ctx.strtab.items[n_strx..][0..self.path.len], self.path); | |
| 2133 | n_strx += @intCast(self.path.len); | |
| 2149 | if (self.path.root_dir.path) |p| { | |
| 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 | 2159 | ctx.strtab.items[n_strx] = 0; |
| 2135 | 2160 | n_strx += 1; |
| 2136 | 2161 | } |
| ... | ... | @@ -2666,11 +2691,12 @@ fn formatPath( |
| 2666 | 2691 | _ = unused_fmt_string; |
| 2667 | 2692 | _ = options; |
| 2668 | 2693 | if (object.in_archive) |ar| { |
| 2669 | try writer.writeAll(ar.path); | |
| 2670 | try writer.writeByte('('); | |
| 2671 | try writer.writeAll(object.path); | |
| 2672 | try writer.writeByte(')'); | |
| 2673 | } else try writer.writeAll(object.path); | |
| 2694 | try writer.print("{}({s})", .{ | |
| 2695 | @as(Path, ar.path), object.path.basename(), | |
| 2696 | }); | |
| 2697 | } else { | |
| 2698 | try writer.print("{}", .{@as(Path, object.path)}); | |
| 2699 | } | |
| 2674 | 2700 | } |
| 2675 | 2701 | |
| 2676 | 2702 | const Section = struct { |
| ... | ... | @@ -2777,7 +2803,7 @@ const CompileUnit = struct { |
| 2777 | 2803 | }; |
| 2778 | 2804 | |
| 2779 | 2805 | const InArchive = struct { |
| 2780 | path: []const u8, | |
| 2806 | path: Path, | |
| 2781 | 2807 | size: u32, |
| 2782 | 2808 | }; |
| 2783 | 2809 | |
| ... | ... | @@ -3170,6 +3196,7 @@ const math = std.math; |
| 3170 | 3196 | const mem = std.mem; |
| 3171 | 3197 | const trace = @import("../../tracy.zig").trace; |
| 3172 | 3198 | const std = @import("std"); |
| 3199 | const Path = std.Build.Cache.Path; | |
| 3173 | 3200 | |
| 3174 | 3201 | const Allocator = mem.Allocator; |
| 3175 | 3202 | const Archive = @import("Archive.zig"); |
src/link/MachO/ZigObject.zig+2-2| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | data: std.ArrayListUnmanaged(u8) = .empty, |
| 2 | 2 | /// Externally owned memory. |
| 3 | path: []const u8, | |
| 3 | basename: []const u8, | |
| 4 | 4 | index: File.Index, |
| 5 | 5 | |
| 6 | 6 | symtab: std.MultiArrayList(Nlist) = .{}, |
| ... | ... | @@ -317,7 +317,7 @@ pub fn updateArSize(self: *ZigObject) void { |
| 317 | 317 | pub fn writeAr(self: ZigObject, ar_format: Archive.Format, writer: anytype) !void { |
| 318 | 318 | // Header |
| 319 | 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 | 321 | // Data |
| 322 | 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 | 23 | _ = unused_fmt_string; |
| 24 | 24 | _ = options; |
| 25 | 25 | switch (file) { |
| 26 | .zig_object => |x| try writer.writeAll(x.path), | |
| 26 | .zig_object => |zo| try writer.writeAll(zo.basename), | |
| 27 | 27 | .internal => try writer.writeAll("internal"), |
| 28 | 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 | 373 | pub const HandleIndex = Index; |
| 374 | 374 | }; |
| 375 | 375 | |
| 376 | const std = @import("std"); | |
| 376 | 377 | const assert = std.debug.assert; |
| 377 | 378 | const log = std.log.scoped(.link); |
| 378 | 379 | const macho = std.macho; |
| 379 | const std = @import("std"); | |
| 380 | const trace = @import("../../tracy.zig").trace; | |
| 381 | ||
| 382 | 380 | const Allocator = std.mem.Allocator; |
| 381 | const Path = std.Build.Cache.Path; | |
| 382 | ||
| 383 | const trace = @import("../../tracy.zig").trace; | |
| 383 | 384 | const Archive = @import("Archive.zig"); |
| 384 | 385 | const Atom = @import("Atom.zig"); |
| 385 | 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 | 72 | } |
| 73 | 73 | |
| 74 | 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 | 77 | const rpath = std.fs.path.dirname(path) orelse "."; |
| 77 | 78 | sizeofcmds += calcInstallNameLen( |
| 78 | 79 | @sizeOf(macho.rpath_command), |
src/link/MachO/relocatable.zig+23-17| ... | ... | @@ -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 | 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 | 5 | var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); |
| 5 | 6 | defer positionals.deinit(); |
| 6 | 7 | try positionals.ensureUnusedCapacity(comp.objects.len); |
| ... | ... | @@ -19,7 +20,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]c |
| 19 | 20 | // TODO: in the future, when we implement `dsymutil` alternative directly in the Zig |
| 20 | 21 | // compiler, investigate if we can get rid of this `if` prong here. |
| 21 | 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 | 24 | const stat = try in_file.stat(); |
| 24 | 25 | const amt = try in_file.copyRangeAll(0, macho_file.base.file.?, 0, stat.size); |
| 25 | 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 | 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 | 77 | const gpa = comp.gpa; |
| 77 | 78 | |
| 78 | 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 | 174 | |
| 174 | 175 | for (files.items) |index| { |
| 175 | 176 | const file = macho_file.getFile(index).?; |
| 176 | const state = switch (file) { | |
| 177 | .zig_object => |x| &x.output_ar_state, | |
| 178 | .object => |x| &x.output_ar_state, | |
| 177 | switch (file) { | |
| 178 | .zig_object => |zo| { | |
| 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 | 194 | else => unreachable, |
| 180 | }; | |
| 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; | |
| 195 | } | |
| 191 | 196 | } |
| 192 | 197 | |
| 193 | 198 | break :blk pos; |
| ... | ... | @@ -777,6 +782,7 @@ const mem = std.mem; |
| 777 | 782 | const state_log = std.log.scoped(.link_state); |
| 778 | 783 | const std = @import("std"); |
| 779 | 784 | const trace = @import("../../tracy.zig").trace; |
| 785 | const Path = std.Build.Cache.Path; | |
| 780 | 786 | |
| 781 | 787 | const Archive = @import("Archive.zig"); |
| 782 | 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 | 15 | if (gop.found_existing) return gop.key_ptr.*; |
| 16 | 16 | |
| 17 | 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 | 20 | self.buffer.appendSliceAssumeCapacity(string); |
| 21 | 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 | 2507 | } else null; |
| 2508 | 2508 | |
| 2509 | 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 | 2511 | var positionals = std.ArrayList([]const u8).init(arena); |
| 2511 | 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 | 2528 | (output_mode == .Lib and link_mode == .dynamic); |
| 2528 | 2529 | if (is_exe_or_dyn_lib) { |
| 2529 | 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 | 2532 | arena, |
| 2532 | 2533 | wasi_libc.emulatedLibCRFileLibName(crt_file), |
| 2533 | 2534 | )); |
| 2534 | 2535 | } |
| 2535 | 2536 | |
| 2536 | 2537 | if (link_libc) { |
| 2537 | try positionals.append(try comp.get_libc_crt_file( | |
| 2538 | try positionals.append(try comp.crtFileAsString( | |
| 2538 | 2539 | arena, |
| 2539 | 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 | 2545 | if (link_libcpp) { |
| 2545 | try positionals.append(comp.libcxx_static_lib.?.full_object_path); | |
| 2546 | try positionals.append(comp.libcxxabi_static_lib.?.full_object_path); | |
| 2546 | try positionals.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena)); | |
| 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 | 2554 | } |
| 2554 | 2555 | |
| 2555 | 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 | 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_obj) |obj| try positionals.append(obj.full_object_path); | |
| 2564 | if (comp.compiler_rt_lib) |lib| try positionals.append(try lib.full_object_path.toString(arena)); | |
| 2565 | if (comp.compiler_rt_obj) |obj| try positionals.append(try obj.full_object_path.toString(arena)); | |
| 2565 | 2566 | |
| 2566 | 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 | 3366 | defer sub_prog_node.end(); |
| 3366 | 3367 | |
| 3367 | 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 | 3370 | if (comp.compiler_rt_lib) |lib| break :blk lib.full_object_path; |
| 3370 | 3371 | if (comp.compiler_rt_obj) |obj| break :blk obj.full_object_path; |
| 3371 | 3372 | break :blk null; |
| ... | ... | @@ -3387,14 +3388,14 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: |
| 3387 | 3388 | comptime assert(Compilation.link_hash_implementation_version == 14); |
| 3388 | 3389 | |
| 3389 | 3390 | for (comp.objects) |obj| { |
| 3390 | _ = try man.addFile(obj.path, null); | |
| 3391 | _ = try man.addFilePath(obj.path, null); | |
| 3391 | 3392 | man.hash.add(obj.must_link); |
| 3392 | 3393 | } |
| 3393 | 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 | 3397 | try man.addOptionalFile(module_obj_path); |
| 3397 | try man.addOptionalFile(compiler_rt_path); | |
| 3398 | try man.addOptionalFilePath(compiler_rt_path); | |
| 3398 | 3399 | man.hash.addOptionalBytes(wasm.entry_name); |
| 3399 | 3400 | man.hash.add(wasm.base.stack_size); |
| 3400 | 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 | 3451 | break :blk comp.c_object_table.keys()[0].status.success.object_path; |
| 3451 | 3452 | |
| 3452 | 3453 | if (module_obj_path) |p| |
| 3453 | break :blk p; | |
| 3454 | break :blk Path.initCwd(p); | |
| 3454 | 3455 | |
| 3455 | 3456 | // TODO I think this is unreachable. Audit this situation when solving the above TODO |
| 3456 | 3457 | // regarding eliding redundant object -> object transformations. |
| 3457 | 3458 | return error.NoObjectsToLink; |
| 3458 | 3459 | }; |
| 3459 | // This can happen when using --enable-cache and using the stage1 backend. In this case | |
| 3460 | // we can skip the file copy. | |
| 3461 | if (!mem.eql(u8, the_object_path, full_out_path)) { | |
| 3462 | try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{}); | |
| 3463 | } | |
| 3460 | try std.fs.Dir.copyFile( | |
| 3461 | the_object_path.root_dir.handle, | |
| 3462 | the_object_path.sub_path, | |
| 3463 | directory.handle, | |
| 3464 | wasm.base.emit.sub_path, | |
| 3465 | .{}, | |
| 3466 | ); | |
| 3464 | 3467 | } else { |
| 3465 | 3468 | // Create an LLD command line and invoke it. |
| 3466 | 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 | 3584 | (comp.config.output_mode == .Lib and comp.config.link_mode == .dynamic); |
| 3582 | 3585 | if (is_exe_or_dyn_lib) { |
| 3583 | 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 | 3588 | arena, |
| 3586 | 3589 | wasi_libc.emulatedLibCRFileLibName(crt_file), |
| 3587 | 3590 | )); |
| 3588 | 3591 | } |
| 3589 | 3592 | |
| 3590 | 3593 | if (comp.config.link_libc) { |
| 3591 | try argv.append(try comp.get_libc_crt_file( | |
| 3594 | try argv.append(try comp.crtFileAsString( | |
| 3592 | 3595 | arena, |
| 3593 | 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 | 3601 | if (comp.config.link_libcpp) { |
| 3599 | try argv.append(comp.libcxx_static_lib.?.full_object_path); | |
| 3600 | try argv.append(comp.libcxxabi_static_lib.?.full_object_path); | |
| 3602 | try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena)); | |
| 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 | 3615 | try argv.append("-no-whole-archive"); |
| 3613 | 3616 | whole_archive = false; |
| 3614 | 3617 | } |
| 3615 | try argv.append(obj.path); | |
| 3618 | try argv.append(try obj.path.toString(arena)); | |
| 3616 | 3619 | } |
| 3617 | 3620 | if (whole_archive) { |
| 3618 | 3621 | try argv.append("-no-whole-archive"); |
| ... | ... | @@ -3620,7 +3623,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: |
| 3620 | 3623 | } |
| 3621 | 3624 | |
| 3622 | 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 | 3628 | if (module_obj_path) |p| { |
| 3626 | 3629 | try argv.append(p); |
| ... | ... | @@ -3630,11 +3633,11 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: |
| 3630 | 3633 | !comp.skip_linker_dependencies and |
| 3631 | 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 | 3639 | if (compiler_rt_path) |p| { |
| 3637 | try argv.append(p); | |
| 3640 | try argv.append(try p.toString(arena)); | |
| 3638 | 3641 | } |
| 3639 | 3642 | |
| 3640 | 3643 | if (comp.verbose_link) { |
src/main.zig+24-23| ... | ... | @@ -13,6 +13,12 @@ const warn = std.log.warn; |
| 13 | 13 | const ThreadPool = std.Thread.Pool; |
| 14 | 14 | const cleanExit = std.process.cleanExit; |
| 15 | 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 | 23 | const tracy = @import("tracy.zig"); |
| 18 | 24 | const Compilation = @import("Compilation.zig"); |
| ... | ... | @@ -20,16 +26,11 @@ const link = @import("link.zig"); |
| 20 | 26 | const Package = @import("Package.zig"); |
| 21 | 27 | const build_options = @import("build_options"); |
| 22 | 28 | const introspect = @import("introspect.zig"); |
| 23 | const EnvVar = std.zig.EnvVar; | |
| 24 | const LibCInstallation = std.zig.LibCInstallation; | |
| 25 | 29 | const wasi_libc = @import("wasi_libc.zig"); |
| 26 | const Cache = std.Build.Cache; | |
| 27 | 30 | const target_util = @import("target.zig"); |
| 28 | 31 | const crash_report = @import("crash_report.zig"); |
| 29 | 32 | const Zcu = @import("Zcu.zig"); |
| 30 | const AstGen = std.zig.AstGen; | |
| 31 | 33 | const mingw = @import("mingw.zig"); |
| 32 | const Server = std.zig.Server; | |
| 33 | 34 | const dev = @import("dev.zig"); |
| 34 | 35 | |
| 35 | 36 | pub const std_options = .{ |
| ... | ... | @@ -1724,14 +1725,14 @@ fn buildOutputType( |
| 1724 | 1725 | } |
| 1725 | 1726 | } else switch (file_ext orelse Compilation.classifyFileExt(arg)) { |
| 1726 | 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 | 1729 | create_module.opts.any_dyn_libs = true; |
| 1729 | 1730 | }, |
| 1730 | 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 | 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 | 1736 | contains_res_file = true; |
| 1736 | 1737 | }, |
| 1737 | 1738 | .manifest => { |
| ... | ... | @@ -1845,20 +1846,20 @@ fn buildOutputType( |
| 1845 | 1846 | }, |
| 1846 | 1847 | .shared_library => { |
| 1847 | 1848 | try create_module.link_objects.append(arena, .{ |
| 1848 | .path = it.only_arg, | |
| 1849 | .path = Path.initCwd(it.only_arg), | |
| 1849 | 1850 | .must_link = must_link, |
| 1850 | 1851 | }); |
| 1851 | 1852 | create_module.opts.any_dyn_libs = true; |
| 1852 | 1853 | }, |
| 1853 | 1854 | .unknown, .object, .static_library => { |
| 1854 | 1855 | try create_module.link_objects.append(arena, .{ |
| 1855 | .path = it.only_arg, | |
| 1856 | .path = Path.initCwd(it.only_arg), | |
| 1856 | 1857 | .must_link = must_link, |
| 1857 | 1858 | }); |
| 1858 | 1859 | }, |
| 1859 | 1860 | .res => { |
| 1860 | 1861 | try create_module.link_objects.append(arena, .{ |
| 1861 | .path = it.only_arg, | |
| 1862 | .path = Path.initCwd(it.only_arg), | |
| 1862 | 1863 | .must_link = must_link, |
| 1863 | 1864 | }); |
| 1864 | 1865 | contains_res_file = true; |
| ... | ... | @@ -1894,7 +1895,7 @@ fn buildOutputType( |
| 1894 | 1895 | // binary: no extra rpaths and DSO filename exactly |
| 1895 | 1896 | // as provided. Hello, Go. |
| 1896 | 1897 | try create_module.link_objects.append(arena, .{ |
| 1897 | .path = it.only_arg, | |
| 1898 | .path = Path.initCwd(it.only_arg), | |
| 1898 | 1899 | .must_link = must_link, |
| 1899 | 1900 | .loption = true, |
| 1900 | 1901 | }); |
| ... | ... | @@ -2532,7 +2533,7 @@ fn buildOutputType( |
| 2532 | 2533 | install_name = linker_args_it.nextOrFatal(); |
| 2533 | 2534 | } else if (mem.eql(u8, arg, "-force_load")) { |
| 2534 | 2535 | try create_module.link_objects.append(arena, .{ |
| 2535 | .path = linker_args_it.nextOrFatal(), | |
| 2536 | .path = Path.initCwd(linker_args_it.nextOrFatal()), | |
| 2536 | 2537 | .must_link = true, |
| 2537 | 2538 | }); |
| 2538 | 2539 | } else if (mem.eql(u8, arg, "-hash-style") or |
| ... | ... | @@ -2707,7 +2708,7 @@ fn buildOutputType( |
| 2707 | 2708 | break :b create_module.c_source_files.items[0].src_path; |
| 2708 | 2709 | |
| 2709 | 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 | 2713 | if (emit_bin == .yes) |
| 2713 | 2714 | break :b emit_bin.yes; |
| ... | ... | @@ -2963,7 +2964,7 @@ fn buildOutputType( |
| 2963 | 2964 | framework_dir_path, |
| 2964 | 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 | 2968 | try resolved_frameworks.append(.{ |
| 2968 | 2969 | .needed = info.needed, |
| 2969 | 2970 | .weak = info.weak, |
| ... | ... | @@ -3635,7 +3636,7 @@ const CreateModule = struct { |
| 3635 | 3636 | name: []const u8, |
| 3636 | 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 | 3641 | c_source_files: std.ArrayListUnmanaged(Compilation.CSourceFile), |
| 3641 | 3642 | rc_source_files: std.ArrayListUnmanaged(Compilation.RcSourceFile), |
| ... | ... | @@ -3808,7 +3809,7 @@ fn createModule( |
| 3808 | 3809 | } |
| 3809 | 3810 | |
| 3810 | 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 | 3813 | try create_module.wasi_emulated_libs.append(arena, crt_file); |
| 3813 | 3814 | continue; |
| 3814 | 3815 | } |
| ... | ... | @@ -3929,7 +3930,7 @@ fn createModule( |
| 3929 | 3930 | target, |
| 3930 | 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 | 3934 | switch (info.preferred_mode) { |
| 3934 | 3935 | .static => try create_module.link_objects.append(arena, .{ .path = path }), |
| 3935 | 3936 | .dynamic => try create_module.resolved_system_libs.append(arena, .{ |
| ... | ... | @@ -3963,7 +3964,7 @@ fn createModule( |
| 3963 | 3964 | target, |
| 3964 | 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 | 3968 | switch (info.fallbackMode()) { |
| 3968 | 3969 | .static => try create_module.link_objects.append(arena, .{ .path = path }), |
| 3969 | 3970 | .dynamic => try create_module.resolved_system_libs.append(arena, .{ |
| ... | ... | @@ -3997,7 +3998,7 @@ fn createModule( |
| 3997 | 3998 | target, |
| 3998 | 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 | 4002 | switch (info.preferred_mode) { |
| 4002 | 4003 | .static => try create_module.link_objects.append(arena, .{ .path = path }), |
| 4003 | 4004 | .dynamic => try create_module.resolved_system_libs.append(arena, .{ |
| ... | ... | @@ -4021,7 +4022,7 @@ fn createModule( |
| 4021 | 4022 | target, |
| 4022 | 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 | 4026 | switch (info.fallbackMode()) { |
| 4026 | 4027 | .static => try create_module.link_objects.append(arena, .{ .path = path }), |
| 4027 | 4028 | .dynamic => try create_module.resolved_system_libs.append(arena, .{ |
| ... | ... | @@ -6163,7 +6164,7 @@ fn cmdAstCheck( |
| 6163 | 6164 | } |
| 6164 | 6165 | |
| 6165 | 6166 | file.mod = try Package.Module.createLimited(arena, .{ |
| 6166 | .root = Cache.Path.cwd(), | |
| 6167 | .root = Path.cwd(), | |
| 6167 | 6168 | .root_src_path = file.sub_file_path, |
| 6168 | 6169 | .fully_qualified_name = "root", |
| 6169 | 6170 | }); |
| ... | ... | @@ -6523,7 +6524,7 @@ fn cmdChangelist( |
| 6523 | 6524 | }; |
| 6524 | 6525 | |
| 6525 | 6526 | file.mod = try Package.Module.createLimited(arena, .{ |
| 6526 | .root = Cache.Path.cwd(), | |
| 6527 | .root = Path.cwd(), | |
| 6527 | 6528 | .root_src_path = file.sub_file_path, |
| 6528 | 6529 | .fully_qualified_name = "root", |
| 6529 | 6530 | }); |
src/mingw.zig+23-19| ... | ... | @@ -11,13 +11,13 @@ const build_options = @import("build_options"); |
| 11 | 11 | const Cache = std.Build.Cache; |
| 12 | 12 | const dev = @import("dev.zig"); |
| 13 | 13 | |
| 14 | pub const CRTFile = enum { | |
| 14 | pub const CrtFile = enum { | |
| 15 | 15 | crt2_o, |
| 16 | 16 | dllcrt2_o, |
| 17 | 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 | 21 | if (!build_options.have_llvm) { |
| 22 | 22 | return error.ZigCompilerNotBuiltWithLLVMExtensions; |
| 23 | 23 | } |
| ... | ... | @@ -160,7 +160,9 @@ fn add_cc_args( |
| 160 | 160 | pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { |
| 161 | 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 | 166 | defer arena_allocator.deinit(); |
| 165 | 167 | const arena = arena_allocator.allocator(); |
| 166 | 168 | |
| ... | ... | @@ -178,7 +180,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { |
| 178 | 180 | |
| 179 | 181 | // Use the global cache directory. |
| 180 | 182 | var cache: Cache = .{ |
| 181 | .gpa = comp.gpa, | |
| 183 | .gpa = gpa, | |
| 182 | 184 | .manifest_dir = try comp.global_cache_directory.handle.makeOpenPath("h", .{}), |
| 183 | 185 | }; |
| 184 | 186 | cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() }); |
| ... | ... | @@ -195,17 +197,18 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { |
| 195 | 197 | |
| 196 | 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}); | |
| 199 | errdefer comp.gpa.free(final_lib_basename); | |
| 200 | const final_lib_basename = try std.fmt.allocPrint(gpa, "{s}.lib", .{lib_name}); | |
| 201 | errdefer gpa.free(final_lib_basename); | |
| 200 | 202 | |
| 201 | 203 | if (try man.hit()) { |
| 202 | 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 | 207 | comp.crt_files.putAssumeCapacityNoClobber(final_lib_basename, .{ |
| 206 | .full_object_path = try comp.global_cache_directory.join(comp.gpa, &[_][]const u8{ | |
| 207 | "o", &digest, final_lib_basename, | |
| 208 | }), | |
| 208 | .full_object_path = .{ | |
| 209 | .root_dir = comp.global_cache_directory, | |
| 210 | .sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename }), | |
| 211 | }, | |
| 209 | 212 | .lock = man.toOwnedLock(), |
| 210 | 213 | }); |
| 211 | 214 | return; |
| ... | ... | @@ -230,7 +233,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { |
| 230 | 233 | }; |
| 231 | 234 | |
| 232 | 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 | 237 | defer aro_comp.deinit(); |
| 235 | 238 | |
| 236 | 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 | 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 | 252 | const builtin_macros = try aro_comp.generateBuiltinMacros(.include_system_defines); |
| 250 | 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 | 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{ | |
| 275 | "o", &digest, final_lib_basename, | |
| 276 | }); | |
| 277 | errdefer comp.gpa.free(lib_final_path); | |
| 277 | const lib_final_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename }); | |
| 278 | errdefer gpa.free(lib_final_path); | |
| 278 | 279 | |
| 279 | 280 | if (!build_options.have_llvm) return error.ZigCompilerNotBuiltWithLLVMExtensions; |
| 280 | 281 | const llvm_bindings = @import("codegen/llvm/bindings.zig"); |
| 281 | 282 | const llvm = @import("codegen/llvm.zig"); |
| 282 | 283 | const arch_tag = llvm.targetArch(target.cpu.arch); |
| 283 | 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 | 286 | if (llvm_bindings.WriteImportLibrary(def_final_path_z.ptr, arch_tag, lib_final_path_z.ptr, true)) { |
| 286 | 287 | // TODO surface a proper error here |
| 287 | 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 | 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 | .full_object_path = lib_final_path, | |
| 296 | try comp.crt_files.putNoClobber(gpa, final_lib_basename, .{ | |
| 297 | .full_object_path = .{ | |
| 298 | .root_dir = comp.global_cache_directory, | |
| 299 | .sub_path = lib_final_path, | |
| 300 | }, | |
| 297 | 301 | .lock = man.toOwnedLock(), |
| 298 | 302 | }); |
| 299 | 303 | } |
src/musl.zig+2-2| ... | ... | @@ -9,7 +9,7 @@ const archName = std.zig.target.muslArchName; |
| 9 | 9 | const Compilation = @import("Compilation.zig"); |
| 10 | 10 | const build_options = @import("build_options"); |
| 11 | 11 | |
| 12 | pub const CRTFile = enum { | |
| 12 | pub const CrtFile = enum { | |
| 13 | 13 | crti_o, |
| 14 | 14 | crtn_o, |
| 15 | 15 | crt1_o, |
| ... | ... | @@ -19,7 +19,7 @@ pub const CRTFile = enum { |
| 19 | 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 | 23 | if (!build_options.have_llvm) { |
| 24 | 24 | return error.ZigCompilerNotBuiltWithLLVMExtensions; |
| 25 | 25 | } |
src/wasi_libc.zig+7-7| ... | ... | @@ -6,7 +6,7 @@ const Allocator = std.mem.Allocator; |
| 6 | 6 | const Compilation = @import("Compilation.zig"); |
| 7 | 7 | const build_options = @import("build_options"); |
| 8 | 8 | |
| 9 | pub const CRTFile = enum { | |
| 9 | pub const CrtFile = enum { | |
| 10 | 10 | crt1_reactor_o, |
| 11 | 11 | crt1_command_o, |
| 12 | 12 | libc_a, |
| ... | ... | @@ -16,7 +16,7 @@ pub const CRTFile = enum { |
| 16 | 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 | 20 | if (mem.eql(u8, lib_name, "wasi-emulated-process-clocks")) { |
| 21 | 21 | return .libwasi_emulated_process_clocks_a; |
| 22 | 22 | } |
| ... | ... | @@ -32,7 +32,7 @@ pub fn getEmulatedLibCRTFile(lib_name: []const u8) ?CRTFile { |
| 32 | 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 | 36 | return switch (crt_file) { |
| 37 | 37 | .libwasi_emulated_process_clocks_a => "libwasi-emulated-process-clocks.a", |
| 38 | 38 | .libwasi_emulated_getpid_a => "libwasi-emulated-getpid.a", |
| ... | ... | @@ -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 | 46 | return switch (wasi_exec_model) { |
| 47 | .reactor => CRTFile.crt1_reactor_o, | |
| 48 | .command => CRTFile.crt1_command_o, | |
| 47 | .reactor => CrtFile.crt1_reactor_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 | 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 | 61 | if (!build_options.have_llvm) { |
| 62 | 62 | return error.ZigCompilerNotBuiltWithLLVMExtensions; |
| 63 | 63 | } |
test/link/elf.zig+7-7| ... | ... | @@ -952,25 +952,25 @@ fn testEmitStaticLib(b: *Build, opts: Options) *Step { |
| 952 | 952 | |
| 953 | 953 | const check = lib.checkObject(); |
| 954 | 954 | check.checkInArchiveSymtab(); |
| 955 | check.checkExactPath("in object", obj1.getEmittedBin()); | |
| 955 | check.checkExact("in object obj1.o"); | |
| 956 | 956 | check.checkExact("foo"); |
| 957 | 957 | check.checkInArchiveSymtab(); |
| 958 | check.checkExactPath("in object", obj1.getEmittedBin()); | |
| 958 | check.checkExact("in object obj1.o"); | |
| 959 | 959 | check.checkExact("bar"); |
| 960 | 960 | check.checkInArchiveSymtab(); |
| 961 | check.checkExactPath("in object", obj1.getEmittedBin()); | |
| 961 | check.checkExact("in object obj1.o"); | |
| 962 | 962 | check.checkExact("fooBar"); |
| 963 | 963 | check.checkInArchiveSymtab(); |
| 964 | check.checkExactPath("in object", obj2.getEmittedBin()); | |
| 964 | check.checkExact("in object obj2.o"); | |
| 965 | 965 | check.checkExact("tentative"); |
| 966 | 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 | 968 | check.checkExact("weakFoo"); |
| 969 | 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 | 971 | check.checkExact("strongBar"); |
| 972 | 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 | 974 | check.checkExact("strongBarAlias"); |
| 975 | 975 | test_step.dependOn(&check.step); |
| 976 | 976 |
test/link/link.zig+1-1| ... | ... | @@ -74,8 +74,8 @@ fn addCompileStep( |
| 74 | 74 | .target = base.target, |
| 75 | 75 | .optimize = base.optimize, |
| 76 | 76 | .root_source_file = rsf: { |
| 77 | const name = b.fmt("{s}.zig", .{overlay.name}); | |
| 78 | 77 | const bytes = overlay.zig_source_bytes orelse break :rsf null; |
| 78 | const name = b.fmt("{s}.zig", .{overlay.name}); | |
| 79 | 79 | break :rsf b.addWriteFiles().add(name, bytes); |
| 80 | 80 | }, |
| 81 | 81 | .pic = overlay.pic, |