authorgravatar for vlkrs@noreply.codeberg.orgvlkrs <vlkrs@noreply.codeberg.org> 2026-07-11 22:51:56+02:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-07-30 17:22:17+02:00
log7ad63f2e5bf3d93e27a5233dcdcc341a5df1ebbe
tree57f2c7530f80cf4a40357b2dd23a19ab941d7fc7
parentbb296ab9b9752893eb362ed951c4ce344214eb96
signaturelock-open Commit is signed but in an unrecognized format.

link: Find versioned shared libraries on OpenBSD

See https://github.com/ziglang/zig/pull/18475 for a prior attempt at implementing this

1 files changed, 57 insertions(+), 0 deletions(-)

src/link.zig+57
...@@ -2239,6 +2239,63 @@ fn resolveLibInput(...@@ -2239,6 +2239,63 @@ 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 }
22412241
2242 // In the case of OpenBSD, dynamic libraries are always versioned, without
2243 // unversioned symlinks, so we need to look for the highest-versioned shared
2244 // library.
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_version = std.SemanticVersion{
2255 .major = 0,
2256 .minor = 0,
2257 .patch = 0,
2258 };
2259 var best_match: ?[]const u8 = null;
2260
2261 var iter = dir.iterate();
2262 while (iter.next(io) catch |err| {
2263 fatal("unable to scan library directory '{s}'", .{@errorName(err)});
2264 }) |entry| {
2265 if (entry.kind != .file) continue;
2266 if (!std.mem.startsWith(u8, entry.name, prefix)) continue;
2267
2268 const rest = entry.name[prefix.len..];
2269 var sit = std.mem.splitScalar(u8, rest, '.');
2270 const major_str = sit.next() orelse continue;
2271 const minor_str = sit.next() orelse continue;
2272 if (sit.next() != null) continue;
2273 const major = std.fmt.parseInt(usize, major_str, 10) catch continue;
2274 const minor = std.fmt.parseInt(usize, minor_str, 10) catch continue;
2275
2276 if (major > best_match_version.major or (major == best_match_version.major and minor >= best_match_version.minor)) {
2277 best_match_version.major = major;
2278 best_match_version.minor = minor;
2279 best_match = try arena.dupe(u8, entry.name);
2280 }
2281 }
2282
2283 if (best_match) |found| {
2284 const test_path: Path = .{
2285 .root_dir = lib_directory,
2286 .sub_path = found,
2287 };
2288 try checked_paths.print(gpa, "\n {f}", .{test_path});
2289 switch (try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, archive_dedup, target, .{
2290 .path = test_path,
2291 .query = name_query.query,
2292 }, link_mode, color)) {
2293 .no_match => {},
2294 .ok => return .ok,
2295 }
2296 }
2297 }
2298
2242 return .no_match;2299 return .no_match;
2243}2300}
22442301