| ... | @@ -2239,6 +2239,60 @@ fn resolveLibInput( | ... | @@ -2239,6 +2239,60 @@ fn resolveLibInput( |
| 2239 | return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, name_query.query); | 2239 | return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, name_query.query); |
| 2240 | } | 2240 | } |
| 2241 | | 2241 | |
| | 2242 | // In the case of OpenBSD, dynamic libraries are always versioned, without |
| | 2243 | // unversioned symlinks. OpenBSD patches LLD to select the highest-versioned |
| | 2244 | // shared library, and this code is intended to match that upstream behavior. |
| | 2245 | if (target.isOpenBSDLibC() and link_mode == .dynamic) versioned: { |
| | 2246 | const prefix = try std.fmt.allocPrint(arena, "lib{s}.so.", .{lib_name}); |
| | 2247 | |
| | 2248 | var dir = lib_directory.handle.openDir(io, ".", .{ .iterate = true }) catch |err| switch (err) { |
| | 2249 | error.NotDir, error.FileNotFound => break :versioned, |
| | 2250 | else => |e| fatal("unable to search for shared library '{s}.*': {s}", .{ prefix, @errorName(e) }), |
| | 2251 | }; |
| | 2252 | defer dir.close(io); |
| | 2253 | |
| | 2254 | var best_match_major: u32 = 0; |
| | 2255 | var best_match_minor: u32 = 0; |
| | 2256 | var best_match: ?[]const u8 = null; |
| | 2257 | |
| | 2258 | var iter = dir.iterate(); |
| | 2259 | while (iter.next(io) catch |err| { |
| | 2260 | fatal("unable to scan library directory '{s}'", .{@errorName(err)}); |
| | 2261 | }) |entry| { |
| | 2262 | if (entry.kind != .file) continue; |
| | 2263 | if (!std.mem.startsWith(u8, entry.name, prefix)) continue; |
| | 2264 | |
| | 2265 | const rest = entry.name[prefix.len..]; |
| | 2266 | var sit = std.mem.splitScalar(u8, rest, '.'); |
| | 2267 | const major_str = sit.next() orelse continue; |
| | 2268 | const minor_str = sit.next() orelse continue; |
| | 2269 | if (sit.next() != null) continue; |
| | 2270 | const major = std.fmt.parseInt(u32, major_str, 10) catch continue; |
| | 2271 | const minor = std.fmt.parseInt(u32, minor_str, 10) catch continue; |
| | 2272 | |
| | 2273 | if (major > best_match_major or (major == best_match_major and minor >= best_match_minor)) { |
| | 2274 | best_match_major = major; |
| | 2275 | best_match_minor = minor; |
| | 2276 | best_match = try arena.dupe(u8, entry.name); |
| | 2277 | } |
| | 2278 | } |
| | 2279 | |
| | 2280 | if (best_match) |found| { |
| | 2281 | const test_path: Path = .{ |
| | 2282 | .root_dir = lib_directory, |
| | 2283 | .sub_path = found, |
| | 2284 | }; |
| | 2285 | try checked_paths.print(gpa, "\n {f}", .{test_path}); |
| | 2286 | switch (try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, archive_dedup, target, .{ |
| | 2287 | .path = test_path, |
| | 2288 | .query = name_query.query, |
| | 2289 | }, link_mode, color)) { |
| | 2290 | .no_match => {}, |
| | 2291 | .ok => return .ok, |
| | 2292 | } |
| | 2293 | } |
| | 2294 | } |
| | 2295 | |
| 2242 | return .no_match; | 2296 | return .no_match; |
| 2243 | } | 2297 | } |
| 2244 | | 2298 | |