diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-08-03 09:53:18 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-08-03 09:53:18 -0700 |
| commit | c4e62be62e8d8a006cc9d7861232f511c5a05385 (patch) | |
| tree | 2e28a575a3eef3bbf80ddd7d8f27ab607d720d85 /src/link | |
| parent | f887b0251822f75dc4a3e24ca5337cb681c1eb1f (diff) | |
| parent | d0fd67cffe664ff70d9a70dd4d2d28aba5a378e8 (diff) | |
| download | zig-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.zig | 3 | ||||
| -rw-r--r-- | src/link/Elf.zig | 10 | ||||
| -rw-r--r-- | src/link/MachO.zig | 74 | ||||
| -rw-r--r-- | src/link/MachO/load_commands.zig | 9 | ||||
| -rw-r--r-- | src/link/MachO/zld.zig | 90 |
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})); |
