Skip to content

Commit d5c44c9

Browse files
committed
link: Simplify library path resolution logic
1 parent 5d5219b commit d5c44c9

File tree

1 file changed

+36
-65
lines changed

1 file changed

+36
-65
lines changed

src/link.zig

Lines changed: 36 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2068,30 +2068,47 @@ fn resolveLibInput(
20682068

20692069
const lib_name = name_query.name;
20702070

2071-
if (target.isDarwin() and link_mode == .dynamic) tbd: {
2072-
// Prefer .tbd over .dylib.
2073-
const test_path: Path = .{
2074-
.root_dir = lib_directory,
2075-
.sub_path = try std.fmt.allocPrint(arena, "lib{s}.tbd", .{lib_name}),
2076-
};
2077-
try checked_paths.writer(gpa).print("\n {}", .{test_path});
2078-
var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {
2079-
error.FileNotFound => break :tbd,
2080-
else => |e| fatal("unable to search for tbd library '{}': {s}", .{ test_path, @errorName(e) }),
2071+
const FilenameBuilder = struct {
2072+
prefix: []const u8,
2073+
suffix: []const u8,
2074+
fn build(self: @This(), allocator: Allocator, library_name: []const u8) ![]const u8 {
2075+
return std.fmt.allocPrint(allocator, "{s}{s}{s}", .{ self.prefix, library_name, self.suffix });
2076+
}
2077+
};
2078+
2079+
const initial_count = 1;
2080+
var filename_builders: []const FilenameBuilder = &[initial_count]FilenameBuilder{.{ .prefix = target.libPrefix(), .suffix = switch (link_mode) {
2081+
.static => target.staticLibSuffix(),
2082+
.dynamic => target.dynamicLibSuffix(),
2083+
} }};
2084+
2085+
if (target.isDarwin() and link_mode == .dynamic) {
2086+
filename_builders =
2087+
// Prefer .tbd over .dylib.
2088+
&[_]FilenameBuilder{.{ .prefix = "lib", .suffix = ".tbd" }}
2089+
// In the case of Darwin, the main check will be .dylib
2090+
++ filename_builders[0..initial_count].*
2091+
// Additionally check for .so files.
2092+
++ &[_]FilenameBuilder{.{ .prefix = "lib", .suffix = ".so" }};
2093+
} else if (target.isMinGW()) {
2094+
// In the case of MinGW, the main check will be `libfoo.dll` and `libfoo.a`, but we also need to
2095+
// look for `libfoo.dll.a`, `foo.dll` and `foo.lib`.
2096+
filename_builders = switch (link_mode) {
2097+
.dynamic => filename_builders[0..initial_count].* ++ &[_]FilenameBuilder{
2098+
.{ .prefix = "lib", .suffix = ".dll.a" },
2099+
.{ .prefix = "", .suffix = ".dll" },
2100+
.{ .prefix = "", .suffix = ".lib" },
2101+
},
2102+
.static => filename_builders[0..initial_count].* ++ &[_]FilenameBuilder{
2103+
.{ .prefix = "", .suffix = ".lib" },
2104+
},
20812105
};
2082-
errdefer file.close();
2083-
return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query);
20842106
}
20852107

2086-
{
2108+
for (filename_builders) |filename_builder| {
20872109
const test_path: Path = .{
20882110
.root_dir = lib_directory,
2089-
.sub_path = try std.fmt.allocPrint(arena, "{s}{s}{s}", .{
2090-
target.libPrefix(), lib_name, switch (link_mode) {
2091-
.static => target.staticLibSuffix(),
2092-
.dynamic => target.dynamicLibSuffix(),
2093-
},
2094-
}),
2111+
.sub_path = try filename_builder.build(arena, lib_name),
20952112
};
20962113
try checked_paths.writer(gpa).print("\n {}", .{test_path});
20972114
switch (try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, .{
@@ -2103,52 +2120,6 @@ fn resolveLibInput(
21032120
}
21042121
}
21052122

2106-
// In the case of Darwin, the main check will be .dylib, so here we
2107-
// additionally check for .so files.
2108-
if (target.isDarwin() and link_mode == .dynamic) so: {
2109-
const test_path: Path = .{
2110-
.root_dir = lib_directory,
2111-
.sub_path = try std.fmt.allocPrint(arena, "lib{s}.so", .{lib_name}),
2112-
};
2113-
try checked_paths.writer(gpa).print("\n {}", .{test_path});
2114-
var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {
2115-
error.FileNotFound => break :so,
2116-
else => |e| fatal("unable to search for so library '{}': {s}", .{
2117-
test_path, @errorName(e),
2118-
}),
2119-
};
2120-
errdefer file.close();
2121-
return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query);
2122-
}
2123-
2124-
// In the case of MinGW, the main check will be `libfoo.dll` and `libfoo.a`, but we also need to
2125-
// look for `foo.dll`, `foo.lib` and `libfoo.dll.a`.
2126-
if (target.isMinGW()) {
2127-
const sub_paths = if (link_mode == .dynamic)
2128-
&[_][]const u8{
2129-
try std.fmt.allocPrint(arena, "lib{s}.dll.a", .{lib_name}),
2130-
try std.fmt.allocPrint(arena, "{s}.dll", .{lib_name}),
2131-
try std.fmt.allocPrint(arena, "{s}.lib", .{lib_name}),
2132-
}
2133-
else
2134-
&[_][]const u8{
2135-
try std.fmt.allocPrint(arena, "{s}.lib", .{lib_name}),
2136-
};
2137-
for (sub_paths) |sub_path| {
2138-
const test_path: Path = .{
2139-
.root_dir = lib_directory,
2140-
.sub_path = sub_path,
2141-
};
2142-
try checked_paths.writer(gpa).print("\n {}", .{test_path});
2143-
var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {
2144-
error.FileNotFound => continue,
2145-
else => |e| fatal("unable to search for {s} library '{}': {s}", .{ @tagName(link_mode), test_path, @errorName(e) }),
2146-
};
2147-
errdefer file.close();
2148-
return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query);
2149-
}
2150-
}
2151-
21522123
return .no_match;
21532124
}
21542125

0 commit comments

Comments
 (0)