| author | |
| committer | |
| log | d09afc08da86b4391f1dda6162621d29075cb8a2 |
| tree | 610f838891db1a1cb268730cb69a70db0467fe06 |
| parent | ddde99bdfa5b2fa9b49c39a0f00a8c232a9576b6 |
4 files changed, 118 insertions(+), 142 deletions(-)
src/Compilation.zig+6-4| ... | ... | @@ -5091,7 +5091,7 @@ fn spawnZigRc( |
| 5091 | 5091 | } |
| 5092 | 5092 | } |
| 5093 | 5093 | |
| 5094 | pub fn tmpFilePath(comp: *Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 { | |
| 5094 | pub fn tmpFilePath(comp: Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 { | |
| 5095 | 5095 | const s = std.fs.path.sep_str; |
| 5096 | 5096 | const rand_int = std.crypto.random.int(u64); |
| 5097 | 5097 | if (comp.local_cache_directory.path) |p| { |
| ... | ... | @@ -5894,14 +5894,16 @@ pub fn lockAndSetMiscFailure( |
| 5894 | 5894 | return setMiscFailure(comp, tag, format, args); |
| 5895 | 5895 | } |
| 5896 | 5896 | |
| 5897 | fn parseLldStderr(comp: *Compilation, comptime prefix: []const u8, stderr: []const u8) Allocator.Error!void { | |
| 5897 | fn parseLldStderr(comp: *Compilation, prefix: []const u8, stderr: []const u8) Allocator.Error!void { | |
| 5898 | 5898 | var context_lines = std.ArrayList([]const u8).init(comp.gpa); |
| 5899 | 5899 | defer context_lines.deinit(); |
| 5900 | 5900 | |
| 5901 | 5901 | var current_err: ?*LldError = null; |
| 5902 | 5902 | var lines = mem.splitSequence(u8, stderr, if (builtin.os.tag == .windows) "\r\n" else "\n"); |
| 5903 | 5903 | while (lines.next()) |line| { |
| 5904 | if (mem.startsWith(u8, line, prefix ++ ":")) { | |
| 5904 | if (line.len > prefix.len + ":".len and | |
| 5905 | mem.eql(u8, line[0..prefix.len], prefix) and line[prefix.len] == ':') | |
| 5906 | { | |
| 5905 | 5907 | if (current_err) |err| { |
| 5906 | 5908 | err.context_lines = try context_lines.toOwnedSlice(); |
| 5907 | 5909 | } |
| ... | ... | @@ -5933,7 +5935,7 @@ fn parseLldStderr(comp: *Compilation, comptime prefix: []const u8, stderr: []con |
| 5933 | 5935 | } |
| 5934 | 5936 | } |
| 5935 | 5937 | |
| 5936 | pub fn lockAndParseLldStderr(comp: *Compilation, comptime prefix: []const u8, stderr: []const u8) void { | |
| 5938 | pub fn lockAndParseLldStderr(comp: *Compilation, prefix: []const u8, stderr: []const u8) void { | |
| 5937 | 5939 | comp.mutex.lock(); |
| 5938 | 5940 | defer comp.mutex.unlock(); |
| 5939 | 5941 |
src/link.zig+110| ... | ... | @@ -19,6 +19,8 @@ const InternPool = @import("InternPool.zig"); |
| 19 | 19 | const Type = @import("type.zig").Type; |
| 20 | 20 | const Value = @import("Value.zig"); |
| 21 | 21 | const LlvmObject = @import("codegen/llvm.zig").Object; |
| 22 | const lldMain = @import("main.zig").lldMain; | |
| 23 | const Package = @import("Package.zig"); | |
| 22 | 24 | |
| 23 | 25 | /// When adding a new field, remember to update `hashAddSystemLibs`. |
| 24 | 26 | /// These are *always* dynamically linked. Static libraries will be |
| ... | ... | @@ -982,3 +984,111 @@ pub const File = struct { |
| 982 | 984 | pub const NvPtx = @import("link/NvPtx.zig"); |
| 983 | 985 | pub const Dwarf = @import("link/Dwarf.zig"); |
| 984 | 986 | }; |
| 987 | ||
| 988 | pub fn spawnLld( | |
| 989 | comp: *Compilation, | |
| 990 | arena: Allocator, | |
| 991 | argv: []const []const u8, | |
| 992 | ) !void { | |
| 993 | if (comp.verbose_link) { | |
| 994 | // Skip over our own name so that the LLD linker name is the first argv item. | |
| 995 | Compilation.dump_argv(argv[1..]); | |
| 996 | } | |
| 997 | ||
| 998 | // If possible, we run LLD as a child process because it does not always | |
| 999 | // behave properly as a library, unfortunately. | |
| 1000 | // https://github.com/ziglang/zig/issues/3825 | |
| 1001 | if (!std.process.can_spawn) { | |
| 1002 | const exit_code = try lldMain(arena, argv, false); | |
| 1003 | if (exit_code == 0) return; | |
| 1004 | if (comp.clang_passthrough_mode) std.process.exit(exit_code); | |
| 1005 | return error.LLDReportedFailure; | |
| 1006 | } | |
| 1007 | ||
| 1008 | var stderr: []u8 = &.{}; | |
| 1009 | defer comp.gpa.free(stderr); | |
| 1010 | ||
| 1011 | var child = std.process.Child.init(argv, arena); | |
| 1012 | const term = (if (comp.clang_passthrough_mode) term: { | |
| 1013 | child.stdin_behavior = .Inherit; | |
| 1014 | child.stdout_behavior = .Inherit; | |
| 1015 | child.stderr_behavior = .Inherit; | |
| 1016 | ||
| 1017 | break :term child.spawnAndWait(); | |
| 1018 | } else term: { | |
| 1019 | child.stdin_behavior = .Ignore; | |
| 1020 | child.stdout_behavior = .Ignore; | |
| 1021 | child.stderr_behavior = .Pipe; | |
| 1022 | ||
| 1023 | child.spawn() catch |err| break :term err; | |
| 1024 | stderr = try child.stderr.?.reader().readAllAlloc(comp.gpa, std.math.maxInt(usize)); | |
| 1025 | break :term child.wait(); | |
| 1026 | }) catch |first_err| term: { | |
| 1027 | const err = switch (first_err) { | |
| 1028 | error.NameTooLong => err: { | |
| 1029 | const s = fs.path.sep_str; | |
| 1030 | const rand_int = std.crypto.random.int(u64); | |
| 1031 | const rsp_path = "tmp" ++ s ++ Package.Manifest.hex64(rand_int) ++ ".rsp"; | |
| 1032 | ||
| 1033 | const rsp_file = try comp.local_cache_directory.handle.createFileZ(rsp_path, .{}); | |
| 1034 | defer comp.local_cache_directory.handle.deleteFileZ(rsp_path) catch |err| | |
| 1035 | log.warn("failed to delete response file {s}: {s}", .{ rsp_path, @errorName(err) }); | |
| 1036 | { | |
| 1037 | defer rsp_file.close(); | |
| 1038 | var rsp_buf = std.io.bufferedWriter(rsp_file.writer()); | |
| 1039 | const rsp_writer = rsp_buf.writer(); | |
| 1040 | for (argv[2..]) |arg| { | |
| 1041 | try rsp_writer.writeByte('"'); | |
| 1042 | for (arg) |c| { | |
| 1043 | switch (c) { | |
| 1044 | '\"', '\\' => try rsp_writer.writeByte('\\'), | |
| 1045 | else => {}, | |
| 1046 | } | |
| 1047 | try rsp_writer.writeByte(c); | |
| 1048 | } | |
| 1049 | try rsp_writer.writeByte('"'); | |
| 1050 | try rsp_writer.writeByte('\n'); | |
| 1051 | } | |
| 1052 | try rsp_buf.flush(); | |
| 1053 | } | |
| 1054 | ||
| 1055 | var rsp_child = std.process.Child.init(&.{ argv[0], argv[1], try std.fmt.allocPrint( | |
| 1056 | arena, | |
| 1057 | "@{s}", | |
| 1058 | .{try comp.local_cache_directory.join(arena, &.{rsp_path})}, | |
| 1059 | ) }, arena); | |
| 1060 | if (comp.clang_passthrough_mode) { | |
| 1061 | rsp_child.stdin_behavior = .Inherit; | |
| 1062 | rsp_child.stdout_behavior = .Inherit; | |
| 1063 | rsp_child.stderr_behavior = .Inherit; | |
| 1064 | ||
| 1065 | break :term rsp_child.spawnAndWait() catch |err| break :err err; | |
| 1066 | } else { | |
| 1067 | rsp_child.stdin_behavior = .Ignore; | |
| 1068 | rsp_child.stdout_behavior = .Ignore; | |
| 1069 | rsp_child.stderr_behavior = .Pipe; | |
| 1070 | ||
| 1071 | rsp_child.spawn() catch |err| break :err err; | |
| 1072 | stderr = try rsp_child.stderr.?.reader().readAllAlloc(comp.gpa, std.math.maxInt(usize)); | |
| 1073 | break :term rsp_child.wait() catch |err| break :err err; | |
| 1074 | } | |
| 1075 | }, | |
| 1076 | else => first_err, | |
| 1077 | }; | |
| 1078 | log.err("unable to spawn {s}: {s}", .{ argv[0], @errorName(err) }); | |
| 1079 | return error.UnableToSpawnSelf; | |
| 1080 | }; | |
| 1081 | ||
| 1082 | switch (term) { | |
| 1083 | .Exited => |code| if (code != 0) { | |
| 1084 | comp.lockAndParseLldStderr(argv[1], stderr); | |
| 1085 | return error.LLDReportedFailure; | |
| 1086 | }, | |
| 1087 | else => { | |
| 1088 | log.err("{s} terminated with stderr:\n{s}", .{ argv[0], stderr }); | |
| 1089 | return error.LLDCrashed; | |
| 1090 | }, | |
| 1091 | } | |
| 1092 | ||
| 1093 | if (stderr.len > 0) log.warn("unexpected LLD stderr:\n{s}", .{stderr}); | |
| 1094 | } |
src/link/Coff/lld.zig+1-69| ... | ... | @@ -9,7 +9,6 @@ const Cache = std.Build.Cache; |
| 9 | 9 | |
| 10 | 10 | const mingw = @import("../../mingw.zig"); |
| 11 | 11 | const link = @import("../../link.zig"); |
| 12 | const lldMain = @import("../../main.zig").lldMain; | |
| 13 | 12 | const trace = @import("../../tracy.zig").trace; |
| 14 | 13 | |
| 15 | 14 | const Allocator = mem.Allocator; |
| ... | ... | @@ -502,74 +501,7 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, prog_node: *std.Progress.Node) |
| 502 | 501 | return error.DllImportLibraryNotFound; |
| 503 | 502 | } |
| 504 | 503 | |
| 505 | if (comp.verbose_link) { | |
| 506 | // Skip over our own name so that the LLD linker name is the first argv item. | |
| 507 | Compilation.dump_argv(argv.items[1..]); | |
| 508 | } | |
| 509 | ||
| 510 | if (std.process.can_spawn) { | |
| 511 | // If possible, we run LLD as a child process because it does not always | |
| 512 | // behave properly as a library, unfortunately. | |
| 513 | // https://github.com/ziglang/zig/issues/3825 | |
| 514 | var child = std.ChildProcess.init(argv.items, arena); | |
| 515 | if (comp.clang_passthrough_mode) { | |
| 516 | child.stdin_behavior = .Inherit; | |
| 517 | child.stdout_behavior = .Inherit; | |
| 518 | child.stderr_behavior = .Inherit; | |
| 519 | ||
| 520 | const term = child.spawnAndWait() catch |err| { | |
| 521 | log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) }); | |
| 522 | return error.UnableToSpawnSelf; | |
| 523 | }; | |
| 524 | switch (term) { | |
| 525 | .Exited => |code| { | |
| 526 | if (code != 0) { | |
| 527 | std.process.exit(code); | |
| 528 | } | |
| 529 | }, | |
| 530 | else => std.process.abort(), | |
| 531 | } | |
| 532 | } else { | |
| 533 | child.stdin_behavior = .Ignore; | |
| 534 | child.stdout_behavior = .Ignore; | |
| 535 | child.stderr_behavior = .Pipe; | |
| 536 | ||
| 537 | try child.spawn(); | |
| 538 | ||
| 539 | const stderr = try child.stderr.?.reader().readAllAlloc(arena, std.math.maxInt(usize)); | |
| 540 | ||
| 541 | const term = child.wait() catch |err| { | |
| 542 | log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) }); | |
| 543 | return error.UnableToSpawnSelf; | |
| 544 | }; | |
| 545 | ||
| 546 | switch (term) { | |
| 547 | .Exited => |code| { | |
| 548 | if (code != 0) { | |
| 549 | comp.lockAndParseLldStderr(linker_command, stderr); | |
| 550 | return error.LLDReportedFailure; | |
| 551 | } | |
| 552 | }, | |
| 553 | else => { | |
| 554 | log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr }); | |
| 555 | return error.LLDCrashed; | |
| 556 | }, | |
| 557 | } | |
| 558 | ||
| 559 | if (stderr.len != 0) { | |
| 560 | log.warn("unexpected LLD stderr:\n{s}", .{stderr}); | |
| 561 | } | |
| 562 | } | |
| 563 | } else { | |
| 564 | const exit_code = try lldMain(arena, argv.items, false); | |
| 565 | if (exit_code != 0) { | |
| 566 | if (comp.clang_passthrough_mode) { | |
| 567 | std.process.exit(exit_code); | |
| 568 | } else { | |
| 569 | return error.LLDReportedFailure; | |
| 570 | } | |
| 571 | } | |
| 572 | } | |
| 504 | try link.spawnLld(comp, arena, argv.items); | |
| 573 | 505 | } |
| 574 | 506 | |
| 575 | 507 | if (!self.base.disable_lld_caching) { |
src/link/Elf.zig+1-69| ... | ... | @@ -2726,74 +2726,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) !voi |
| 2726 | 2726 | try argv.append("-Bsymbolic"); |
| 2727 | 2727 | } |
| 2728 | 2728 | |
| 2729 | if (comp.verbose_link) { | |
| 2730 | // Skip over our own name so that the LLD linker name is the first argv item. | |
| 2731 | Compilation.dump_argv(argv.items[1..]); | |
| 2732 | } | |
| 2733 | ||
| 2734 | if (std.process.can_spawn) { | |
| 2735 | // If possible, we run LLD as a child process because it does not always | |
| 2736 | // behave properly as a library, unfortunately. | |
| 2737 | // https://github.com/ziglang/zig/issues/3825 | |
| 2738 | var child = std.ChildProcess.init(argv.items, arena); | |
| 2739 | if (comp.clang_passthrough_mode) { | |
| 2740 | child.stdin_behavior = .Inherit; | |
| 2741 | child.stdout_behavior = .Inherit; | |
| 2742 | child.stderr_behavior = .Inherit; | |
| 2743 | ||
| 2744 | const term = child.spawnAndWait() catch |err| { | |
| 2745 | log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) }); | |
| 2746 | return error.UnableToSpawnSelf; | |
| 2747 | }; | |
| 2748 | switch (term) { | |
| 2749 | .Exited => |code| { | |
| 2750 | if (code != 0) { | |
| 2751 | std.process.exit(code); | |
| 2752 | } | |
| 2753 | }, | |
| 2754 | else => std.process.abort(), | |
| 2755 | } | |
| 2756 | } else { | |
| 2757 | child.stdin_behavior = .Ignore; | |
| 2758 | child.stdout_behavior = .Ignore; | |
| 2759 | child.stderr_behavior = .Pipe; | |
| 2760 | ||
| 2761 | try child.spawn(); | |
| 2762 | ||
| 2763 | const stderr = try child.stderr.?.reader().readAllAlloc(arena, std.math.maxInt(usize)); | |
| 2764 | ||
| 2765 | const term = child.wait() catch |err| { | |
| 2766 | log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) }); | |
| 2767 | return error.UnableToSpawnSelf; | |
| 2768 | }; | |
| 2769 | ||
| 2770 | switch (term) { | |
| 2771 | .Exited => |code| { | |
| 2772 | if (code != 0) { | |
| 2773 | comp.lockAndParseLldStderr(linker_command, stderr); | |
| 2774 | return error.LLDReportedFailure; | |
| 2775 | } | |
| 2776 | }, | |
| 2777 | else => { | |
| 2778 | log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr }); | |
| 2779 | return error.LLDCrashed; | |
| 2780 | }, | |
| 2781 | } | |
| 2782 | ||
| 2783 | if (stderr.len != 0) { | |
| 2784 | log.warn("unexpected LLD stderr:\n{s}", .{stderr}); | |
| 2785 | } | |
| 2786 | } | |
| 2787 | } else { | |
| 2788 | const exit_code = try lldMain(arena, argv.items, false); | |
| 2789 | if (exit_code != 0) { | |
| 2790 | if (comp.clang_passthrough_mode) { | |
| 2791 | std.process.exit(exit_code); | |
| 2792 | } else { | |
| 2793 | return error.LLDReportedFailure; | |
| 2794 | } | |
| 2795 | } | |
| 2796 | } | |
| 2729 | try link.spawnLld(comp, arena, argv.items); | |
| 2797 | 2730 | } |
| 2798 | 2731 | |
| 2799 | 2732 | if (!self.base.disable_lld_caching) { |
| ... | ... | @@ -6500,7 +6433,6 @@ const eh_frame = @import("Elf/eh_frame.zig"); |
| 6500 | 6433 | const gc = @import("Elf/gc.zig"); |
| 6501 | 6434 | const glibc = @import("../glibc.zig"); |
| 6502 | 6435 | const link = @import("../link.zig"); |
| 6503 | const lldMain = @import("../main.zig").lldMain; | |
| 6504 | 6436 | const merge_section = @import("Elf/merge_section.zig"); |
| 6505 | 6437 | const musl = @import("../musl.zig"); |
| 6506 | 6438 | const relocatable = @import("Elf/relocatable.zig"); |