mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
lld: use a response file on NameTooLong
This commit is contained in:
parent
ddde99bdfa
commit
d09afc08da
@ -5091,7 +5091,7 @@ fn spawnZigRc(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tmpFilePath(comp: *Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 {
|
||||
pub fn tmpFilePath(comp: Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 {
|
||||
const s = std.fs.path.sep_str;
|
||||
const rand_int = std.crypto.random.int(u64);
|
||||
if (comp.local_cache_directory.path) |p| {
|
||||
@ -5894,14 +5894,16 @@ pub fn lockAndSetMiscFailure(
|
||||
return setMiscFailure(comp, tag, format, args);
|
||||
}
|
||||
|
||||
fn parseLldStderr(comp: *Compilation, comptime prefix: []const u8, stderr: []const u8) Allocator.Error!void {
|
||||
fn parseLldStderr(comp: *Compilation, prefix: []const u8, stderr: []const u8) Allocator.Error!void {
|
||||
var context_lines = std.ArrayList([]const u8).init(comp.gpa);
|
||||
defer context_lines.deinit();
|
||||
|
||||
var current_err: ?*LldError = null;
|
||||
var lines = mem.splitSequence(u8, stderr, if (builtin.os.tag == .windows) "\r\n" else "\n");
|
||||
while (lines.next()) |line| {
|
||||
if (mem.startsWith(u8, line, prefix ++ ":")) {
|
||||
if (line.len > prefix.len + ":".len and
|
||||
mem.eql(u8, line[0..prefix.len], prefix) and line[prefix.len] == ':')
|
||||
{
|
||||
if (current_err) |err| {
|
||||
err.context_lines = try context_lines.toOwnedSlice();
|
||||
}
|
||||
@ -5933,7 +5935,7 @@ fn parseLldStderr(comp: *Compilation, comptime prefix: []const u8, stderr: []con
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lockAndParseLldStderr(comp: *Compilation, comptime prefix: []const u8, stderr: []const u8) void {
|
||||
pub fn lockAndParseLldStderr(comp: *Compilation, prefix: []const u8, stderr: []const u8) void {
|
||||
comp.mutex.lock();
|
||||
defer comp.mutex.unlock();
|
||||
|
||||
|
||||
110
src/link.zig
110
src/link.zig
@ -19,6 +19,8 @@ const InternPool = @import("InternPool.zig");
|
||||
const Type = @import("type.zig").Type;
|
||||
const Value = @import("Value.zig");
|
||||
const LlvmObject = @import("codegen/llvm.zig").Object;
|
||||
const lldMain = @import("main.zig").lldMain;
|
||||
const Package = @import("Package.zig");
|
||||
|
||||
/// When adding a new field, remember to update `hashAddSystemLibs`.
|
||||
/// These are *always* dynamically linked. Static libraries will be
|
||||
@ -982,3 +984,111 @@ pub const File = struct {
|
||||
pub const NvPtx = @import("link/NvPtx.zig");
|
||||
pub const Dwarf = @import("link/Dwarf.zig");
|
||||
};
|
||||
|
||||
pub fn spawnLld(
|
||||
comp: *Compilation,
|
||||
arena: Allocator,
|
||||
argv: []const []const u8,
|
||||
) !void {
|
||||
if (comp.verbose_link) {
|
||||
// Skip over our own name so that the LLD linker name is the first argv item.
|
||||
Compilation.dump_argv(argv[1..]);
|
||||
}
|
||||
|
||||
// If possible, we run LLD as a child process because it does not always
|
||||
// behave properly as a library, unfortunately.
|
||||
// https://github.com/ziglang/zig/issues/3825
|
||||
if (!std.process.can_spawn) {
|
||||
const exit_code = try lldMain(arena, argv, false);
|
||||
if (exit_code == 0) return;
|
||||
if (comp.clang_passthrough_mode) std.process.exit(exit_code);
|
||||
return error.LLDReportedFailure;
|
||||
}
|
||||
|
||||
var stderr: []u8 = &.{};
|
||||
defer comp.gpa.free(stderr);
|
||||
|
||||
var child = std.process.Child.init(argv, arena);
|
||||
const term = (if (comp.clang_passthrough_mode) term: {
|
||||
child.stdin_behavior = .Inherit;
|
||||
child.stdout_behavior = .Inherit;
|
||||
child.stderr_behavior = .Inherit;
|
||||
|
||||
break :term child.spawnAndWait();
|
||||
} else term: {
|
||||
child.stdin_behavior = .Ignore;
|
||||
child.stdout_behavior = .Ignore;
|
||||
child.stderr_behavior = .Pipe;
|
||||
|
||||
child.spawn() catch |err| break :term err;
|
||||
stderr = try child.stderr.?.reader().readAllAlloc(comp.gpa, std.math.maxInt(usize));
|
||||
break :term child.wait();
|
||||
}) catch |first_err| term: {
|
||||
const err = switch (first_err) {
|
||||
error.NameTooLong => err: {
|
||||
const s = fs.path.sep_str;
|
||||
const rand_int = std.crypto.random.int(u64);
|
||||
const rsp_path = "tmp" ++ s ++ Package.Manifest.hex64(rand_int) ++ ".rsp";
|
||||
|
||||
const rsp_file = try comp.local_cache_directory.handle.createFileZ(rsp_path, .{});
|
||||
defer comp.local_cache_directory.handle.deleteFileZ(rsp_path) catch |err|
|
||||
log.warn("failed to delete response file {s}: {s}", .{ rsp_path, @errorName(err) });
|
||||
{
|
||||
defer rsp_file.close();
|
||||
var rsp_buf = std.io.bufferedWriter(rsp_file.writer());
|
||||
const rsp_writer = rsp_buf.writer();
|
||||
for (argv[2..]) |arg| {
|
||||
try rsp_writer.writeByte('"');
|
||||
for (arg) |c| {
|
||||
switch (c) {
|
||||
'\"', '\\' => try rsp_writer.writeByte('\\'),
|
||||
else => {},
|
||||
}
|
||||
try rsp_writer.writeByte(c);
|
||||
}
|
||||
try rsp_writer.writeByte('"');
|
||||
try rsp_writer.writeByte('\n');
|
||||
}
|
||||
try rsp_buf.flush();
|
||||
}
|
||||
|
||||
var rsp_child = std.process.Child.init(&.{ argv[0], argv[1], try std.fmt.allocPrint(
|
||||
arena,
|
||||
"@{s}",
|
||||
.{try comp.local_cache_directory.join(arena, &.{rsp_path})},
|
||||
) }, arena);
|
||||
if (comp.clang_passthrough_mode) {
|
||||
rsp_child.stdin_behavior = .Inherit;
|
||||
rsp_child.stdout_behavior = .Inherit;
|
||||
rsp_child.stderr_behavior = .Inherit;
|
||||
|
||||
break :term rsp_child.spawnAndWait() catch |err| break :err err;
|
||||
} else {
|
||||
rsp_child.stdin_behavior = .Ignore;
|
||||
rsp_child.stdout_behavior = .Ignore;
|
||||
rsp_child.stderr_behavior = .Pipe;
|
||||
|
||||
rsp_child.spawn() catch |err| break :err err;
|
||||
stderr = try rsp_child.stderr.?.reader().readAllAlloc(comp.gpa, std.math.maxInt(usize));
|
||||
break :term rsp_child.wait() catch |err| break :err err;
|
||||
}
|
||||
},
|
||||
else => first_err,
|
||||
};
|
||||
log.err("unable to spawn {s}: {s}", .{ argv[0], @errorName(err) });
|
||||
return error.UnableToSpawnSelf;
|
||||
};
|
||||
|
||||
switch (term) {
|
||||
.Exited => |code| if (code != 0) {
|
||||
comp.lockAndParseLldStderr(argv[1], stderr);
|
||||
return error.LLDReportedFailure;
|
||||
},
|
||||
else => {
|
||||
log.err("{s} terminated with stderr:\n{s}", .{ argv[0], stderr });
|
||||
return error.LLDCrashed;
|
||||
},
|
||||
}
|
||||
|
||||
if (stderr.len > 0) log.warn("unexpected LLD stderr:\n{s}", .{stderr});
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@ const Cache = std.Build.Cache;
|
||||
|
||||
const mingw = @import("../../mingw.zig");
|
||||
const link = @import("../../link.zig");
|
||||
const lldMain = @import("../../main.zig").lldMain;
|
||||
const trace = @import("../../tracy.zig").trace;
|
||||
|
||||
const Allocator = mem.Allocator;
|
||||
@ -502,74 +501,7 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, prog_node: *std.Progress.Node)
|
||||
return error.DllImportLibraryNotFound;
|
||||
}
|
||||
|
||||
if (comp.verbose_link) {
|
||||
// Skip over our own name so that the LLD linker name is the first argv item.
|
||||
Compilation.dump_argv(argv.items[1..]);
|
||||
}
|
||||
|
||||
if (std.process.can_spawn) {
|
||||
// If possible, we run LLD as a child process because it does not always
|
||||
// behave properly as a library, unfortunately.
|
||||
// https://github.com/ziglang/zig/issues/3825
|
||||
var child = std.ChildProcess.init(argv.items, arena);
|
||||
if (comp.clang_passthrough_mode) {
|
||||
child.stdin_behavior = .Inherit;
|
||||
child.stdout_behavior = .Inherit;
|
||||
child.stderr_behavior = .Inherit;
|
||||
|
||||
const term = child.spawnAndWait() catch |err| {
|
||||
log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
|
||||
return error.UnableToSpawnSelf;
|
||||
};
|
||||
switch (term) {
|
||||
.Exited => |code| {
|
||||
if (code != 0) {
|
||||
std.process.exit(code);
|
||||
}
|
||||
},
|
||||
else => std.process.abort(),
|
||||
}
|
||||
} else {
|
||||
child.stdin_behavior = .Ignore;
|
||||
child.stdout_behavior = .Ignore;
|
||||
child.stderr_behavior = .Pipe;
|
||||
|
||||
try child.spawn();
|
||||
|
||||
const stderr = try child.stderr.?.reader().readAllAlloc(arena, std.math.maxInt(usize));
|
||||
|
||||
const term = child.wait() catch |err| {
|
||||
log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
|
||||
return error.UnableToSpawnSelf;
|
||||
};
|
||||
|
||||
switch (term) {
|
||||
.Exited => |code| {
|
||||
if (code != 0) {
|
||||
comp.lockAndParseLldStderr(linker_command, stderr);
|
||||
return error.LLDReportedFailure;
|
||||
}
|
||||
},
|
||||
else => {
|
||||
log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
|
||||
return error.LLDCrashed;
|
||||
},
|
||||
}
|
||||
|
||||
if (stderr.len != 0) {
|
||||
log.warn("unexpected LLD stderr:\n{s}", .{stderr});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const exit_code = try lldMain(arena, argv.items, false);
|
||||
if (exit_code != 0) {
|
||||
if (comp.clang_passthrough_mode) {
|
||||
std.process.exit(exit_code);
|
||||
} else {
|
||||
return error.LLDReportedFailure;
|
||||
}
|
||||
}
|
||||
}
|
||||
try link.spawnLld(comp, arena, argv.items);
|
||||
}
|
||||
|
||||
if (!self.base.disable_lld_caching) {
|
||||
|
||||
@ -2726,74 +2726,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) !voi
|
||||
try argv.append("-Bsymbolic");
|
||||
}
|
||||
|
||||
if (comp.verbose_link) {
|
||||
// Skip over our own name so that the LLD linker name is the first argv item.
|
||||
Compilation.dump_argv(argv.items[1..]);
|
||||
}
|
||||
|
||||
if (std.process.can_spawn) {
|
||||
// If possible, we run LLD as a child process because it does not always
|
||||
// behave properly as a library, unfortunately.
|
||||
// https://github.com/ziglang/zig/issues/3825
|
||||
var child = std.ChildProcess.init(argv.items, arena);
|
||||
if (comp.clang_passthrough_mode) {
|
||||
child.stdin_behavior = .Inherit;
|
||||
child.stdout_behavior = .Inherit;
|
||||
child.stderr_behavior = .Inherit;
|
||||
|
||||
const term = child.spawnAndWait() catch |err| {
|
||||
log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
|
||||
return error.UnableToSpawnSelf;
|
||||
};
|
||||
switch (term) {
|
||||
.Exited => |code| {
|
||||
if (code != 0) {
|
||||
std.process.exit(code);
|
||||
}
|
||||
},
|
||||
else => std.process.abort(),
|
||||
}
|
||||
} else {
|
||||
child.stdin_behavior = .Ignore;
|
||||
child.stdout_behavior = .Ignore;
|
||||
child.stderr_behavior = .Pipe;
|
||||
|
||||
try child.spawn();
|
||||
|
||||
const stderr = try child.stderr.?.reader().readAllAlloc(arena, std.math.maxInt(usize));
|
||||
|
||||
const term = child.wait() catch |err| {
|
||||
log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
|
||||
return error.UnableToSpawnSelf;
|
||||
};
|
||||
|
||||
switch (term) {
|
||||
.Exited => |code| {
|
||||
if (code != 0) {
|
||||
comp.lockAndParseLldStderr(linker_command, stderr);
|
||||
return error.LLDReportedFailure;
|
||||
}
|
||||
},
|
||||
else => {
|
||||
log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
|
||||
return error.LLDCrashed;
|
||||
},
|
||||
}
|
||||
|
||||
if (stderr.len != 0) {
|
||||
log.warn("unexpected LLD stderr:\n{s}", .{stderr});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const exit_code = try lldMain(arena, argv.items, false);
|
||||
if (exit_code != 0) {
|
||||
if (comp.clang_passthrough_mode) {
|
||||
std.process.exit(exit_code);
|
||||
} else {
|
||||
return error.LLDReportedFailure;
|
||||
}
|
||||
}
|
||||
}
|
||||
try link.spawnLld(comp, arena, argv.items);
|
||||
}
|
||||
|
||||
if (!self.base.disable_lld_caching) {
|
||||
@ -6500,7 +6433,6 @@ const eh_frame = @import("Elf/eh_frame.zig");
|
||||
const gc = @import("Elf/gc.zig");
|
||||
const glibc = @import("../glibc.zig");
|
||||
const link = @import("../link.zig");
|
||||
const lldMain = @import("../main.zig").lldMain;
|
||||
const merge_section = @import("Elf/merge_section.zig");
|
||||
const musl = @import("../musl.zig");
|
||||
const relocatable = @import("Elf/relocatable.zig");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user