diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2021-12-11 00:26:50 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2021-12-12 00:32:03 +0100 |
| commit | dbfcebf8d88b91c5a85366da09a4ce69c0bb5dc6 (patch) | |
| tree | e8f255a5277c428a2f598a6352a1d3b04f6c19ea | |
| parent | efdb94486b78fa143f8d684609cb4c5d3de10124 (diff) | |
| download | zig-dbfcebf8d88b91c5a85366da09a4ce69c0bb5dc6.tar.gz zig-dbfcebf8d88b91c5a85366da09a4ce69c0bb5dc6.zip | |
macho: allow undefined symbols in dylibs
We now respect both `-fallow-shlib-undefined` and
`-Wl,"-undefined=dynamic_lookup"` flags. This is the first step
towards solving issues #8180 and #3000. We currently do not expose
any other ld64 equivalent flag for `-undefined` flag - we basically
throw an error should the user specify a different flag. Support for
those is conditional on closing #8180. As a result of this change,
it is now possible to generate a valid native Node.js addon with Zig
for macOS.
| -rw-r--r-- | src/link/MachO.zig | 20 | ||||
| -rw-r--r-- | src/main.zig | 10 |
2 files changed, 28 insertions, 2 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig index a67d3a4452..9983235d4f 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -444,6 +444,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib; const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe; const stack_size = self.base.options.stack_size_override orelse 0; + const allow_undef = is_dyn_lib and (self.base.options.allow_shlib_undefined orelse false); const id_symlink_basename = "zld.id"; @@ -847,6 +848,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { try argv.append(try std.fmt.allocPrint(arena, "-F{s}", .{framework_dir})); } + if (allow_undef) { + try argv.append("-undefined"); + try argv.append("dynamic_lookup"); + } + Compilation.dump_argv(argv.items); } @@ -899,6 +905,16 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { }; _ = self.unresolved.swapRemove(resolv.where_index); continue; + } else if (allow_undef) { + const n_desc = @bitCast( + u16, + macho.BIND_SPECIAL_DYLIB_FLAT_LOOKUP * @intCast(i16, macho.N_SYMBOL_RESOLVER), + ); + // TODO allow_shlib_undefined is an ELF flag so figure out macOS specific flags too. + sym.n_type = macho.N_EXT; + sym.n_desc = n_desc; + _ = self.unresolved.swapRemove(resolv.where_index); + continue; } log.err("undefined reference to symbol '{s}'", .{sym_name}); @@ -5111,7 +5127,7 @@ fn writeDyldInfoData(self: *MachO) !void { try bind_pointers.append(.{ .offset = binding.offset + base_offset, .segment_id = match.seg, - .dylib_ordinal = @divExact(bind_sym.n_desc, macho.N_SYMBOL_RESOLVER), + .dylib_ordinal = @divExact(@bitCast(i16, bind_sym.n_desc), macho.N_SYMBOL_RESOLVER), .name = self.getString(bind_sym.n_strx), }); }, @@ -5133,7 +5149,7 @@ fn writeDyldInfoData(self: *MachO) !void { try lazy_bind_pointers.append(.{ .offset = binding.offset + base_offset, .segment_id = match.seg, - .dylib_ordinal = @divExact(bind_sym.n_desc, macho.N_SYMBOL_RESOLVER), + .dylib_ordinal = @divExact(@bitCast(i16, bind_sym.n_desc), macho.N_SYMBOL_RESOLVER), .name = self.getString(bind_sym.n_strx), }); }, diff --git a/src/main.zig b/src/main.zig index c29a272660..761935c897 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1703,6 +1703,16 @@ fn buildOutputType( } emit_implib = .{ .yes = linker_args.items[i] }; emit_implib_arg_provided = true; + } else if (mem.eql(u8, arg, "-undefined")) { + i += 1; + if (i >= linker_args.items.len) { + fatal("expected linker arg after '{s}'", .{arg}); + } + if (mem.eql(u8, "dynamic_lookup", linker_args.items[i])) { + linker_allow_shlib_undefined = true; + } else { + fatal("unsupported -undefined option '{s}'", .{linker_args.items[i]}); + } } else { warn("unsupported linker arg: {s}", .{arg}); } |
