Merge pull request #6990 from kubkon/system-linker-hack

Re-enable system linker hack
master
Andrew Kelley 2020-11-06 13:22:03 -05:00 committed by GitHub
commit a9e09a8be4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 92 additions and 57 deletions

View File

@ -396,8 +396,8 @@ fn configureStage2(b: *Builder, exe: anytype, ctx: Context, need_cpp_includes: b
try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null, need_cpp_includes); try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null, need_cpp_includes);
exe.linkSystemLibrary("pthread"); exe.linkSystemLibrary("pthread");
// TODO LLD cannot perform this link. // TODO LLD cannot perform this link.
// Set ZIG_SYSTEM_LINKER_HACK env var to use system linker ld instead.
// See https://github.com/ziglang/zig/issues/1535 // See https://github.com/ziglang/zig/issues/1535
exe.enableSystemLinkerHack();
} else |err| switch (err) { } else |err| switch (err) {
error.RequiredLibraryNotFound => { error.RequiredLibraryNotFound => {
// System compiler, not gcc. // System compiler, not gcc.

View File

@ -1237,7 +1237,6 @@ pub const LibExeObjStep = struct {
packages: ArrayList(Pkg), packages: ArrayList(Pkg),
build_options_contents: std.ArrayList(u8), build_options_contents: std.ArrayList(u8),
build_options_artifact_args: std.ArrayList(BuildOptionArtifactArg), build_options_artifact_args: std.ArrayList(BuildOptionArtifactArg),
system_linker_hack: bool = false,
object_src: []const u8, object_src: []const u8,
@ -1898,10 +1897,6 @@ pub const LibExeObjStep = struct {
self.exec_cmd_args = args; self.exec_cmd_args = args;
} }
pub fn enableSystemLinkerHack(self: *LibExeObjStep) void {
self.system_linker_hack = true;
}
fn linkLibraryOrObject(self: *LibExeObjStep, other: *LibExeObjStep) void { fn linkLibraryOrObject(self: *LibExeObjStep, other: *LibExeObjStep) void {
self.step.dependOn(&other.step); self.step.dependOn(&other.step);
self.link_objects.append(LinkObject{ .OtherStep = other }) catch unreachable; self.link_objects.append(LinkObject{ .OtherStep = other }) catch unreachable;
@ -2283,10 +2278,6 @@ pub const LibExeObjStep = struct {
} }
} }
if (self.system_linker_hack) {
try zig_args.append("--system-linker-hack");
}
if (self.valgrind_support) |valgrind_support| { if (self.valgrind_support) |valgrind_support| {
if (valgrind_support) { if (valgrind_support) {
try zig_args.append("-fvalgrind"); try zig_args.append("-fvalgrind");

View File

@ -472,13 +472,22 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
break :blk false; break :blk false;
}; };
const syslibroot = if (build_options.have_llvm and comptime std.Target.current.isDarwin()) outer: { const DarwinOptions = struct {
const path = if (use_lld and options.is_native_os and options.target.isDarwin()) inner: { syslibroot: ?[]const u8 = null,
const syslibroot_path = try std.zig.system.getSDKPath(arena); system_linker_hack: bool = false,
break :inner syslibroot_path; };
} else null;
break :outer path; const darwin_options: DarwinOptions = if (build_options.have_llvm and comptime std.Target.current.isDarwin()) outer: {
} else null; const opts: DarwinOptions = if (use_lld and options.is_native_os and options.target.isDarwin()) inner: {
const syslibroot = try std.zig.system.getSDKPath(arena);
const system_linker_hack = std.os.getenv("ZIG_SYSTEM_LINKER_HACK") != null;
break :inner .{
.syslibroot = syslibroot,
.system_linker_hack = system_linker_hack,
};
} else .{};
break :outer opts;
} else .{};
const link_libc = options.link_libc or target_util.osRequiresLibC(options.target); const link_libc = options.link_libc or target_util.osRequiresLibC(options.target);
@ -775,13 +784,14 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
.optimize_mode = options.optimize_mode, .optimize_mode = options.optimize_mode,
.use_lld = use_lld, .use_lld = use_lld,
.use_llvm = use_llvm, .use_llvm = use_llvm,
.system_linker_hack = darwin_options.system_linker_hack,
.link_libc = link_libc, .link_libc = link_libc,
.link_libcpp = options.link_libcpp, .link_libcpp = options.link_libcpp,
.objects = options.link_objects, .objects = options.link_objects,
.frameworks = options.frameworks, .frameworks = options.frameworks,
.framework_dirs = options.framework_dirs, .framework_dirs = options.framework_dirs,
.system_libs = system_libs, .system_libs = system_libs,
.syslibroot = syslibroot, .syslibroot = darwin_options.syslibroot,
.lib_dirs = options.lib_dirs, .lib_dirs = options.lib_dirs,
.rpath_list = options.rpath_list, .rpath_list = options.rpath_list,
.strip = strip, .strip = strip,

View File

@ -57,6 +57,9 @@ pub const Options = struct {
/// other objects. /// other objects.
/// Otherwise (depending on `use_lld`) this link code directly outputs and updates the final binary. /// Otherwise (depending on `use_lld`) this link code directly outputs and updates the final binary.
use_llvm: bool, use_llvm: bool,
/// Darwin-only. If this is true, `use_llvm` is true, and `is_native_os` is true, this link code will
/// use system linker `ld` instead of the LLD.
system_linker_hack: bool,
link_libc: bool, link_libc: bool,
link_libcpp: bool, link_libcpp: bool,
function_sections: bool, function_sections: bool,

View File

@ -532,11 +532,19 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
// Create an LLD command line and invoke it. // Create an LLD command line and invoke it.
var argv = std.ArrayList([]const u8).init(self.base.allocator); var argv = std.ArrayList([]const u8).init(self.base.allocator);
defer argv.deinit(); 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");
try argv.append("-error-limit"); // TODO https://github.com/ziglang/zig/issues/6971
try argv.append("0"); // Note that there is no need to check if running natively since we do that already
// when setting `system_linker_hack` in Compilation struct.
if (self.base.options.system_linker_hack) {
try argv.append("ld");
} else {
// Even though we're calling LLD as a library it thinks the first argument is its own exe name.
try argv.append("lld");
try argv.append("-error-limit");
try argv.append("0");
}
try argv.append("-demangle"); try argv.append("-demangle");
@ -703,42 +711,65 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
Compilation.dump_argv(argv.items); Compilation.dump_argv(argv.items);
} }
const new_argv = try arena.allocSentinel(?[*:0]const u8, argv.items.len, null); // TODO https://github.com/ziglang/zig/issues/6971
for (argv.items) |arg, i| { // Note that there is no need to check if running natively since we do that already
new_argv[i] = try arena.dupeZ(u8, arg); // when setting `system_linker_hack` in Compilation struct.
} if (self.base.options.system_linker_hack) {
const result = try std.ChildProcess.exec(.{ .allocator = self.base.allocator, .argv = argv.items });
defer {
self.base.allocator.free(result.stdout);
self.base.allocator.free(result.stderr);
}
if (result.stdout.len != 0) {
std.log.warn("unexpected LD stdout: {}", .{result.stdout});
}
if (result.stderr.len != 0) {
std.log.warn("unexpected LD stderr: {}", .{result.stderr});
}
if (result.term != .Exited or result.term.Exited != 0) {
// TODO parse this output and surface with the Compilation API rather than
// directly outputting to stderr here.
std.debug.print("{}", .{result.stderr});
return error.LDReportedFailure;
}
} else {
const new_argv = try arena.allocSentinel(?[*:0]const u8, argv.items.len, null);
for (argv.items) |arg, i| {
new_argv[i] = try arena.dupeZ(u8, arg);
}
var stderr_context: LLDContext = .{ var stderr_context: LLDContext = .{
.macho = self, .macho = self,
.data = std.ArrayList(u8).init(self.base.allocator), .data = std.ArrayList(u8).init(self.base.allocator),
}; };
defer stderr_context.data.deinit(); defer stderr_context.data.deinit();
var stdout_context: LLDContext = .{ var stdout_context: LLDContext = .{
.macho = self, .macho = self,
.data = std.ArrayList(u8).init(self.base.allocator), .data = std.ArrayList(u8).init(self.base.allocator),
}; };
defer stdout_context.data.deinit(); defer stdout_context.data.deinit();
const llvm = @import("../llvm.zig"); const llvm = @import("../llvm.zig");
const ok = llvm.Link( const ok = llvm.Link(
.MachO, .MachO,
new_argv.ptr, new_argv.ptr,
new_argv.len, new_argv.len,
append_diagnostic, append_diagnostic,
@ptrToInt(&stdout_context), @ptrToInt(&stdout_context),
@ptrToInt(&stderr_context), @ptrToInt(&stderr_context),
); );
if (stderr_context.oom or stdout_context.oom) return error.OutOfMemory; if (stderr_context.oom or stdout_context.oom) return error.OutOfMemory;
if (stdout_context.data.items.len != 0) { if (stdout_context.data.items.len != 0) {
std.log.warn("unexpected LLD stdout: {}", .{stdout_context.data.items}); std.log.warn("unexpected LLD stdout: {}", .{stdout_context.data.items});
} }
if (!ok) { if (!ok) {
// TODO parse this output and surface with the Compilation API rather than // TODO parse this output and surface with the Compilation API rather than
// directly outputting to stderr here. // directly outputting to stderr here.
std.debug.print("{}", .{stderr_context.data.items}); std.debug.print("{}", .{stderr_context.data.items});
return error.LLDReportedFailure; return error.LLDReportedFailure;
} }
if (stderr_context.data.items.len != 0) { if (stderr_context.data.items.len != 0) {
std.log.warn("unexpected LLD stderr: {}", .{stderr_context.data.items}); std.log.warn("unexpected LLD stderr: {}", .{stderr_context.data.items});
}
} }
} }