diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-01-25 10:30:17 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-01-25 12:07:04 +0100 |
| commit | dc9b6ecb551d6ae7992c31fb28a0fdc94f0c8e4c (patch) | |
| tree | 3df6cb6577921a94dbf930faf940068464813925 /src/link/MachO.zig | |
| parent | 51d60d1a606224357d406d1addf4701099f678d6 (diff) | |
| download | zig-dc9b6ecb551d6ae7992c31fb28a0fdc94f0c8e4c.tar.gz zig-dc9b6ecb551d6ae7992c31fb28a0fdc94f0c8e4c.zip | |
macho: refactor resolving libs and frameworks when searching dependent dylibs
Diffstat (limited to 'src/link/MachO.zig')
| -rw-r--r-- | src/link/MachO.zig | 126 |
1 files changed, 63 insertions, 63 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 1829a645cc..6a170f9ca0 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -1173,58 +1173,54 @@ fn isHoisted(self: *MachO, install_name: []const u8) bool { return false; } -fn accessPath( +fn accessLibPath2( arena: Allocator, test_path: *std.ArrayList(u8), checked_paths: *std.ArrayList([]const u8), - path: []const u8, -) !bool { - test_path.clearRetainingCapacity(); - try test_path.appendSlice(path); - std.fs.cwd().access(path, .{}) catch |err| switch (err) { - error.FileNotFound => { - try checked_paths.append(try arena.dupe(u8, test_path.items)); - return false; - }, - else => |e| return e, - }; - return true; -} - -fn resolveLib( - arena: Allocator, - test_path: *std.ArrayList(u8), - checked_paths: *std.ArrayList([]const u8), - search_dirs: []const []const u8, + search_dir: []const u8, name: []const u8, ) !bool { - const path = try std.fmt.allocPrint(arena, "lib{s}", .{name}); - for (search_dirs) |dir| { - for (&[_][]const u8{ ".tbd", ".dylib" }) |ext| { - const with_ext = try std.fmt.allocPrint(arena, "{s}{s}", .{ path, ext }); - const full_path = try std.fs.path.join(arena, &[_][]const u8{ dir, with_ext }); - if (try accessPath(arena, test_path, checked_paths, full_path)) return true; - } + const sep = fs.path.sep_str; + + for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { + test_path.clearRetainingCapacity(); + try test_path.writer().print("{s}" ++ sep ++ "lib{s}{s}", .{ search_dir, name, ext }); + try checked_paths.append(try arena.dupe(u8, test_path.items)); + std.fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { + error.FileNotFound => continue, + else => |e| return e, + }; + return true; } + return false; } -fn resolveFramework( +fn accessFrameworkPath( arena: Allocator, test_path: *std.ArrayList(u8), checked_paths: *std.ArrayList([]const u8), - search_dirs: []const []const u8, + search_dir: []const u8, name: []const u8, ) !bool { - const prefix = try std.fmt.allocPrint(arena, "{s}.framework", .{name}); - const path = try std.fs.path.join(arena, &[_][]const u8{ prefix, name }); - for (search_dirs) |dir| { - for (&[_][]const u8{ ".tbd", ".dylib" }) |ext| { - const with_ext = try std.fmt.allocPrint(arena, "{s}{s}", .{ path, ext }); - const full_path = try std.fs.path.join(arena, &[_][]const u8{ dir, with_ext }); - if (try accessPath(arena, test_path, checked_paths, full_path)) return true; - } + const sep = fs.path.sep_str; + + for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { + test_path.clearRetainingCapacity(); + try test_path.writer().print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}{s}", .{ + search_dir, + name, + name, + ext, + }); + try checked_paths.append(try arena.dupe(u8, test_path.items)); + std.fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { + error.FileNotFound => continue, + else => |e| return e, + }; + return true; } + return false; } @@ -1265,38 +1261,39 @@ fn parseDependentDylibs(self: *MachO) !void { var checked_paths = std.ArrayList([]const u8).init(arena); const full_path = full_path: { - fail: { + { const stem = std.fs.path.stem(id.name); // Framework - if (try resolveFramework( - arena, - &test_path, - &checked_paths, - framework_dirs, - stem, - )) break :full_path test_path.items; + for (framework_dirs) |dir| { + test_path.clearRetainingCapacity(); + if (try accessFrameworkPath(arena, &test_path, &checked_paths, dir, stem)) break :full_path test_path.items; + } // Library const lib_name = eatPrefix(stem, "lib") orelse stem; - if (try resolveLib( - arena, - &test_path, - &checked_paths, - lib_dirs, - lib_name, - )) break :full_path test_path.items; - break :fail; + for (lib_dirs) |dir| { + test_path.clearRetainingCapacity(); + if (try accessLibPath2(arena, &test_path, &checked_paths, dir, lib_name)) break :full_path test_path.items; + } } if (std.fs.path.isAbsolute(id.name)) { - const path = if (self.base.comp.sysroot) |root| - try std.fs.path.join(arena, &.{ root, id.name }) - else - id.name; - for (&[_][]const u8{ "", ".tbd", ".dylib" }) |ext| { - const full_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ path, ext }); - if (try accessPath(arena, &test_path, &checked_paths, full_path)) break :full_path test_path.items; + const existing_ext = std.fs.path.extension(id.name); + const path = if (existing_ext.len > 0) id.name[0 .. id.name.len - existing_ext.len] else id.name; + for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { + test_path.clearRetainingCapacity(); + if (self.base.comp.sysroot) |root| { + try test_path.writer().print("{s}" ++ std.fs.path.sep_str ++ "{s}{s}", .{ root, path, ext }); + } else { + try test_path.writer().print("{s}{s}", .{ path, ext }); + } + try checked_paths.append(try arena.dupe(u8, test_path.items)); + std.fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { + error.FileNotFound => continue, + else => |e| return e, + }; + break :full_path test_path.items; } } @@ -1305,6 +1302,7 @@ fn parseDependentDylibs(self: *MachO) !void { for (self.getFile(dylib.umbrella).?.dylib.rpaths.keys()) |rpath| { const prefix = eatPrefix(rpath, "@loader_path/") orelse rpath; const rel_path = try std.fs.path.join(arena, &.{ prefix, path }); + try checked_paths.append(rel_path); var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined; const full_path = std.fs.realpath(rel_path, &buffer) catch continue; break :full_path full_path; @@ -1317,8 +1315,11 @@ fn parseDependentDylibs(self: *MachO) !void { return error.Unhandled; } + try checked_paths.append(try arena.dupe(u8, id.name)); var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined; - const full_path = std.fs.realpath(id.name, &buffer) catch { + if (std.fs.realpath(id.name, &buffer)) |full_path| { + break :full_path full_path; + } else |_| { try self.reportMissingDependencyError( self.getFile(dylib_index).?.dylib.getUmbrella(self).index, id.name, @@ -1328,8 +1329,7 @@ fn parseDependentDylibs(self: *MachO) !void { ); has_errors = true; continue; - }; - break :full_path full_path; + } }; const lib = SystemLib{ .path = full_path, |
