| author | |
| committer | |
| log | cf33f1003fd02abaf91078725d9c972dd51fc5e1 |
| tree | 4005c517ac60d12213b095ec60def90ea5f6230a |
| parent | ecd95943a9a174284a5e90f208df4d508aafd098 |
linker still wants the path to the shared object, but now also accepts
an exact name to put into the NEEDED entry.
closes #3182310 files changed, 87 insertions(+), 86 deletions(-)
src/Compilation.zig+3-2| ... | @@ -2891,12 +2891,13 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE | ... | @@ -2891,12 +2891,13 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE |
| 2891 | } | 2891 | } |
| 2892 | } | 2892 | } |
| 2893 | 2893 | ||
| 2894 | for (comp.link_inputs) |input| if (input.path()) |path| { | 2894 | for (comp.link_inputs) |input| { |
| 2895 | const path = input.path(); | ||
| 2895 | try comp.appendFileSystemInput(try .fromUnresolved(arena, comp.dirs, &.{ | 2896 | try comp.appendFileSystemInput(try .fromUnresolved(arena, comp.dirs, &.{ |
| 2896 | path.root_dir.path orelse ".", | 2897 | path.root_dir.path orelse ".", |
| 2897 | path.sub_path, | 2898 | path.sub_path, |
| 2898 | })); | 2899 | })); |
| 2899 | }; | 2900 | } |
| 2900 | 2901 | ||
| 2901 | // For compiling Win32 resources, we rely on the cache hash system to avoid duplicating work. | 2902 | // For compiling Win32 resources, we rely on the cache hash system to avoid duplicating work. |
| 2902 | // Add a Job for each Win32 resource file. | 2903 | // Add a Job for each Win32 resource file. |
src/link.zig+21-27| ... | @@ -1506,7 +1506,6 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { | ... | @@ -1506,7 +1506,6 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { |
| 1506 | .object => |obj| diags.addParseError(obj.path, "failed to parse object: {t}", .{e}), | 1506 | .object => |obj| diags.addParseError(obj.path, "failed to parse object: {t}", .{e}), |
| 1507 | .archive => |obj| diags.addParseError(obj.path, "failed to parse archive: {t}", .{e}), | 1507 | .archive => |obj| diags.addParseError(obj.path, "failed to parse archive: {t}", .{e}), |
| 1508 | .res => |res| diags.addParseError(res.path, "failed to parse Windows resource: {t}", .{e}), | 1508 | .res => |res| diags.addParseError(res.path, "failed to parse Windows resource: {t}", .{e}), |
| 1509 | .dso_exact => diags.addError("failed to handle dso_exact: {t}", .{e}), | ||
| 1510 | }, | 1509 | }, |
| 1511 | }; | 1510 | }; |
| 1512 | prog_node.completeOne(); | 1511 | prog_node.completeOne(); |
| ... | @@ -1821,8 +1820,6 @@ pub const UnresolvedInput = union(enum) { | ... | @@ -1821,8 +1820,6 @@ pub const UnresolvedInput = union(enum) { |
| 1821 | /// Strings that come from GNU ld scripts. Is it a filename? Is it a path? | 1820 | /// Strings that come from GNU ld scripts. Is it a filename? Is it a path? |
| 1822 | /// Who knows! Fuck around and find out. | 1821 | /// Who knows! Fuck around and find out. |
| 1823 | ambiguous_name: NameQuery, | 1822 | ambiguous_name: NameQuery, |
| 1824 | /// Put exactly this string in the dynamic section, no rpath. | ||
| 1825 | dso_exact: Input.DsoExact, | ||
| 1826 | 1823 | ||
| 1827 | pub const NameQuery = struct { | 1824 | pub const NameQuery = struct { |
| 1828 | name: []const u8, | 1825 | name: []const u8, |
| ... | @@ -1875,7 +1872,6 @@ pub const Input = union(enum) { | ... | @@ -1875,7 +1872,6 @@ pub const Input = union(enum) { |
| 1875 | /// May not be a GNU ld script. Those are resolved when converting from | 1872 | /// May not be a GNU ld script. Those are resolved when converting from |
| 1876 | /// `UnresolvedInput` to `Input` values. | 1873 | /// `UnresolvedInput` to `Input` values. |
| 1877 | dso: Dso, | 1874 | dso: Dso, |
| 1878 | dso_exact: DsoExact, | ||
| 1879 | 1875 | ||
| 1880 | pub const Object = struct { | 1876 | pub const Object = struct { |
| 1881 | path: Path, | 1877 | path: Path, |
| ... | @@ -1895,6 +1891,9 @@ pub const Input = union(enum) { | ... | @@ -1895,6 +1891,9 @@ pub const Input = union(enum) { |
| 1895 | needed: bool, | 1891 | needed: bool, |
| 1896 | weak: bool, | 1892 | weak: bool, |
| 1897 | reexport: bool, | 1893 | reexport: bool, |
| 1894 | /// Does not include any ":" prefix. Indicates that this string, exactly, should go into the NEEDED | ||
| 1895 | /// entry, without affecting any rpaths. | ||
| 1896 | exact_name: ?[]const u8, | ||
| 1898 | }; | 1897 | }; |
| 1899 | 1898 | ||
| 1900 | pub const DsoExact = struct { | 1899 | pub const DsoExact = struct { |
| ... | @@ -1903,21 +1902,17 @@ pub const Input = union(enum) { | ... | @@ -1903,21 +1902,17 @@ pub const Input = union(enum) { |
| 1903 | name: []const u8, | 1902 | name: []const u8, |
| 1904 | }; | 1903 | }; |
| 1905 | 1904 | ||
| 1906 | /// Returns `null` in the case of `dso_exact`. | 1905 | pub fn path(input: Input) Path { |
| 1907 | pub fn path(input: Input) ?Path { | ||
| 1908 | return switch (input) { | 1906 | return switch (input) { |
| 1909 | .object, .archive => |obj| obj.path, | 1907 | .object, .archive => |obj| obj.path, |
| 1910 | inline .res, .dso => |x| x.path, | 1908 | inline .res, .dso => |x| x.path, |
| 1911 | .dso_exact => null, | ||
| 1912 | }; | 1909 | }; |
| 1913 | } | 1910 | } |
| 1914 | 1911 | ||
| 1915 | /// Returns `null` in the case of `dso_exact`. | 1912 | pub fn pathAndFile(input: Input) struct { Path, Io.File } { |
| 1916 | pub fn pathAndFile(input: Input) ?struct { Path, Io.File } { | ||
| 1917 | return switch (input) { | 1913 | return switch (input) { |
| 1918 | .object, .archive => |obj| .{ obj.path, obj.file }, | 1914 | .object, .archive => |obj| .{ obj.path, obj.file }, |
| 1919 | inline .res, .dso => |x| .{ x.path, x.file }, | 1915 | inline .res, .dso => |x| .{ x.path, x.file }, |
| 1920 | .dso_exact => null, | ||
| 1921 | }; | 1916 | }; |
| 1922 | } | 1917 | } |
| 1923 | 1918 | ||
| ... | @@ -1925,7 +1920,6 @@ pub const Input = union(enum) { | ... | @@ -1925,7 +1920,6 @@ pub const Input = union(enum) { |
| 1925 | return switch (input) { | 1920 | return switch (input) { |
| 1926 | .object, .archive => |obj| obj.path.basename(), | 1921 | .object, .archive => |obj| obj.path.basename(), |
| 1927 | inline .res, .dso => |x| x.path.basename(), | 1922 | inline .res, .dso => |x| x.path.basename(), |
| 1928 | .dso_exact => "dso_exact", | ||
| 1929 | }; | 1923 | }; |
| 1930 | } | 1924 | } |
| 1931 | }; | 1925 | }; |
| ... | @@ -1956,9 +1950,7 @@ pub fn hashInputs(man: *Cache.Manifest, link_inputs: []const Input) !void { | ... | @@ -1956,9 +1950,7 @@ pub fn hashInputs(man: *Cache.Manifest, link_inputs: []const Input) !void { |
| 1956 | man.hash.add(dso.needed); | 1950 | man.hash.add(dso.needed); |
| 1957 | man.hash.add(dso.weak); | 1951 | man.hash.add(dso.weak); |
| 1958 | man.hash.add(dso.reexport); | 1952 | man.hash.add(dso.reexport); |
| 1959 | }, | 1953 | man.hash.addOptionalBytes(dso.exact_name); |
| 1960 | .dso_exact => |dso_exact| { | ||
| 1961 | man.hash.addBytes(dso_exact.name); | ||
| 1962 | }, | 1954 | }, |
| 1963 | } | 1955 | } |
| 1964 | } | 1956 | } |
| ... | @@ -2194,10 +2186,6 @@ pub fn resolveInputs( | ... | @@ -2194,10 +2186,6 @@ pub fn resolveInputs( |
| 2194 | } | 2186 | } |
| 2195 | continue; | 2187 | continue; |
| 2196 | }, | 2188 | }, |
| 2197 | .dso_exact => |dso_exact| { | ||
| 2198 | try resolved_inputs.append(gpa, .{ .dso_exact = dso_exact }); | ||
| 2199 | continue; | ||
| 2200 | }, | ||
| 2201 | } | 2189 | } |
| 2202 | comptime unreachable; | 2190 | comptime unreachable; |
| 2203 | } | 2191 | } |
| ... | @@ -2418,13 +2406,18 @@ fn finishResolveLibInput( | ... | @@ -2418,13 +2406,18 @@ fn finishResolveLibInput( |
| 2418 | .hidden = query.hidden, | 2406 | .hidden = query.hidden, |
| 2419 | } }); | 2407 | } }); |
| 2420 | }, | 2408 | }, |
| 2421 | .dynamic => resolved_inputs.appendAssumeCapacity(.{ .dso = .{ | 2409 | .dynamic => resolved_inputs.appendAssumeCapacity(.{ |
| 2422 | .path = path, | 2410 | .dso = .{ |
| 2423 | .file = file, | 2411 | .path = path, |
| 2424 | .needed = query.needed, | 2412 | .file = file, |
| 2425 | .weak = query.weak, | 2413 | .needed = query.needed, |
| 2426 | .reexport = query.reexport, | 2414 | .weak = query.weak, |
| 2427 | } }), | 2415 | .reexport = query.reexport, |
| 2416 | // Here we assume that `Path.sub_path` is usable as `exact_name`, however the code after this point | ||
| 2417 | // has no business making that assumption. | ||
| 2418 | .exact_name = if (query.name_done) path.sub_path else null, | ||
| 2419 | }, | ||
| 2420 | }), | ||
| 2428 | } | 2421 | } |
| 2429 | return .ok; | 2422 | return .ok; |
| 2430 | } | 2423 | } |
| ... | @@ -2608,6 +2601,7 @@ pub fn openDso(io: Io, path: Path, needed: bool, weak: bool, reexport: bool) !In | ... | @@ -2608,6 +2601,7 @@ pub fn openDso(io: Io, path: Path, needed: bool, weak: bool, reexport: bool) !In |
| 2608 | .needed = needed, | 2601 | .needed = needed, |
| 2609 | .weak = weak, | 2602 | .weak = weak, |
| 2610 | .reexport = reexport, | 2603 | .reexport = reexport, |
| 2604 | .exact_name = null, | ||
| 2611 | }; | 2605 | }; |
| 2612 | } | 2606 | } |
| 2613 | 2607 | ||
| ... | @@ -2639,7 +2633,7 @@ pub fn anyObjectInputs(inputs: []const Input) bool { | ... | @@ -2639,7 +2633,7 @@ pub fn anyObjectInputs(inputs: []const Input) bool { |
| 2639 | pub fn countObjectInputs(inputs: []const Input) usize { | 2633 | pub fn countObjectInputs(inputs: []const Input) usize { |
| 2640 | var count: usize = 0; | 2634 | var count: usize = 0; |
| 2641 | for (inputs) |input| switch (input) { | 2635 | for (inputs) |input| switch (input) { |
| 2642 | .dso, .dso_exact => continue, | 2636 | .dso => continue, |
| 2643 | .res, .object, .archive => count += 1, | 2637 | .res, .object, .archive => count += 1, |
| 2644 | }; | 2638 | }; |
| 2645 | return count; | 2639 | return count; |
| ... | @@ -2649,7 +2643,7 @@ pub fn countObjectInputs(inputs: []const Input) usize { | ... | @@ -2649,7 +2643,7 @@ pub fn countObjectInputs(inputs: []const Input) usize { |
| 2649 | pub fn firstObjectInput(inputs: []const Input) ?Input.Object { | 2643 | pub fn firstObjectInput(inputs: []const Input) ?Input.Object { |
| 2650 | for (inputs) |input| switch (input) { | 2644 | for (inputs) |input| switch (input) { |
| 2651 | .object, .archive => |obj| return obj, | 2645 | .object, .archive => |obj| return obj, |
| 2652 | .res, .dso, .dso_exact => continue, | 2646 | .res, .dso => continue, |
| 2653 | }; | 2647 | }; |
| 2654 | return null; | 2648 | return null; |
| 2655 | } | 2649 | } |
src/link/Coff.zig+1-2| ... | @@ -3905,7 +3905,7 @@ pub fn loadInput(coff: *Coff, input: link.Input) link.Error!void { | ... | @@ -3905,7 +3905,7 @@ pub fn loadInput(coff: *Coff, input: link.Input) link.Error!void { |
| 3905 | const comp = coff.base.comp; | 3905 | const comp = coff.base.comp; |
| 3906 | const io = comp.io; | 3906 | const io = comp.io; |
| 3907 | 3907 | ||
| 3908 | const path = input.path() orelse unreachable; | 3908 | const path = input.path(); |
| 3909 | const gop = try coff.inputs.getOrPut(comp.gpa, path); | 3909 | const gop = try coff.inputs.getOrPut(comp.gpa, path); |
| 3910 | if (gop.found_existing) return; | 3910 | if (gop.found_existing) return; |
| 3911 | errdefer _ = coff.inputs.swapRemove(path); | 3911 | errdefer _ = coff.inputs.swapRemove(path); |
| ... | @@ -3935,7 +3935,6 @@ pub fn loadInput(coff: *Coff, input: link.Input) link.Error!void { | ... | @@ -3935,7 +3935,6 @@ pub fn loadInput(coff: *Coff, input: link.Input) link.Error!void { |
| 3935 | coff.loadDll(dso.path, &fr) catch |err| | 3935 | coff.loadDll(dso.path, &fr) catch |err| |
| 3936 | return coff.failLoadInput(err, &fr, dso.path); | 3936 | return coff.failLoadInput(err, &fr, dso.path); |
| 3937 | }, | 3937 | }, |
| 3938 | .dso_exact => unreachable, | ||
| 3939 | } | 3938 | } |
| 3940 | } | 3939 | } |
| 3941 | 3940 |
src/link/Elf.zig+2-2| ... | @@ -722,7 +722,6 @@ pub fn loadInput(self: *Elf, input: link.Input) !void { | ... | @@ -722,7 +722,6 @@ pub fn loadInput(self: *Elf, input: link.Input) !void { |
| 722 | const argv = &self.dump_argv_list; | 722 | const argv = &self.dump_argv_list; |
| 723 | switch (input) { | 723 | switch (input) { |
| 724 | .res => unreachable, | 724 | .res => unreachable, |
| 725 | .dso_exact => |dso_exact| try argv.appendSlice(gpa, &.{ "-l", dso_exact.name }), | ||
| 726 | .object, .archive => |obj| try argv.append(gpa, try obj.path.toString(comp.arena)), | 725 | .object, .archive => |obj| try argv.append(gpa, try obj.path.toString(comp.arena)), |
| 727 | .dso => |dso| try argv.append(gpa, try dso.path.toString(comp.arena)), | 726 | .dso => |dso| try argv.append(gpa, try dso.path.toString(comp.arena)), |
| 728 | } | 727 | } |
| ... | @@ -730,7 +729,6 @@ pub fn loadInput(self: *Elf, input: link.Input) !void { | ... | @@ -730,7 +729,6 @@ pub fn loadInput(self: *Elf, input: link.Input) !void { |
| 730 | 729 | ||
| 731 | switch (input) { | 730 | switch (input) { |
| 732 | .res => unreachable, | 731 | .res => unreachable, |
| 733 | .dso_exact => @panic("TODO"), | ||
| 734 | .object => |obj| try parseObject(self, obj), | 732 | .object => |obj| try parseObject(self, obj), |
| 735 | .archive => |obj| if (self.base.isStaticLib()) { | 733 | .archive => |obj| if (self.base.isStaticLib()) { |
| 736 | // Ignore static library inputs when generating a static library. | 734 | // Ignore static library inputs when generating a static library. |
| ... | @@ -1120,6 +1118,8 @@ fn parseDso( | ... | @@ -1120,6 +1118,8 @@ fn parseDso( |
| 1120 | 1118 | ||
| 1121 | const handle = dso.file; | 1119 | const handle = dso.file; |
| 1122 | 1120 | ||
| 1121 | if (dso.exact_name != null) @panic("TODO"); | ||
| 1122 | |||
| 1123 | const stat: Stat = .init(try handle.stat(io)); | 1123 | const stat: Stat = .init(try handle.stat(io)); |
| 1124 | var header = try SharedObject.parseHeader(gpa, io, diags, dso.path, handle, stat, target); | 1124 | var header = try SharedObject.parseHeader(gpa, io, diags, dso.path, handle, stat, target); |
| 1125 | defer header.deinit(gpa); | 1125 | defer header.deinit(gpa); |
src/link/Elf2.zig+12-19| ... | @@ -6228,36 +6228,29 @@ fn loadInputInner(elf: *Elf, input: link.Input) (Error || error{BadMagic})!void | ... | @@ -6228,36 +6228,29 @@ fn loadInputInner(elf: *Elf, input: link.Input) (Error || error{BadMagic})!void |
| 6228 | }, | 6228 | }, |
| 6229 | .res => unreachable, | 6229 | .res => unreachable, |
| 6230 | .dso => |dso| { | 6230 | .dso => |dso| { |
| 6231 | if (dso.exact_name) |exact_name| { | ||
| 6232 | // This means the path field is still valid, but the NEEDED entry must be set to | ||
| 6233 | // exactly the `exact_name` string. | ||
| 6234 | std.debug.panic("load dso_exact {q}", .{exact_name}); | ||
| 6235 | if (elf.shndx.dynamic != .UNDEF) { | ||
| 6236 | try elf.needed.put(elf.base.comp.gpa, try elf.string(.dynstr, exact_name), {}); | ||
| 6237 | } | ||
| 6238 | } | ||
| 6231 | try elf.needed.ensureUnusedCapacity(elf.base.comp.gpa, 1); | 6239 | try elf.needed.ensureUnusedCapacity(elf.base.comp.gpa, 1); |
| 6232 | var fr = dso.file.reader(io, &buf); | 6240 | var fr = dso.file.reader(io, &buf); |
| 6233 | elf.loadDso(dso.path, &fr) catch |err| switch (err) { | 6241 | elf.loadDso(dso.path, &fr) catch |err| switch (err) { |
| 6234 | else => |e| return e, | 6242 | else => |e| return e, |
| 6235 | error.EndOfStream => return diags.failParse( | 6243 | error.EndOfStream => return diags.failParse(dso.path, "unexpected eof", .{}), |
| 6236 | dso.path, | ||
| 6237 | "unexpected eof", | ||
| 6238 | .{}, | ||
| 6239 | ), | ||
| 6240 | error.AccessDenied, error.Unexpected, error.Unseekable => |e| return diags.fail( | 6244 | error.AccessDenied, error.Unexpected, error.Unseekable => |e| return diags.fail( |
| 6241 | "failed to read \"{f}\": {t}", | 6245 | "failed to read {qf}: {t}", |
| 6242 | .{ dso.path.fmtEscapeString(), e }, | 6246 | .{ dso.path, e }, |
| 6243 | ), | 6247 | ), |
| 6244 | error.ReadFailed => switch (fr.err.?) { | 6248 | error.ReadFailed => switch (fr.err.?) { |
| 6245 | error.Canceled => |e| return e, | 6249 | error.Canceled => |e| return e, |
| 6246 | else => |e| return diags.fail( | 6250 | else => |e| return diags.fail("failed to read {qf}: {t}", .{ dso.path, e }), |
| 6247 | "failed to read \"{f}\": {t}", | ||
| 6248 | .{ dso.path.fmtEscapeString(), e }, | ||
| 6249 | ), | ||
| 6250 | }, | 6251 | }, |
| 6251 | }; | 6252 | }; |
| 6252 | }, | 6253 | }, |
| 6253 | .dso_exact => |dso_exact| { | ||
| 6254 | log.debug("load dso_exact '{f}'", .{std.zig.fmtString(dso_exact.name)}); | ||
| 6255 | if (elf.shndx.dynamic != .UNDEF) { | ||
| 6256 | try elf.needed.put(elf.base.comp.gpa, try elf.string(.dynstr, dso_exact.name), {}); | ||
| 6257 | } | ||
| 6258 | // TODO: we need to get a resolved file path from the frontend, because we need to read | ||
| 6259 | // the shared object to discover symbol types. | ||
| 6260 | }, | ||
| 6261 | } | 6254 | } |
| 6262 | } | 6255 | } |
| 6263 | fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadParseInputError || error{BadMagic})!void { | 6256 | fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadParseInputError || error{BadMagic})!void { |
src/link/Lld.zig+22-14| ... | @@ -309,9 +309,9 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) link.Error!void { | ... | @@ -309,9 +309,9 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) link.Error!void { |
| 309 | 309 | ||
| 310 | try object_files.ensureUnusedCapacity(arena, comp.link_inputs.len); | 310 | try object_files.ensureUnusedCapacity(arena, comp.link_inputs.len); |
| 311 | for (comp.link_inputs) |input| switch (input) { | 311 | for (comp.link_inputs) |input| switch (input) { |
| 312 | .dso, .dso_exact, .archive => {}, // static archives should not contain shared libraries or other static archives | 312 | .dso, .archive => {}, // static archives should not contain shared libraries or other static archives |
| 313 | .res, .object => { | 313 | .res, .object => { |
| 314 | const path = try input.path().?.toStringZ(arena); | 314 | const path = try input.path().toStringZ(arena); |
| 315 | object_files.appendAssumeCapacity(path); | 315 | object_files.appendAssumeCapacity(path); |
| 316 | }, | 316 | }, |
| 317 | }; | 317 | }; |
| ... | @@ -551,7 +551,6 @@ fn coffLink(lld: *Lld, arena: Allocator) !void { | ... | @@ -551,7 +551,6 @@ fn coffLink(lld: *Lld, arena: Allocator) !void { |
| 551 | 551 | ||
| 552 | try argv.ensureUnusedCapacity(comp.link_inputs.len); | 552 | try argv.ensureUnusedCapacity(comp.link_inputs.len); |
| 553 | for (comp.link_inputs) |link_input| switch (link_input) { | 553 | for (comp.link_inputs) |link_input| switch (link_input) { |
| 554 | .dso_exact => unreachable, // not applicable to PE/COFF | ||
| 555 | inline .dso, .res => |x| { | 554 | inline .dso, .res => |x| { |
| 556 | argv.appendAssumeCapacity(try x.path.toString(arena)); | 555 | argv.appendAssumeCapacity(try x.path.toString(arena)); |
| 557 | }, | 556 | }, |
| ... | @@ -1114,10 +1113,6 @@ fn elfLink(lld: *Lld, arena: Allocator) !void { | ... | @@ -1114,10 +1113,6 @@ fn elfLink(lld: *Lld, arena: Allocator) !void { |
| 1114 | } | 1113 | } |
| 1115 | try argv.append(try obj.path.toString(arena)); | 1114 | try argv.append(try obj.path.toString(arena)); |
| 1116 | }, | 1115 | }, |
| 1117 | .dso_exact => |dso_exact| { | ||
| 1118 | assert(dso_exact.name[0] == ':'); | ||
| 1119 | try argv.appendSlice(&.{ "-l", dso_exact.name }); | ||
| 1120 | }, | ||
| 1121 | }; | 1116 | }; |
| 1122 | 1117 | ||
| 1123 | if (whole_archive) { | 1118 | if (whole_archive) { |
| ... | @@ -1161,7 +1156,7 @@ fn elfLink(lld: *Lld, arena: Allocator) !void { | ... | @@ -1161,7 +1156,7 @@ fn elfLink(lld: *Lld, arena: Allocator) !void { |
| 1161 | 1156 | ||
| 1162 | for (base.comp.link_inputs) |link_input| switch (link_input) { | 1157 | for (base.comp.link_inputs) |link_input| switch (link_input) { |
| 1163 | .res => unreachable, // Windows-only | 1158 | .res => unreachable, // Windows-only |
| 1164 | .object, .archive, .dso_exact => continue, | 1159 | .object, .archive => continue, |
| 1165 | .dso => |dso| { | 1160 | .dso => |dso| { |
| 1166 | const lib_as_needed = !dso.needed; | 1161 | const lib_as_needed = !dso.needed; |
| 1167 | switch ((@as(u2, @intFromBool(lib_as_needed)) << 1) | @intFromBool(as_needed)) { | 1162 | switch ((@as(u2, @intFromBool(lib_as_needed)) << 1) | @intFromBool(as_needed)) { |
| ... | @@ -1176,11 +1171,25 @@ fn elfLink(lld: *Lld, arena: Allocator) !void { | ... | @@ -1176,11 +1171,25 @@ fn elfLink(lld: *Lld, arena: Allocator) !void { |
| 1176 | }, | 1171 | }, |
| 1177 | } | 1172 | } |
| 1178 | 1173 | ||
| 1179 | // By this time, we depend on these libs being dynamically linked | 1174 | if (dso.exact_name) |exact_name| { |
| 1180 | // libraries and not static libraries (the check for that needs to be earlier), | 1175 | // LLD does not have a way to specify full path to the DSO while also specifying |
| 1181 | // but they could be full paths to .so files, in which case we | 1176 | // the exact value for NEEDED, so we have to use a combination of -L and -l args. |
| 1182 | // want to avoid prepending "-l". | 1177 | assert(mem.endsWith(u8, dso.path.sub_path, exact_name)); |
| 1183 | argv.appendAssumeCapacity(try dso.path.toString(arena)); | 1178 | const truncated_path: Cache.Path = .{ |
| 1179 | .root_dir = dso.path.root_dir, | ||
| 1180 | .sub_path = dso.path.sub_path[0 .. dso.path.sub_path.len - exact_name.len], | ||
| 1181 | }; | ||
| 1182 | try argv.ensureUnusedCapacity(3); | ||
| 1183 | argv.appendAssumeCapacity("-L"); | ||
| 1184 | argv.appendAssumeCapacity(try truncated_path.toString(arena)); | ||
| 1185 | argv.appendAssumeCapacity(try arena.print("-l:{s}", .{exact_name})); | ||
| 1186 | } else { | ||
| 1187 | // By this time, we depend on these libs being dynamically linked | ||
| 1188 | // libraries and not static libraries (the check for that needs to be earlier), | ||
| 1189 | // but they could be full paths to .so files, in which case we | ||
| 1190 | // want to avoid prepending "-l". | ||
| 1191 | argv.appendAssumeCapacity(try dso.path.toString(arena)); | ||
| 1192 | } | ||
| 1184 | }, | 1193 | }, |
| 1185 | }; | 1194 | }; |
| 1186 | 1195 | ||
| ... | @@ -1588,7 +1597,6 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void { | ... | @@ -1588,7 +1597,6 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void { |
| 1588 | .dso => |dso| { | 1597 | .dso => |dso| { |
| 1589 | try argv.append(try dso.path.toString(arena)); | 1598 | try argv.append(try dso.path.toString(arena)); |
| 1590 | }, | 1599 | }, |
| 1591 | .dso_exact => unreachable, | ||
| 1592 | .res => unreachable, | 1600 | .res => unreachable, |
| 1593 | }; | 1601 | }; |
| 1594 | if (whole_archive) { | 1602 | if (whole_archive) { |
src/link/MachO.zig+21-13| ... | @@ -372,7 +372,6 @@ pub fn flush( | ... | @@ -372,7 +372,6 @@ pub fn flush( |
| 372 | for (comp.link_inputs) |link_input| switch (link_input) { | 372 | for (comp.link_inputs) |link_input| switch (link_input) { |
| 373 | .dso => continue, // handled below | 373 | .dso => continue, // handled below |
| 374 | .object, .archive => positionals.appendAssumeCapacity(link_input), | 374 | .object, .archive => positionals.appendAssumeCapacity(link_input), |
| 375 | .dso_exact => @panic("TODO"), | ||
| 376 | .res => unreachable, | 375 | .res => unreachable, |
| 377 | }; | 376 | }; |
| 378 | 377 | ||
| ... | @@ -406,7 +405,7 @@ pub fn flush( | ... | @@ -406,7 +405,7 @@ pub fn flush( |
| 406 | 405 | ||
| 407 | for (positionals.items) |link_input| { | 406 | for (positionals.items) |link_input| { |
| 408 | self.classifyInputFile(link_input) catch |err| | 407 | self.classifyInputFile(link_input) catch |err| |
| 409 | diags.addParseError(link_input.path().?, "failed to read input file: {s}", .{@errorName(err)}); | 408 | diags.addParseError(link_input.path(), "failed to read input file: {t}", .{err}); |
| 410 | } | 409 | } |
| 411 | 410 | ||
| 412 | var system_libs = std.array_list.Managed(SystemLib).init(gpa); | 411 | var system_libs = std.array_list.Managed(SystemLib).init(gpa); |
| ... | @@ -447,11 +446,11 @@ pub fn flush( | ... | @@ -447,11 +446,11 @@ pub fn flush( |
| 447 | }; | 446 | }; |
| 448 | 447 | ||
| 449 | for (comp.link_inputs) |link_input| switch (link_input) { | 448 | for (comp.link_inputs) |link_input| switch (link_input) { |
| 450 | .object, .archive, .dso_exact => continue, | 449 | .object, .archive => continue, |
| 451 | .res => unreachable, | 450 | .res => unreachable, |
| 452 | .dso => { | 451 | .dso => { |
| 453 | self.classifyInputFile(link_input) catch |err| | 452 | self.classifyInputFile(link_input) catch |err| |
| 454 | diags.addParseError(link_input.path().?, "failed to parse input file: {s}", .{@errorName(err)}); | 453 | diags.addParseError(link_input.path(), "failed to parse input file: {t}", .{err}); |
| 455 | }, | 454 | }, |
| 456 | }; | 455 | }; |
| 457 | 456 | ||
| ... | @@ -655,8 +654,13 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { | ... | @@ -655,8 +654,13 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 655 | for (comp.link_inputs) |link_input| switch (link_input) { | 654 | for (comp.link_inputs) |link_input| switch (link_input) { |
| 656 | .object, .archive => |obj| try argv.append(try obj.path.toString(arena)), | 655 | .object, .archive => |obj| try argv.append(try obj.path.toString(arena)), |
| 657 | .res => |res| try argv.append(try res.path.toString(arena)), | 656 | .res => |res| try argv.append(try res.path.toString(arena)), |
| 658 | .dso => |dso| try argv.append(try dso.path.toString(arena)), | 657 | .dso => |dso| { |
| 659 | .dso_exact => |dso_exact| try argv.appendSlice(&.{ "-l", dso_exact.name }), | 658 | if (dso.exact_name) |exact_name| { |
| 659 | try argv.appendSlice(&.{ "-l", try arena.print(":{s}", .{exact_name}) }); | ||
| 660 | } else { | ||
| 661 | try argv.append(try dso.path.toString(arena)); | ||
| 662 | } | ||
| 663 | }, | ||
| 660 | }; | 664 | }; |
| 661 | 665 | ||
| 662 | for (comp.c_objects.items) |c_object| { | 666 | for (comp.c_objects.items) |c_object| { |
| ... | @@ -748,7 +752,6 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { | ... | @@ -748,7 +752,6 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 748 | if (obj.must_link) try argv.append("-force_load"); // TODO: verify this | 752 | if (obj.must_link) try argv.append("-force_load"); // TODO: verify this |
| 749 | try argv.append(try obj.path.toString(arena)); | 753 | try argv.append(try obj.path.toString(arena)); |
| 750 | }, | 754 | }, |
| 751 | .dso_exact => |dso_exact| try argv.appendSlice(&.{ "-l", dso_exact.name }), | ||
| 752 | }; | 755 | }; |
| 753 | 756 | ||
| 754 | for (comp.c_objects.items) |c_object| { | 757 | for (comp.c_objects.items) |c_object| { |
| ... | @@ -775,15 +778,21 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { | ... | @@ -775,15 +778,21 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 775 | } | 778 | } |
| 776 | 779 | ||
| 777 | for (comp.link_inputs) |link_input| switch (link_input) { | 780 | for (comp.link_inputs) |link_input| switch (link_input) { |
| 778 | .object, .archive, .dso_exact => continue, // handled above | 781 | .object, .archive => continue, // handled above |
| 779 | .res => unreachable, // windows only | 782 | .res => unreachable, // windows only |
| 780 | .dso => |dso| { | 783 | .dso => |dso| { |
| 784 | try argv.ensureUnusedCapacity(2); | ||
| 781 | if (dso.needed) { | 785 | if (dso.needed) { |
| 782 | try argv.appendSlice(&.{ "-needed-l", try dso.path.toString(arena) }); | 786 | argv.appendAssumeCapacity("-needed-l"); |
| 783 | } else if (dso.weak) { | 787 | } else if (dso.weak) { |
| 784 | try argv.appendSlice(&.{ "-weak-l", try dso.path.toString(arena) }); | 788 | argv.appendAssumeCapacity("-weak-l"); |
| 789 | } else { | ||
| 790 | argv.appendAssumeCapacity("-l"); | ||
| 791 | } | ||
| 792 | if (dso.exact_name) |exact_name| { | ||
| 793 | argv.appendAssumeCapacity(try arena.print(":{s}", .{exact_name})); | ||
| 785 | } else { | 794 | } else { |
| 786 | try argv.appendSlice(&.{ "-l", try dso.path.toString(arena) }); | 795 | argv.appendAssumeCapacity(try dso.path.toString(arena)); |
| 787 | } | 796 | } |
| 788 | }, | 797 | }, |
| 789 | }; | 798 | }; |
| ... | @@ -870,7 +879,7 @@ pub fn classifyInputFile(self: *MachO, input: link.Input) !void { | ... | @@ -870,7 +879,7 @@ pub fn classifyInputFile(self: *MachO, input: link.Input) !void { |
| 870 | const comp = self.base.comp; | 879 | const comp = self.base.comp; |
| 871 | const io = comp.io; | 880 | const io = comp.io; |
| 872 | 881 | ||
| 873 | const path, const file = input.pathAndFile().?; | 882 | const path, const file = input.pathAndFile(); |
| 874 | // TODO don't classify now, it's too late. The input file has already been classified | 883 | // TODO don't classify now, it's too late. The input file has already been classified |
| 875 | log.debug("classifying input file {f}", .{path}); | 884 | log.debug("classifying input file {f}", .{path}); |
| 876 | 885 | ||
| ... | @@ -4478,7 +4487,6 @@ const SystemLib = struct { | ... | @@ -4478,7 +4487,6 @@ const SystemLib = struct { |
| 4478 | 4487 | ||
| 4479 | fn fromLinkInput(link_input: link.Input) SystemLib { | 4488 | fn fromLinkInput(link_input: link.Input) SystemLib { |
| 4480 | return switch (link_input) { | 4489 | return switch (link_input) { |
| 4481 | .dso_exact => unreachable, | ||
| 4482 | .res => unreachable, | 4490 | .res => unreachable, |
| 4483 | .object, .archive => |obj| .{ | 4491 | .object, .archive => |obj| .{ |
| 4484 | .path = obj.path, | 4492 | .path = obj.path, |
src/link/MachO/relocatable.zig+3-3| ... | @@ -19,7 +19,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat | ... | @@ -19,7 +19,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat |
| 19 | // Instead of invoking a full-blown `-r` mode on the input which sadly will strip all | 19 | // Instead of invoking a full-blown `-r` mode on the input which sadly will strip all |
| 20 | // debug info segments/sections (this is apparently by design by Apple), we copy | 20 | // debug info segments/sections (this is apparently by design by Apple), we copy |
| 21 | // the *only* input file over. | 21 | // the *only* input file over. |
| 22 | const path = positionals.items[0].path().?; | 22 | const path = positionals.items[0].path(); |
| 23 | const in_file = path.root_dir.handle.openFile(io, path.sub_path, .{}) catch |err| | 23 | const in_file = path.root_dir.handle.openFile(io, path.sub_path, .{}) catch |err| |
| 24 | return diags.fail("failed to open {f}: {s}", .{ path, @errorName(err) }); | 24 | return diags.fail("failed to open {f}: {s}", .{ path, @errorName(err) }); |
| 25 | const stat = in_file.stat(io) catch |err| | 25 | const stat = in_file.stat(io) catch |err| |
| ... | @@ -31,7 +31,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat | ... | @@ -31,7 +31,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat |
| 31 | 31 | ||
| 32 | for (positionals.items) |link_input| { | 32 | for (positionals.items) |link_input| { |
| 33 | macho_file.classifyInputFile(link_input) catch |err| | 33 | macho_file.classifyInputFile(link_input) catch |err| |
| 34 | diags.addParseError(link_input.path().?, "failed to read input file: {s}", .{@errorName(err)}); | 34 | diags.addParseError(link_input.path(), "failed to read input file: {t}", .{err}); |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | if (diags.hasErrors()) return error.AlreadyReported; | 37 | if (diags.hasErrors()) return error.AlreadyReported; |
| ... | @@ -102,7 +102,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? | ... | @@ -102,7 +102,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? |
| 102 | 102 | ||
| 103 | for (positionals.items) |link_input| { | 103 | for (positionals.items) |link_input| { |
| 104 | macho_file.classifyInputFile(link_input) catch |err| | 104 | macho_file.classifyInputFile(link_input) catch |err| |
| 105 | diags.addParseError(link_input.path().?, "failed to read input file: {s}", .{@errorName(err)}); | 105 | diags.addParseError(link_input.path(), "failed to read input file: {t}", .{err}); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | if (diags.hasErrors()) return error.AlreadyReported; | 108 | if (diags.hasErrors()) return error.AlreadyReported; |
src/link/Wasm.zig-2| ... | @@ -3788,7 +3788,6 @@ pub fn loadInput(wasm: *Wasm, input: link.Input) !void { | ... | @@ -3788,7 +3788,6 @@ pub fn loadInput(wasm: *Wasm, input: link.Input) !void { |
| 3788 | const argv = &wasm.dump_argv_list; | 3788 | const argv = &wasm.dump_argv_list; |
| 3789 | switch (input) { | 3789 | switch (input) { |
| 3790 | .res => unreachable, | 3790 | .res => unreachable, |
| 3791 | .dso_exact => unreachable, | ||
| 3792 | .dso => unreachable, | 3791 | .dso => unreachable, |
| 3793 | .object, .archive => |obj| { | 3792 | .object, .archive => |obj| { |
| 3794 | try argv.append(gpa, try obj.path.toString(comp.arena)); | 3793 | try argv.append(gpa, try obj.path.toString(comp.arena)); |
| ... | @@ -3798,7 +3797,6 @@ pub fn loadInput(wasm: *Wasm, input: link.Input) !void { | ... | @@ -3798,7 +3797,6 @@ pub fn loadInput(wasm: *Wasm, input: link.Input) !void { |
| 3798 | 3797 | ||
| 3799 | switch (input) { | 3798 | switch (input) { |
| 3800 | .res => unreachable, | 3799 | .res => unreachable, |
| 3801 | .dso_exact => unreachable, | ||
| 3802 | .dso => unreachable, | 3800 | .dso => unreachable, |
| 3803 | .object => |obj| try parseObject(wasm, obj), | 3801 | .object => |obj| try parseObject(wasm, obj), |
| 3804 | .archive => |obj| try parseArchive(wasm, obj), | 3802 | .archive => |obj| try parseArchive(wasm, obj), |
src/main.zig+2-2| ... | @@ -4277,10 +4277,10 @@ fn createModule( | ... | @@ -4277,10 +4277,10 @@ fn createModule( |
| 4277 | &create_module.link_inputs, | 4277 | &create_module.link_inputs, |
| 4278 | create_module.lib_directories.items, | 4278 | create_module.lib_directories.items, |
| 4279 | color, | 4279 | color, |
| 4280 | ) catch |err| fatal("failed to resolve link inputs: {s}", .{@errorName(err)}); | 4280 | ) catch |err| fatal("failed to resolve link inputs: {t}", .{err}); |
| 4281 | 4281 | ||
| 4282 | if (!create_module.opts.any_dyn_libs) for (create_module.link_inputs.items) |item| switch (item) { | 4282 | if (!create_module.opts.any_dyn_libs) for (create_module.link_inputs.items) |item| switch (item) { |
| 4283 | .dso, .dso_exact => { | 4283 | .dso => { |
| 4284 | create_module.opts.any_dyn_libs = true; | 4284 | create_module.opts.any_dyn_libs = true; |
| 4285 | break; | 4285 | break; |
| 4286 | }, | 4286 | }, |