authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-25 10:30:17+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-25 12:07:04+01:00
logdc9b6ecb551d6ae7992c31fb28a0fdc94f0c8e4c
tree3df6cb6577921a94dbf930faf940068464813925
parent51d60d1a606224357d406d1addf4701099f678d6

macho: refactor resolving libs and frameworks when searching dependent dylibs


1 files changed, 63 insertions(+), 63 deletions(-)

src/link/MachO.zig+63-63
......@@ -1173,58 +1173,54 @@ fn isHoisted(self: *MachO, install_name: []const u8) bool {
11731173 return false;
11741174}
11751175
1176fn accessPath(
1176fn accessLibPath2(
11771177 arena: Allocator,
11781178 test_path: *std.ArrayList(u8),
11791179 checked_paths: *std.ArrayList([]const u8),
1180 path: []const u8,
1181) !bool {
1182 test_path.clearRetainingCapacity();
1183 try test_path.appendSlice(path);
1184 std.fs.cwd().access(path, .{}) catch |err| switch (err) {
1185 error.FileNotFound => {
1186 try checked_paths.append(try arena.dupe(u8, test_path.items));
1187 return false;
1188 },
1189 else => |e| return e,
1190 };
1191 return true;
1192}
1193
1194fn resolveLib(
1195 arena: Allocator,
1196 test_path: *std.ArrayList(u8),
1197 checked_paths: *std.ArrayList([]const u8),
1198 search_dirs: []const []const u8,
1180 search_dir: []const u8,
11991181 name: []const u8,
12001182) !bool {
1201 const path = try std.fmt.allocPrint(arena, "lib{s}", .{name});
1202 for (search_dirs) |dir| {
1203 for (&[_][]const u8{ ".tbd", ".dylib" }) |ext| {
1204 const with_ext = try std.fmt.allocPrint(arena, "{s}{s}", .{ path, ext });
1205 const full_path = try std.fs.path.join(arena, &[_][]const u8{ dir, with_ext });
1206 if (try accessPath(arena, test_path, checked_paths, full_path)) return true;
1207 }
1183 const sep = fs.path.sep_str;
1184
1185 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
1186 test_path.clearRetainingCapacity();
1187 try test_path.writer().print("{s}" ++ sep ++ "lib{s}{s}", .{ search_dir, name, ext });
1188 try checked_paths.append(try arena.dupe(u8, test_path.items));
1189 std.fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {
1190 error.FileNotFound => continue,
1191 else => |e| return e,
1192 };
1193 return true;
12081194 }
1195
12091196 return false;
12101197}
12111198
1212fn resolveFramework(
1199fn accessFrameworkPath(
12131200 arena: Allocator,
12141201 test_path: *std.ArrayList(u8),
12151202 checked_paths: *std.ArrayList([]const u8),
1216 search_dirs: []const []const u8,
1203 search_dir: []const u8,
12171204 name: []const u8,
12181205) !bool {
1219 const prefix = try std.fmt.allocPrint(arena, "{s}.framework", .{name});
1220 const path = try std.fs.path.join(arena, &[_][]const u8{ prefix, name });
1221 for (search_dirs) |dir| {
1222 for (&[_][]const u8{ ".tbd", ".dylib" }) |ext| {
1223 const with_ext = try std.fmt.allocPrint(arena, "{s}{s}", .{ path, ext });
1224 const full_path = try std.fs.path.join(arena, &[_][]const u8{ dir, with_ext });
1225 if (try accessPath(arena, test_path, checked_paths, full_path)) return true;
1226 }
1206 const sep = fs.path.sep_str;
1207
1208 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
1209 test_path.clearRetainingCapacity();
1210 try test_path.writer().print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}{s}", .{
1211 search_dir,
1212 name,
1213 name,
1214 ext,
1215 });
1216 try checked_paths.append(try arena.dupe(u8, test_path.items));
1217 std.fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {
1218 error.FileNotFound => continue,
1219 else => |e| return e,
1220 };
1221 return true;
12271222 }
1223
12281224 return false;
12291225}
12301226
......@@ -1265,38 +1261,39 @@ fn parseDependentDylibs(self: *MachO) !void {
12651261 var checked_paths = std.ArrayList([]const u8).init(arena);
12661262
12671263 const full_path = full_path: {
1268 fail: {
1264 {
12691265 const stem = std.fs.path.stem(id.name);
12701266
12711267 // Framework
1272 if (try resolveFramework(
1273 arena,
1274 &test_path,
1275 &checked_paths,
1276 framework_dirs,
1277 stem,
1278 )) break :full_path test_path.items;
1268 for (framework_dirs) |dir| {
1269 test_path.clearRetainingCapacity();
1270 if (try accessFrameworkPath(arena, &test_path, &checked_paths, dir, stem)) break :full_path test_path.items;
1271 }
12791272
12801273 // Library
12811274 const lib_name = eatPrefix(stem, "lib") orelse stem;
1282 if (try resolveLib(
1283 arena,
1284 &test_path,
1285 &checked_paths,
1286 lib_dirs,
1287 lib_name,
1288 )) break :full_path test_path.items;
1289 break :fail;
1275 for (lib_dirs) |dir| {
1276 test_path.clearRetainingCapacity();
1277 if (try accessLibPath2(arena, &test_path, &checked_paths, dir, lib_name)) break :full_path test_path.items;
1278 }
12901279 }
12911280
12921281 if (std.fs.path.isAbsolute(id.name)) {
1293 const path = if (self.base.comp.sysroot) |root|
1294 try std.fs.path.join(arena, &.{ root, id.name })
1295 else
1296 id.name;
1297 for (&[_][]const u8{ "", ".tbd", ".dylib" }) |ext| {
1298 const full_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ path, ext });
1299 if (try accessPath(arena, &test_path, &checked_paths, full_path)) break :full_path test_path.items;
1282 const existing_ext = std.fs.path.extension(id.name);
1283 const path = if (existing_ext.len > 0) id.name[0 .. id.name.len - existing_ext.len] else id.name;
1284 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
1285 test_path.clearRetainingCapacity();
1286 if (self.base.comp.sysroot) |root| {
1287 try test_path.writer().print("{s}" ++ std.fs.path.sep_str ++ "{s}{s}", .{ root, path, ext });
1288 } else {
1289 try test_path.writer().print("{s}{s}", .{ path, ext });
1290 }
1291 try checked_paths.append(try arena.dupe(u8, test_path.items));
1292 std.fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {
1293 error.FileNotFound => continue,
1294 else => |e| return e,
1295 };
1296 break :full_path test_path.items;
13001297 }
13011298 }
13021299
......@@ -1305,6 +1302,7 @@ fn parseDependentDylibs(self: *MachO) !void {
13051302 for (self.getFile(dylib.umbrella).?.dylib.rpaths.keys()) |rpath| {
13061303 const prefix = eatPrefix(rpath, "@loader_path/") orelse rpath;
13071304 const rel_path = try std.fs.path.join(arena, &.{ prefix, path });
1305 try checked_paths.append(rel_path);
13081306 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
13091307 const full_path = std.fs.realpath(rel_path, &buffer) catch continue;
13101308 break :full_path full_path;
......@@ -1317,8 +1315,11 @@ fn parseDependentDylibs(self: *MachO) !void {
13171315 return error.Unhandled;
13181316 }
13191317
1318 try checked_paths.append(try arena.dupe(u8, id.name));
13201319 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
1321 const full_path = std.fs.realpath(id.name, &buffer) catch {
1320 if (std.fs.realpath(id.name, &buffer)) |full_path| {
1321 break :full_path full_path;
1322 } else |_| {
13221323 try self.reportMissingDependencyError(
13231324 self.getFile(dylib_index).?.dylib.getUmbrella(self).index,
13241325 id.name,
......@@ -1328,8 +1329,7 @@ fn parseDependentDylibs(self: *MachO) !void {
13281329 );
13291330 has_errors = true;
13301331 continue;
1331 };
1332 break :full_path full_path;
1332 }
13331333 };
13341334 const lib = SystemLib{
13351335 .path = full_path,