| ... | @@ -679,10 +679,20 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { | ... | @@ -679,10 +679,20 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 679 | // the relocatable object files. | 679 | // the relocatable object files. |
| 680 | self.invalidate_relocs = true; | 680 | self.invalidate_relocs = true; |
| 681 | | 681 | |
| | 682 | // Unpack must-link archives |
| | 683 | var must_link_archives = std.StringArrayHashMap(void).init(arena); |
| | 684 | try must_link_archives.ensureTotalCapacity(@intCast(u32, self.base.options.must_link_objects.len)); |
| | 685 | for (self.base.options.must_link_objects) |lib| { |
| | 686 | _ = must_link_archives.getOrPutAssumeCapacity(lib); |
| | 687 | } |
| | 688 | |
| 682 | // Positional arguments to the linker such as object files and static archives. | 689 | // Positional arguments to the linker such as object files and static archives. |
| 683 | var positionals = std.ArrayList([]const u8).init(arena); | 690 | var positionals = std.ArrayList([]const u8).init(arena); |
| 684 | | 691 | try positionals.ensureUnusedCapacity(self.base.options.objects.len); |
| 685 | try positionals.appendSlice(self.base.options.objects); | 692 | for (self.base.options.objects) |obj| { |
| | 693 | if (must_link_archives.contains(obj)) continue; |
| | 694 | _ = positionals.appendAssumeCapacity(obj); |
| | 695 | } |
| 686 | | 696 | |
| 687 | for (comp.c_object_table.keys()) |key| { | 697 | for (comp.c_object_table.keys()) |key| { |
| 688 | try positionals.append(key.status.success.object_path); | 698 | try positionals.append(key.status.success.object_path); |
| ... | @@ -889,12 +899,17 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { | ... | @@ -889,12 +899,17 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 889 | try argv.append("dynamic_lookup"); | 899 | try argv.append("dynamic_lookup"); |
| 890 | } | 900 | } |
| 891 | | 901 | |
| | 902 | for (self.base.options.must_link_objects) |lib| { |
| | 903 | try argv.append(try std.fmt.allocPrint(arena, "-force_load {s}", .{lib})); |
| | 904 | } |
| | 905 | |
| 892 | Compilation.dump_argv(argv.items); | 906 | Compilation.dump_argv(argv.items); |
| 893 | } | 907 | } |
| 894 | | 908 | |
| 895 | var dependent_libs = std.fifo.LinearFifo(Dylib.Id, .Dynamic).init(self.base.allocator); | 909 | var dependent_libs = std.fifo.LinearFifo(Dylib.Id, .Dynamic).init(self.base.allocator); |
| 896 | defer dependent_libs.deinit(); | 910 | defer dependent_libs.deinit(); |
| 897 | try self.parseInputFiles(positionals.items, self.base.options.sysroot, &dependent_libs); | 911 | try self.parseInputFiles(positionals.items, self.base.options.sysroot, &dependent_libs); |
| | 912 | try self.parseAndForceLoadStaticArchives(must_link_archives.keys()); |
| 898 | try self.parseLibs(libs.items, self.base.options.sysroot, &dependent_libs); | 913 | try self.parseLibs(libs.items, self.base.options.sysroot, &dependent_libs); |
| 899 | try self.parseDependentLibs(self.base.options.sysroot, &dependent_libs); | 914 | try self.parseDependentLibs(self.base.options.sysroot, &dependent_libs); |
| 900 | } | 915 | } |
| ... | @@ -1203,7 +1218,7 @@ fn parseObject(self: *MachO, path: []const u8) !bool { | ... | @@ -1203,7 +1218,7 @@ fn parseObject(self: *MachO, path: []const u8) !bool { |
| 1203 | return true; | 1218 | return true; |
| 1204 | } | 1219 | } |
| 1205 | | 1220 | |
| 1206 | fn parseArchive(self: *MachO, path: []const u8) !bool { | 1221 | fn parseArchive(self: *MachO, path: []const u8, force_load: bool) !bool { |
| 1207 | const file = fs.cwd().openFile(path, .{}) catch |err| switch (err) { | 1222 | const file = fs.cwd().openFile(path, .{}) catch |err| switch (err) { |
| 1208 | error.FileNotFound => return false, | 1223 | error.FileNotFound => return false, |
| 1209 | else => |e| return e, | 1224 | else => |e| return e, |
| ... | @@ -1226,7 +1241,23 @@ fn parseArchive(self: *MachO, path: []const u8) !bool { | ... | @@ -1226,7 +1241,23 @@ fn parseArchive(self: *MachO, path: []const u8) !bool { |
| 1226 | else => |e| return e, | 1241 | else => |e| return e, |
| 1227 | }; | 1242 | }; |
| 1228 | | 1243 | |
| 1229 | try self.archives.append(self.base.allocator, archive); | 1244 | if (force_load) { |
| | 1245 | defer archive.deinit(self.base.allocator); |
| | 1246 | // Get all offsets from the ToC |
| | 1247 | var offsets = std.AutoArrayHashMap(u32, void).init(self.base.allocator); |
| | 1248 | defer offsets.deinit(); |
| | 1249 | for (archive.toc.values()) |offs| { |
| | 1250 | for (offs.items) |off| { |
| | 1251 | _ = try offsets.getOrPut(off); |
| | 1252 | } |
| | 1253 | } |
| | 1254 | for (offsets.keys()) |off| { |
| | 1255 | const object = try self.objects.addOne(self.base.allocator); |
| | 1256 | object.* = try archive.parseObject(self.base.allocator, self.base.options.target, off); |
| | 1257 | } |
| | 1258 | } else { |
| | 1259 | try self.archives.append(self.base.allocator, archive); |
| | 1260 | } |
| 1230 | | 1261 | |
| 1231 | return true; | 1262 | return true; |
| 1232 | } | 1263 | } |
| ... | @@ -1311,7 +1342,7 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const | ... | @@ -1311,7 +1342,7 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const |
| 1311 | log.debug("parsing input file path '{s}'", .{full_path}); | 1342 | log.debug("parsing input file path '{s}'", .{full_path}); |
| 1312 | | 1343 | |
| 1313 | if (try self.parseObject(full_path)) continue; | 1344 | if (try self.parseObject(full_path)) continue; |
| 1314 | if (try self.parseArchive(full_path)) continue; | 1345 | if (try self.parseArchive(full_path, false)) continue; |
| 1315 | if (try self.parseDylib(full_path, .{ | 1346 | if (try self.parseDylib(full_path, .{ |
| 1316 | .syslibroot = syslibroot, | 1347 | .syslibroot = syslibroot, |
| 1317 | .dependent_libs = dependent_libs, | 1348 | .dependent_libs = dependent_libs, |
| ... | @@ -1321,6 +1352,21 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const | ... | @@ -1321,6 +1352,21 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const |
| 1321 | } | 1352 | } |
| 1322 | } | 1353 | } |
| 1323 | | 1354 | |
| | 1355 | fn parseAndForceLoadStaticArchives(self: *MachO, files: []const []const u8) !void { |
| | 1356 | for (files) |file_name| { |
| | 1357 | const full_path = full_path: { |
| | 1358 | var buffer: [fs.MAX_PATH_BYTES]u8 = undefined; |
| | 1359 | const path = try fs.realpath(file_name, &buffer); |
| | 1360 | break :full_path try self.base.allocator.dupe(u8, path); |
| | 1361 | }; |
| | 1362 | defer self.base.allocator.free(full_path); |
| | 1363 | log.debug("parsing and force loading static archive '{s}'", .{full_path}); |
| | 1364 | |
| | 1365 | if (try self.parseArchive(full_path, true)) continue; |
| | 1366 | log.warn("unknown filetype: expected static archive: '{s}'", .{file_name}); |
| | 1367 | } |
| | 1368 | } |
| | 1369 | |
| 1324 | fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8, dependent_libs: anytype) !void { | 1370 | fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8, dependent_libs: anytype) !void { |
| 1325 | for (libs) |lib| { | 1371 | for (libs) |lib| { |
| 1326 | log.debug("parsing lib path '{s}'", .{lib}); | 1372 | log.debug("parsing lib path '{s}'", .{lib}); |
| ... | @@ -1328,7 +1374,7 @@ fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8, de | ... | @@ -1328,7 +1374,7 @@ fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8, de |
| 1328 | .syslibroot = syslibroot, | 1374 | .syslibroot = syslibroot, |
| 1329 | .dependent_libs = dependent_libs, | 1375 | .dependent_libs = dependent_libs, |
| 1330 | })) continue; | 1376 | })) continue; |
| 1331 | if (try self.parseArchive(lib)) continue; | 1377 | if (try self.parseArchive(lib, false)) continue; |
| 1332 | | 1378 | |
| 1333 | log.warn("unknown filetype for a library: '{s}'", .{lib}); | 1379 | log.warn("unknown filetype for a library: '{s}'", .{lib}); |
| 1334 | } | 1380 | } |