| ... | @@ -174,72 +174,97 @@ pub const SdkLayout = enum { | ... | @@ -174,72 +174,97 @@ pub const SdkLayout = enum { |
| 174 | vendored, | 174 | vendored, |
| 175 | }; | 175 | }; |
| 176 | | 176 | |
| 177 | pub fn open( | 177 | pub fn createEmpty( |
| 178 | arena: Allocator, | 178 | arena: Allocator, |
| 179 | comp: *Compilation, | 179 | comp: *Compilation, |
| 180 | emit: Compilation.Emit, | 180 | emit: Compilation.Emit, |
| 181 | options: link.File.OpenOptions, | 181 | options: link.File.OpenOptions, |
| 182 | ) !*MachO { | 182 | ) !*MachO { |
| 183 | const target = comp.root_mod.resolved_target.result; | 183 | const target = comp.root_mod.resolved_target.result; |
| 184 | const use_lld = build_options.have_llvm and comp.config.use_lld; | | |
| 185 | const use_llvm = comp.config.use_llvm; | | |
| 186 | assert(target.ofmt == .macho); | 184 | assert(target.ofmt == .macho); |
| 187 | | 185 | const use_llvm = comp.config.use_llvm; |
| 188 | const gpa = comp.gpa; | 186 | const gpa = comp.gpa; |
| 189 | const mode: Mode = mode: { | 187 | const optimize_mode = comp.root_mod.optimize_mode; |
| 190 | if (use_llvm or comp.module == null or comp.cache_use == .whole) | 188 | const output_mode = comp.config.output_mode; |
| 191 | break :mode .zld; | 189 | const link_mode = comp.config.link_mode; |
| 192 | break :mode .incremental; | | |
| 193 | }; | | |
| 194 | const sub_path = if (mode == .zld) blk: { | | |
| 195 | if (comp.module == null) { | | |
| 196 | // No point in opening a file, we would not write anything to it. | | |
| 197 | // Initialize with empty. | | |
| 198 | return createEmpty(arena, comp, emit, options); | | |
| 199 | } | | |
| 200 | // Open a temporary object file, not the final output file because we | | |
| 201 | // want to link with LLD. | | |
| 202 | break :blk try std.fmt.allocPrint(arena, "{s}{s}", .{ | | |
| 203 | emit.sub_path, target.ofmt.fileExt(target.cpu.arch), | | |
| 204 | }); | | |
| 205 | } else emit.sub_path; | | |
| 206 | | 190 | |
| 207 | const self = try createEmpty(arena, comp, emit, options); | 191 | // TODO: get rid of zld mode |
| | 192 | const mode: Mode = if (use_llvm or !comp.config.have_zcu or comp.cache_use == .whole) |
| | 193 | .zld |
| | 194 | else |
| | 195 | .incremental; |
| | 196 | |
| | 197 | // If using "zld mode" to link, this code should produce an object file so that it |
| | 198 | // can be passed to "zld mode". TODO: get rid of "zld mode". |
| | 199 | // If using LLVM to generate the object file for the zig compilation unit, |
| | 200 | // we need a place to put the object file so that it can be subsequently |
| | 201 | // handled. |
| | 202 | const zcu_object_sub_path = if (mode != .zld and !use_llvm) |
| | 203 | null |
| | 204 | else |
| | 205 | try std.fmt.allocPrint(arena, "{s}.o", .{emit.sub_path}); |
| | 206 | |
| | 207 | const self = try arena.create(MachO); |
| | 208 | self.* = .{ |
| | 209 | .base = .{ |
| | 210 | .tag = .macho, |
| | 211 | .comp = comp, |
| | 212 | .emit = emit, |
| | 213 | .zcu_object_sub_path = zcu_object_sub_path, |
| | 214 | .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), |
| | 215 | .print_gc_sections = options.print_gc_sections, |
| | 216 | .stack_size = options.stack_size orelse 16777216, |
| | 217 | .allow_shlib_undefined = options.allow_shlib_undefined orelse false, |
| | 218 | .file = null, |
| | 219 | .disable_lld_caching = options.disable_lld_caching, |
| | 220 | .build_id = options.build_id, |
| | 221 | .rpath_list = options.rpath_list, |
| | 222 | .force_undefined_symbols = options.force_undefined_symbols, |
| | 223 | }, |
| | 224 | .mode = mode, |
| | 225 | .pagezero_vmsize = options.pagezero_size orelse default_pagezero_vmsize, |
| | 226 | .headerpad_size = options.headerpad_size orelse default_headerpad_size, |
| | 227 | .headerpad_max_install_names = options.headerpad_max_install_names, |
| | 228 | .dead_strip_dylibs = options.dead_strip_dylibs, |
| | 229 | .sdk_layout = options.darwin_sdk_layout, |
| | 230 | .frameworks = options.frameworks, |
| | 231 | .install_name = options.install_name, |
| | 232 | .entitlements = options.entitlements, |
| | 233 | .compatibility_version = options.compatibility_version, |
| | 234 | }; |
| | 235 | if (use_llvm and comp.config.have_zcu) { |
| | 236 | self.llvm_object = try LlvmObject.create(arena, comp); |
| | 237 | } |
| 208 | errdefer self.base.destroy(); | 238 | errdefer self.base.destroy(); |
| 209 | | 239 | |
| | 240 | log.debug("selected linker mode '{s}'", .{@tagName(self.mode)}); |
| | 241 | |
| 210 | if (mode == .zld) { | 242 | if (mode == .zld) { |
| 211 | // TODO this zcu_object_sub_path isn't enough; in the case of `zig build-exe`, | 243 | // TODO: get rid of zld mode |
| 212 | // we also want to put the intermediary object file in the cache while the | | |
| 213 | // main emit directory is the cwd. | | |
| 214 | self.base.zcu_object_sub_path = sub_path; | | |
| 215 | return self; | 244 | return self; |
| 216 | } | 245 | } |
| 217 | | 246 | |
| 218 | const file = try emit.directory.handle.createFile(sub_path, .{ | 247 | const file = try emit.directory.handle.createFile(emit.sub_path, .{ |
| 219 | .truncate = false, | 248 | .truncate = true, |
| 220 | .read = true, | 249 | .read = true, |
| 221 | .mode = link.File.determineMode( | 250 | .mode = link.File.determineMode(false, output_mode, link_mode), |
| 222 | use_lld, | | |
| 223 | comp.config.output_mode, | | |
| 224 | comp.config.link_mode, | | |
| 225 | ), | | |
| 226 | }); | 251 | }); |
| 227 | self.base.file = file; | 252 | self.base.file = file; |
| 228 | | 253 | |
| 229 | if (comp.config.debug_format != .strip and comp.module != null) { | 254 | if (comp.config.debug_format != .strip and comp.module != null) { |
| 230 | // Create dSYM bundle. | 255 | // Create dSYM bundle. |
| 231 | log.debug("creating {s}.dSYM bundle", .{sub_path}); | 256 | log.debug("creating {s}.dSYM bundle", .{emit.sub_path}); |
| 232 | | 257 | |
| 233 | const d_sym_path = try std.fmt.allocPrint( | 258 | const d_sym_path = try std.fmt.allocPrint( |
| 234 | arena, | 259 | arena, |
| 235 | "{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF", | 260 | "{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF", |
| 236 | .{sub_path}, | 261 | .{emit.sub_path}, |
| 237 | ); | 262 | ); |
| 238 | | 263 | |
| 239 | var d_sym_bundle = try emit.directory.handle.makeOpenPath(d_sym_path, .{}); | 264 | var d_sym_bundle = try emit.directory.handle.makeOpenPath(d_sym_path, .{}); |
| 240 | defer d_sym_bundle.close(); | 265 | defer d_sym_bundle.close(); |
| 241 | | 266 | |
| 242 | const d_sym_file = try d_sym_bundle.createFile(sub_path, .{ | 267 | const d_sym_file = try d_sym_bundle.createFile(emit.sub_path, .{ |
| 243 | .truncate = false, | 268 | .truncate = false, |
| 244 | .read = true, | 269 | .read = true, |
| 245 | }); | 270 | }); |
| ... | @@ -273,53 +298,15 @@ pub fn open( | ... | @@ -273,53 +298,15 @@ pub fn open( |
| 273 | return self; | 298 | return self; |
| 274 | } | 299 | } |
| 275 | | 300 | |
| 276 | pub fn createEmpty( | 301 | pub fn open( |
| 277 | arena: Allocator, | 302 | arena: Allocator, |
| 278 | comp: *Compilation, | 303 | comp: *Compilation, |
| 279 | emit: Compilation.Emit, | 304 | emit: Compilation.Emit, |
| 280 | options: link.File.OpenOptions, | 305 | options: link.File.OpenOptions, |
| 281 | ) !*MachO { | 306 | ) !*MachO { |
| 282 | const optimize_mode = comp.root_mod.optimize_mode; | 307 | // TODO: restore saved linker state, don't truncate the file, and |
| 283 | const use_llvm = comp.config.use_llvm; | 308 | // participate in incremental compilation. |
| 284 | | 309 | return createEmpty(arena, comp, emit, options); |
| 285 | const self = try arena.create(MachO); | | |
| 286 | self.* = .{ | | |
| 287 | .base = .{ | | |
| 288 | .tag = .macho, | | |
| 289 | .comp = comp, | | |
| 290 | .emit = emit, | | |
| 291 | .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), | | |
| 292 | .print_gc_sections = options.print_gc_sections, | | |
| 293 | .stack_size = options.stack_size orelse 16777216, | | |
| 294 | .allow_shlib_undefined = options.allow_shlib_undefined orelse false, | | |
| 295 | .file = null, | | |
| 296 | .disable_lld_caching = options.disable_lld_caching, | | |
| 297 | .build_id = options.build_id, | | |
| 298 | .rpath_list = options.rpath_list, | | |
| 299 | .force_undefined_symbols = options.force_undefined_symbols, | | |
| 300 | }, | | |
| 301 | .mode = if (use_llvm or comp.module == null or comp.cache_use == .whole) | | |
| 302 | .zld | | |
| 303 | else | | |
| 304 | .incremental, | | |
| 305 | .pagezero_vmsize = options.pagezero_size orelse default_pagezero_vmsize, | | |
| 306 | .headerpad_size = options.headerpad_size orelse default_headerpad_size, | | |
| 307 | .headerpad_max_install_names = options.headerpad_max_install_names, | | |
| 308 | .dead_strip_dylibs = options.dead_strip_dylibs, | | |
| 309 | .sdk_layout = options.darwin_sdk_layout, | | |
| 310 | .frameworks = options.frameworks, | | |
| 311 | .install_name = options.install_name, | | |
| 312 | .entitlements = options.entitlements, | | |
| 313 | .compatibility_version = options.compatibility_version, | | |
| 314 | }; | | |
| 315 | | | |
| 316 | if (use_llvm and comp.module != null) { | | |
| 317 | self.llvm_object = try LlvmObject.create(arena, comp); | | |
| 318 | } | | |
| 319 | | | |
| 320 | log.debug("selected linker mode '{s}'", .{@tagName(self.mode)}); | | |
| 321 | | | |
| 322 | return self; | | |
| 323 | } | 310 | } |
| 324 | | 311 | |
| 325 | pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 312 | pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { |