| ... | @@ -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 | } |
| 1175 | | 1175 | |
| 1176 | fn accessPath( | 1176 | fn 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 | | | |
| 1194 | fn 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 | } |
| 1211 | | 1198 | |
| 1212 | fn resolveFramework( | 1199 | fn 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 | } |
| 1230 | | 1226 | |
| ... | @@ -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); |
| 1266 | | 1262 | |
| 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); |
| 1270 | | 1266 | |
| 1271 | // Framework | 1267 | // 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; | | |
| 1279 | | 1272 | |
| 1280 | // Library | 1273 | // 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 | } |
| 1291 | | 1280 | |
| 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 | else | 1284 | 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 | } |
| 1302 | | 1299 | |
| ... | @@ -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 | } |
| 1319 | | 1317 | |
| | 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, |