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 {...@@ -1173,58 +1173,54 @@ fn isHoisted(self: *MachO, install_name: []const u8) bool {
1173 return false;1173 return false;
1174}1174}
11751175
1176fn accessPath(1176fn accessLibPath2(
1177 arena: Allocator,1177 arena: Allocator,
1178 test_path: *std.ArrayList(u8),1178 test_path: *std.ArrayList(u8),
1179 checked_paths: *std.ArrayList([]const u8),1179 checked_paths: *std.ArrayList([]const u8),
1180 path: []const u8,1180 search_dir: []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,
1199 name: []const u8,1181 name: []const u8,
1200) !bool {1182) !bool {
1201 const path = try std.fmt.allocPrint(arena, "lib{s}", .{name});1183 const sep = fs.path.sep_str;
1202 for (search_dirs) |dir| {1184
1203 for (&[_][]const u8{ ".tbd", ".dylib" }) |ext| {1185 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
1204 const with_ext = try std.fmt.allocPrint(arena, "{s}{s}", .{ path, ext });1186 test_path.clearRetainingCapacity();
1205 const full_path = try std.fs.path.join(arena, &[_][]const u8{ dir, with_ext });1187 try test_path.writer().print("{s}" ++ sep ++ "lib{s}{s}", .{ search_dir, name, ext });
1206 if (try accessPath(arena, test_path, checked_paths, full_path)) return true;1188 try checked_paths.append(try arena.dupe(u8, test_path.items));
1207 }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;
1208 }1194 }
1195
1209 return false;1196 return false;
1210}1197}
12111198
1212fn resolveFramework(1199fn accessFrameworkPath(
1213 arena: Allocator,1200 arena: Allocator,
1214 test_path: *std.ArrayList(u8),1201 test_path: *std.ArrayList(u8),
1215 checked_paths: *std.ArrayList([]const u8),1202 checked_paths: *std.ArrayList([]const u8),
1216 search_dirs: []const []const u8,1203 search_dir: []const u8,
1217 name: []const u8,1204 name: []const u8,
1218) !bool {1205) !bool {
1219 const prefix = try std.fmt.allocPrint(arena, "{s}.framework", .{name});1206 const sep = fs.path.sep_str;
1220 const path = try std.fs.path.join(arena, &[_][]const u8{ prefix, name });1207
1221 for (search_dirs) |dir| {1208 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
1222 for (&[_][]const u8{ ".tbd", ".dylib" }) |ext| {1209 test_path.clearRetainingCapacity();
1223 const with_ext = try std.fmt.allocPrint(arena, "{s}{s}", .{ path, ext });1210 try test_path.writer().print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}{s}", .{
1224 const full_path = try std.fs.path.join(arena, &[_][]const u8{ dir, with_ext });1211 search_dir,
1225 if (try accessPath(arena, test_path, checked_paths, full_path)) return true;1212 name,
1226 }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;
1227 }1222 }
1223
1228 return false;1224 return false;
1229}1225}
12301226
...@@ -1265,38 +1261,39 @@ fn parseDependentDylibs(self: *MachO) !void {...@@ -1265,38 +1261,39 @@ fn parseDependentDylibs(self: *MachO) !void {
1265 var checked_paths = std.ArrayList([]const u8).init(arena);1261 var checked_paths = std.ArrayList([]const u8).init(arena);
12661262
1267 const full_path = full_path: {1263 const full_path = full_path: {
1268 fail: {1264 {
1269 const stem = std.fs.path.stem(id.name);1265 const stem = std.fs.path.stem(id.name);
12701266
1271 // Framework1267 // Framework
1272 if (try resolveFramework(1268 for (framework_dirs) |dir| {
1273 arena,1269 test_path.clearRetainingCapacity();
1274 &test_path,1270 if (try accessFrameworkPath(arena, &test_path, &checked_paths, dir, stem)) break :full_path test_path.items;
1275 &checked_paths,1271 }
1276 framework_dirs,
1277 stem,
1278 )) break :full_path test_path.items;
12791272
1280 // Library1273 // Library
1281 const lib_name = eatPrefix(stem, "lib") orelse stem;1274 const lib_name = eatPrefix(stem, "lib") orelse stem;
1282 if (try resolveLib(1275 for (lib_dirs) |dir| {
1283 arena,1276 test_path.clearRetainingCapacity();
1284 &test_path,1277 if (try accessLibPath2(arena, &test_path, &checked_paths, dir, lib_name)) break :full_path test_path.items;
1285 &checked_paths,1278 }
1286 lib_dirs,
1287 lib_name,
1288 )) break :full_path test_path.items;
1289 break :fail;
1290 }1279 }
12911280
1292 if (std.fs.path.isAbsolute(id.name)) {1281 if (std.fs.path.isAbsolute(id.name)) {
1293 const path = if (self.base.comp.sysroot) |root|1282 const existing_ext = std.fs.path.extension(id.name);
1294 try std.fs.path.join(arena, &.{ root, id.name })1283 const path = if (existing_ext.len > 0) id.name[0 .. id.name.len - existing_ext.len] else id.name;
1295 else1284 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
1296 id.name;1285 test_path.clearRetainingCapacity();
1297 for (&[_][]const u8{ "", ".tbd", ".dylib" }) |ext| {1286 if (self.base.comp.sysroot) |root| {
1298 const full_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ path, ext });1287 try test_path.writer().print("{s}" ++ std.fs.path.sep_str ++ "{s}{s}", .{ root, path, ext });
1299 if (try accessPath(arena, &test_path, &checked_paths, full_path)) break :full_path test_path.items;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;
1300 }1297 }
1301 }1298 }
13021299
...@@ -1305,6 +1302,7 @@ fn parseDependentDylibs(self: *MachO) !void {...@@ -1305,6 +1302,7 @@ fn parseDependentDylibs(self: *MachO) !void {
1305 for (self.getFile(dylib.umbrella).?.dylib.rpaths.keys()) |rpath| {1302 for (self.getFile(dylib.umbrella).?.dylib.rpaths.keys()) |rpath| {
1306 const prefix = eatPrefix(rpath, "@loader_path/") orelse rpath;1303 const prefix = eatPrefix(rpath, "@loader_path/") orelse rpath;
1307 const rel_path = try std.fs.path.join(arena, &.{ prefix, path });1304 const rel_path = try std.fs.path.join(arena, &.{ prefix, path });
1305 try checked_paths.append(rel_path);
1308 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;1306 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
1309 const full_path = std.fs.realpath(rel_path, &buffer) catch continue;1307 const full_path = std.fs.realpath(rel_path, &buffer) catch continue;
1310 break :full_path full_path;1308 break :full_path full_path;
...@@ -1317,8 +1315,11 @@ fn parseDependentDylibs(self: *MachO) !void {...@@ -1317,8 +1315,11 @@ fn parseDependentDylibs(self: *MachO) !void {
1317 return error.Unhandled;1315 return error.Unhandled;
1318 }1316 }
13191317
1318 try checked_paths.append(try arena.dupe(u8, id.name));
1320 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;1319 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 |_| {
1322 try self.reportMissingDependencyError(1323 try self.reportMissingDependencyError(
1323 self.getFile(dylib_index).?.dylib.getUmbrella(self).index,1324 self.getFile(dylib_index).?.dylib.getUmbrella(self).index,
1324 id.name,1325 id.name,
...@@ -1328,8 +1329,7 @@ fn parseDependentDylibs(self: *MachO) !void {...@@ -1328,8 +1329,7 @@ fn parseDependentDylibs(self: *MachO) !void {
1328 );1329 );
1329 has_errors = true;1330 has_errors = true;
1330 continue;1331 continue;
1331 };1332 }
1332 break :full_path full_path;
1333 };1333 };
1334 const lib = SystemLib{1334 const lib = SystemLib{
1335 .path = full_path,1335 .path = full_path,