diff --git a/src/Compilation.zig b/src/Compilation.zig index cc2e2a916b..2ab9dde35c 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -451,6 +451,11 @@ pub const CacheMode = link.CacheMode; pub const LinkObject = struct { path: []const u8, must_link: bool = false, + // When the library is passed via a positional argument, it will be + // added as a full path. If it's `-l`, then just the basename. + // + // Consistent with `withLOption` variable name in lld ELF driver. + loption: bool = false, }; pub const InitOptions = struct { @@ -2196,7 +2201,7 @@ fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemo /// to remind the programmer to update multiple related pieces of code that /// are in different locations. Bump this number when adding or deleting /// anything from the link cache manifest. -pub const link_hash_implementation_version = 8; +pub const link_hash_implementation_version = 9; fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifest) !void { const gpa = comp.gpa; @@ -2206,7 +2211,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - comptime assert(link_hash_implementation_version == 8); + comptime assert(link_hash_implementation_version == 9); if (comp.bin_file.options.module) |mod| { const main_zig_file = try mod.main_pkg.root_src_directory.join(arena, &[_][]const u8{ @@ -2244,6 +2249,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes for (comp.bin_file.options.objects) |obj| { _ = try man.addFile(obj.path, null); man.hash.add(obj.must_link); + man.hash.add(obj.loption); } for (comp.c_object_table.keys()) |key| { diff --git a/src/link.zig b/src/link.zig index 79ac33b892..471b26ae9f 100644 --- a/src/link.zig +++ b/src/link.zig @@ -1020,6 +1020,7 @@ pub const File = struct { for (base.options.objects) |obj| { _ = try man.addFile(obj.path, null); man.hash.add(obj.must_link); + man.hash.add(obj.loption); } for (comp.c_object_table.keys()) |key| { _ = try man.addFile(key.status.success.object_path, null); diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 656b0f9a97..6be20efe11 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -63,7 +63,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod man = comp.cache_parent.obtain(); self.base.releaseLock(); - comptime assert(Compilation.link_hash_implementation_version == 8); + comptime assert(Compilation.link_hash_implementation_version == 9); for (self.base.options.objects) |obj| { _ = try man.addFile(obj.path, null); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 9fa48a9e62..2a28f880ac 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1371,13 +1371,14 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // We are about to obtain this lock, so here we give other processes a chance first. self.base.releaseLock(); - comptime assert(Compilation.link_hash_implementation_version == 8); + comptime assert(Compilation.link_hash_implementation_version == 9); try man.addOptionalFile(self.base.options.linker_script); try man.addOptionalFile(self.base.options.version_script); for (self.base.options.objects) |obj| { _ = try man.addFile(obj.path, null); man.hash.add(obj.must_link); + man.hash.add(obj.loption); } for (comp.c_object_table.keys()) |key| { _ = try man.addFile(key.status.success.object_path, null); @@ -1719,6 +1720,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v for (self.base.options.objects) |obj| { if (Compilation.classifyFileExt(obj.path) == .shared_library) { const lib_dir_path = std.fs.path.dirname(obj.path) orelse continue; + if (obj.loption) continue; + if ((try rpath_table.fetchPut(lib_dir_path, {})) == null) { try argv.append("-rpath"); try argv.append(lib_dir_path); @@ -1767,6 +1770,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append("-no-whole-archive"); whole_archive = false; } + + if (obj.loption) { + assert(obj.path[0] == ':'); + try argv.append("-l"); + } try argv.append(obj.path); } if (whole_archive) { diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index b151aee19b..4f7e615c79 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -3494,7 +3494,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr // We are about to obtain this lock, so here we give other processes a chance first. macho_file.base.releaseLock(); - comptime assert(Compilation.link_hash_implementation_version == 8); + comptime assert(Compilation.link_hash_implementation_version == 9); for (options.objects) |obj| { _ = try man.addFile(obj.path, null); diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 5dfc91d4ce..befd2d68c9 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -3150,7 +3150,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l // We are about to obtain this lock, so here we give other processes a chance first. wasm.base.releaseLock(); - comptime assert(Compilation.link_hash_implementation_version == 8); + comptime assert(Compilation.link_hash_implementation_version == 9); for (options.objects) |obj| { _ = try man.addFile(obj.path, null); @@ -4199,7 +4199,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! // We are about to obtain this lock, so here we give other processes a chance first. wasm.base.releaseLock(); - comptime assert(Compilation.link_hash_implementation_version == 8); + comptime assert(Compilation.link_hash_implementation_version == 9); for (wasm.base.options.objects) |obj| { _ = try man.addFile(obj.path, null); diff --git a/src/main.zig b/src/main.zig index f7afbe767b..b4778c1b00 100644 --- a/src/main.zig +++ b/src/main.zig @@ -889,14 +889,6 @@ fn buildOutputType( var link_objects = std.ArrayList(Compilation.LinkObject).init(gpa); defer link_objects.deinit(); - // This map is a flag per link_objects item, used to represent the - // `-l :file.so` syntax from gcc/clang. - // This is only exposed from the `zig cc` interface. It means that the `path` - // field from the corresponding `link_objects` element is a suffix, and is - // to be tried against each library path as a prefix until an existing file is found. - // This map remains empty for the main CLI. - var link_objects_lib_search_paths: std.AutoHashMapUnmanaged(u32, void) = .{}; - var framework_dirs = std.ArrayList([]const u8).init(gpa); defer framework_dirs.deinit(); @@ -1627,14 +1619,15 @@ fn buildOutputType( // We don't know whether this library is part of libc or libc++ until // we resolve the target, so we simply append to the list for now. if (mem.startsWith(u8, it.only_arg, ":")) { - // This "feature" of gcc/clang means to treat this as a positional - // link object, but using the library search directories as a prefix. + // -l :path/to/filename is used when callers need + // more control over what's in the resulting + // binary: no extra rpaths and DSO filename exactly + // as provided. Hello, Go. try link_objects.append(.{ - .path = it.only_arg[1..], + .path = it.only_arg, .must_link = must_link, + .loption = true, }); - const index = @intCast(u32, link_objects.items.len - 1); - try link_objects_lib_search_paths.put(arena, index, {}); } else if (force_static_libs) { try static_libs.append(it.only_arg); } else { @@ -2640,30 +2633,6 @@ fn buildOutputType( } } - // Resolve `-l :file.so` syntax from `zig cc`. We use a separate map for this data - // since this is an uncommon case. - { - var it = link_objects_lib_search_paths.iterator(); - while (it.next()) |item| { - const link_object_i = item.key_ptr.*; - const suffix = link_objects.items[link_object_i].path; - - for (lib_dirs.items) |lib_dir_path| { - const test_path = try fs.path.join(arena, &.{ lib_dir_path, suffix }); - fs.cwd().access(test_path, .{}) catch |err| switch (err) { - error.FileNotFound => continue, - else => |e| fatal("unable to search for library '{s}': {s}", .{ - test_path, @errorName(e), - }), - }; - link_objects.items[link_object_i].path = test_path; - break; - } else { - fatal("library '{s}' not found", .{suffix}); - } - } - } - const object_format = target_info.target.ofmt; if (output_mode == .Obj and (object_format == .coff or object_format == .macho)) {