diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-18 19:05:06 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-18 19:05:06 +0100 |
| commit | 46171bf6c89dc2c2b8f155c8511b62e5cd52e3bc (patch) | |
| tree | 7ae0f3662be1266e37bb8ef4ede4fe5ebe5c4b6f /src | |
| parent | ee705e3ac71205142a4457acd2677f7be921d62b (diff) | |
| download | zig-46171bf6c89dc2c2b8f155c8511b62e5cd52e3bc.tar.gz zig-46171bf6c89dc2c2b8f155c8511b62e5cd52e3bc.zip | |
macho+zld: clean up how to interface with link.zig and openPath()
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/MachO.zig | 69 |
1 files changed, 42 insertions, 27 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 368914e1be..2f76c49667 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -60,6 +60,17 @@ pub const SearchStrategy = enum { dylibs_first, }; +/// Mode of operation of the linker. +pub const Mode = enum { + /// Incremental mode will preallocate segments/sections and is compatible with + /// watch and HCS modes of operation. + incremental, + /// Zld mode will link relocatables in a traditional, one-shot + /// fashion (default for LLVM backend). It acts as a drop-in replacement for + /// LLD. + zld, +}; + const Section = struct { header: macho.section_64, segment_index: u8, @@ -98,10 +109,7 @@ d_sym: ?DebugSymbols = null, /// For x86_64 that's 4KB, whereas for aarch64, that's 16KB. page_size: u16, -/// Mode of operation: incremental - will preallocate segments/sections and is compatible with -/// watch and HCS modes of operation; one_shot - will link relocatables in a traditional, one-shot -/// fashion (default for LLVM backend). -mode: enum { incremental, one_shot }, +mode: Mode, dyld_info_cmd: macho.dyld_info_command = .{}, symtab_cmd: macho.symtab_command = .{}, @@ -314,33 +322,42 @@ pub const default_headerpad_size: u32 = 0x1000; pub fn openPath(allocator: Allocator, options: link.Options) !*MachO { assert(options.target.ofmt == .macho); - if (options.emit == null or options.module == null) { + if (options.emit == null) { return createEmpty(allocator, options); } const emit = options.emit.?; + const mode: Mode = mode: { + if (options.use_llvm or options.module == null or options.cache_mode == .whole) + break :mode .zld; + break :mode .incremental; + }; + const sub_path = if (mode == .zld) blk: { + if (options.module == null) { + // No point in opening a file, we would not write anything to it. + // Initialize with empty. + return createEmpty(allocator, options); + } + // Open a temporary object file, not the final output file because we + // want to link with LLD. + break :blk try std.fmt.allocPrint(allocator, "{s}{s}", .{ + emit.sub_path, options.target.ofmt.fileExt(options.target.cpu.arch), + }); + } else emit.sub_path; + errdefer if (mode == .zld) allocator.free(sub_path); + const self = try createEmpty(allocator, options); - errdefer { - self.base.file = null; - self.base.destroy(); - } + errdefer self.base.destroy(); - if (build_options.have_llvm and options.use_llvm and options.module != null) { + if (mode == .zld) { // TODO this intermediary_basename isn't enough; in the case of `zig build-exe`, // we also want to put the intermediary object file in the cache while the // main emit directory is the cwd. - self.base.intermediary_basename = try std.fmt.allocPrint(allocator, "{s}{s}", .{ - emit.sub_path, options.target.ofmt.fileExt(options.target.cpu.arch), - }); + self.base.intermediary_basename = sub_path; + return self; } - if (self.base.intermediary_basename != null) switch (options.output_mode) { - .Obj => return self, - .Lib => if (options.link_mode == .Static) return self, - else => {}, - }; - - const file = try emit.directory.handle.createFile(emit.sub_path, .{ + const file = try emit.directory.handle.createFile(sub_path, .{ .truncate = false, .read = true, .mode = link.determineMode(options), @@ -348,23 +365,21 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO { errdefer file.close(); self.base.file = file; - if (self.mode == .one_shot) return self; - if (!options.strip and options.module != null) { // Create dSYM bundle. - log.debug("creating {s}.dSYM bundle", .{emit.sub_path}); + log.debug("creating {s}.dSYM bundle", .{sub_path}); const d_sym_path = try fmt.allocPrint( allocator, "{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF", - .{emit.sub_path}, + .{sub_path}, ); defer allocator.free(d_sym_path); var d_sym_bundle = try emit.directory.handle.makeOpenPath(d_sym_path, .{}); defer d_sym_bundle.close(); - const d_sym_file = try d_sym_bundle.createFile(emit.sub_path, .{ + const d_sym_file = try d_sym_bundle.createFile(sub_path, .{ .truncate = false, .read = true, }); @@ -413,7 +428,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO { }, .page_size = page_size, .mode = if (use_llvm or options.module == null or options.cache_mode == .whole) - .one_shot + .zld else .incremental, }; @@ -447,7 +462,7 @@ pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) li } switch (self.mode) { - .one_shot => return zld.linkWithZld(self, comp, prog_node), + .zld => return zld.linkWithZld(self, comp, prog_node), .incremental => return self.flushModule(comp, prog_node), } } |
