aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-08-03 09:53:18 -0700
committerGitHub <noreply@github.com>2023-08-03 09:53:18 -0700
commitc4e62be62e8d8a006cc9d7861232f511c5a05385 (patch)
tree2e28a575a3eef3bbf80ddd7d8f27ab607d720d85 /src/link
parentf887b0251822f75dc4a3e24ca5337cb681c1eb1f (diff)
parentd0fd67cffe664ff70d9a70dd4d2d28aba5a378e8 (diff)
downloadzig-c4e62be62e8d8a006cc9d7861232f511c5a05385.tar.gz
zig-c4e62be62e8d8a006cc9d7861232f511c5a05385.zip
Merge pull request #16058 from ziglang/frontend-lib-paths
compiler: resolve library paths in the frontend
Diffstat (limited to 'src/link')
-rw-r--r--src/link/Coff/lld.zig3
-rw-r--r--src/link/Elf.zig10
-rw-r--r--src/link/MachO.zig74
-rw-r--r--src/link/MachO/load_commands.zig9
-rw-r--r--src/link/MachO/zld.zig90
5 files changed, 58 insertions, 128 deletions
diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig
index 800b128081..bd82254e6a 100644
--- a/src/link/Coff/lld.zig
+++ b/src/link/Coff/lld.zig
@@ -88,7 +88,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
}
}
}
- link.hashAddSystemLibs(&man.hash, self.base.options.system_libs);
+ try link.hashAddSystemLibs(&man, self.base.options.system_libs);
man.hash.addListOfBytes(self.base.options.force_undefined_symbols.keys());
man.hash.addOptional(self.base.options.subsystem);
man.hash.add(self.base.options.is_test);
@@ -405,6 +405,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
try argv.append(try comp.get_libc_crt_file(arena, "mingw32.lib"));
try argv.append(try comp.get_libc_crt_file(arena, "mingwex.lib"));
try argv.append(try comp.get_libc_crt_file(arena, "msvcrt-os.lib"));
+ try argv.append(try comp.get_libc_crt_file(arena, "uuid.lib"));
for (mingw.always_link_libs) |name| {
if (!self.base.options.system_libs.contains(name)) {
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index c4371fbcbf..dd88d47fab 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -1428,7 +1428,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
}
man.hash.addOptionalBytes(self.base.options.soname);
man.hash.addOptional(self.base.options.version);
- link.hashAddSystemLibs(&man.hash, self.base.options.system_libs);
+ try link.hashAddSystemLibs(&man, self.base.options.system_libs);
man.hash.addListOfBytes(self.base.options.force_undefined_symbols.keys());
man.hash.add(allow_shlib_undefined);
man.hash.add(self.base.options.bind_global_refs_locally);
@@ -1824,8 +1824,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
argv.appendAssumeCapacity("--as-needed");
var as_needed = true;
- for (system_libs, 0..) |link_lib, i| {
- const lib_as_needed = !system_libs_values[i].needed;
+ for (system_libs_values) |lib_info| {
+ const lib_as_needed = !lib_info.needed;
switch ((@as(u2, @intFromBool(lib_as_needed)) << 1) | @intFromBool(as_needed)) {
0b00, 0b11 => {},
0b01 => {
@@ -1842,9 +1842,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
// libraries and not static libraries (the check for that needs to be earlier),
// but they could be full paths to .so files, in which case we
// want to avoid prepending "-l".
- const ext = Compilation.classifyFileExt(link_lib);
- const arg = if (ext == .shared_library) link_lib else try std.fmt.allocPrint(arena, "-l{s}", .{link_lib});
- argv.appendAssumeCapacity(arg);
+ argv.appendAssumeCapacity(lib_info.path.?);
}
if (!as_needed) {
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 44e6acc397..1f2dd4f8b0 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -58,11 +58,6 @@ const Rebase = @import("MachO/dyld_info/Rebase.zig");
pub const base_tag: File.Tag = File.Tag.macho;
-pub const SearchStrategy = enum {
- paths_first,
- dylibs_first,
-};
-
/// Mode of operation of the linker.
pub const Mode = enum {
/// Incremental mode will preallocate segments/sections and is compatible with
@@ -834,39 +829,50 @@ pub fn resolveLibSystem(
out_libs: anytype,
) !void {
// If we were given the sysroot, try to look there first for libSystem.B.{dylib, tbd}.
- var libsystem_available = false;
- if (syslibroot != null) blk: {
- // Try stub file first. If we hit it, then we're done as the stub file
- // re-exports every single symbol definition.
- for (search_dirs) |dir| {
- if (try resolveLib(arena, dir, "System", ".tbd")) |full_path| {
- try out_libs.put(full_path, .{ .needed = true });
- libsystem_available = true;
- break :blk;
- }
+ if (syslibroot) |root| {
+ const full_dir_path = try std.fs.path.join(arena, &.{ root, "usr", "lib" });
+ if (try resolveLibSystemInDirs(arena, &.{full_dir_path}, out_libs)) return;
+ }
+
+ // Next, try input search dirs if we are linking on a custom host such as Nix.
+ if (try resolveLibSystemInDirs(arena, search_dirs, out_libs)) return;
+
+ // As a fallback, try linking against Zig shipped stub.
+ const libsystem_name = try std.fmt.allocPrint(arena, "libSystem.{d}.tbd", .{
+ target.os.version_range.semver.min.major,
+ });
+ const full_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
+ "libc", "darwin", libsystem_name,
+ });
+ try out_libs.put(full_path, .{
+ .needed = true,
+ .weak = false,
+ .path = full_path,
+ });
+}
+
+fn resolveLibSystemInDirs(arena: Allocator, dirs: []const []const u8, out_libs: anytype) !bool {
+ // Try stub file first. If we hit it, then we're done as the stub file
+ // re-exports every single symbol definition.
+ for (dirs) |dir| {
+ if (try resolveLib(arena, dir, "System", ".tbd")) |full_path| {
+ try out_libs.put(full_path, .{ .needed = true, .weak = false, .path = full_path });
+ return true;
}
- // If we didn't hit the stub file, try .dylib next. However, libSystem.dylib
- // doesn't export libc.dylib which we'll need to resolve subsequently also.
- for (search_dirs) |dir| {
- if (try resolveLib(arena, dir, "System", ".dylib")) |libsystem_path| {
- if (try resolveLib(arena, dir, "c", ".dylib")) |libc_path| {
- try out_libs.put(libsystem_path, .{ .needed = true });
- try out_libs.put(libc_path, .{ .needed = true });
- libsystem_available = true;
- break :blk;
- }
+ }
+ // If we didn't hit the stub file, try .dylib next. However, libSystem.dylib
+ // doesn't export libc.dylib which we'll need to resolve subsequently also.
+ for (dirs) |dir| {
+ if (try resolveLib(arena, dir, "System", ".dylib")) |libsystem_path| {
+ if (try resolveLib(arena, dir, "c", ".dylib")) |libc_path| {
+ try out_libs.put(libsystem_path, .{ .needed = true, .weak = false, .path = libsystem_path });
+ try out_libs.put(libc_path, .{ .needed = true, .weak = false, .path = libc_path });
+ return true;
}
}
}
- if (!libsystem_available) {
- const libsystem_name = try std.fmt.allocPrint(arena, "libSystem.{d}.tbd", .{
- target.os.version_range.semver.min.major,
- });
- const full_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
- "libc", "darwin", libsystem_name,
- });
- try out_libs.put(full_path, .{ .needed = true });
- }
+
+ return false;
}
pub fn resolveSearchDir(
diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig
index 10f446f191..8f803d98cb 100644
--- a/src/link/MachO/load_commands.zig
+++ b/src/link/MachO/load_commands.zig
@@ -278,11 +278,10 @@ pub fn writeBuildVersionLC(options: *const link.Options, lc_writer: anytype) !vo
const platform_version = @as(u32, @intCast(ver.major << 16 | ver.minor << 8));
break :blk platform_version;
};
- const sdk_version = if (options.native_darwin_sdk) |sdk| blk: {
- const ver = sdk.version;
- const sdk_version = @as(u32, @intCast(ver.major << 16 | ver.minor << 8));
- break :blk sdk_version;
- } else platform_version;
+ const sdk_version: u32 = if (options.darwin_sdk_version) |ver|
+ @intCast(ver.major << 16 | ver.minor << 8)
+ else
+ platform_version;
const is_simulator_abi = options.target.abi == .simulator;
try lc_writer.writeStruct(macho.build_version_command{
.cmdsize = cmdsize,
diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig
index 39b64fe178..56eee2b546 100644
--- a/src/link/MachO/zld.zig
+++ b/src/link/MachO/zld.zig
@@ -3410,7 +3410,6 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
// installation sources because they are always a product of the compiler version + target information.
man.hash.add(stack_size);
man.hash.addOptional(options.pagezero_size);
- man.hash.addOptional(options.search_strategy);
man.hash.addOptional(options.headerpad_size);
man.hash.add(options.headerpad_max_install_names);
man.hash.add(gc_sections);
@@ -3418,13 +3417,13 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
man.hash.add(options.strip);
man.hash.addListOfBytes(options.lib_dirs);
man.hash.addListOfBytes(options.framework_dirs);
- link.hashAddSystemLibs(&man.hash, options.frameworks);
+ link.hashAddFrameworks(&man.hash, options.frameworks);
man.hash.addListOfBytes(options.rpath_list);
if (is_dyn_lib) {
man.hash.addOptionalBytes(options.install_name);
man.hash.addOptional(options.version);
}
- link.hashAddSystemLibs(&man.hash, options.system_libs);
+ try link.hashAddSystemLibs(&man, options.system_libs);
man.hash.addOptionalBytes(options.sysroot);
man.hash.addListOfBytes(options.force_undefined_symbols.keys());
try man.addOptionalFile(options.entitlements);
@@ -3550,84 +3549,15 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
try positionals.append(comp.libcxx_static_lib.?.full_object_path);
}
- // Shared and static libraries passed via `-l` flag.
- var candidate_libs = std.StringArrayHashMap(link.SystemLib).init(arena);
-
- const system_lib_names = options.system_libs.keys();
- for (system_lib_names) |system_lib_name| {
- // By this time, we depend on these libs being dynamically linked libraries and not static libraries
- // (the check for that needs to be earlier), but they could be full paths to .dylib files, in which
- // case we want to avoid prepending "-l".
- if (Compilation.classifyFileExt(system_lib_name) == .shared_library) {
- try positionals.append(system_lib_name);
- continue;
- }
-
- const system_lib_info = options.system_libs.get(system_lib_name).?;
- try candidate_libs.put(system_lib_name, .{
- .needed = system_lib_info.needed,
- .weak = system_lib_info.weak,
- });
- }
-
- var lib_dirs = std.ArrayList([]const u8).init(arena);
- for (options.lib_dirs) |dir| {
- if (try MachO.resolveSearchDir(arena, dir, options.sysroot)) |search_dir| {
- try lib_dirs.append(search_dir);
- } else {
- log.warn("directory not found for '-L{s}'", .{dir});
- }
- }
-
var libs = std.StringArrayHashMap(link.SystemLib).init(arena);
- // Assume ld64 default -search_paths_first if no strategy specified.
- const search_strategy = options.search_strategy orelse .paths_first;
- outer: for (candidate_libs.keys()) |lib_name| {
- switch (search_strategy) {
- .paths_first => {
- // Look in each directory for a dylib (stub first), and then for archive
- for (lib_dirs.items) |dir| {
- for (&[_][]const u8{ ".tbd", ".dylib", ".a" }) |ext| {
- if (try MachO.resolveLib(arena, dir, lib_name, ext)) |full_path| {
- try libs.put(full_path, candidate_libs.get(lib_name).?);
- continue :outer;
- }
- }
- } else {
- log.warn("library not found for '-l{s}'", .{lib_name});
- lib_not_found = true;
- }
- },
- .dylibs_first => {
- // First, look for a dylib in each search dir
- for (lib_dirs.items) |dir| {
- for (&[_][]const u8{ ".tbd", ".dylib" }) |ext| {
- if (try MachO.resolveLib(arena, dir, lib_name, ext)) |full_path| {
- try libs.put(full_path, candidate_libs.get(lib_name).?);
- continue :outer;
- }
- }
- } else for (lib_dirs.items) |dir| {
- if (try MachO.resolveLib(arena, dir, lib_name, ".a")) |full_path| {
- try libs.put(full_path, candidate_libs.get(lib_name).?);
- } else {
- log.warn("library not found for '-l{s}'", .{lib_name});
- lib_not_found = true;
- }
- }
- },
- }
- }
-
- if (lib_not_found) {
- log.warn("Library search paths:", .{});
- for (lib_dirs.items) |dir| {
- log.warn(" {s}", .{dir});
- }
+ {
+ const vals = options.system_libs.values();
+ try libs.ensureUnusedCapacity(vals.len);
+ for (vals) |v| libs.putAssumeCapacity(v.path.?, v);
}
- try MachO.resolveLibSystem(arena, comp, options.sysroot, target, lib_dirs.items, &libs);
+ try MachO.resolveLibSystem(arena, comp, options.sysroot, target, options.lib_dirs, &libs);
// frameworks
var framework_dirs = std.ArrayList([]const u8).init(arena);
@@ -3647,6 +3577,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
try libs.put(full_path, .{
.needed = info.needed,
.weak = info.weak,
+ .path = full_path,
});
continue :outer;
}
@@ -3698,11 +3629,6 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
try argv.append(try std.fmt.allocPrint(arena, "0x{x}", .{pagezero_size}));
}
- if (options.search_strategy) |strat| switch (strat) {
- .paths_first => try argv.append("-search_paths_first"),
- .dylibs_first => try argv.append("-search_dylibs_first"),
- };
-
if (options.headerpad_size) |headerpad_size| {
try argv.append("-headerpad_size");
try argv.append(try std.fmt.allocPrint(arena, "0x{x}", .{headerpad_size}));