| ... | ... | @@ -25,6 +25,7 @@ const lldMain = @import("main.zig").lldMain; |
| 25 | 25 | const Package = @import("Package.zig"); |
| 26 | 26 | const dev = @import("dev.zig"); |
| 27 | 27 | const ThreadSafeQueue = @import("ThreadSafeQueue.zig").ThreadSafeQueue; |
| 28 | const target_util = @import("target.zig"); |
| 28 | 29 | |
| 29 | 30 | pub const LdScript = @import("link/LdScript.zig"); |
| 30 | 31 | |
| ... | ... | @@ -1364,6 +1365,10 @@ pub const File = struct { |
| 1364 | 1365 | /// Loads the objects, shared objects, and archives that are already |
| 1365 | 1366 | /// known from the command line. |
| 1366 | 1367 | load_explicitly_provided, |
| 1368 | /// Loads the shared objects and archives by resolving |
| 1369 | /// `target_util.libcFullLinkFlags()` against the host libc |
| 1370 | /// installation. |
| 1371 | load_host_libc, |
| 1367 | 1372 | /// Tells the linker to load an object file by path. |
| 1368 | 1373 | load_object: Path, |
| 1369 | 1374 | /// Tells the linker to load a static library by path. |
| ... | ... | @@ -1393,6 +1398,45 @@ pub const File = struct { |
| 1393 | 1398 | }; |
| 1394 | 1399 | } |
| 1395 | 1400 | }, |
| 1401 | .load_host_libc => { |
| 1402 | const target = comp.root_mod.resolved_target.result; |
| 1403 | const flags = target_util.libcFullLinkFlags(target); |
| 1404 | const crt_dir = comp.libc_installation.?.crt_dir.?; |
| 1405 | const sep = std.fs.path.sep_str; |
| 1406 | const diags = &comp.link_diags; |
| 1407 | for (flags) |flag| { |
| 1408 | assert(mem.startsWith(u8, flag, "-l")); |
| 1409 | const lib_name = flag["-l".len..]; |
| 1410 | switch (comp.config.link_mode) { |
| 1411 | .dynamic => d: { |
| 1412 | const path = Path.initCwd( |
| 1413 | std.fmt.allocPrint(comp.arena, "{s}" ++ sep ++ "{s}{s}{s}", .{ |
| 1414 | crt_dir, target.libPrefix(), lib_name, target.dynamicLibSuffix(), |
| 1415 | }) catch return diags.setAllocFailure(), |
| 1416 | ); |
| 1417 | base.openLoadDso(path, .{ |
| 1418 | .preferred_mode = .dynamic, |
| 1419 | .search_strategy = .paths_first, |
| 1420 | }) catch |err| switch (err) { |
| 1421 | error.FileNotFound => break :d, // also try static |
| 1422 | error.LinkFailure => return, // error reported via diags |
| 1423 | else => |e| diags.addParseError(path, "failed to parse shared library: {s}", .{@errorName(e)}), |
| 1424 | }; |
| 1425 | continue; |
| 1426 | }, |
| 1427 | .static => {}, |
| 1428 | } |
| 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 | } |
| 1439 | }, |
| 1396 | 1440 | .load_object => |path| { |
| 1397 | 1441 | base.openLoadObject(path) catch |err| switch (err) { |
| 1398 | 1442 | error.LinkFailure => return, // error reported via link_diags |
| ... | ... | @@ -1873,7 +1917,7 @@ pub fn resolveInputs( |
| 1873 | 1917 | } |
| 1874 | 1918 | } |
| 1875 | 1919 | |
| 1876 | | const AccessLibPathResult = enum { ok, no_match }; |
| 1920 | const ResolveLibInputResult = enum { ok, no_match }; |
| 1877 | 1921 | const fatal = std.process.fatal; |
| 1878 | 1922 | |
| 1879 | 1923 | fn resolveLibInput( |
| ... | ... | @@ -1892,7 +1936,7 @@ fn resolveLibInput( |
| 1892 | 1936 | target: std.Target, |
| 1893 | 1937 | link_mode: std.builtin.LinkMode, |
| 1894 | 1938 | color: std.zig.Color, |
| 1895 | | ) Allocator.Error!AccessLibPathResult { |
| 1939 | ) Allocator.Error!ResolveLibInputResult { |
| 1896 | 1940 | try resolved_inputs.ensureUnusedCapacity(gpa, 1); |
| 1897 | 1941 | |
| 1898 | 1942 | const lib_name = name_query.name; |
| ... | ... | @@ -1909,7 +1953,7 @@ fn resolveLibInput( |
| 1909 | 1953 | else => |e| fatal("unable to search for tbd library '{}': {s}", .{ test_path, @errorName(e) }), |
| 1910 | 1954 | }; |
| 1911 | 1955 | errdefer file.close(); |
| 1912 | | return finishAccessLibPath(resolved_inputs, test_path, file, link_mode, name_query.query); |
| 1956 | return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query); |
| 1913 | 1957 | } |
| 1914 | 1958 | |
| 1915 | 1959 | { |
| ... | ... | @@ -1947,7 +1991,7 @@ fn resolveLibInput( |
| 1947 | 1991 | }), |
| 1948 | 1992 | }; |
| 1949 | 1993 | errdefer file.close(); |
| 1950 | | return finishAccessLibPath(resolved_inputs, test_path, file, link_mode, name_query.query); |
| 1994 | return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query); |
| 1951 | 1995 | } |
| 1952 | 1996 | |
| 1953 | 1997 | // In the case of MinGW, the main check will be .lib but we also need to |
| ... | ... | @@ -1963,19 +2007,19 @@ fn resolveLibInput( |
| 1963 | 2007 | else => |e| fatal("unable to search for static library '{}': {s}", .{ test_path, @errorName(e) }), |
| 1964 | 2008 | }; |
| 1965 | 2009 | errdefer file.close(); |
| 1966 | | return finishAccessLibPath(resolved_inputs, test_path, file, link_mode, name_query.query); |
| 2010 | return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query); |
| 1967 | 2011 | } |
| 1968 | 2012 | |
| 1969 | 2013 | return .no_match; |
| 1970 | 2014 | } |
| 1971 | 2015 | |
| 1972 | | fn finishAccessLibPath( |
| 2016 | fn finishResolveLibInput( |
| 1973 | 2017 | resolved_inputs: *std.ArrayListUnmanaged(Input), |
| 1974 | 2018 | path: Path, |
| 1975 | 2019 | file: std.fs.File, |
| 1976 | 2020 | link_mode: std.builtin.LinkMode, |
| 1977 | 2021 | query: UnresolvedInput.Query, |
| 1978 | | ) AccessLibPathResult { |
| 2022 | ) ResolveLibInputResult { |
| 1979 | 2023 | switch (link_mode) { |
| 1980 | 2024 | .static => resolved_inputs.appendAssumeCapacity(.{ .archive = .{ |
| 1981 | 2025 | .path = path, |
| ... | ... | @@ -2052,7 +2096,7 @@ fn resolvePathInputLib( |
| 2052 | 2096 | pq: UnresolvedInput.PathQuery, |
| 2053 | 2097 | link_mode: std.builtin.LinkMode, |
| 2054 | 2098 | color: std.zig.Color, |
| 2055 | | ) Allocator.Error!AccessLibPathResult { |
| 2099 | ) Allocator.Error!ResolveLibInputResult { |
| 2056 | 2100 | try resolved_inputs.ensureUnusedCapacity(gpa, 1); |
| 2057 | 2101 | |
| 2058 | 2102 | const test_path: Path = pq.path; |
| ... | ... | @@ -2074,7 +2118,7 @@ fn resolvePathInputLib( |
| 2074 | 2118 | if (n != ld_script_bytes.items.len) break :elf_file; |
| 2075 | 2119 | if (!mem.eql(u8, ld_script_bytes.items[0..4], "\x7fELF")) break :elf_file; |
| 2076 | 2120 | // Appears to be an ELF file. |
| 2077 | | return finishAccessLibPath(resolved_inputs, test_path, file, link_mode, pq.query); |
| 2121 | return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query); |
| 2078 | 2122 | } |
| 2079 | 2123 | const stat = file.stat() catch |err| |
| 2080 | 2124 | fatal("failed to stat {}: {s}", .{ test_path, @errorName(err) }); |
| ... | ... | @@ -2140,7 +2184,7 @@ fn resolvePathInputLib( |
| 2140 | 2184 | }), |
| 2141 | 2185 | }; |
| 2142 | 2186 | errdefer file.close(); |
| 2143 | | return finishAccessLibPath(resolved_inputs, test_path, file, link_mode, pq.query); |
| 2187 | return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query); |
| 2144 | 2188 | } |
| 2145 | 2189 | |
| 2146 | 2190 | pub fn openObject(path: Path, must_link: bool, hidden: bool) !Input.Object { |