| ... | @@ -444,6 +444,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { | ... | @@ -444,6 +444,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 444 | const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib; | 444 | const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib; |
| 445 | const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe; | 445 | const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe; |
| 446 | const stack_size = self.base.options.stack_size_override orelse 0; | 446 | const stack_size = self.base.options.stack_size_override orelse 0; |
| | 447 | const allow_undef = is_dyn_lib and (self.base.options.allow_shlib_undefined orelse false); |
| 447 | | 448 | |
| 448 | const id_symlink_basename = "zld.id"; | 449 | const id_symlink_basename = "zld.id"; |
| 449 | | 450 | |
| ... | @@ -847,6 +848,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { | ... | @@ -847,6 +848,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 847 | try argv.append(try std.fmt.allocPrint(arena, "-F{s}", .{framework_dir})); | 848 | try argv.append(try std.fmt.allocPrint(arena, "-F{s}", .{framework_dir})); |
| 848 | } | 849 | } |
| 849 | | 850 | |
| | 851 | if (allow_undef) { |
| | 852 | try argv.append("-undefined"); |
| | 853 | try argv.append("dynamic_lookup"); |
| | 854 | } |
| | 855 | |
| 850 | Compilation.dump_argv(argv.items); | 856 | Compilation.dump_argv(argv.items); |
| 851 | } | 857 | } |
| 852 | | 858 | |
| ... | @@ -899,6 +905,16 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { | ... | @@ -899,6 +905,16 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 899 | }; | 905 | }; |
| 900 | _ = self.unresolved.swapRemove(resolv.where_index); | 906 | _ = self.unresolved.swapRemove(resolv.where_index); |
| 901 | continue; | 907 | continue; |
| | 908 | } else if (allow_undef) { |
| | 909 | const n_desc = @bitCast( |
| | 910 | u16, |
| | 911 | macho.BIND_SPECIAL_DYLIB_FLAT_LOOKUP * @intCast(i16, macho.N_SYMBOL_RESOLVER), |
| | 912 | ); |
| | 913 | // TODO allow_shlib_undefined is an ELF flag so figure out macOS specific flags too. |
| | 914 | sym.n_type = macho.N_EXT; |
| | 915 | sym.n_desc = n_desc; |
| | 916 | _ = self.unresolved.swapRemove(resolv.where_index); |
| | 917 | continue; |
| 902 | } | 918 | } |
| 903 | | 919 | |
| 904 | log.err("undefined reference to symbol '{s}'", .{sym_name}); | 920 | log.err("undefined reference to symbol '{s}'", .{sym_name}); |
| ... | @@ -5111,7 +5127,7 @@ fn writeDyldInfoData(self: *MachO) !void { | ... | @@ -5111,7 +5127,7 @@ fn writeDyldInfoData(self: *MachO) !void { |
| 5111 | try bind_pointers.append(.{ | 5127 | try bind_pointers.append(.{ |
| 5112 | .offset = binding.offset + base_offset, | 5128 | .offset = binding.offset + base_offset, |
| 5113 | .segment_id = match.seg, | 5129 | .segment_id = match.seg, |
| 5114 | .dylib_ordinal = @divExact(bind_sym.n_desc, macho.N_SYMBOL_RESOLVER), | 5130 | .dylib_ordinal = @divExact(@bitCast(i16, bind_sym.n_desc), macho.N_SYMBOL_RESOLVER), |
| 5115 | .name = self.getString(bind_sym.n_strx), | 5131 | .name = self.getString(bind_sym.n_strx), |
| 5116 | }); | 5132 | }); |
| 5117 | }, | 5133 | }, |
| ... | @@ -5133,7 +5149,7 @@ fn writeDyldInfoData(self: *MachO) !void { | ... | @@ -5133,7 +5149,7 @@ fn writeDyldInfoData(self: *MachO) !void { |
| 5133 | try lazy_bind_pointers.append(.{ | 5149 | try lazy_bind_pointers.append(.{ |
| 5134 | .offset = binding.offset + base_offset, | 5150 | .offset = binding.offset + base_offset, |
| 5135 | .segment_id = match.seg, | 5151 | .segment_id = match.seg, |
| 5136 | .dylib_ordinal = @divExact(bind_sym.n_desc, macho.N_SYMBOL_RESOLVER), | 5152 | .dylib_ordinal = @divExact(@bitCast(i16, bind_sym.n_desc), macho.N_SYMBOL_RESOLVER), |
| 5137 | .name = self.getString(bind_sym.n_strx), | 5153 | .name = self.getString(bind_sym.n_strx), |
| 5138 | }); | 5154 | }); |
| 5139 | }, | 5155 | }, |