| ... | ... | @@ -1009,11 +1009,25 @@ pub const File = struct { |
| 1009 | 1009 | } |
| 1010 | 1010 | |
| 1011 | 1011 | /// Opens a path as a static library and parses it into the linker. |
| 1012 | | fn openLoadArchive(base: *File, path: Path) anyerror!void { |
| 1013 | | const diags = &base.comp.link_diags; |
| 1014 | | const input = try openArchiveInput(diags, path, false, false); |
| 1015 | | errdefer input.archive.file.close(); |
| 1016 | | try loadInput(base, input); |
| 1012 | /// If `query` is non-null, allows GNU ld scripts. |
| 1013 | fn openLoadArchive(base: *File, path: Path, opt_query: ?UnresolvedInput.Query) anyerror!void { |
| 1014 | if (opt_query) |query| { |
| 1015 | const archive = try openObject(path, query.must_link, query.hidden); |
| 1016 | errdefer archive.file.close(); |
| 1017 | loadInput(base, .{ .archive = archive }) catch |err| switch (err) { |
| 1018 | error.BadMagic, error.UnexpectedEndOfFile => { |
| 1019 | if (base.tag != .elf) return err; |
| 1020 | try loadGnuLdScript(base, path, query, archive.file); |
| 1021 | archive.file.close(); |
| 1022 | return; |
| 1023 | }, |
| 1024 | else => return err, |
| 1025 | }; |
| 1026 | } else { |
| 1027 | const archive = try openObject(path, false, false); |
| 1028 | errdefer archive.file.close(); |
| 1029 | try loadInput(base, .{ .archive = archive }); |
| 1030 | } |
| 1017 | 1031 | } |
| 1018 | 1032 | |
| 1019 | 1033 | /// Opens a path as a shared library and parses it into the linker. |
| ... | ... | @@ -1060,7 +1074,7 @@ pub const File = struct { |
| 1060 | 1074 | switch (Compilation.classifyFileExt(arg.path)) { |
| 1061 | 1075 | .shared_library => try openLoadDso(base, new_path, query), |
| 1062 | 1076 | .object => try openLoadObject(base, new_path), |
| 1063 | | .static_library => try openLoadArchive(base, new_path), |
| 1077 | .static_library => try openLoadArchive(base, new_path, query), |
| 1064 | 1078 | else => diags.addParseError(path, "GNU ld script references file with unrecognized extension: {s}", .{arg.path}), |
| 1065 | 1079 | } |
| 1066 | 1080 | } else { |
| ... | ... | @@ -1408,33 +1422,51 @@ pub const File = struct { |
| 1408 | 1422 | assert(mem.startsWith(u8, flag, "-l")); |
| 1409 | 1423 | const lib_name = flag["-l".len..]; |
| 1410 | 1424 | switch (comp.config.link_mode) { |
| 1411 | | .dynamic => d: { |
| 1412 | | const path = Path.initCwd( |
| 1425 | .dynamic => { |
| 1426 | const dso_path = Path.initCwd( |
| 1413 | 1427 | std.fmt.allocPrint(comp.arena, "{s}" ++ sep ++ "{s}{s}{s}", .{ |
| 1414 | 1428 | crt_dir, target.libPrefix(), lib_name, target.dynamicLibSuffix(), |
| 1415 | 1429 | }) catch return diags.setAllocFailure(), |
| 1416 | 1430 | ); |
| 1417 | | base.openLoadDso(path, .{ |
| 1431 | base.openLoadDso(dso_path, .{ |
| 1418 | 1432 | .preferred_mode = .dynamic, |
| 1419 | 1433 | .search_strategy = .paths_first, |
| 1420 | 1434 | }) catch |err| switch (err) { |
| 1421 | | error.FileNotFound => break :d, // also try static |
| 1435 | error.FileNotFound => { |
| 1436 | // Also try static. |
| 1437 | const archive_path = Path.initCwd( |
| 1438 | std.fmt.allocPrint(comp.arena, "{s}" ++ sep ++ "{s}{s}{s}", .{ |
| 1439 | crt_dir, target.libPrefix(), lib_name, target.staticLibSuffix(), |
| 1440 | }) catch return diags.setAllocFailure(), |
| 1441 | ); |
| 1442 | base.openLoadArchive(archive_path, .{ |
| 1443 | .preferred_mode = .dynamic, |
| 1444 | .search_strategy = .paths_first, |
| 1445 | }) catch |archive_err| switch (archive_err) { |
| 1446 | error.LinkFailure => return, // error reported via diags |
| 1447 | else => |e| diags.addParseError(dso_path, "failed to parse archive {}: {s}", .{ archive_path, @errorName(e) }), |
| 1448 | }; |
| 1449 | }, |
| 1450 | error.LinkFailure => return, // error reported via diags |
| 1451 | else => |e| diags.addParseError(dso_path, "failed to parse shared library: {s}", .{@errorName(e)}), |
| 1452 | }; |
| 1453 | }, |
| 1454 | .static => { |
| 1455 | const path = Path.initCwd( |
| 1456 | std.fmt.allocPrint(comp.arena, "{s}" ++ sep ++ "{s}{s}{s}", .{ |
| 1457 | crt_dir, target.libPrefix(), lib_name, target.staticLibSuffix(), |
| 1458 | }) catch return diags.setAllocFailure(), |
| 1459 | ); |
| 1460 | // glibc sometimes makes even archive files GNU ld scripts. |
| 1461 | base.openLoadArchive(path, .{ |
| 1462 | .preferred_mode = .static, |
| 1463 | .search_strategy = .no_fallback, |
| 1464 | }) catch |err| switch (err) { |
| 1422 | 1465 | error.LinkFailure => return, // error reported via diags |
| 1423 | | else => |e| diags.addParseError(path, "failed to parse shared library: {s}", .{@errorName(e)}), |
| 1466 | else => |e| diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(e)}), |
| 1424 | 1467 | }; |
| 1425 | | continue; |
| 1426 | 1468 | }, |
| 1427 | | .static => {}, |
| 1428 | 1469 | } |
| 1429 | | const path = Path.initCwd( |
| 1430 | | std.fmt.allocPrint(comp.arena, "{s}" ++ sep ++ "{s}{s}{s}", .{ |
| 1431 | | crt_dir, target.libPrefix(), lib_name, target.staticLibSuffix(), |
| 1432 | | }) catch return diags.setAllocFailure(), |
| 1433 | | ); |
| 1434 | | base.openLoadArchive(path) catch |err| switch (err) { |
| 1435 | | error.LinkFailure => return, // error reported via diags |
| 1436 | | else => |e| diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(e)}), |
| 1437 | | }; |
| 1438 | 1470 | } |
| 1439 | 1471 | }, |
| 1440 | 1472 | .load_object => |path| { |
| ... | ... | @@ -1444,7 +1476,7 @@ pub const File = struct { |
| 1444 | 1476 | }; |
| 1445 | 1477 | }, |
| 1446 | 1478 | .load_archive => |path| { |
| 1447 | | base.openLoadArchive(path) catch |err| switch (err) { |
| 1479 | base.openLoadArchive(path, null) catch |err| switch (err) { |
| 1448 | 1480 | error.LinkFailure => return, // error reported via link_diags |
| 1449 | 1481 | else => |e| comp.link_diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(e)}), |
| 1450 | 1482 | }; |