MachO: add the same workaround for no -r LLD flag support

This is the MachO equivalent for the code added to COFF for doing the
file copy when the input and output are both just one object file.
This commit is contained in:
Andrew Kelley 2020-09-30 01:00:06 -07:00
parent 2a893efae1
commit 3249e5d952
2 changed files with 218 additions and 196 deletions

View File

@ -319,7 +319,6 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
break :blk full_obj_path;
} else null;
const is_obj = self.base.options.output_mode == .Obj;
const is_lib = self.base.options.output_mode == .Lib;
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;
@ -391,14 +390,37 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
};
}
const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
if (self.base.options.output_mode == .Obj) {
// LLD's MachO driver does not support the equvialent of `-r` so we do a simple file copy
// here. TODO: think carefully about how we can avoid this redundant operation when doing
// build-obj. See also the corresponding TODO in linkAsArchive.
const the_object_path = blk: {
if (self.base.options.objects.len != 0)
break :blk self.base.options.objects[0];
if (comp.c_object_table.count() != 0)
break :blk comp.c_object_table.items()[0].key.status.success.object_path;
if (module_obj_path) |p|
break :blk p;
// TODO I think this is unreachable. Audit this situation when solving the above TODO
// regarding eliding redundant object -> object transformations.
return error.NoObjectsToLink;
};
// This can happen when using --enable-cache and using the stage1 backend. In this case
// we can skip the file copy.
if (!mem.eql(u8, the_object_path, full_out_path)) {
try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{});
}
} else {
// Create an LLD command line and invoke it.
var argv = std.ArrayList([]const u8).init(self.base.allocator);
defer argv.deinit();
// Even though we're calling LLD as a library it thinks the first argument is its own exe name.
try argv.append("lld");
if (is_obj) {
try argv.append("-r");
}
try argv.append("-error-limit");
try argv.append("0");
@ -474,7 +496,6 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
try argv.append("-pie");
}
const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
try argv.append("-o");
try argv.append(full_out_path);
@ -528,7 +549,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
}
// libc++ dep
if (!is_obj and self.base.options.link_libcpp) {
if (self.base.options.link_libcpp) {
try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
try argv.append(comp.libcxx_static_lib.?.full_object_path);
}
@ -601,6 +622,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
if (stderr_context.data.items.len != 0) {
std.log.warn("unexpected LLD stderr: {}", .{stderr_context.data.items});
}
}
if (!self.base.options.disable_lld_caching) {
// Update the dangling symlink with the digest. If it fails we can continue; it only

View File

@ -1337,12 +1337,12 @@ fn buildOutputType(
}
};
if (output_mode == .Obj and object_format == .coff) {
if (output_mode == .Obj and (object_format == .coff or object_format == .macho)) {
const total_obj_count = c_source_files.items.len +
@boolToInt(root_src_file != null) +
link_objects.items.len;
if (total_obj_count > 1) {
fatal("COFF does not support linking multiple objects into one", .{});
fatal("{s} does not support linking multiple objects into one", .{@tagName(object_format)});
}
}