| ... | ... | @@ -174,72 +174,97 @@ pub const SdkLayout = enum { |
| 174 | 174 | vendored, |
| 175 | 175 | }; |
| 176 | 176 | |
| 177 | | pub fn open( |
| 177 | pub fn createEmpty( |
| 178 | 178 | arena: Allocator, |
| 179 | 179 | comp: *Compilation, |
| 180 | 180 | emit: Compilation.Emit, |
| 181 | 181 | options: link.File.OpenOptions, |
| 182 | 182 | ) !*MachO { |
| 183 | 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 | 184 | assert(target.ofmt == .macho); |
| 187 | | |
| 185 | const use_llvm = comp.config.use_llvm; |
| 188 | 186 | const gpa = comp.gpa; |
| 189 | | const mode: Mode = mode: { |
| 190 | | if (use_llvm or comp.module == null or comp.cache_use == .whole) |
| 191 | | break :mode .zld; |
| 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; |
| 187 | const optimize_mode = comp.root_mod.optimize_mode; |
| 188 | const output_mode = comp.config.output_mode; |
| 189 | const link_mode = comp.config.link_mode; |
| 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 | 238 | errdefer self.base.destroy(); |
| 209 | 239 | |
| 240 | log.debug("selected linker mode '{s}'", .{@tagName(self.mode)}); |
| 241 | |
| 210 | 242 | if (mode == .zld) { |
| 211 | | // TODO this zcu_object_sub_path isn't enough; in the case of `zig build-exe`, |
| 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; |
| 243 | // TODO: get rid of zld mode |
| 215 | 244 | return self; |
| 216 | 245 | } |
| 217 | 246 | |
| 218 | | const file = try emit.directory.handle.createFile(sub_path, .{ |
| 219 | | .truncate = false, |
| 247 | const file = try emit.directory.handle.createFile(emit.sub_path, .{ |
| 248 | .truncate = true, |
| 220 | 249 | .read = true, |
| 221 | | .mode = link.File.determineMode( |
| 222 | | use_lld, |
| 223 | | comp.config.output_mode, |
| 224 | | comp.config.link_mode, |
| 225 | | ), |
| 250 | .mode = link.File.determineMode(false, output_mode, link_mode), |
| 226 | 251 | }); |
| 227 | 252 | self.base.file = file; |
| 228 | 253 | |
| 229 | 254 | if (comp.config.debug_format != .strip and comp.module != null) { |
| 230 | 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 | 258 | const d_sym_path = try std.fmt.allocPrint( |
| 234 | 259 | arena, |
| 235 | 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 | 264 | var d_sym_bundle = try emit.directory.handle.makeOpenPath(d_sym_path, .{}); |
| 240 | 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 | 268 | .truncate = false, |
| 244 | 269 | .read = true, |
| 245 | 270 | }); |
| ... | ... | @@ -273,53 +298,15 @@ pub fn open( |
| 273 | 298 | return self; |
| 274 | 299 | } |
| 275 | 300 | |
| 276 | | pub fn createEmpty( |
| 301 | pub fn open( |
| 277 | 302 | arena: Allocator, |
| 278 | 303 | comp: *Compilation, |
| 279 | 304 | emit: Compilation.Emit, |
| 280 | 305 | options: link.File.OpenOptions, |
| 281 | 306 | ) !*MachO { |
| 282 | | const optimize_mode = comp.root_mod.optimize_mode; |
| 283 | | const use_llvm = comp.config.use_llvm; |
| 284 | | |
| 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; |
| 307 | // TODO: restore saved linker state, don't truncate the file, and |
| 308 | // participate in incremental compilation. |
| 309 | return createEmpty(arena, comp, emit, options); |
| 323 | 310 | } |
| 324 | 311 | |
| 325 | 312 | pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { |