| ... | ... | @@ -712,6 +712,14 @@ fn buildOutputType( |
| 712 | 712 | var link_objects = std.ArrayList(Compilation.LinkObject).init(gpa); |
| 713 | 713 | defer link_objects.deinit(); |
| 714 | 714 | |
| 715 | // This map is a flag per link_objects item, used to represent the |
| 716 | // `-l :file.so` syntax from gcc/clang. |
| 717 | // This is only exposed from the `zig cc` interface. It means that the `path` |
| 718 | // field from the corresponding `link_objects` element is a suffix, and is |
| 719 | // to be tried against each library path as a prefix until an existing file is found. |
| 720 | // This map remains empty for the main CLI. |
| 721 | var link_objects_lib_search_paths: std.AutoHashMapUnmanaged(u32, void) = .{}; |
| 722 | |
| 715 | 723 | var framework_dirs = std.ArrayList([]const u8).init(gpa); |
| 716 | 724 | defer framework_dirs.deinit(); |
| 717 | 725 | |
| ... | ... | @@ -1338,7 +1346,16 @@ fn buildOutputType( |
| 1338 | 1346 | // -l |
| 1339 | 1347 | // We don't know whether this library is part of libc or libc++ until |
| 1340 | 1348 | // we resolve the target, so we simply append to the list for now. |
| 1341 | | if (force_static_libs) { |
| 1349 | if (mem.startsWith(u8, it.only_arg, ":")) { |
| 1350 | // This "feature" of gcc/clang means to treat this as a positional |
| 1351 | // link object, but using the library search directories as a prefix. |
| 1352 | try link_objects.append(.{ |
| 1353 | .path = it.only_arg[1..], |
| 1354 | .must_link = must_link, |
| 1355 | }); |
| 1356 | const index = @intCast(u32, link_objects.items.len - 1); |
| 1357 | try link_objects_lib_search_paths.put(arena, index, {}); |
| 1358 | } else if (force_static_libs) { |
| 1342 | 1359 | try static_libs.append(it.only_arg); |
| 1343 | 1360 | } else { |
| 1344 | 1361 | try system_libs.put(it.only_arg, .{ .needed = needed }); |
| ... | ... | @@ -2137,6 +2154,30 @@ fn buildOutputType( |
| 2137 | 2154 | } |
| 2138 | 2155 | } |
| 2139 | 2156 | |
| 2157 | // Resolve `-l :file.so` syntax from `zig cc`. We use a separate map for this data |
| 2158 | // since this is an uncommon case. |
| 2159 | { |
| 2160 | var it = link_objects_lib_search_paths.iterator(); |
| 2161 | while (it.next()) |item| { |
| 2162 | const link_object_i = item.key_ptr.*; |
| 2163 | const suffix = link_objects.items[link_object_i].path; |
| 2164 | |
| 2165 | for (lib_dirs.items) |lib_dir_path| { |
| 2166 | const test_path = try fs.path.join(arena, &.{ lib_dir_path, suffix }); |
| 2167 | fs.cwd().access(test_path, .{}) catch |err| switch (err) { |
| 2168 | error.FileNotFound => continue, |
| 2169 | else => |e| fatal("unable to search for library '{s}': {s}", .{ |
| 2170 | test_path, @errorName(e), |
| 2171 | }), |
| 2172 | }; |
| 2173 | link_objects.items[link_object_i].path = test_path; |
| 2174 | break; |
| 2175 | } else { |
| 2176 | fatal("library '{s}' not found", .{suffix}); |
| 2177 | } |
| 2178 | } |
| 2179 | } |
| 2180 | |
| 2140 | 2181 | const object_format: std.Target.ObjectFormat = blk: { |
| 2141 | 2182 | const ofmt = target_ofmt orelse break :blk target_info.target.getObjectFormat(); |
| 2142 | 2183 | if (mem.eql(u8, ofmt, "elf")) { |