| ... | @@ -995,11 +995,7 @@ pub const File = struct { | ... | @@ -995,11 +995,7 @@ pub const File = struct { |
| 995 | .{}, | 995 | .{}, |
| 996 | ) catch |err| { | 996 | ) catch |err| { |
| 997 | const diags = &base.comp.link_diags; | 997 | const diags = &base.comp.link_diags; |
| 998 | return diags.fail("failed to copy '{f}' to '{f}': {t}", .{ | 998 | return diags.fail("failed to copy {qf} to {qf}: {t}", .{ cached_pp_file_path, emit, err }); |
| 999 | std.fmt.alt(@as(Path, cached_pp_file_path), .formatEscapeChar), | | |
| 1000 | std.fmt.alt(@as(Path, emit), .formatEscapeChar), | | |
| 1001 | err, | | |
| 1002 | }); | | |
| 1003 | }; | 999 | }; |
| 1004 | return; | 1000 | return; |
| 1005 | } | 1001 | } |
| ... | @@ -1740,7 +1736,7 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void | ... | @@ -1740,7 +1736,7 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void |
| 1740 | if (comp.bin_file) |lf| { | 1736 | if (comp.bin_file) |lf| { |
| 1741 | lf.updateLineNumber(pt, line_update.inst, line_update.line) catch |err| switch (err) { | 1737 | lf.updateLineNumber(pt, line_update.inst, line_update.line) catch |err| switch (err) { |
| 1742 | error.OutOfMemory => diags.setAllocFailure(), | 1738 | error.OutOfMemory => diags.setAllocFailure(), |
| 1743 | else => |e| log.err("update line number failed: {s}", .{@errorName(e)}), | 1739 | else => |e| log.err("update line number failed: {t}", .{e}), |
| 1744 | }; | 1740 | }; |
| 1745 | } | 1741 | } |
| 1746 | } | 1742 | } |
| ... | @@ -1753,7 +1749,7 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void | ... | @@ -1753,7 +1749,7 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void |
| 1753 | if (comp.bin_file) |lf| { | 1749 | if (comp.bin_file) |lf| { |
| 1754 | lf.lostTracking(pt, ti) catch |err| switch (err) { | 1750 | lf.lostTracking(pt, ti) catch |err| switch (err) { |
| 1755 | error.OutOfMemory => diags.setAllocFailure(), | 1751 | error.OutOfMemory => diags.setAllocFailure(), |
| 1756 | else => |e| log.err("lost tracking failed: {s}", .{@errorName(e)}), | 1752 | else => |e| log.err("lost tracking failed: {t}", .{e}), |
| 1757 | }; | 1753 | }; |
| 1758 | } | 1754 | } |
| 1759 | } | 1755 | } |
| ... | @@ -1845,6 +1841,14 @@ pub const UnresolvedInput = union(enum) { | ... | @@ -1845,6 +1841,14 @@ pub const UnresolvedInput = union(enum) { |
| 1845 | must_link: bool = false, | 1841 | must_link: bool = false, |
| 1846 | hidden: bool = false, | 1842 | hidden: bool = false, |
| 1847 | allow_so_scripts: bool = false, | 1843 | allow_so_scripts: bool = false, |
| | 1844 | // Corresponds to GNU ld `-l :path/to/filename`: |
| | 1845 | // * No extra rpaths. |
| | 1846 | // * NEEDED entry should be exactly the string |
| | 1847 | // after the colon. No file system paths prepended. |
| | 1848 | // * The DSO still must be found at compile/link |
| | 1849 | // time and its entries used to resolve symbols. |
| | 1850 | // CGo compilation depends on this. |
| | 1851 | name_done: bool = false, |
| 1848 | preferred_mode: std.lang.LinkMode, | 1852 | preferred_mode: std.lang.LinkMode, |
| 1849 | search_strategy: SearchStrategy, | 1853 | search_strategy: SearchStrategy, |
| 1850 | | 1854 | |
| ... | @@ -2201,8 +2205,8 @@ pub fn resolveInputs( | ... | @@ -2201,8 +2205,8 @@ pub fn resolveInputs( |
| 2201 | if (failed_libs.items.len > 0) { | 2205 | if (failed_libs.items.len > 0) { |
| 2202 | for (failed_libs.items) |f| { | 2206 | for (failed_libs.items) |f| { |
| 2203 | const searched_paths = if (f.checked_paths.len == 0) " none" else f.checked_paths; | 2207 | const searched_paths = if (f.checked_paths.len == 0) " none" else f.checked_paths; |
| 2204 | std.log.err("unable to find {s} system library '{s}' using strategy '{s}'. searched paths:{s}", .{ | 2208 | std.log.err("unable to find {t} system library {q} using strategy {t}. searched paths:{s}", .{ |
| 2205 | @tagName(f.preferred_mode), f.name, @tagName(f.strategy), searched_paths, | 2209 | f.preferred_mode, f.name, f.strategy, searched_paths, |
| 2206 | }); | 2210 | }); |
| 2207 | } | 2211 | } |
| 2208 | std.process.exit(1); | 2212 | std.process.exit(1); |
| ... | @@ -2237,7 +2241,7 @@ fn resolveLibInput( | ... | @@ -2237,7 +2241,7 @@ fn resolveLibInput( |
| 2237 | | 2241 | |
| 2238 | const lib_name = name_query.name; | 2242 | const lib_name = name_query.name; |
| 2239 | | 2243 | |
| 2240 | if (target.os.tag.isDarwin() and link_mode == .dynamic) tbd: { | 2244 | if (target.os.tag.isDarwin() and link_mode == .dynamic and !name_query.query.name_done) tbd: { |
| 2241 | // Prefer .tbd over .dylib. | 2245 | // Prefer .tbd over .dylib. |
| 2242 | const test_path: Path = .{ | 2246 | const test_path: Path = .{ |
| 2243 | .root_dir = lib_directory, | 2247 | .root_dir = lib_directory, |
| ... | @@ -2246,7 +2250,7 @@ fn resolveLibInput( | ... | @@ -2246,7 +2250,7 @@ fn resolveLibInput( |
| 2246 | try checked_paths.print(gpa, "\n {f}", .{test_path}); | 2250 | try checked_paths.print(gpa, "\n {f}", .{test_path}); |
| 2247 | var file = test_path.root_dir.handle.openFile(io, test_path.sub_path, .{}) catch |err| switch (err) { | 2251 | var file = test_path.root_dir.handle.openFile(io, test_path.sub_path, .{}) catch |err| switch (err) { |
| 2248 | error.FileNotFound => break :tbd, | 2252 | error.FileNotFound => break :tbd, |
| 2249 | else => |e| fatal("unable to search for tbd library '{f}': {s}", .{ test_path, @errorName(e) }), | 2253 | else => |e| fatal("searching for tbd library {qf}: {t}", .{ test_path, e }), |
| 2250 | }; | 2254 | }; |
| 2251 | errdefer file.close(io); | 2255 | errdefer file.close(io); |
| 2252 | return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, name_query.query); | 2256 | return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, name_query.query); |
| ... | @@ -2255,8 +2259,9 @@ fn resolveLibInput( | ... | @@ -2255,8 +2259,9 @@ fn resolveLibInput( |
| 2255 | { | 2259 | { |
| 2256 | const test_path: Path = .{ | 2260 | const test_path: Path = .{ |
| 2257 | .root_dir = lib_directory, | 2261 | .root_dir = lib_directory, |
| 2258 | .sub_path = try std.fmt.allocPrint(arena, "{s}{s}{s}", .{ | 2262 | .sub_path = if (name_query.query.name_done) lib_name else try std.fmt.allocPrint(arena, "{s}{s}{s}", .{ |
| 2259 | target.libPrefix(), lib_name, | 2263 | target.libPrefix(), |
| | 2264 | lib_name, |
| 2260 | switch (link_mode) { | 2265 | switch (link_mode) { |
| 2261 | .static => target.staticLibSuffix(), | 2266 | .static => target.staticLibSuffix(), |
| 2262 | .dynamic => target.dynamicLibSuffix(), | 2267 | .dynamic => target.dynamicLibSuffix(), |
| ... | @@ -2275,7 +2280,7 @@ fn resolveLibInput( | ... | @@ -2275,7 +2280,7 @@ fn resolveLibInput( |
| 2275 | | 2280 | |
| 2276 | // In the case of Darwin, the main check will be .dylib, so here we | 2281 | // In the case of Darwin, the main check will be .dylib, so here we |
| 2277 | // additionally check for .so files. | 2282 | // additionally check for .so files. |
| 2278 | if (target.os.tag.isDarwin() and link_mode == .dynamic) so: { | 2283 | if (target.os.tag.isDarwin() and link_mode == .dynamic and !name_query.query.name_done) so: { |
| 2279 | const test_path: Path = .{ | 2284 | const test_path: Path = .{ |
| 2280 | .root_dir = lib_directory, | 2285 | .root_dir = lib_directory, |
| 2281 | .sub_path = try std.fmt.allocPrint(arena, "lib{s}.so", .{lib_name}), | 2286 | .sub_path = try std.fmt.allocPrint(arena, "lib{s}.so", .{lib_name}), |
| ... | @@ -2283,9 +2288,7 @@ fn resolveLibInput( | ... | @@ -2283,9 +2288,7 @@ fn resolveLibInput( |
| 2283 | try checked_paths.print(gpa, "\n {f}", .{test_path}); | 2288 | try checked_paths.print(gpa, "\n {f}", .{test_path}); |
| 2284 | var file = test_path.root_dir.handle.openFile(io, test_path.sub_path, .{}) catch |err| switch (err) { | 2289 | var file = test_path.root_dir.handle.openFile(io, test_path.sub_path, .{}) catch |err| switch (err) { |
| 2285 | error.FileNotFound => break :so, | 2290 | error.FileNotFound => break :so, |
| 2286 | else => |e| fatal("unable to search for so library '{f}': {s}", .{ | 2291 | else => |e| fatal("unable to search for so library {qf}: {t}", .{ test_path, e }), |
| 2287 | test_path, @errorName(e), | | |
| 2288 | }), | | |
| 2289 | }; | 2292 | }; |
| 2290 | errdefer file.close(io); | 2293 | errdefer file.close(io); |
| 2291 | return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, name_query.query); | 2294 | return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, name_query.query); |
| ... | @@ -2293,7 +2296,7 @@ fn resolveLibInput( | ... | @@ -2293,7 +2296,7 @@ fn resolveLibInput( |
| 2293 | | 2296 | |
| 2294 | // In the case of MinGW, the main check will be .lib but we also need to | 2297 | // In the case of MinGW, the main check will be .lib but we also need to |
| 2295 | // look for `libfoo.a`. | 2298 | // look for `libfoo.a`. |
| 2296 | if (target.isMinGW() and link_mode == .static) mingw: { | 2299 | if (target.isMinGW() and link_mode == .static and !name_query.query.name_done) mingw: { |
| 2297 | const test_path: Path = .{ | 2300 | const test_path: Path = .{ |
| 2298 | .root_dir = lib_directory, | 2301 | .root_dir = lib_directory, |
| 2299 | .sub_path = try std.fmt.allocPrint(arena, "lib{s}.a", .{lib_name}), | 2302 | .sub_path = try std.fmt.allocPrint(arena, "lib{s}.a", .{lib_name}), |
| ... | @@ -2301,7 +2304,7 @@ fn resolveLibInput( | ... | @@ -2301,7 +2304,7 @@ fn resolveLibInput( |
| 2301 | try checked_paths.print(gpa, "\n {f}", .{test_path}); | 2304 | try checked_paths.print(gpa, "\n {f}", .{test_path}); |
| 2302 | var file = test_path.root_dir.handle.openFile(io, test_path.sub_path, .{}) catch |err| switch (err) { | 2305 | var file = test_path.root_dir.handle.openFile(io, test_path.sub_path, .{}) catch |err| switch (err) { |
| 2303 | error.FileNotFound => break :mingw, | 2306 | error.FileNotFound => break :mingw, |
| 2304 | else => |e| fatal("unable to search for static library '{f}': {s}", .{ test_path, @errorName(e) }), | 2307 | else => |e| fatal("unable to search for static library {qf}: {t}", .{ test_path, e }), |
| 2305 | }; | 2308 | }; |
| 2306 | errdefer file.close(io); | 2309 | errdefer file.close(io); |
| 2307 | return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, name_query.query); | 2310 | return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, name_query.query); |
| ... | @@ -2310,12 +2313,14 @@ fn resolveLibInput( | ... | @@ -2310,12 +2313,14 @@ fn resolveLibInput( |
| 2310 | // In the case of OpenBSD, dynamic libraries are always versioned, without | 2313 | // In the case of OpenBSD, dynamic libraries are always versioned, without |
| 2311 | // unversioned symlinks. OpenBSD patches LLD to select the highest-versioned | 2314 | // unversioned symlinks. OpenBSD patches LLD to select the highest-versioned |
| 2312 | // shared library, and this code is intended to match that upstream behavior. | 2315 | // shared library, and this code is intended to match that upstream behavior. |
| 2313 | if (target.isOpenBSDLibC() and link_mode == .dynamic) versioned: { | 2316 | if (target.isOpenBSDLibC() and link_mode == .dynamic and !name_query.query.name_done) versioned: { |
| 2314 | const prefix = try std.fmt.allocPrint(arena, "lib{s}.so.", .{lib_name}); | 2317 | const prefix = try std.fmt.allocPrint(arena, "lib{s}.so.", .{lib_name}); |
| 2315 | | 2318 | |
| 2316 | var dir = lib_directory.handle.openDir(io, ".", .{ .iterate = true }) catch |err| switch (err) { | 2319 | var dir = lib_directory.handle.openDir(io, ".", .{ .iterate = true }) catch |err| switch (err) { |
| 2317 | error.NotDir, error.FileNotFound => break :versioned, | 2320 | error.NotDir, error.FileNotFound => break :versioned, |
| 2318 | else => |e| fatal("unable to search for shared library '{s}.*': {s}", .{ prefix, @errorName(e) }), | 2321 | else => |e| fatal("unable to search for shared library \"{f}.*\": {t}", .{ |
| | 2322 | std.zig.fmtString(prefix), e, |
| | 2323 | }), |
| 2319 | }; | 2324 | }; |
| 2320 | defer dir.close(io); | 2325 | defer dir.close(io); |
| 2321 | | 2326 | |
| ... | @@ -2325,7 +2330,7 @@ fn resolveLibInput( | ... | @@ -2325,7 +2330,7 @@ fn resolveLibInput( |
| 2325 | | 2330 | |
| 2326 | var iter = dir.iterate(); | 2331 | var iter = dir.iterate(); |
| 2327 | while (iter.next(io) catch |err| { | 2332 | while (iter.next(io) catch |err| { |
| 2328 | fatal("unable to scan library directory '{s}'", .{@errorName(err)}); | 2333 | fatal("scanning library directory: {t}", .{err}); |
| 2329 | }) |entry| { | 2334 | }) |entry| { |
| 2330 | if (entry.kind != .file) continue; | 2335 | if (entry.kind != .file) continue; |
| 2331 | if (!std.mem.startsWith(u8, entry.name, prefix)) continue; | 2336 | if (!std.mem.startsWith(u8, entry.name, prefix)) continue; |
| ... | @@ -2445,7 +2450,7 @@ fn resolvePathInput( | ... | @@ -2445,7 +2450,7 @@ fn resolvePathInput( |
| 2445 | .shared_library => return try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, archive_dedup, target, pq, .dynamic, color), | 2450 | .shared_library => return try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, archive_dedup, target, pq, .dynamic, color), |
| 2446 | .object => { | 2451 | .object => { |
| 2447 | var file = pq.path.root_dir.handle.openFile(io, pq.path.sub_path, .{}) catch |err| | 2452 | var file = pq.path.root_dir.handle.openFile(io, pq.path.sub_path, .{}) catch |err| |
| 2448 | fatal("failed to open object {f}: {s}", .{ pq.path, @errorName(err) }); | 2453 | fatal("failed to open object {f}: {t}", .{ pq.path, err }); |
| 2449 | errdefer file.close(io); | 2454 | errdefer file.close(io); |
| 2450 | try resolved_inputs.append(gpa, .{ .object = .{ | 2455 | try resolved_inputs.append(gpa, .{ .object = .{ |
| 2451 | .path = pq.path, | 2456 | .path = pq.path, |
| ... | @@ -2457,7 +2462,7 @@ fn resolvePathInput( | ... | @@ -2457,7 +2462,7 @@ fn resolvePathInput( |
| 2457 | }, | 2462 | }, |
| 2458 | .res => { | 2463 | .res => { |
| 2459 | var file = pq.path.root_dir.handle.openFile(io, pq.path.sub_path, .{}) catch |err| | 2464 | var file = pq.path.root_dir.handle.openFile(io, pq.path.sub_path, .{}) catch |err| |
| 2460 | fatal("failed to open windows resource {f}: {s}", .{ pq.path, @errorName(err) }); | 2465 | fatal("failed to open windows resource {f}: {t}", .{ pq.path, err }); |
| 2461 | errdefer file.close(io); | 2466 | errdefer file.close(io); |
| 2462 | try resolved_inputs.append(gpa, .{ .res = .{ | 2467 | try resolved_inputs.append(gpa, .{ .res = .{ |
| 2463 | .path = pq.path, | 2468 | .path = pq.path, |
| ... | @@ -2498,14 +2503,14 @@ fn resolvePathInputLib( | ... | @@ -2498,14 +2503,14 @@ fn resolvePathInputLib( |
| 2498 | }) { | 2503 | }) { |
| 2499 | var file = test_path.root_dir.handle.openFile(io, test_path.sub_path, .{}) catch |err| switch (err) { | 2504 | var file = test_path.root_dir.handle.openFile(io, test_path.sub_path, .{}) catch |err| switch (err) { |
| 2500 | error.FileNotFound => return .no_match, | 2505 | error.FileNotFound => return .no_match, |
| 2501 | else => |e| fatal("unable to search for {t} library '{f}': {t}", .{ | 2506 | else => |e| fatal("unable to search for {t} library {qf}: {t}", .{ |
| 2502 | link_mode, std.fmt.alt(test_path, .formatEscapeChar), e, | 2507 | link_mode, std.fmt.alt(test_path, .formatEscapeChar), e, |
| 2503 | }), | 2508 | }), |
| 2504 | }; | 2509 | }; |
| 2505 | errdefer file.close(io); | 2510 | errdefer file.close(io); |
| 2506 | try ld_script_bytes.resize(gpa, @max(std.elf.MAGIC.len, std.elf.ARMAG.len)); | 2511 | try ld_script_bytes.resize(gpa, @max(std.elf.MAGIC.len, std.elf.ARMAG.len)); |
| 2507 | const n = file.readPositionalAll(io, ld_script_bytes.items, 0) catch |err| | 2512 | const n = file.readPositionalAll(io, ld_script_bytes.items, 0) catch |err| |
| 2508 | fatal("failed to read '{f}': {t}", .{ std.fmt.alt(test_path, .formatEscapeChar), err }); | 2513 | fatal("failed to read {qf}: {t}", .{ test_path, err }); |
| 2509 | const buf = ld_script_bytes.items[0..n]; | 2514 | const buf = ld_script_bytes.items[0..n]; |
| 2510 | if (mem.startsWith(u8, buf, std.elf.MAGIC) or | 2515 | if (mem.startsWith(u8, buf, std.elf.MAGIC) or |
| 2511 | mem.startsWith(u8, buf, std.elf.ARMAG) or | 2516 | mem.startsWith(u8, buf, std.elf.ARMAG) or |
| ... | @@ -2577,9 +2582,7 @@ fn resolvePathInputLib( | ... | @@ -2577,9 +2582,7 @@ fn resolvePathInputLib( |
| 2577 | | 2582 | |
| 2578 | var file = test_path.root_dir.handle.openFile(io, test_path.sub_path, .{}) catch |err| switch (err) { | 2583 | var file = test_path.root_dir.handle.openFile(io, test_path.sub_path, .{}) catch |err| switch (err) { |
| 2579 | error.FileNotFound => return .no_match, | 2584 | error.FileNotFound => return .no_match, |
| 2580 | else => |e| fatal("unable to search for {s} library {f}: {s}", .{ | 2585 | else => |e| fatal("unable to search for {t} library {f}: {t}", .{ link_mode, test_path, e }), |
| 2581 | @tagName(link_mode), test_path, @errorName(e), | | |
| 2582 | }), | | |
| 2583 | }; | 2586 | }; |
| 2584 | errdefer file.close(io); | 2587 | errdefer file.close(io); |
| 2585 | return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, pq.query); | 2588 | return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, pq.query); |