authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-10-23 22:39:57-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-10-23 22:39:57-04:00
log794dc694b140908a9affc5b449cda09bbe971cfe
treeb654e9bfafeb399e8e3355a523b22e7d40f29660
parenta07f288eb1772ac25fd0785b142c6ee7e09b2986
parent2bb713ca1cc66b7c56b2d7a4187095da91be8738
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #17686 from ziglang/elf-non-nixos

elf: fix linking against system libc libs

1 files changed, 46 insertions(+), 48 deletions(-)

src/link/Elf.zig+46-48
......@@ -1318,15 +1318,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
13181318 defer test_path.deinit();
13191319 for (self.base.options.lib_dirs) |lib_dir_path| {
13201320 for (self.base.options.system_libs.keys()) |link_lib| {
1321 test_path.clearRetainingCapacity();
1322 const sep = fs.path.sep_str;
1323 try test_path.writer().print("{s}" ++ sep ++ "lib{s}.so", .{
1324 lib_dir_path, link_lib,
1325 });
1326 fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {
1327 error.FileNotFound => continue,
1328 else => |e| return e,
1329 };
1321 if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic)))
1322 continue;
13301323 _ = try rpath_table.put(lib_dir_path, {});
13311324 }
13321325 }
......@@ -1392,11 +1385,33 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
13921385 if (self.base.options.libc_installation) |lc| {
13931386 const flags = target_util.libcFullLinkFlags(target);
13941387 try system_libs.ensureUnusedCapacity(flags.len);
1388
1389 var test_path = std.ArrayList(u8).init(arena);
1390 var checked_paths = std.ArrayList([]const u8).init(arena);
1391
13951392 for (flags) |flag| {
1396 const lib_path = try std.fmt.allocPrint(arena, "{s}{c}lib{s}.so", .{
1397 lc.crt_dir.?, fs.path.sep, flag["-l".len..],
1398 });
1399 system_libs.appendAssumeCapacity(.{ .path = lib_path });
1393 checked_paths.clearRetainingCapacity();
1394 const lib_name = flag["-l".len..];
1395
1396 success: {
1397 if (!self.isStatic()) {
1398 if (try self.accessLibPath(&test_path, &checked_paths, lc.crt_dir.?, lib_name, .Dynamic))
1399 break :success;
1400 }
1401 if (try self.accessLibPath(&test_path, &checked_paths, lc.crt_dir.?, lib_name, .Static))
1402 break :success;
1403
1404 try self.reportMissingLibraryError(
1405 checked_paths.items,
1406 "missing system library: '{s}' was not found",
1407 .{lib_name},
1408 );
1409
1410 continue;
1411 }
1412
1413 const resolved_path = try arena.dupe(u8, test_path.items);
1414 system_libs.appendAssumeCapacity(.{ .path = resolved_path });
14001415 }
14011416 } else if (target.isGnuLibC()) {
14021417 try system_libs.ensureUnusedCapacity(glibc.libs.len + 1);
......@@ -1422,10 +1437,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
14221437
14231438 for (system_libs.items) |lib| {
14241439 var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined };
1425 const in_file = std.fs.cwd().openFile(lib.path, .{}) catch |err| {
1426 try self.handleAndReportParseError(lib.path, err, &parse_ctx);
1427 continue;
1428 };
1440 const in_file = try std.fs.cwd().openFile(lib.path, .{});
14291441 defer in_file.close();
14301442 self.parseLibrary(in_file, lib, false, &parse_ctx) catch |err|
14311443 try self.handleAndReportParseError(lib.path, err, &parse_ctx);
......@@ -1832,15 +1844,6 @@ fn parseLdScript(self: *Elf, in_file: std.fs.File, lib: SystemLib, ctx: *ParseEr
18321844 if (try self.accessLibPath(&test_path, &checked_paths, lib_dir, lib_name, .Static))
18331845 break :success;
18341846 }
1835
1836 try self.reportMissingLibraryError(
1837 checked_paths.items,
1838 "missing library dependency: GNU ld script '{s}' requires '{s}', but file not found",
1839 .{
1840 lib.path,
1841 scr_obj.path,
1842 },
1843 );
18441847 } else {
18451848 var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;
18461849 if (fs.realpath(scr_obj.path, &buffer)) |path| {
......@@ -1854,16 +1857,17 @@ fn parseLdScript(self: *Elf, in_file: std.fs.File, lib: SystemLib, ctx: *ParseEr
18541857 if (try self.accessLibPath(&test_path, &checked_paths, lib_dir, scr_obj.path, null))
18551858 break :success;
18561859 }
1857
1858 try self.reportMissingLibraryError(
1859 checked_paths.items,
1860 "missing library dependency: GNU ld script '{s}' requires '{s}', but file not found",
1861 .{
1862 lib.path,
1863 scr_obj.path,
1864 },
1865 );
18661860 }
1861
1862 try self.reportMissingLibraryError(
1863 checked_paths.items,
1864 "missing library dependency: GNU ld script '{s}' requires '{s}', but file not found",
1865 .{
1866 lib.path,
1867 scr_obj.path,
1868 },
1869 );
1870 continue;
18671871 }
18681872
18691873 const full_path = test_path.items;
......@@ -1881,7 +1885,7 @@ fn parseLdScript(self: *Elf, in_file: std.fs.File, lib: SystemLib, ctx: *ParseEr
18811885fn accessLibPath(
18821886 self: *Elf,
18831887 test_path: *std.ArrayList(u8),
1884 checked_paths: *std.ArrayList([]const u8),
1888 checked_paths: ?*std.ArrayList([]const u8),
18851889 lib_dir_path: []const u8,
18861890 lib_name: []const u8,
18871891 link_mode: ?std.builtin.LinkMode,
......@@ -1898,7 +1902,9 @@ fn accessLibPath(
18981902 .Dynamic => target.dynamicLibSuffix(),
18991903 } else "",
19001904 });
1901 try checked_paths.append(try self.base.allocator.dupe(u8, test_path.items));
1905 if (checked_paths) |cpaths| {
1906 try cpaths.append(try self.base.allocator.dupe(u8, test_path.items));
1907 }
19021908 fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {
19031909 error.FileNotFound => return false,
19041910 else => |e| return e,
......@@ -2532,19 +2538,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
25322538 }
25332539
25342540 if (self.base.options.each_lib_rpath) {
2535 var test_path = std.ArrayList(u8).init(self.base.allocator);
2536 defer test_path.deinit();
2541 var test_path = std.ArrayList(u8).init(arena);
25372542 for (self.base.options.lib_dirs) |lib_dir_path| {
25382543 for (self.base.options.system_libs.keys()) |link_lib| {
2539 test_path.clearRetainingCapacity();
2540 const sep = fs.path.sep_str;
2541 try test_path.writer().print("{s}" ++ sep ++ "lib{s}.so", .{
2542 lib_dir_path, link_lib,
2543 });
2544 fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {
2545 error.FileNotFound => continue,
2546 else => |e| return e,
2547 };
2544 if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic)))
2545 continue;
25482546 if ((try rpath_table.fetchPut(lib_dir_path, {})) == null) {
25492547 try argv.append("-rpath");
25502548 try argv.append(lib_dir_path);