authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-06-30 00:03:55+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-06-30 00:03:55+02:00
log81bf05bf6c1249c39273b494d3e337d300b4ddd5
tree9b53744d1d3a31ac82e153173bb9abe7bb52c999
parent37fbf5b0d3b0be131903e4895ee3703393b32d8f
parent0e15205521b9a8c95db3c1714dffe3be1df5cda1
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #9266 from ziglang/zld-dylibs

zig ld can create dylibs now; remove system linker hack and any mention of ld64.lld from the codebase

10 files changed, 303 insertions(+), 535 deletions(-)

cmake/Findlld.cmake-1
...@@ -42,7 +42,6 @@ else()...@@ -42,7 +42,6 @@ else()
42 FIND_AND_ADD_LLD_LIB(lldMinGW)42 FIND_AND_ADD_LLD_LIB(lldMinGW)
43 FIND_AND_ADD_LLD_LIB(lldELF)43 FIND_AND_ADD_LLD_LIB(lldELF)
44 FIND_AND_ADD_LLD_LIB(lldCOFF)44 FIND_AND_ADD_LLD_LIB(lldCOFF)
45 FIND_AND_ADD_LLD_LIB(lldMachO)
46 FIND_AND_ADD_LLD_LIB(lldWasm)45 FIND_AND_ADD_LLD_LIB(lldWasm)
47 FIND_AND_ADD_LLD_LIB(lldReaderWriter)46 FIND_AND_ADD_LLD_LIB(lldReaderWriter)
48 FIND_AND_ADD_LLD_LIB(lldCore)47 FIND_AND_ADD_LLD_LIB(lldCore)
src/Compilation.zig+2-13
...@@ -879,24 +879,16 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -879,24 +879,16 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
879 break :blk false;879 break :blk false;
880 };880 };
881881
882 const darwin_can_use_system_linker_and_sdk =882 const darwin_can_use_system_sdk =
883 // comptime conditions883 // comptime conditions
884 ((build_options.have_llvm and comptime std.Target.current.isDarwin()) and884 ((build_options.have_llvm and comptime std.Target.current.isDarwin()) and
885 // runtime conditions885 // runtime conditions
886 (use_lld and std.builtin.os.tag == .macos and options.target.isDarwin()));886 (use_lld and std.builtin.os.tag == .macos and options.target.isDarwin()));
887887
888 const darwin_system_linker_hack = blk: {
889 if (darwin_can_use_system_linker_and_sdk) {
890 break :blk std.os.getenv("ZIG_SYSTEM_LINKER_HACK") != null;
891 } else {
892 break :blk false;
893 }
894 };
895
896 const sysroot = blk: {888 const sysroot = blk: {
897 if (options.sysroot) |sysroot| {889 if (options.sysroot) |sysroot| {
898 break :blk sysroot;890 break :blk sysroot;
899 } else if (darwin_can_use_system_linker_and_sdk) {891 } else if (darwin_can_use_system_sdk) {
900 // TODO Revisit this targeting versions lower than macOS 11 when LLVM 12 is out.892 // TODO Revisit this targeting versions lower than macOS 11 when LLVM 12 is out.
901 // See https://github.com/ziglang/zig/issues/6996893 // See https://github.com/ziglang/zig/issues/6996
902 const at_least_big_sur = options.target.os.getVersionRange().semver.min.major >= 11;894 const at_least_big_sur = options.target.os.getVersionRange().semver.min.major >= 11;
...@@ -915,8 +907,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -915,8 +907,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
915 break :blk false;907 break :blk false;
916 } else if (options.c_source_files.len == 0) {908 } else if (options.c_source_files.len == 0) {
917 break :blk false;909 break :blk false;
918 } else if (darwin_system_linker_hack) {
919 break :blk false;
920 } else switch (options.output_mode) {910 } else switch (options.output_mode) {
921 .Lib, .Obj => break :blk false,911 .Lib, .Obj => break :blk false,
922 .Exe => switch (options.optimize_mode) {912 .Exe => switch (options.optimize_mode) {
...@@ -1295,7 +1285,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1295,7 +1285,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1295 .optimize_mode = options.optimize_mode,1285 .optimize_mode = options.optimize_mode,
1296 .use_lld = use_lld,1286 .use_lld = use_lld,
1297 .use_llvm = use_llvm,1287 .use_llvm = use_llvm,
1298 .system_linker_hack = darwin_system_linker_hack,
1299 .link_libc = link_libc,1288 .link_libc = link_libc,
1300 .link_libcpp = link_libcpp,1289 .link_libcpp = link_libcpp,
1301 .link_libunwind = link_libunwind,1290 .link_libunwind = link_libunwind,
src/codegen/llvm/bindings.zig-2
...@@ -496,12 +496,10 @@ fn LLVMInitializeAllAsmParsers() callconv(.C) void {...@@ -496,12 +496,10 @@ fn LLVMInitializeAllAsmParsers() callconv(.C) void {
496496
497extern fn ZigLLDLinkCOFF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;497extern fn ZigLLDLinkCOFF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
498extern fn ZigLLDLinkELF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;498extern fn ZigLLDLinkELF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
499extern fn ZigLLDLinkMachO(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
500extern fn ZigLLDLinkWasm(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;499extern fn ZigLLDLinkWasm(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
501500
502pub const LinkCOFF = ZigLLDLinkCOFF;501pub const LinkCOFF = ZigLLDLinkCOFF;
503pub const LinkELF = ZigLLDLinkELF;502pub const LinkELF = ZigLLDLinkELF;
504pub const LinkMachO = ZigLLDLinkMachO;
505pub const LinkWasm = ZigLLDLinkWasm;503pub const LinkWasm = ZigLLDLinkWasm;
506504
507pub const ObjectFormatType = enum(c_int) {505pub const ObjectFormatType = enum(c_int) {
src/link.zig-3
...@@ -61,9 +61,6 @@ pub const Options = struct {...@@ -61,9 +61,6 @@ pub const Options = struct {
61 /// other objects.61 /// other objects.
62 /// Otherwise (depending on `use_lld`) this link code directly outputs and updates the final binary.62 /// Otherwise (depending on `use_lld`) this link code directly outputs and updates the final binary.
63 use_llvm: bool,63 use_llvm: bool,
64 /// Darwin-only. If this is true, `use_llvm` is true, and `is_native_os` is true, this link code will
65 /// use system linker `ld` instead of the LLD.
66 system_linker_hack: bool,
67 link_libc: bool,64 link_libc: bool,
68 link_libcpp: bool,65 link_libcpp: bool,
69 link_libunwind: bool,66 link_libunwind: bool,
src/link/MachO.zig+171-440
...@@ -430,7 +430,7 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*MachO {...@@ -430,7 +430,7 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*MachO {
430430
431pub fn flush(self: *MachO, comp: *Compilation) !void {431pub fn flush(self: *MachO, comp: *Compilation) !void {
432 if (build_options.have_llvm and self.base.options.use_lld) {432 if (build_options.have_llvm and self.base.options.use_lld) {
433 return self.linkWithLLD(comp);433 return self.linkWithZld(comp);
434 } else {434 } else {
435 switch (self.base.options.effectiveOutputMode()) {435 switch (self.base.options.effectiveOutputMode()) {
436 .Exe, .Obj => {},436 .Exe, .Obj => {},
...@@ -593,7 +593,7 @@ fn resolveFramework(...@@ -593,7 +593,7 @@ fn resolveFramework(
593 return null;593 return null;
594}594}
595595
596fn linkWithLLD(self: *MachO, comp: *Compilation) !void {596fn linkWithZld(self: *MachO, comp: *Compilation) !void {
597 const tracy = trace(@src());597 const tracy = trace(@src());
598 defer tracy.end();598 defer tracy.end();
599599
...@@ -631,7 +631,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -631,7 +631,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
631 const stack_size = self.base.options.stack_size_override orelse 0;631 const stack_size = self.base.options.stack_size_override orelse 0;
632 const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os;632 const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os;
633633
634 const id_symlink_basename = "lld.id";634 const id_symlink_basename = "zld.id";
635635
636 var man: Cache.Manifest = undefined;636 var man: Cache.Manifest = undefined;
637 defer if (!self.base.options.disable_lld_caching) man.deinit();637 defer if (!self.base.options.disable_lld_caching) man.deinit();
...@@ -669,7 +669,6 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -669,7 +669,6 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
669 man.hash.addStringSet(self.base.options.system_libs);669 man.hash.addStringSet(self.base.options.system_libs);
670 man.hash.add(allow_shlib_undefined);670 man.hash.add(allow_shlib_undefined);
671 man.hash.add(self.base.options.bind_global_refs_locally);671 man.hash.add(self.base.options.bind_global_refs_locally);
672 man.hash.add(self.base.options.system_linker_hack);
673 man.hash.addOptionalBytes(self.base.options.sysroot);672 man.hash.addOptionalBytes(self.base.options.sysroot);
674673
675 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.674 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
...@@ -682,17 +681,17 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -682,17 +681,17 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
682 id_symlink_basename,681 id_symlink_basename,
683 &prev_digest_buf,682 &prev_digest_buf,
684 ) catch |err| blk: {683 ) catch |err| blk: {
685 log.debug("MachO LLD new_digest={s} error: {s}", .{ std.fmt.fmtSliceHexLower(&digest), @errorName(err) });684 log.debug("MachO Zld new_digest={s} error: {s}", .{ std.fmt.fmtSliceHexLower(&digest), @errorName(err) });
686 // Handle this as a cache miss.685 // Handle this as a cache miss.
687 break :blk prev_digest_buf[0..0];686 break :blk prev_digest_buf[0..0];
688 };687 };
689 if (mem.eql(u8, prev_digest, &digest)) {688 if (mem.eql(u8, prev_digest, &digest)) {
690 log.debug("MachO LLD digest={s} match - skipping invocation", .{std.fmt.fmtSliceHexLower(&digest)});689 log.debug("MachO Zld digest={s} match - skipping invocation", .{std.fmt.fmtSliceHexLower(&digest)});
691 // Hot diggity dog! The output binary is already there.690 // Hot diggity dog! The output binary is already there.
692 self.base.lock = man.toOwnedLock();691 self.base.lock = man.toOwnedLock();
693 return;692 return;
694 }693 }
695 log.debug("MachO LLD prev_digest={s} new_digest={s}", .{ std.fmt.fmtSliceHexLower(prev_digest), std.fmt.fmtSliceHexLower(&digest) });694 log.debug("MachO Zld prev_digest={s} new_digest={s}", .{ std.fmt.fmtSliceHexLower(prev_digest), std.fmt.fmtSliceHexLower(&digest) });
696695
697 // We are about to change the output file to be different, so we invalidate the build hash now.696 // We are about to change the output file to be different, so we invalidate the build hash now.
698 directory.handle.deleteFile(id_symlink_basename) catch |err| switch (err) {697 directory.handle.deleteFile(id_symlink_basename) catch |err| switch (err) {
...@@ -726,495 +725,227 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -726,495 +725,227 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
726 if (!mem.eql(u8, the_object_path, full_out_path)) {725 if (!mem.eql(u8, the_object_path, full_out_path)) {
727 try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{});726 try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{});
728 }727 }
729 } else outer: {728 } else {
730 const use_zld = blk: {729 var zld = Zld.init(self.base.allocator);
731 if (self.base.options.is_native_os and self.base.options.system_linker_hack) {730 defer {
732 // If the user forces the use of ld64, make sure we are running native!731 zld.closeFiles();
733 break :blk false;732 zld.deinit();
734 }733 }
735734 zld.target = target;
736 if (self.base.options.target.cpu.arch == .aarch64) {735 zld.stack_size = stack_size;
737 // On aarch64, always use zld.
738 break :blk true;
739 }
740
741 if (self.base.options.output_mode == .Lib or
742 self.base.options.linker_script != null)
743 {
744 // Fallback to LLD in this handful of cases on x86_64 only.
745 break :blk false;
746 }
747736
748 break :blk true;737 // Positional arguments to the linker such as object files and static archives.
749 };738 var positionals = std.ArrayList([]const u8).init(arena);
750739
751 if (use_zld) {740 try positionals.appendSlice(self.base.options.objects);
752 var zld = Zld.init(self.base.allocator);
753 defer {
754 zld.closeFiles();
755 zld.deinit();
756 }
757 zld.arch = target.cpu.arch;
758 zld.stack_size = stack_size;
759741
760 // Positional arguments to the linker such as object files and static archives.742 for (comp.c_object_table.keys()) |key| {
761 var positionals = std.ArrayList([]const u8).init(arena);743 try positionals.append(key.status.success.object_path);
744 }
762745
763 try positionals.appendSlice(self.base.options.objects);746 if (module_obj_path) |p| {
747 try positionals.append(p);
748 }
764749
765 for (comp.c_object_table.keys()) |key| {750 try positionals.append(comp.compiler_rt_static_lib.?.full_object_path);
766 try positionals.append(key.status.success.object_path);
767 }
768751
769 if (module_obj_path) |p| {752 // libc++ dep
770 try positionals.append(p);753 if (self.base.options.link_libcpp) {
771 }754 try positionals.append(comp.libcxxabi_static_lib.?.full_object_path);
755 try positionals.append(comp.libcxx_static_lib.?.full_object_path);
756 }
772757
773 try positionals.append(comp.compiler_rt_static_lib.?.full_object_path);758 // Shared and static libraries passed via `-l` flag.
759 var search_lib_names = std.ArrayList([]const u8).init(arena);
774760
775 // libc++ dep761 const system_libs = self.base.options.system_libs.keys();
776 if (self.base.options.link_libcpp) {762 for (system_libs) |link_lib| {
777 try positionals.append(comp.libcxxabi_static_lib.?.full_object_path);763 // By this time, we depend on these libs being dynamically linked libraries and not static libraries
778 try positionals.append(comp.libcxx_static_lib.?.full_object_path);764 // (the check for that needs to be earlier), but they could be full paths to .dylib files, in which
765 // case we want to avoid prepending "-l".
766 if (Compilation.classifyFileExt(link_lib) == .shared_library) {
767 try positionals.append(link_lib);
768 continue;
779 }769 }
780770
781 // Shared and static libraries passed via `-l` flag.771 try search_lib_names.append(link_lib);
782 var search_lib_names = std.ArrayList([]const u8).init(arena);772 }
783
784 const system_libs = self.base.options.system_libs.keys();
785 for (system_libs) |link_lib| {
786 // By this time, we depend on these libs being dynamically linked libraries and not static libraries
787 // (the check for that needs to be earlier), but they could be full paths to .dylib files, in which
788 // case we want to avoid prepending "-l".
789 if (Compilation.classifyFileExt(link_lib) == .shared_library) {
790 try positionals.append(link_lib);
791 continue;
792 }
793773
794 try search_lib_names.append(link_lib);774 var lib_dirs = std.ArrayList([]const u8).init(arena);
775 for (self.base.options.lib_dirs) |dir| {
776 if (try resolveSearchDir(arena, dir, self.base.options.sysroot)) |search_dir| {
777 try lib_dirs.append(search_dir);
778 } else {
779 log.warn("directory not found for '-L{s}'", .{dir});
795 }780 }
781 }
796782
797 var lib_dirs = std.ArrayList([]const u8).init(arena);783 var libs = std.ArrayList([]const u8).init(arena);
798 for (self.base.options.lib_dirs) |dir| {784 var lib_not_found = false;
799 if (try resolveSearchDir(arena, dir, self.base.options.sysroot)) |search_dir| {785 for (search_lib_names.items) |lib_name| {
800 try lib_dirs.append(search_dir);786 // Assume ld64 default: -search_paths_first
801 } else {787 // Look in each directory for a dylib (stub first), and then for archive
802 log.warn("directory not found for '-L{s}'", .{dir});788 // TODO implement alternative: -search_dylibs_first
789 for (&[_][]const u8{ ".tbd", ".dylib", ".a" }) |ext| {
790 if (try resolveLib(arena, lib_dirs.items, lib_name, ext)) |full_path| {
791 try libs.append(full_path);
792 break;
803 }793 }
794 } else {
795 log.warn("library not found for '-l{s}'", .{lib_name});
796 lib_not_found = true;
804 }797 }
798 }
805799
806 var libs = std.ArrayList([]const u8).init(arena);800 if (lib_not_found) {
807 var lib_not_found = false;801 log.warn("Library search paths:", .{});
808 for (search_lib_names.items) |lib_name| {802 for (lib_dirs.items) |dir| {
809 // Assume ld64 default: -search_paths_first803 log.warn(" {s}", .{dir});
810 // Look in each directory for a dylib (stub first), and then for archive
811 // TODO implement alternative: -search_dylibs_first
812 for (&[_][]const u8{ ".tbd", ".dylib", ".a" }) |ext| {
813 if (try resolveLib(arena, lib_dirs.items, lib_name, ext)) |full_path| {
814 try libs.append(full_path);
815 break;
816 }
817 } else {
818 log.warn("library not found for '-l{s}'", .{lib_name});
819 lib_not_found = true;
820 }
821 }804 }
805 }
822806
823 if (lib_not_found) {807 // If we're compiling native and we can find libSystem.B.{dylib, tbd},
824 log.warn("Library search paths:", .{});808 // we link against that instead of embedded libSystem.B.tbd file.
825 for (lib_dirs.items) |dir| {809 var native_libsystem_available = false;
826 log.warn(" {s}", .{dir});810 if (self.base.options.is_native_os) blk: {
827 }811 // Try stub file first. If we hit it, then we're done as the stub file
812 // re-exports every single symbol definition.
813 if (try resolveLib(arena, lib_dirs.items, "System", ".tbd")) |full_path| {
814 try libs.append(full_path);
815 native_libsystem_available = true;
816 break :blk;
828 }817 }
829818 // If we didn't hit the stub file, try .dylib next. However, libSystem.dylib
830 // If we're compiling native and we can find libSystem.B.{dylib, tbd},819 // doesn't export libc.dylib which we'll need to resolve subsequently also.
831 // we link against that instead of embedded libSystem.B.tbd file.820 if (try resolveLib(arena, lib_dirs.items, "System", ".dylib")) |libsystem_path| {
832 var native_libsystem_available = false;821 if (try resolveLib(arena, lib_dirs.items, "c", ".dylib")) |libc_path| {
833 if (self.base.options.is_native_os) blk: {822 try libs.append(libsystem_path);
834 // Try stub file first. If we hit it, then we're done as the stub file823 try libs.append(libc_path);
835 // re-exports every single symbol definition.
836 if (try resolveLib(arena, lib_dirs.items, "System", ".tbd")) |full_path| {
837 try libs.append(full_path);
838 native_libsystem_available = true;824 native_libsystem_available = true;
839 break :blk;825 break :blk;
840 }826 }
841 // If we didn't hit the stub file, try .dylib next. However, libSystem.dylib
842 // doesn't export libc.dylib which we'll need to resolve subsequently also.
843 if (try resolveLib(arena, lib_dirs.items, "System", ".dylib")) |libsystem_path| {
844 if (try resolveLib(arena, lib_dirs.items, "c", ".dylib")) |libc_path| {
845 try libs.append(libsystem_path);
846 try libs.append(libc_path);
847 native_libsystem_available = true;
848 break :blk;
849 }
850 }
851 }827 }
852 if (!native_libsystem_available) {828 }
853 const full_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{829 if (!native_libsystem_available) {
854 "libc", "darwin", "libSystem.B.tbd",830 const full_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
855 });831 "libc", "darwin", "libSystem.B.tbd",
856 try libs.append(full_path);
857 }
858
859 // frameworks
860 var framework_dirs = std.ArrayList([]const u8).init(arena);
861 for (self.base.options.framework_dirs) |dir| {
862 if (try resolveSearchDir(arena, dir, self.base.options.sysroot)) |search_dir| {
863 try framework_dirs.append(search_dir);
864 } else {
865 log.warn("directory not found for '-F{s}'", .{dir});
866 }
867 }
868
869 var framework_not_found = false;
870 for (self.base.options.frameworks) |framework| {
871 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
872 if (try resolveFramework(arena, framework_dirs.items, framework, ext)) |full_path| {
873 try libs.append(full_path);
874 break;
875 }
876 } else {
877 log.warn("framework not found for '-f{s}'", .{framework});
878 framework_not_found = true;
879 }
880 }
881
882 if (framework_not_found) {
883 log.warn("Framework search paths:", .{});
884 for (framework_dirs.items) |dir| {
885 log.warn(" {s}", .{dir});
886 }
887 }
888
889 // rpaths
890 var rpath_table = std.StringArrayHashMap(void).init(arena);
891 for (self.base.options.rpath_list) |rpath| {
892 if (rpath_table.contains(rpath)) continue;
893 try rpath_table.putNoClobber(rpath, {});
894 }
895
896 var rpaths = std.ArrayList([]const u8).init(arena);
897 try rpaths.ensureCapacity(rpath_table.count());
898 for (rpath_table.keys()) |*key| {
899 rpaths.appendAssumeCapacity(key.*);
900 }
901
902 if (self.base.options.verbose_link) {
903 var argv = std.ArrayList([]const u8).init(arena);
904
905 try argv.append("zig");
906 try argv.append("ld");
907
908 if (self.base.options.sysroot) |syslibroot| {
909 try argv.append("-syslibroot");
910 try argv.append(syslibroot);
911 }
912
913 for (rpaths.items) |rpath| {
914 try argv.append("-rpath");
915 try argv.append(rpath);
916 }
917
918 try argv.appendSlice(positionals.items);
919
920 try argv.append("-o");
921 try argv.append(full_out_path);
922
923 if (native_libsystem_available) {
924 try argv.append("-lSystem");
925 try argv.append("-lc");
926 }
927
928 for (search_lib_names.items) |l_name| {
929 try argv.append(try std.fmt.allocPrint(arena, "-l{s}", .{l_name}));
930 }
931
932 for (self.base.options.lib_dirs) |lib_dir| {
933 try argv.append(try std.fmt.allocPrint(arena, "-L{s}", .{lib_dir}));
934 }
935
936 Compilation.dump_argv(argv.items);
937 }
938
939 try zld.link(positionals.items, full_out_path, .{
940 .syslibroot = self.base.options.sysroot,
941 .libs = libs.items,
942 .rpaths = rpaths.items,
943 });832 });
944833 try libs.append(full_path);
945 break :outer;
946 }834 }
947835
948 // Create an LLD command line and invoke it.836 // frameworks
949 var argv = std.ArrayList([]const u8).init(self.base.allocator);837 var framework_dirs = std.ArrayList([]const u8).init(arena);
950 defer argv.deinit();838 for (self.base.options.framework_dirs) |dir| {
951839 if (try resolveSearchDir(arena, dir, self.base.options.sysroot)) |search_dir| {
952 // TODO https://github.com/ziglang/zig/issues/6971840 try framework_dirs.append(search_dir);
953 // Note that there is no need to check if running natively since we do that already841 } else {
954 // when setting `system_linker_hack` in Compilation struct.842 log.warn("directory not found for '-F{s}'", .{dir});
955 if (self.base.options.system_linker_hack) {843 }
956 try argv.append("ld");
957 } else {
958 // We will invoke ourselves as a child process to gain access to LLD.
959 // This is necessary because LLD does not behave properly as a library -
960 // it calls exit() and does not reset all global data between invocations.
961 try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, "ld64.lld" });
962
963 try argv.append("-error-limit");
964 try argv.append("0");
965 }844 }
966845
967 if (self.base.options.lto) {846 var framework_not_found = false;
968 switch (self.base.options.optimize_mode) {847 for (self.base.options.frameworks) |framework| {
969 .Debug => {},848 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
970 .ReleaseSmall => try argv.append("-O2"),849 if (try resolveFramework(arena, framework_dirs.items, framework, ext)) |full_path| {
971 .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),850 try libs.append(full_path);
851 break;
852 }
853 } else {
854 log.warn("framework not found for '-f{s}'", .{framework});
855 framework_not_found = true;
972 }856 }
973 }857 }
974 try argv.append("-demangle");
975858
976 if (self.base.options.rdynamic and !self.base.options.system_linker_hack) {859 if (framework_not_found) {
977 try argv.append("--export-dynamic");860 log.warn("Framework search paths:", .{});
861 for (framework_dirs.items) |dir| {
862 log.warn(" {s}", .{dir});
863 }
978 }864 }
979865
980 try argv.appendSlice(self.base.options.extra_lld_args);866 // rpaths
981867 var rpath_table = std.StringArrayHashMap(void).init(arena);
982 if (self.base.options.z_nodelete) {868 for (self.base.options.rpath_list) |rpath| {
983 try argv.append("-z");869 if (rpath_table.contains(rpath)) continue;
984 try argv.append("nodelete");870 try rpath_table.putNoClobber(rpath, {});
985 }
986 if (self.base.options.z_defs) {
987 try argv.append("-z");
988 try argv.append("defs");
989 }871 }
990872
991 if (is_exe_or_dyn_lib) {873 var rpaths = std.ArrayList([]const u8).init(arena);
992 try argv.append("-dynamic");874 try rpaths.ensureCapacity(rpath_table.count());
875 for (rpath_table.keys()) |*key| {
876 rpaths.appendAssumeCapacity(key.*);
993 }877 }
994878
995 if (is_dyn_lib) {879 const output: Zld.Output = output: {
996 try argv.append("-dylib");880 if (is_dyn_lib) {
997881 const install_name = try std.fmt.allocPrint(arena, "@rpath/{s}", .{
998 if (self.base.options.version) |ver| {882 self.base.options.emit.?.sub_path,
999 const compat_vers = try std.fmt.allocPrint(arena, "{d}.0.0", .{ver.major});883 });
1000 try argv.append("-compatibility_version");884 break :output .{
1001 try argv.append(compat_vers);885 .tag = .dylib,
1002886 .path = full_out_path,
1003 const cur_vers = try std.fmt.allocPrint(arena, "{d}.{d}.{d}", .{ ver.major, ver.minor, ver.patch });887 .install_name = install_name,
1004 try argv.append("-current_version");888 };
1005 try argv.append(cur_vers);
1006 }889 }
890 break :output .{
891 .tag = .exe,
892 .path = full_out_path,
893 };
894 };
1007895
1008 const dylib_install_name = try std.fmt.allocPrint(arena, "@rpath/{s}", .{self.base.options.emit.?.sub_path});896 if (self.base.options.verbose_link) {
1009 try argv.append("-install_name");897 var argv = std.ArrayList([]const u8).init(arena);
1010 try argv.append(dylib_install_name);
1011 }
1012898
1013 try argv.append("-arch");899 try argv.append("zig");
1014 try argv.append(darwinArchString(target.cpu.arch));900 try argv.append("ld");
1015901
1016 switch (target.os.tag) {902 if (is_exe_or_dyn_lib) {
1017 .macos => {903 try argv.append("-dynamic");
1018 try argv.append("-macosx_version_min");904 }
1019 },
1020 .ios, .tvos, .watchos => switch (target.cpu.arch) {
1021 .i386, .x86_64 => {
1022 try argv.append("-ios_simulator_version_min");
1023 },
1024 else => {
1025 try argv.append("-iphoneos_version_min");
1026 },
1027 },
1028 else => unreachable,
1029 }
1030 const ver = target.os.version_range.semver.min;
1031 const version_string = try std.fmt.allocPrint(arena, "{d}.{d}.{d}", .{ ver.major, ver.minor, ver.patch });
1032 try argv.append(version_string);
1033905
1034 try argv.append("-sdk_version");906 if (is_dyn_lib) {
1035 try argv.append(version_string);907 try argv.append("-dylib");
1036908
1037 if (target_util.requiresPIE(target) and self.base.options.output_mode == .Exe) {909 try argv.append("-install_name");
1038 try argv.append("-pie");910 try argv.append(output.install_name.?);
1039 }911 }
1040912
1041 try argv.append("-o");913 if (self.base.options.sysroot) |syslibroot| {
1042 try argv.append(full_out_path);914 try argv.append("-syslibroot");
915 try argv.append(syslibroot);
916 }
1043917
1044 // rpaths918 for (rpaths.items) |rpath| {
1045 var rpath_table = std.StringHashMap(void).init(self.base.allocator);
1046 defer rpath_table.deinit();
1047 for (self.base.options.rpath_list) |rpath| {
1048 if ((try rpath_table.fetchPut(rpath, {})) == null) {
1049 try argv.append("-rpath");919 try argv.append("-rpath");
1050 try argv.append(rpath);920 try argv.append(rpath);
1051 }921 }
1052 }
1053 if (is_dyn_lib) {
1054 if ((try rpath_table.fetchPut(full_out_path, {})) == null) {
1055 try argv.append("-rpath");
1056 try argv.append(full_out_path);
1057 }
1058 }
1059
1060 if (self.base.options.sysroot) |dir| {
1061 try argv.append("-syslibroot");
1062 try argv.append(dir);
1063 }
1064
1065 for (self.base.options.lib_dirs) |lib_dir| {
1066 try argv.append("-L");
1067 try argv.append(lib_dir);
1068 }
1069
1070 // Positional arguments to the linker such as object files.
1071 try argv.appendSlice(self.base.options.objects);
1072
1073 for (comp.c_object_table.keys()) |key| {
1074 try argv.append(key.status.success.object_path);
1075 }
1076 if (module_obj_path) |p| {
1077 try argv.append(p);
1078 }
1079922
1080 // compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce923 try argv.appendSlice(positionals.items);
1081 if (is_exe_or_dyn_lib and !self.base.options.skip_linker_dependencies) {
1082 try argv.append(comp.compiler_rt_static_lib.?.full_object_path);
1083 }
1084924
1085 // Shared libraries.925 try argv.append("-o");
1086 const system_libs = self.base.options.system_libs.keys();926 try argv.append(output.path);
1087 try argv.ensureCapacity(argv.items.len + system_libs.len);
1088 for (system_libs) |link_lib| {
1089 // By this time, we depend on these libs being dynamically linked libraries and not static libraries
1090 // (the check for that needs to be earlier), but they could be full paths to .dylib files, in which
1091 // case we want to avoid prepending "-l".
1092 const ext = Compilation.classifyFileExt(link_lib);
1093 const arg = if (ext == .shared_library) link_lib else try std.fmt.allocPrint(arena, "-l{s}", .{link_lib});
1094 argv.appendAssumeCapacity(arg);
1095 }
1096
1097 // libc++ dep
1098 if (self.base.options.link_libcpp) {
1099 try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
1100 try argv.append(comp.libcxx_static_lib.?.full_object_path);
1101 }
1102927
1103 // On Darwin, libSystem has libc in it, but also you have to use it928 if (native_libsystem_available) {
1104 // to make syscalls because the syscall numbers are not documented929 try argv.append("-lSystem");
1105 // and change between versions. So we always link against libSystem.930 try argv.append("-lc");
1106 // LLD craps out if you do -lSystem cross compiling, so until that
1107 // codebase gets some love from the new maintainers we're left with
1108 // this dirty hack.
1109 if (self.base.options.is_native_os) {
1110 try argv.append("-lSystem");
1111 }
1112
1113 for (self.base.options.framework_dirs) |framework_dir| {
1114 try argv.append("-F");
1115 try argv.append(framework_dir);
1116 }
1117 for (self.base.options.frameworks) |framework| {
1118 try argv.append("-framework");
1119 try argv.append(framework);
1120 }
1121
1122 if (allow_shlib_undefined) {
1123 try argv.append("-undefined");
1124 try argv.append("dynamic_lookup");
1125 }
1126 if (self.base.options.bind_global_refs_locally) {
1127 try argv.append("-Bsymbolic");
1128 }
1129
1130 if (self.base.options.verbose_link) {
1131 // Potentially skip over our own name so that the LLD linker name is the first argv item.
1132 const adjusted_argv = if (self.base.options.system_linker_hack) argv.items else argv.items[1..];
1133 Compilation.dump_argv(adjusted_argv);
1134 }
1135
1136 // TODO https://github.com/ziglang/zig/issues/6971
1137 // Note that there is no need to check if running natively since we do that already
1138 // when setting `system_linker_hack` in Compilation struct.
1139 if (self.base.options.system_linker_hack) {
1140 const result = try std.ChildProcess.exec(.{ .allocator = self.base.allocator, .argv = argv.items });
1141 defer {
1142 self.base.allocator.free(result.stdout);
1143 self.base.allocator.free(result.stderr);
1144 }931 }
1145 if (result.stdout.len != 0) {
1146 log.warn("unexpected LD stdout: {s}", .{result.stdout});
1147 }
1148 if (result.stderr.len != 0) {
1149 log.warn("unexpected LD stderr: {s}", .{result.stderr});
1150 }
1151 if (result.term != .Exited or result.term.Exited != 0) {
1152 // TODO parse this output and surface with the Compilation API rather than
1153 // directly outputting to stderr here.
1154 log.err("{s}", .{result.stderr});
1155 return error.LDReportedFailure;
1156 }
1157 } else {
1158 // Sadly, we must run LLD as a child process because it does not behave
1159 // properly as a library.
1160 const child = try std.ChildProcess.init(argv.items, arena);
1161 defer child.deinit();
1162
1163 if (comp.clang_passthrough_mode) {
1164 child.stdin_behavior = .Inherit;
1165 child.stdout_behavior = .Inherit;
1166 child.stderr_behavior = .Inherit;
1167
1168 const term = child.spawnAndWait() catch |err| {
1169 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
1170 return error.UnableToSpawnSelf;
1171 };
1172 switch (term) {
1173 .Exited => |code| {
1174 if (code != 0) {
1175 // TODO https://github.com/ziglang/zig/issues/6342
1176 std.process.exit(1);
1177 }
1178 },
1179 else => {
1180 log.err("{s} terminated", .{argv.items[0]});
1181 return error.LLDCrashed;
1182 },
1183 }
1184 } else {
1185 child.stdin_behavior = .Ignore;
1186 child.stdout_behavior = .Ignore;
1187 child.stderr_behavior = .Pipe;
1188
1189 try child.spawn();
1190
1191 const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
1192932
1193 const term = child.wait() catch |err| {933 for (search_lib_names.items) |l_name| {
1194 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });934 try argv.append(try std.fmt.allocPrint(arena, "-l{s}", .{l_name}));
1195 return error.UnableToSpawnSelf;935 }
1196 };
1197
1198 switch (term) {
1199 .Exited => |code| {
1200 if (code != 0) {
1201 // TODO parse this output and surface with the Compilation API rather than
1202 // directly outputting to stderr here.
1203 std.debug.print("{s}", .{stderr});
1204 return error.LLDReportedFailure;
1205 }
1206 },
1207 else => {
1208 log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
1209 return error.LLDCrashed;
1210 },
1211 }
1212936
1213 if (stderr.len != 0) {937 for (self.base.options.lib_dirs) |lib_dir| {
1214 log.warn("unexpected LLD stderr:\n{s}", .{stderr});938 try argv.append(try std.fmt.allocPrint(arena, "-L{s}", .{lib_dir}));
1215 }
1216 }939 }
940
941 Compilation.dump_argv(argv.items);
1217 }942 }
943
944 try zld.link(positionals.items, output, .{
945 .syslibroot = self.base.options.sysroot,
946 .libs = libs.items,
947 .rpaths = rpaths.items,
948 });
1218 }949 }
1219950
1220 if (!self.base.options.disable_lld_caching) {951 if (!self.base.options.disable_lld_caching) {
src/link/MachO/Trie.zig+3-2
...@@ -334,8 +334,9 @@ pub fn finalize(self: *Trie) !void {...@@ -334,8 +334,9 @@ pub fn finalize(self: *Trie) !void {
334 self.ordered_nodes.shrinkRetainingCapacity(0);334 self.ordered_nodes.shrinkRetainingCapacity(0);
335 try self.ordered_nodes.ensureCapacity(self.allocator, self.node_count);335 try self.ordered_nodes.ensureCapacity(self.allocator, self.node_count);
336336
337 const Fifo = std.fifo.LinearFifo(*Node, .{ .Static = std.math.maxInt(u8) });337 var fifo = std.fifo.LinearFifo(*Node, .Dynamic).init(self.allocator);
338 var fifo = Fifo.init();338 defer fifo.deinit();
339
339 try fifo.writeItem(self.root.?);340 try fifo.writeItem(self.root.?);
340341
341 while (fifo.readItem()) |next| {342 while (fifo.readItem()) |next| {
src/link/MachO/Zld.zig+127-64
...@@ -25,10 +25,10 @@ usingnamespace @import("bind.zig");...@@ -25,10 +25,10 @@ usingnamespace @import("bind.zig");
2525
26allocator: *Allocator,26allocator: *Allocator,
2727
28arch: ?std.Target.Cpu.Arch = null,28target: ?std.Target = null,
29page_size: ?u16 = null,29page_size: ?u16 = null,
30file: ?fs.File = null,30file: ?fs.File = null,
31out_path: ?[]const u8 = null,31output: ?Output = null,
3232
33// TODO these args will become obselete once Zld is coalesced with incremental33// TODO these args will become obselete once Zld is coalesced with incremental
34// linker.34// linker.
...@@ -54,6 +54,7 @@ dylinker_cmd_index: ?u16 = null,...@@ -54,6 +54,7 @@ dylinker_cmd_index: ?u16 = null,
54data_in_code_cmd_index: ?u16 = null,54data_in_code_cmd_index: ?u16 = null,
55function_starts_cmd_index: ?u16 = null,55function_starts_cmd_index: ?u16 = null,
56main_cmd_index: ?u16 = null,56main_cmd_index: ?u16 = null,
57dylib_id_cmd_index: ?u16 = null,
57version_min_cmd_index: ?u16 = null,58version_min_cmd_index: ?u16 = null,
58source_version_cmd_index: ?u16 = null,59source_version_cmd_index: ?u16 = null,
59uuid_cmd_index: ?u16 = null,60uuid_cmd_index: ?u16 = null,
...@@ -118,6 +119,12 @@ got_entries: std.ArrayListUnmanaged(*Symbol) = .{},...@@ -118,6 +119,12 @@ got_entries: std.ArrayListUnmanaged(*Symbol) = .{},
118119
119stub_helper_stubs_start_off: ?u64 = null,120stub_helper_stubs_start_off: ?u64 = null,
120121
122pub const Output = struct {
123 tag: enum { exe, dylib },
124 path: []const u8,
125 install_name: ?[]const u8 = null,
126};
127
121const TlvOffset = struct {128const TlvOffset = struct {
122 source_addr: u64,129 source_addr: u64,
123 offset: u64,130 offset: u64,
...@@ -200,36 +207,17 @@ const LinkArgs = struct {...@@ -200,36 +207,17 @@ const LinkArgs = struct {
200 rpaths: []const []const u8,207 rpaths: []const []const u8,
201};208};
202209
203pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8, args: LinkArgs) !void {210pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArgs) !void {
204 if (files.len == 0) return error.NoInputFiles;211 if (files.len == 0) return error.NoInputFiles;
205 if (out_path.len == 0) return error.EmptyOutputPath;212 if (output.path.len == 0) return error.EmptyOutputPath;
206
207 if (self.arch == null) {
208 // Try inferring the arch from the object files.
209 self.arch = blk: {
210 const file = try fs.cwd().openFile(files[0], .{});
211 defer file.close();
212 var reader = file.reader();
213 const header = try reader.readStruct(macho.mach_header_64);
214 const arch: std.Target.Cpu.Arch = switch (header.cputype) {
215 macho.CPU_TYPE_X86_64 => .x86_64,
216 macho.CPU_TYPE_ARM64 => .aarch64,
217 else => |value| {
218 log.err("unsupported cpu architecture 0x{x}", .{value});
219 return error.UnsupportedCpuArchitecture;
220 },
221 };
222 break :blk arch;
223 };
224 }
225213
226 self.page_size = switch (self.arch.?) {214 self.page_size = switch (self.target.?.cpu.arch) {
227 .aarch64 => 0x4000,215 .aarch64 => 0x4000,
228 .x86_64 => 0x1000,216 .x86_64 => 0x1000,
229 else => unreachable,217 else => unreachable,
230 };218 };
231 self.out_path = out_path;219 self.output = output;
232 self.file = try fs.cwd().createFile(out_path, .{220 self.file = try fs.cwd().createFile(self.output.?.path, .{
233 .truncate = true,221 .truncate = true,
234 .read = true,222 .read = true,
235 .mode = if (std.Target.current.os.tag == .windows) 0 else 0o777,223 .mode = if (std.Target.current.os.tag == .windows) 0 else 0o777,
...@@ -263,19 +251,19 @@ fn parseInputFiles(self: *Zld, files: []const []const u8, syslibroot: ?[]const u...@@ -263,19 +251,19 @@ fn parseInputFiles(self: *Zld, files: []const []const u8, syslibroot: ?[]const u
263 break :full_path try self.allocator.dupe(u8, path);251 break :full_path try self.allocator.dupe(u8, path);
264 };252 };
265253
266 if (try Object.createAndParseFromPath(self.allocator, self.arch.?, full_path)) |object| {254 if (try Object.createAndParseFromPath(self.allocator, self.target.?.cpu.arch, full_path)) |object| {
267 try self.objects.append(self.allocator, object);255 try self.objects.append(self.allocator, object);
268 continue;256 continue;
269 }257 }
270258
271 if (try Archive.createAndParseFromPath(self.allocator, self.arch.?, full_path)) |archive| {259 if (try Archive.createAndParseFromPath(self.allocator, self.target.?.cpu.arch, full_path)) |archive| {
272 try self.archives.append(self.allocator, archive);260 try self.archives.append(self.allocator, archive);
273 continue;261 continue;
274 }262 }
275263
276 if (try Dylib.createAndParseFromPath(264 if (try Dylib.createAndParseFromPath(
277 self.allocator,265 self.allocator,
278 self.arch.?,266 self.target.?.cpu.arch,
279 full_path,267 full_path,
280 .{ .syslibroot = syslibroot },268 .{ .syslibroot = syslibroot },
281 )) |dylibs| {269 )) |dylibs| {
...@@ -292,7 +280,7 @@ fn parseLibs(self: *Zld, libs: []const []const u8, syslibroot: ?[]const u8) !voi...@@ -292,7 +280,7 @@ fn parseLibs(self: *Zld, libs: []const []const u8, syslibroot: ?[]const u8) !voi
292 for (libs) |lib| {280 for (libs) |lib| {
293 if (try Dylib.createAndParseFromPath(281 if (try Dylib.createAndParseFromPath(
294 self.allocator,282 self.allocator,
295 self.arch.?,283 self.target.?.cpu.arch,
296 lib,284 lib,
297 .{ .syslibroot = syslibroot },285 .{ .syslibroot = syslibroot },
298 )) |dylibs| {286 )) |dylibs| {
...@@ -301,7 +289,7 @@ fn parseLibs(self: *Zld, libs: []const []const u8, syslibroot: ?[]const u8) !voi...@@ -301,7 +289,7 @@ fn parseLibs(self: *Zld, libs: []const []const u8, syslibroot: ?[]const u8) !voi
301 continue;289 continue;
302 }290 }
303291
304 if (try Archive.createAndParseFromPath(self.allocator, self.arch.?, lib)) |archive| {292 if (try Archive.createAndParseFromPath(self.allocator, self.target.?.cpu.arch, lib)) |archive| {
305 try self.archives.append(self.allocator, archive);293 try self.archives.append(self.allocator, archive);
306 continue;294 continue;
307 }295 }
...@@ -989,7 +977,7 @@ fn allocateTextSegment(self: *Zld) !void {...@@ -989,7 +977,7 @@ fn allocateTextSegment(self: *Zld) !void {
989 const stub_helper = &seg.sections.items[self.stub_helper_section_index.?];977 const stub_helper = &seg.sections.items[self.stub_helper_section_index.?];
990 stubs.size += nstubs * stubs.reserved2;978 stubs.size += nstubs * stubs.reserved2;
991979
992 const stub_size: u4 = switch (self.arch.?) {980 const stub_size: u4 = switch (self.target.?.cpu.arch) {
993 .x86_64 => 10,981 .x86_64 => 10,
994 .aarch64 => 3 * @sizeOf(u32),982 .aarch64 => 3 * @sizeOf(u32),
995 else => unreachable,983 else => unreachable,
...@@ -1226,7 +1214,7 @@ fn writeStubHelperCommon(self: *Zld) !void {...@@ -1226,7 +1214,7 @@ fn writeStubHelperCommon(self: *Zld) !void {
1226 const data = &data_segment.sections.items[self.data_section_index.?];1214 const data = &data_segment.sections.items[self.data_section_index.?];
12271215
1228 self.stub_helper_stubs_start_off = blk: {1216 self.stub_helper_stubs_start_off = blk: {
1229 switch (self.arch.?) {1217 switch (self.target.?.cpu.arch) {
1230 .x86_64 => {1218 .x86_64 => {
1231 const code_size = 15;1219 const code_size = 15;
1232 var code: [code_size]u8 = undefined;1220 var code: [code_size]u8 = undefined;
...@@ -1358,7 +1346,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void {...@@ -1358,7 +1346,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void {
1358 const data_segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment;1346 const data_segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1359 const la_symbol_ptr = data_segment.sections.items[self.la_symbol_ptr_section_index.?];1347 const la_symbol_ptr = data_segment.sections.items[self.la_symbol_ptr_section_index.?];
13601348
1361 const stub_size: u4 = switch (self.arch.?) {1349 const stub_size: u4 = switch (self.target.?.cpu.arch) {
1362 .x86_64 => 10,1350 .x86_64 => 10,
1363 .aarch64 => 3 * @sizeOf(u32),1351 .aarch64 => 3 * @sizeOf(u32),
1364 else => unreachable,1352 else => unreachable,
...@@ -1384,7 +1372,7 @@ fn writeStub(self: *Zld, index: u32) !void {...@@ -1384,7 +1372,7 @@ fn writeStub(self: *Zld, index: u32) !void {
1384 log.debug("writing stub at 0x{x}", .{stub_off});1372 log.debug("writing stub at 0x{x}", .{stub_off});
1385 var code = try self.allocator.alloc(u8, stubs.reserved2);1373 var code = try self.allocator.alloc(u8, stubs.reserved2);
1386 defer self.allocator.free(code);1374 defer self.allocator.free(code);
1387 switch (self.arch.?) {1375 switch (self.target.?.cpu.arch) {
1388 .x86_64 => {1376 .x86_64 => {
1389 assert(la_ptr_addr >= stub_addr + stubs.reserved2);1377 assert(la_ptr_addr >= stub_addr + stubs.reserved2);
1390 const displacement = try math.cast(u32, la_ptr_addr - stub_addr - stubs.reserved2);1378 const displacement = try math.cast(u32, la_ptr_addr - stub_addr - stubs.reserved2);
...@@ -1447,7 +1435,7 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void {...@@ -1447,7 +1435,7 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void {
1447 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;1435 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1448 const stub_helper = text_segment.sections.items[self.stub_helper_section_index.?];1436 const stub_helper = text_segment.sections.items[self.stub_helper_section_index.?];
14491437
1450 const stub_size: u4 = switch (self.arch.?) {1438 const stub_size: u4 = switch (self.target.?.cpu.arch) {
1451 .x86_64 => 10,1439 .x86_64 => 10,
1452 .aarch64 => 3 * @sizeOf(u32),1440 .aarch64 => 3 * @sizeOf(u32),
1453 else => unreachable,1441 else => unreachable,
...@@ -1455,7 +1443,7 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void {...@@ -1455,7 +1443,7 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void {
1455 const stub_off = self.stub_helper_stubs_start_off.? + index * stub_size;1443 const stub_off = self.stub_helper_stubs_start_off.? + index * stub_size;
1456 var code = try self.allocator.alloc(u8, stub_size);1444 var code = try self.allocator.alloc(u8, stub_size);
1457 defer self.allocator.free(code);1445 defer self.allocator.free(code);
1458 switch (self.arch.?) {1446 switch (self.target.?.cpu.arch) {
1459 .x86_64 => {1447 .x86_64 => {
1460 const displacement = try math.cast(1448 const displacement = try math.cast(
1461 i32,1449 i32,
...@@ -1999,7 +1987,7 @@ fn populateMetadata(self: *Zld) !void {...@@ -1999,7 +1987,7 @@ fn populateMetadata(self: *Zld) !void {
1999 if (self.text_section_index == null) {1987 if (self.text_section_index == null) {
2000 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;1988 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2001 self.text_section_index = @intCast(u16, text_seg.sections.items.len);1989 self.text_section_index = @intCast(u16, text_seg.sections.items.len);
2002 const alignment: u2 = switch (self.arch.?) {1990 const alignment: u2 = switch (self.target.?.cpu.arch) {
2003 .x86_64 => 0,1991 .x86_64 => 0,
2004 .aarch64 => 2,1992 .aarch64 => 2,
2005 else => unreachable, // unhandled architecture type1993 else => unreachable, // unhandled architecture type
...@@ -2013,12 +2001,12 @@ fn populateMetadata(self: *Zld) !void {...@@ -2013,12 +2001,12 @@ fn populateMetadata(self: *Zld) !void {
2013 if (self.stubs_section_index == null) {2001 if (self.stubs_section_index == null) {
2014 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;2002 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2015 self.stubs_section_index = @intCast(u16, text_seg.sections.items.len);2003 self.stubs_section_index = @intCast(u16, text_seg.sections.items.len);
2016 const alignment: u2 = switch (self.arch.?) {2004 const alignment: u2 = switch (self.target.?.cpu.arch) {
2017 .x86_64 => 0,2005 .x86_64 => 0,
2018 .aarch64 => 2,2006 .aarch64 => 2,
2019 else => unreachable, // unhandled architecture type2007 else => unreachable, // unhandled architecture type
2020 };2008 };
2021 const stub_size: u4 = switch (self.arch.?) {2009 const stub_size: u4 = switch (self.target.?.cpu.arch) {
2022 .x86_64 => 6,2010 .x86_64 => 6,
2023 .aarch64 => 3 * @sizeOf(u32),2011 .aarch64 => 3 * @sizeOf(u32),
2024 else => unreachable, // unhandled architecture type2012 else => unreachable, // unhandled architecture type
...@@ -2033,12 +2021,12 @@ fn populateMetadata(self: *Zld) !void {...@@ -2033,12 +2021,12 @@ fn populateMetadata(self: *Zld) !void {
2033 if (self.stub_helper_section_index == null) {2021 if (self.stub_helper_section_index == null) {
2034 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;2022 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2035 self.stub_helper_section_index = @intCast(u16, text_seg.sections.items.len);2023 self.stub_helper_section_index = @intCast(u16, text_seg.sections.items.len);
2036 const alignment: u2 = switch (self.arch.?) {2024 const alignment: u2 = switch (self.target.?.cpu.arch) {
2037 .x86_64 => 0,2025 .x86_64 => 0,
2038 .aarch64 => 2,2026 .aarch64 => 2,
2039 else => unreachable, // unhandled architecture type2027 else => unreachable, // unhandled architecture type
2040 };2028 };
2041 const stub_helper_size: u6 = switch (self.arch.?) {2029 const stub_helper_size: u6 = switch (self.target.?.cpu.arch) {
2042 .x86_64 => 15,2030 .x86_64 => 15,
2043 .aarch64 => 6 * @sizeOf(u32),2031 .aarch64 => 6 * @sizeOf(u32),
2044 else => unreachable,2032 else => unreachable,
...@@ -2187,7 +2175,7 @@ fn populateMetadata(self: *Zld) !void {...@@ -2187,7 +2175,7 @@ fn populateMetadata(self: *Zld) !void {
2187 try self.load_commands.append(self.allocator, .{ .Dylinker = dylinker_cmd });2175 try self.load_commands.append(self.allocator, .{ .Dylinker = dylinker_cmd });
2188 }2176 }
21892177
2190 if (self.main_cmd_index == null) {2178 if (self.main_cmd_index == null and self.output.?.tag == .exe) {
2191 self.main_cmd_index = @intCast(u16, self.load_commands.items.len);2179 self.main_cmd_index = @intCast(u16, self.load_commands.items.len);
2192 try self.load_commands.append(self.allocator, .{2180 try self.load_commands.append(self.allocator, .{
2193 .Main = .{2181 .Main = .{
...@@ -2199,6 +2187,41 @@ fn populateMetadata(self: *Zld) !void {...@@ -2199,6 +2187,41 @@ fn populateMetadata(self: *Zld) !void {
2199 });2187 });
2200 }2188 }
22012189
2190 if (self.dylib_id_cmd_index == null and self.output.?.tag == .dylib) {
2191 self.dylib_id_cmd_index = @intCast(u16, self.load_commands.items.len);
2192 var dylib_cmd = try createLoadDylibCommand(
2193 self.allocator,
2194 self.output.?.install_name.?,
2195 2,
2196 0x10000, // TODO forward user-provided versions
2197 0x10000,
2198 );
2199 errdefer dylib_cmd.deinit(self.allocator);
2200 dylib_cmd.inner.cmd = macho.LC_ID_DYLIB;
2201 try self.load_commands.append(self.allocator, .{ .Dylib = dylib_cmd });
2202 }
2203
2204 if (self.version_min_cmd_index == null) {
2205 self.version_min_cmd_index = @intCast(u16, self.load_commands.items.len);
2206 const cmd: u32 = switch (self.target.?.os.tag) {
2207 .macos => macho.LC_VERSION_MIN_MACOSX,
2208 .ios => macho.LC_VERSION_MIN_IPHONEOS,
2209 .tvos => macho.LC_VERSION_MIN_TVOS,
2210 .watchos => macho.LC_VERSION_MIN_WATCHOS,
2211 else => unreachable, // wrong OS
2212 };
2213 const ver = self.target.?.os.version_range.semver.min;
2214 const version = ver.major << 16 | ver.minor << 8 | ver.patch;
2215 try self.load_commands.append(self.allocator, .{
2216 .VersionMin = .{
2217 .cmd = cmd,
2218 .cmdsize = @sizeOf(macho.version_min_command),
2219 .version = version,
2220 .sdk = version,
2221 },
2222 });
2223 }
2224
2202 if (self.source_version_cmd_index == null) {2225 if (self.source_version_cmd_index == null) {
2203 self.source_version_cmd_index = @intCast(u16, self.load_commands.items.len);2226 self.source_version_cmd_index = @intCast(u16, self.load_commands.items.len);
2204 try self.load_commands.append(self.allocator, .{2227 try self.load_commands.append(self.allocator, .{
...@@ -2237,7 +2260,7 @@ fn addDataInCodeLC(self: *Zld) !void {...@@ -2237,7 +2260,7 @@ fn addDataInCodeLC(self: *Zld) !void {
2237}2260}
22382261
2239fn addCodeSignatureLC(self: *Zld) !void {2262fn addCodeSignatureLC(self: *Zld) !void {
2240 if (self.code_signature_cmd_index == null and self.arch.? == .aarch64) {2263 if (self.code_signature_cmd_index == null and self.target.?.cpu.arch == .aarch64) {
2241 self.code_signature_cmd_index = @intCast(u16, self.load_commands.items.len);2264 self.code_signature_cmd_index = @intCast(u16, self.load_commands.items.len);
2242 try self.load_commands.append(self.allocator, .{2265 try self.load_commands.append(self.allocator, .{
2243 .LinkeditData = .{2266 .LinkeditData = .{
...@@ -2355,19 +2378,20 @@ fn flush(self: *Zld) !void {...@@ -2355,19 +2378,20 @@ fn flush(self: *Zld) !void {
2355 seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);2378 seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);
2356 }2379 }
23572380
2358 if (self.arch.? == .aarch64) {2381 if (self.target.?.cpu.arch == .aarch64) {
2359 try self.writeCodeSignaturePadding();2382 try self.writeCodeSignaturePadding();
2360 }2383 }
23612384
2362 try self.writeLoadCommands();2385 try self.writeLoadCommands();
2363 try self.writeHeader();2386 try self.writeHeader();
23642387
2365 if (self.arch.? == .aarch64) {2388 if (self.target.?.cpu.arch == .aarch64) {
2366 try self.writeCodeSignature();2389 try self.writeCodeSignature();
2367 }2390 }
23682391
2369 if (comptime std.Target.current.isDarwin() and std.Target.current.cpu.arch == .aarch64) {2392 if (comptime std.Target.current.isDarwin() and std.Target.current.cpu.arch == .aarch64) {
2370 try fs.cwd().copyFile(self.out_path.?, fs.cwd(), self.out_path.?, .{});2393 const out_path = self.output.?.path;
2394 try fs.cwd().copyFile(out_path, fs.cwd(), out_path, .{});
2371 }2395 }
2372}2396}
23732397
...@@ -2392,6 +2416,8 @@ fn writeGotEntries(self: *Zld) !void {...@@ -2392,6 +2416,8 @@ fn writeGotEntries(self: *Zld) !void {
2392}2416}
23932417
2394fn setEntryPoint(self: *Zld) !void {2418fn setEntryPoint(self: *Zld) !void {
2419 if (self.output.?.tag != .exe) return;
2420
2395 // TODO we should respect the -entry flag passed in by the user to set a custom2421 // TODO we should respect the -entry flag passed in by the user to set a custom
2396 // entrypoint. For now, assume default of `_main`.2422 // entrypoint. For now, assume default of `_main`.
2397 const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;2423 const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
...@@ -2636,12 +2662,12 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void {...@@ -2636,12 +2662,12 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void {
2636 }2662 }
2637 assert(self.stubs.items.len <= offsets.items.len);2663 assert(self.stubs.items.len <= offsets.items.len);
26382664
2639 const stub_size: u4 = switch (self.arch.?) {2665 const stub_size: u4 = switch (self.target.?.cpu.arch) {
2640 .x86_64 => 10,2666 .x86_64 => 10,
2641 .aarch64 => 3 * @sizeOf(u32),2667 .aarch64 => 3 * @sizeOf(u32),
2642 else => unreachable,2668 else => unreachable,
2643 };2669 };
2644 const off: u4 = switch (self.arch.?) {2670 const off: u4 = switch (self.target.?.cpu.arch) {
2645 .x86_64 => 1,2671 .x86_64 => 1,
2646 .aarch64 => 2 * @sizeOf(u32),2672 .aarch64 => 2 * @sizeOf(u32),
2647 else => unreachable,2673 else => unreachable,
...@@ -2660,17 +2686,40 @@ fn writeExportInfo(self: *Zld) !void {...@@ -2660,17 +2686,40 @@ fn writeExportInfo(self: *Zld) !void {
2660 defer trie.deinit();2686 defer trie.deinit();
26612687
2662 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;2688 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2689 const base_address = text_segment.inner.vmaddr;
26632690
2664 // TODO export items for dylibs2691 // TODO handle macho.EXPORT_SYMBOL_FLAGS_REEXPORT and macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER.
2665 const sym = self.globals.get("_main") orelse return error.MissingMainEntrypoint;2692 log.debug("writing export trie", .{});
2666 const reg = sym.cast(Symbol.Regular) orelse unreachable;
2667 assert(reg.address >= text_segment.inner.vmaddr);
26682693
2669 try trie.put(.{2694 const Sorter = struct {
2670 .name = sym.name,2695 fn lessThan(_: void, a: []const u8, b: []const u8) bool {
2671 .vmaddr_offset = reg.address - text_segment.inner.vmaddr,2696 return mem.lessThan(u8, a, b);
2672 .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR,2697 }
2673 });2698 };
2699
2700 var sorted_globals = std.ArrayList([]const u8).init(self.allocator);
2701 defer sorted_globals.deinit();
2702
2703 for (self.globals.values()) |sym| {
2704 const reg = sym.cast(Symbol.Regular) orelse continue;
2705 if (reg.linkage != .global) continue;
2706 try sorted_globals.append(sym.name);
2707 }
2708
2709 std.sort.sort([]const u8, sorted_globals.items, {}, Sorter.lessThan);
2710
2711 for (sorted_globals.items) |sym_name| {
2712 const sym = self.globals.get(sym_name) orelse unreachable;
2713 const reg = sym.cast(Symbol.Regular) orelse unreachable;
2714
2715 log.debug(" | putting '{s}' defined at 0x{x}", .{ reg.base.name, reg.address });
2716
2717 try trie.put(.{
2718 .name = sym.name,
2719 .vmaddr_offset = reg.address - base_address,
2720 .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR,
2721 });
2722 }
26742723
2675 try trie.finalize();2724 try trie.finalize();
26762725
...@@ -2975,7 +3024,7 @@ fn writeStringTable(self: *Zld) !void {...@@ -2975,7 +3024,7 @@ fn writeStringTable(self: *Zld) !void {
29753024
2976 try self.file.?.pwriteAll(self.strtab.items, symtab.stroff);3025 try self.file.?.pwriteAll(self.strtab.items, symtab.stroff);
29773026
2978 if (symtab.strsize > self.strtab.items.len and self.arch.? == .x86_64) {3027 if (symtab.strsize > self.strtab.items.len and self.target.?.cpu.arch == .x86_64) {
2979 // This is the last section, so we need to pad it out.3028 // This is the last section, so we need to pad it out.
2980 try self.file.?.pwriteAll(&[_]u8{0}, seg.inner.fileoff + seg.inner.filesize - 1);3029 try self.file.?.pwriteAll(&[_]u8{0}, seg.inner.fileoff + seg.inner.filesize - 1);
2981 }3030 }
...@@ -3023,7 +3072,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void {...@@ -3023,7 +3072,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void {
3023 const code_sig_cmd = &self.load_commands.items[self.code_signature_cmd_index.?].LinkeditData;3072 const code_sig_cmd = &self.load_commands.items[self.code_signature_cmd_index.?].LinkeditData;
3024 const fileoff = seg.inner.fileoff + seg.inner.filesize;3073 const fileoff = seg.inner.fileoff + seg.inner.filesize;
3025 const needed_size = CodeSignature.calcCodeSignaturePaddingSize(3074 const needed_size = CodeSignature.calcCodeSignaturePaddingSize(
3026 self.out_path.?,3075 self.output.?.path,
3027 fileoff,3076 fileoff,
3028 self.page_size.?,3077 self.page_size.?,
3029 );3078 );
...@@ -3049,7 +3098,7 @@ fn writeCodeSignature(self: *Zld) !void {...@@ -3049,7 +3098,7 @@ fn writeCodeSignature(self: *Zld) !void {
3049 defer code_sig.deinit();3098 defer code_sig.deinit();
3050 try code_sig.calcAdhocSignature(3099 try code_sig.calcAdhocSignature(
3051 self.file.?,3100 self.file.?,
3052 self.out_path.?,3101 self.output.?.path,
3053 text_seg.inner,3102 text_seg.inner,
3054 code_sig_cmd,3103 code_sig_cmd,
3055 .Exe,3104 .Exe,
...@@ -3091,7 +3140,7 @@ fn writeHeader(self: *Zld) !void {...@@ -3091,7 +3140,7 @@ fn writeHeader(self: *Zld) !void {
3091 cpu_subtype: macho.cpu_subtype_t,3140 cpu_subtype: macho.cpu_subtype_t,
3092 };3141 };
30933142
3094 const cpu_info: CpuInfo = switch (self.arch.?) {3143 const cpu_info: CpuInfo = switch (self.target.?.cpu.arch) {
3095 .aarch64 => .{3144 .aarch64 => .{
3096 .cpu_type = macho.CPU_TYPE_ARM64,3145 .cpu_type = macho.CPU_TYPE_ARM64,
3097 .cpu_subtype = macho.CPU_SUBTYPE_ARM_ALL,3146 .cpu_subtype = macho.CPU_SUBTYPE_ARM_ALL,
...@@ -3104,8 +3153,22 @@ fn writeHeader(self: *Zld) !void {...@@ -3104,8 +3153,22 @@ fn writeHeader(self: *Zld) !void {
3104 };3153 };
3105 header.cputype = cpu_info.cpu_type;3154 header.cputype = cpu_info.cpu_type;
3106 header.cpusubtype = cpu_info.cpu_subtype;3155 header.cpusubtype = cpu_info.cpu_subtype;
3107 header.filetype = macho.MH_EXECUTE;3156
3108 header.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL;3157 switch (self.output.?.tag) {
3158 .exe => {
3159 header.filetype = macho.MH_EXECUTE;
3160 header.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL;
3161 },
3162 .dylib => {
3163 header.filetype = macho.MH_DYLIB;
3164 header.flags = macho.MH_NOUNDEFS |
3165 macho.MH_DYLDLINK |
3166 macho.MH_PIE |
3167 macho.MH_TWOLEVEL |
3168 macho.MH_NO_REEXPORTED_DYLIBS;
3169 },
3170 }
3171
3109 header.reserved = 0;3172 header.reserved = 0;
31103173
3111 if (self.tlv_section_index) |_|3174 if (self.tlv_section_index) |_|
src/main.zig-4
...@@ -226,7 +226,6 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v...@@ -226,7 +226,6 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
226 {226 {
227 return punt_to_clang(arena, args);227 return punt_to_clang(arena, args);
228 } else if (mem.eql(u8, cmd, "ld.lld") or228 } else if (mem.eql(u8, cmd, "ld.lld") or
229 mem.eql(u8, cmd, "ld64.lld") or
230 mem.eql(u8, cmd, "lld-link") or229 mem.eql(u8, cmd, "lld-link") or
231 mem.eql(u8, cmd, "wasm-ld"))230 mem.eql(u8, cmd, "wasm-ld"))
232 {231 {
...@@ -3384,7 +3383,6 @@ fn punt_to_llvm_ar(arena: *Allocator, args: []const []const u8) error{OutOfMemor...@@ -3384,7 +3383,6 @@ fn punt_to_llvm_ar(arena: *Allocator, args: []const []const u8) error{OutOfMemor
33843383
3385/// The first argument determines which backend is invoked. The options are:3384/// The first argument determines which backend is invoked. The options are:
3386/// * `ld.lld` - ELF3385/// * `ld.lld` - ELF
3387/// * `ld64.lld` - Mach-O
3388/// * `lld-link` - COFF3386/// * `lld-link` - COFF
3389/// * `wasm-ld` - WebAssembly3387/// * `wasm-ld` - WebAssembly
3390/// TODO https://github.com/ziglang/zig/issues/32573388/// TODO https://github.com/ziglang/zig/issues/3257
...@@ -3402,8 +3400,6 @@ pub fn punt_to_lld(arena: *Allocator, args: []const []const u8) error{OutOfMemor...@@ -3402,8 +3400,6 @@ pub fn punt_to_lld(arena: *Allocator, args: []const []const u8) error{OutOfMemor
3402 const argc = @intCast(c_int, argv.len);3400 const argc = @intCast(c_int, argv.len);
3403 if (mem.eql(u8, args[1], "ld.lld")) {3401 if (mem.eql(u8, args[1], "ld.lld")) {
3404 break :rc llvm.LinkELF(argc, argv.ptr, true);3402 break :rc llvm.LinkELF(argc, argv.ptr, true);
3405 } else if (mem.eql(u8, args[1], "ld64.lld")) {
3406 break :rc llvm.LinkMachO(argc, argv.ptr, true);
3407 } else if (mem.eql(u8, args[1], "lld-link")) {3403 } else if (mem.eql(u8, args[1], "lld-link")) {
3408 break :rc llvm.LinkCOFF(argc, argv.ptr, true);3404 break :rc llvm.LinkCOFF(argc, argv.ptr, true);
3409 } else if (mem.eql(u8, args[1], "wasm-ld")) {3405 } else if (mem.eql(u8, args[1], "wasm-ld")) {
src/zig_llvm.cpp-5
...@@ -1187,11 +1187,6 @@ int ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early) {...@@ -1187,11 +1187,6 @@ int ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early) {
1187 return lld::elf::link(args, can_exit_early, llvm::outs(), llvm::errs());1187 return lld::elf::link(args, can_exit_early, llvm::outs(), llvm::errs());
1188}1188}
11891189
1190int ZigLLDLinkMachO(int argc, const char **argv, bool can_exit_early) {
1191 std::vector<const char *> args(argv, argv + argc);
1192 return lld::mach_o::link(args, can_exit_early, llvm::outs(), llvm::errs());
1193}
1194
1195int ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early) {1190int ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early) {
1196 std::vector<const char *> args(argv, argv + argc);1191 std::vector<const char *> args(argv, argv + argc);
1197 return lld::wasm::link(args, can_exit_early, llvm::outs(), llvm::errs());1192 return lld::wasm::link(args, can_exit_early, llvm::outs(), llvm::errs());
src/zig_llvm.h-1
...@@ -514,7 +514,6 @@ ZIG_EXTERN_C const char *ZigLLVMGetEnvironmentTypeName(enum ZigLLVM_EnvironmentT...@@ -514,7 +514,6 @@ ZIG_EXTERN_C const char *ZigLLVMGetEnvironmentTypeName(enum ZigLLVM_EnvironmentT
514514
515ZIG_EXTERN_C int ZigLLDLinkCOFF(int argc, const char **argv, bool can_exit_early);515ZIG_EXTERN_C int ZigLLDLinkCOFF(int argc, const char **argv, bool can_exit_early);
516ZIG_EXTERN_C int ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early);516ZIG_EXTERN_C int ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early);
517ZIG_EXTERN_C int ZigLLDLinkMachO(int argc, const char **argv, bool can_exit_early);
518ZIG_EXTERN_C int ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early);517ZIG_EXTERN_C int ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early);
519518
520ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count,519ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count,