mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 04:17:49 +00:00
fix MachO linking
* fix relationship between createEmpty/open (similar logic as 607111aa758002bc51914b7dc800b23927c931b8) * still resolve the start symbol when linking libc because when zig is the linker it still needs to know the entry symbol. * make use_llvm=false when there is no zig compilation unit.
This commit is contained in:
parent
944b0ef518
commit
b36659c972
@ -178,6 +178,9 @@ pub fn resolve(options: Options) ResolveError!Config {
|
||||
// For example, Zig can emit .bc and .ll files directly, and this is still considered
|
||||
// using "the LLVM backend".
|
||||
const use_llvm = b: {
|
||||
// If we have no zig code to compile, no need for LLVM.
|
||||
if (!options.have_zcu) break :b false;
|
||||
|
||||
// If emitting to LLVM bitcode object format, must use LLVM backend.
|
||||
if (options.emit_llvm_ir or options.emit_llvm_bc) {
|
||||
if (options.use_llvm == false)
|
||||
@ -202,13 +205,10 @@ pub fn resolve(options: Options) ResolveError!Config {
|
||||
|
||||
if (options.use_llvm) |x| break :b x;
|
||||
|
||||
// If we have no zig code to compile, no need for LLVM.
|
||||
if (!options.have_zcu) break :b false;
|
||||
|
||||
// If we cannot use LLVM libraries, then our own backends will be a
|
||||
// better default since the LLVM backend can only produce bitcode
|
||||
// and not an object file or executable.
|
||||
if (!use_lib_llvm) break :b false;
|
||||
if (!use_lib_llvm and options.emit_bin) break :b false;
|
||||
|
||||
// Prefer LLVM for release builds.
|
||||
if (root_optimize_mode != .Debug) break :b true;
|
||||
@ -339,10 +339,6 @@ pub fn resolve(options: Options) ResolveError!Config {
|
||||
.default => b: {
|
||||
if (options.output_mode != .Exe) break :b null;
|
||||
|
||||
// When linking libc, the entry point is inside libc and not in the
|
||||
// zig compilation unit.
|
||||
if (link_libc) break :b null;
|
||||
|
||||
// When producing C source code, the decision of entry point is made
|
||||
// when compiling the C code, not when producing the C code.
|
||||
if (target.ofmt == .c) break :b null;
|
||||
|
||||
@ -320,8 +320,8 @@ pub fn createEmpty(
|
||||
}
|
||||
errdefer self.base.destroy();
|
||||
|
||||
if (use_lld and use_llvm) {
|
||||
// LLVM emits the object file; LLD links it into the final product.
|
||||
if (use_lld and (use_llvm or !comp.config.have_zcu)) {
|
||||
// LLVM emits the object file (if any); LLD links it into the final product.
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@ -328,8 +328,8 @@ pub fn createEmpty(
|
||||
}
|
||||
errdefer self.base.destroy();
|
||||
|
||||
if (use_lld and use_llvm) {
|
||||
// LLVM emits the object file; LLD links it into the final product.
|
||||
if (use_lld and (use_llvm or !comp.config.have_zcu)) {
|
||||
// LLVM emits the object file (if any); LLD links it into the final product.
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@ -174,72 +174,97 @@ pub const SdkLayout = enum {
|
||||
vendored,
|
||||
};
|
||||
|
||||
pub fn open(
|
||||
pub fn createEmpty(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
options: link.File.OpenOptions,
|
||||
) !*MachO {
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
const use_lld = build_options.have_llvm and comp.config.use_lld;
|
||||
const use_llvm = comp.config.use_llvm;
|
||||
assert(target.ofmt == .macho);
|
||||
|
||||
const use_llvm = comp.config.use_llvm;
|
||||
const gpa = comp.gpa;
|
||||
const mode: Mode = mode: {
|
||||
if (use_llvm or comp.module == null or comp.cache_use == .whole)
|
||||
break :mode .zld;
|
||||
break :mode .incremental;
|
||||
};
|
||||
const sub_path = if (mode == .zld) blk: {
|
||||
if (comp.module == null) {
|
||||
// No point in opening a file, we would not write anything to it.
|
||||
// Initialize with empty.
|
||||
return createEmpty(arena, comp, emit, options);
|
||||
}
|
||||
// Open a temporary object file, not the final output file because we
|
||||
// want to link with LLD.
|
||||
break :blk try std.fmt.allocPrint(arena, "{s}{s}", .{
|
||||
emit.sub_path, target.ofmt.fileExt(target.cpu.arch),
|
||||
});
|
||||
} else emit.sub_path;
|
||||
const optimize_mode = comp.root_mod.optimize_mode;
|
||||
const output_mode = comp.config.output_mode;
|
||||
const link_mode = comp.config.link_mode;
|
||||
|
||||
const self = try createEmpty(arena, comp, emit, options);
|
||||
// TODO: get rid of zld mode
|
||||
const mode: Mode = if (use_llvm or !comp.config.have_zcu or comp.cache_use == .whole)
|
||||
.zld
|
||||
else
|
||||
.incremental;
|
||||
|
||||
// If using "zld mode" to link, this code should produce an object file so that it
|
||||
// can be passed to "zld mode". TODO: get rid of "zld mode".
|
||||
// If using LLVM to generate the object file for the zig compilation unit,
|
||||
// we need a place to put the object file so that it can be subsequently
|
||||
// handled.
|
||||
const zcu_object_sub_path = if (mode != .zld and !use_llvm)
|
||||
null
|
||||
else
|
||||
try std.fmt.allocPrint(arena, "{s}.o", .{emit.sub_path});
|
||||
|
||||
const self = try arena.create(MachO);
|
||||
self.* = .{
|
||||
.base = .{
|
||||
.tag = .macho,
|
||||
.comp = comp,
|
||||
.emit = emit,
|
||||
.zcu_object_sub_path = zcu_object_sub_path,
|
||||
.gc_sections = options.gc_sections orelse (optimize_mode != .Debug),
|
||||
.print_gc_sections = options.print_gc_sections,
|
||||
.stack_size = options.stack_size orelse 16777216,
|
||||
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
|
||||
.file = null,
|
||||
.disable_lld_caching = options.disable_lld_caching,
|
||||
.build_id = options.build_id,
|
||||
.rpath_list = options.rpath_list,
|
||||
.force_undefined_symbols = options.force_undefined_symbols,
|
||||
},
|
||||
.mode = mode,
|
||||
.pagezero_vmsize = options.pagezero_size orelse default_pagezero_vmsize,
|
||||
.headerpad_size = options.headerpad_size orelse default_headerpad_size,
|
||||
.headerpad_max_install_names = options.headerpad_max_install_names,
|
||||
.dead_strip_dylibs = options.dead_strip_dylibs,
|
||||
.sdk_layout = options.darwin_sdk_layout,
|
||||
.frameworks = options.frameworks,
|
||||
.install_name = options.install_name,
|
||||
.entitlements = options.entitlements,
|
||||
.compatibility_version = options.compatibility_version,
|
||||
};
|
||||
if (use_llvm and comp.config.have_zcu) {
|
||||
self.llvm_object = try LlvmObject.create(arena, comp);
|
||||
}
|
||||
errdefer self.base.destroy();
|
||||
|
||||
log.debug("selected linker mode '{s}'", .{@tagName(self.mode)});
|
||||
|
||||
if (mode == .zld) {
|
||||
// TODO this zcu_object_sub_path 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.zcu_object_sub_path = sub_path;
|
||||
// TODO: get rid of zld mode
|
||||
return self;
|
||||
}
|
||||
|
||||
const file = try emit.directory.handle.createFile(sub_path, .{
|
||||
.truncate = false,
|
||||
const file = try emit.directory.handle.createFile(emit.sub_path, .{
|
||||
.truncate = true,
|
||||
.read = true,
|
||||
.mode = link.File.determineMode(
|
||||
use_lld,
|
||||
comp.config.output_mode,
|
||||
comp.config.link_mode,
|
||||
),
|
||||
.mode = link.File.determineMode(false, output_mode, link_mode),
|
||||
});
|
||||
self.base.file = file;
|
||||
|
||||
if (comp.config.debug_format != .strip and comp.module != null) {
|
||||
// Create dSYM bundle.
|
||||
log.debug("creating {s}.dSYM bundle", .{sub_path});
|
||||
log.debug("creating {s}.dSYM bundle", .{emit.sub_path});
|
||||
|
||||
const d_sym_path = try std.fmt.allocPrint(
|
||||
arena,
|
||||
"{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF",
|
||||
.{sub_path},
|
||||
.{emit.sub_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(sub_path, .{
|
||||
const d_sym_file = try d_sym_bundle.createFile(emit.sub_path, .{
|
||||
.truncate = false,
|
||||
.read = true,
|
||||
});
|
||||
@ -273,53 +298,15 @@ pub fn open(
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn createEmpty(
|
||||
pub fn open(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
options: link.File.OpenOptions,
|
||||
) !*MachO {
|
||||
const optimize_mode = comp.root_mod.optimize_mode;
|
||||
const use_llvm = comp.config.use_llvm;
|
||||
|
||||
const self = try arena.create(MachO);
|
||||
self.* = .{
|
||||
.base = .{
|
||||
.tag = .macho,
|
||||
.comp = comp,
|
||||
.emit = emit,
|
||||
.gc_sections = options.gc_sections orelse (optimize_mode != .Debug),
|
||||
.print_gc_sections = options.print_gc_sections,
|
||||
.stack_size = options.stack_size orelse 16777216,
|
||||
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
|
||||
.file = null,
|
||||
.disable_lld_caching = options.disable_lld_caching,
|
||||
.build_id = options.build_id,
|
||||
.rpath_list = options.rpath_list,
|
||||
.force_undefined_symbols = options.force_undefined_symbols,
|
||||
},
|
||||
.mode = if (use_llvm or comp.module == null or comp.cache_use == .whole)
|
||||
.zld
|
||||
else
|
||||
.incremental,
|
||||
.pagezero_vmsize = options.pagezero_size orelse default_pagezero_vmsize,
|
||||
.headerpad_size = options.headerpad_size orelse default_headerpad_size,
|
||||
.headerpad_max_install_names = options.headerpad_max_install_names,
|
||||
.dead_strip_dylibs = options.dead_strip_dylibs,
|
||||
.sdk_layout = options.darwin_sdk_layout,
|
||||
.frameworks = options.frameworks,
|
||||
.install_name = options.install_name,
|
||||
.entitlements = options.entitlements,
|
||||
.compatibility_version = options.compatibility_version,
|
||||
};
|
||||
|
||||
if (use_llvm and comp.module != null) {
|
||||
self.llvm_object = try LlvmObject.create(arena, comp);
|
||||
}
|
||||
|
||||
log.debug("selected linker mode '{s}'", .{@tagName(self.mode)});
|
||||
|
||||
return self;
|
||||
// TODO: restore saved linker state, don't truncate the file, and
|
||||
// participate in incremental compilation.
|
||||
return createEmpty(arena, comp, emit, options);
|
||||
}
|
||||
|
||||
pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
|
||||
|
||||
@ -440,8 +440,8 @@ pub fn createEmpty(
|
||||
}
|
||||
errdefer wasm.base.destroy();
|
||||
|
||||
if (use_lld and use_llvm) {
|
||||
// LLVM emits the object file; LLD links it into the final product.
|
||||
if (use_lld and (use_llvm or !comp.config.have_zcu)) {
|
||||
// LLVM emits the object file (if any); LLD links it into the final product.
|
||||
return wasm;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user