| author | |
| committer | |
| log | 8e6c038dd81fa7eddfdac882aa3b1d5edbdcf329 |
| tree | fa3390a85e0836ad4dcc6420e92965c7317b90c7 |
| parent | f5c0c0803fab4a18d612cc8b8649566463cf5d60 |
| parent | 0c1d610015e04c96508750e95b2f88408ded8843 |
| signature |
zld: resolve frameworks in BFS order and handle additional macOS flags5 files changed, 106 insertions(+), 75 deletions(-)
src/Compilation.zig+2| ... | @@ -758,6 +758,7 @@ pub const InitOptions = struct { | ... | @@ -758,6 +758,7 @@ pub const InitOptions = struct { |
| 758 | image_base_override: ?u64 = null, | 758 | image_base_override: ?u64 = null, |
| 759 | self_exe_path: ?[]const u8 = null, | 759 | self_exe_path: ?[]const u8 = null, |
| 760 | version: ?std.builtin.Version = null, | 760 | version: ?std.builtin.Version = null, |
| 761 | compatibility_version: ?std.builtin.Version = null, | ||
| 761 | libc_installation: ?*const LibCInstallation = null, | 762 | libc_installation: ?*const LibCInstallation = null, |
| 762 | machine_code_model: std.builtin.CodeModel = .default, | 763 | machine_code_model: std.builtin.CodeModel = .default, |
| 763 | clang_preprocessor_mode: ClangPreprocessorMode = .no, | 764 | clang_preprocessor_mode: ClangPreprocessorMode = .no, |
| ... | @@ -1439,6 +1440,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -1439,6 +1440,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1439 | .extra_lld_args = options.lld_argv, | 1440 | .extra_lld_args = options.lld_argv, |
| 1440 | .soname = options.soname, | 1441 | .soname = options.soname, |
| 1441 | .version = options.version, | 1442 | .version = options.version, |
| 1443 | .compatibility_version = options.compatibility_version, | ||
| 1442 | .libc_installation = libc_dirs.libc_installation, | 1444 | .libc_installation = libc_dirs.libc_installation, |
| 1443 | .pic = pic, | 1445 | .pic = pic, |
| 1444 | .pie = pie, | 1446 | .pie = pie, |
src/link.zig+1| ... | @@ -143,6 +143,7 @@ pub const Options = struct { | ... | @@ -143,6 +143,7 @@ pub const Options = struct { |
| 143 | rpath_list: []const []const u8, | 143 | rpath_list: []const []const u8, |
| 144 | 144 | ||
| 145 | version: ?std.builtin.Version, | 145 | version: ?std.builtin.Version, |
| 146 | compatibility_version: ?std.builtin.Version, | ||
| 146 | libc_installation: ?*const LibCInstallation, | 147 | libc_installation: ?*const LibCInstallation, |
| 147 | 148 | ||
| 148 | /// WASI-only. Type of WASI execution model ("command" or "reactor"). | 149 | /// WASI-only. Type of WASI execution model ("command" or "reactor"). |
src/link/MachO.zig+63-13| ... | @@ -842,8 +842,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { | ... | @@ -842,8 +842,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 842 | Compilation.dump_argv(argv.items); | 842 | Compilation.dump_argv(argv.items); |
| 843 | } | 843 | } |
| 844 | 844 | ||
| 845 | try self.parseInputFiles(positionals.items, self.base.options.sysroot); | 845 | var dependent_libs = std.fifo.LinearFifo(Dylib.Id, .Dynamic).init(self.base.allocator); |
| 846 | try self.parseLibs(libs.items, self.base.options.sysroot); | 846 | defer dependent_libs.deinit(); |
| 847 | try self.parseInputFiles(positionals.items, self.base.options.sysroot, &dependent_libs); | ||
| 848 | try self.parseLibs(libs.items, self.base.options.sysroot, &dependent_libs); | ||
| 849 | try self.parseDependentLibs(self.base.options.sysroot, &dependent_libs); | ||
| 847 | } | 850 | } |
| 848 | 851 | ||
| 849 | if (self.bss_section_index) |idx| { | 852 | if (self.bss_section_index) |idx| { |
| ... | @@ -1161,7 +1164,8 @@ const ParseDylibError = error{ | ... | @@ -1161,7 +1164,8 @@ const ParseDylibError = error{ |
| 1161 | } || fs.File.OpenError || std.os.PReadError || Dylib.Id.ParseError; | 1164 | } || fs.File.OpenError || std.os.PReadError || Dylib.Id.ParseError; |
| 1162 | 1165 | ||
| 1163 | const DylibCreateOpts = struct { | 1166 | const DylibCreateOpts = struct { |
| 1164 | syslibroot: ?[]const u8 = null, | 1167 | syslibroot: ?[]const u8, |
| 1168 | dependent_libs: *std.fifo.LinearFifo(Dylib.Id, .Dynamic), | ||
| 1165 | id: ?Dylib.Id = null, | 1169 | id: ?Dylib.Id = null, |
| 1166 | is_dependent: bool = false, | 1170 | is_dependent: bool = false, |
| 1167 | }; | 1171 | }; |
| ... | @@ -1181,7 +1185,7 @@ pub fn parseDylib(self: *MachO, path: []const u8, opts: DylibCreateOpts) ParseDy | ... | @@ -1181,7 +1185,7 @@ pub fn parseDylib(self: *MachO, path: []const u8, opts: DylibCreateOpts) ParseDy |
| 1181 | .file = file, | 1185 | .file = file, |
| 1182 | }; | 1186 | }; |
| 1183 | 1187 | ||
| 1184 | dylib.parse(self.base.allocator, self.base.options.target) catch |err| switch (err) { | 1188 | dylib.parse(self.base.allocator, self.base.options.target, opts.dependent_libs) catch |err| switch (err) { |
| 1185 | error.EndOfStream, error.NotDylib => { | 1189 | error.EndOfStream, error.NotDylib => { |
| 1186 | try file.seekTo(0); | 1190 | try file.seekTo(0); |
| 1187 | 1191 | ||
| ... | @@ -1191,7 +1195,7 @@ pub fn parseDylib(self: *MachO, path: []const u8, opts: DylibCreateOpts) ParseDy | ... | @@ -1191,7 +1195,7 @@ pub fn parseDylib(self: *MachO, path: []const u8, opts: DylibCreateOpts) ParseDy |
| 1191 | }; | 1195 | }; |
| 1192 | defer lib_stub.deinit(); | 1196 | defer lib_stub.deinit(); |
| 1193 | 1197 | ||
| 1194 | try dylib.parseFromStub(self.base.allocator, self.base.options.target, lib_stub); | 1198 | try dylib.parseFromStub(self.base.allocator, self.base.options.target, lib_stub, opts.dependent_libs); |
| 1195 | }, | 1199 | }, |
| 1196 | else => |e| return e, | 1200 | else => |e| return e, |
| 1197 | }; | 1201 | }; |
| ... | @@ -1218,14 +1222,10 @@ pub fn parseDylib(self: *MachO, path: []const u8, opts: DylibCreateOpts) ParseDy | ... | @@ -1218,14 +1222,10 @@ pub fn parseDylib(self: *MachO, path: []const u8, opts: DylibCreateOpts) ParseDy |
| 1218 | try self.referenced_dylibs.putNoClobber(self.base.allocator, dylib_id, {}); | 1222 | try self.referenced_dylibs.putNoClobber(self.base.allocator, dylib_id, {}); |
| 1219 | } | 1223 | } |
| 1220 | 1224 | ||
| 1221 | // TODO this should not be performed if the user specifies `-flat_namespace` flag. | ||
| 1222 | // See ld64 manpages. | ||
| 1223 | try dylib.parseDependentLibs(self, opts.syslibroot); | ||
| 1224 | |||
| 1225 | return true; | 1225 | return true; |
| 1226 | } | 1226 | } |
| 1227 | 1227 | ||
| 1228 | fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const u8) !void { | 1228 | fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const u8, dependent_libs: anytype) !void { |
| 1229 | for (files) |file_name| { | 1229 | for (files) |file_name| { |
| 1230 | const full_path = full_path: { | 1230 | const full_path = full_path: { |
| 1231 | var buffer: [fs.MAX_PATH_BYTES]u8 = undefined; | 1231 | var buffer: [fs.MAX_PATH_BYTES]u8 = undefined; |
| ... | @@ -1239,17 +1239,19 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const | ... | @@ -1239,17 +1239,19 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const |
| 1239 | if (try self.parseArchive(full_path)) continue; | 1239 | if (try self.parseArchive(full_path)) continue; |
| 1240 | if (try self.parseDylib(full_path, .{ | 1240 | if (try self.parseDylib(full_path, .{ |
| 1241 | .syslibroot = syslibroot, | 1241 | .syslibroot = syslibroot, |
| 1242 | .dependent_libs = dependent_libs, | ||
| 1242 | })) continue; | 1243 | })) continue; |
| 1243 | 1244 | ||
| 1244 | log.warn("unknown filetype for positional input file: '{s}'", .{file_name}); | 1245 | log.warn("unknown filetype for positional input file: '{s}'", .{file_name}); |
| 1245 | } | 1246 | } |
| 1246 | } | 1247 | } |
| 1247 | 1248 | ||
| 1248 | fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8) !void { | 1249 | fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8, dependent_libs: anytype) !void { |
| 1249 | for (libs) |lib| { | 1250 | for (libs) |lib| { |
| 1250 | log.debug("parsing lib path '{s}'", .{lib}); | 1251 | log.debug("parsing lib path '{s}'", .{lib}); |
| 1251 | if (try self.parseDylib(lib, .{ | 1252 | if (try self.parseDylib(lib, .{ |
| 1252 | .syslibroot = syslibroot, | 1253 | .syslibroot = syslibroot, |
| 1254 | .dependent_libs = dependent_libs, | ||
| 1253 | })) continue; | 1255 | })) continue; |
| 1254 | if (try self.parseArchive(lib)) continue; | 1256 | if (try self.parseArchive(lib)) continue; |
| 1255 | 1257 | ||
| ... | @@ -1257,6 +1259,50 @@ fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8) !v | ... | @@ -1257,6 +1259,50 @@ fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8) !v |
| 1257 | } | 1259 | } |
| 1258 | } | 1260 | } |
| 1259 | 1261 | ||
| 1262 | fn parseDependentLibs(self: *MachO, syslibroot: ?[]const u8, dependent_libs: anytype) !void { | ||
| 1263 | // At this point, we can now parse dependents of dylibs preserving the inclusion order of: | ||
| 1264 | // 1) anything on the linker line is parsed first | ||
| 1265 | // 2) afterwards, we parse dependents of the included dylibs | ||
| 1266 | // TODO this should not be performed if the user specifies `-flat_namespace` flag. | ||
| 1267 | // See ld64 manpages. | ||
| 1268 | var arena_alloc = std.heap.ArenaAllocator.init(self.base.allocator); | ||
| 1269 | const arena = &arena_alloc.allocator; | ||
| 1270 | defer arena_alloc.deinit(); | ||
| 1271 | |||
| 1272 | while (dependent_libs.readItem()) |*id| { | ||
| 1273 | defer id.deinit(self.base.allocator); | ||
| 1274 | |||
| 1275 | if (self.dylibs_map.contains(id.name)) continue; | ||
| 1276 | |||
| 1277 | const has_ext = blk: { | ||
| 1278 | const basename = fs.path.basename(id.name); | ||
| 1279 | break :blk mem.lastIndexOfScalar(u8, basename, '.') != null; | ||
| 1280 | }; | ||
| 1281 | const extension = if (has_ext) fs.path.extension(id.name) else ""; | ||
| 1282 | const without_ext = if (has_ext) blk: { | ||
| 1283 | const index = mem.lastIndexOfScalar(u8, id.name, '.') orelse unreachable; | ||
| 1284 | break :blk id.name[0..index]; | ||
| 1285 | } else id.name; | ||
| 1286 | |||
| 1287 | for (&[_][]const u8{ extension, ".tbd" }) |ext| { | ||
| 1288 | const with_ext = try std.fmt.allocPrint(arena, "{s}{s}", .{ without_ext, ext }); | ||
| 1289 | const full_path = if (syslibroot) |root| try fs.path.join(arena, &.{ root, with_ext }) else with_ext; | ||
| 1290 | |||
| 1291 | log.debug("trying dependency at fully resolved path {s}", .{full_path}); | ||
| 1292 | |||
| 1293 | const did_parse_successfully = try self.parseDylib(full_path, .{ | ||
| 1294 | .id = id.*, | ||
| 1295 | .syslibroot = syslibroot, | ||
| 1296 | .is_dependent = true, | ||
| 1297 | .dependent_libs = dependent_libs, | ||
| 1298 | }); | ||
| 1299 | if (did_parse_successfully) break; | ||
| 1300 | } else { | ||
| 1301 | log.warn("unable to resolve dependency {s}", .{id.name}); | ||
| 1302 | } | ||
| 1303 | } | ||
| 1304 | } | ||
| 1305 | |||
| 1260 | pub const MatchingSection = struct { | 1306 | pub const MatchingSection = struct { |
| 1261 | seg: u16, | 1307 | seg: u16, |
| 1262 | sect: u16, | 1308 | sect: u16, |
| ... | @@ -3992,12 +4038,16 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -3992,12 +4038,16 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3992 | self.base.options.emit.?.sub_path, | 4038 | self.base.options.emit.?.sub_path, |
| 3993 | }); | 4039 | }); |
| 3994 | defer self.base.allocator.free(install_name); | 4040 | defer self.base.allocator.free(install_name); |
| 4041 | const current_version = self.base.options.version orelse | ||
| 4042 | std.builtin.Version{ .major = 1, .minor = 0, .patch = 0 }; | ||
| 4043 | const compat_version = self.base.options.compatibility_version orelse | ||
| 4044 | std.builtin.Version{ .major = 1, .minor = 0, .patch = 0 }; | ||
| 3995 | var dylib_cmd = try commands.createLoadDylibCommand( | 4045 | var dylib_cmd = try commands.createLoadDylibCommand( |
| 3996 | self.base.allocator, | 4046 | self.base.allocator, |
| 3997 | install_name, | 4047 | install_name, |
| 3998 | 2, | 4048 | 2, |
| 3999 | 0x10000, // TODO forward user-provided versions | 4049 | current_version.major << 16 | current_version.minor << 8 | current_version.patch, |
| 4000 | 0x10000, | 4050 | compat_version.major << 16 | compat_version.minor << 8 | compat_version.patch, |
| 4001 | ); | 4051 | ); |
| 4002 | errdefer dylib_cmd.deinit(self.base.allocator); | 4052 | errdefer dylib_cmd.deinit(self.base.allocator); |
| 4003 | dylib_cmd.inner.cmd = macho.LC_ID_DYLIB; | 4053 | dylib_cmd.inner.cmd = macho.LC_ID_DYLIB; |
src/link/MachO/Dylib.zig+16-62| ... | @@ -38,9 +38,6 @@ id: ?Id = null, | ... | @@ -38,9 +38,6 @@ id: ?Id = null, |
| 38 | /// a symbol is referenced by an object file. | 38 | /// a symbol is referenced by an object file. |
| 39 | symbols: std.StringArrayHashMapUnmanaged(void) = .{}, | 39 | symbols: std.StringArrayHashMapUnmanaged(void) = .{}, |
| 40 | 40 | ||
| 41 | /// Array list of all dependent libs of this dylib. | ||
| 42 | dependent_libs: std.ArrayListUnmanaged(Id) = .{}, | ||
| 43 | |||
| 44 | pub const Id = struct { | 41 | pub const Id = struct { |
| 45 | name: []const u8, | 42 | name: []const u8, |
| 46 | timestamp: u32, | 43 | timestamp: u32, |
| ... | @@ -139,10 +136,6 @@ pub fn deinit(self: *Dylib, allocator: *Allocator) void { | ... | @@ -139,10 +136,6 @@ pub fn deinit(self: *Dylib, allocator: *Allocator) void { |
| 139 | } | 136 | } |
| 140 | self.symbols.deinit(allocator); | 137 | self.symbols.deinit(allocator); |
| 141 | 138 | ||
| 142 | for (self.dependent_libs.items) |*id| { | ||
| 143 | id.deinit(allocator); | ||
| 144 | } | ||
| 145 | self.dependent_libs.deinit(allocator); | ||
| 146 | allocator.free(self.name); | 139 | allocator.free(self.name); |
| 147 | 140 | ||
| 148 | if (self.id) |*id| { | 141 | if (self.id) |*id| { |
| ... | @@ -150,7 +143,7 @@ pub fn deinit(self: *Dylib, allocator: *Allocator) void { | ... | @@ -150,7 +143,7 @@ pub fn deinit(self: *Dylib, allocator: *Allocator) void { |
| 150 | } | 143 | } |
| 151 | } | 144 | } |
| 152 | 145 | ||
| 153 | pub fn parse(self: *Dylib, allocator: *Allocator, target: std.Target) !void { | 146 | pub fn parse(self: *Dylib, allocator: *Allocator, target: std.Target, dependent_libs: anytype) !void { |
| 154 | log.debug("parsing shared library '{s}'", .{self.name}); | 147 | log.debug("parsing shared library '{s}'", .{self.name}); |
| 155 | 148 | ||
| 156 | self.library_offset = try fat.getLibraryOffset(self.file.reader(), target); | 149 | self.library_offset = try fat.getLibraryOffset(self.file.reader(), target); |
| ... | @@ -172,12 +165,12 @@ pub fn parse(self: *Dylib, allocator: *Allocator, target: std.Target) !void { | ... | @@ -172,12 +165,12 @@ pub fn parse(self: *Dylib, allocator: *Allocator, target: std.Target) !void { |
| 172 | return error.MismatchedCpuArchitecture; | 165 | return error.MismatchedCpuArchitecture; |
| 173 | } | 166 | } |
| 174 | 167 | ||
| 175 | try self.readLoadCommands(allocator, reader); | 168 | try self.readLoadCommands(allocator, reader, dependent_libs); |
| 176 | try self.parseId(allocator); | 169 | try self.parseId(allocator); |
| 177 | try self.parseSymbols(allocator); | 170 | try self.parseSymbols(allocator); |
| 178 | } | 171 | } |
| 179 | 172 | ||
| 180 | fn readLoadCommands(self: *Dylib, allocator: *Allocator, reader: anytype) !void { | 173 | fn readLoadCommands(self: *Dylib, allocator: *Allocator, reader: anytype, dependent_libs: anytype) !void { |
| 181 | const should_lookup_reexports = self.header.?.flags & macho.MH_NO_REEXPORTED_DYLIBS == 0; | 174 | const should_lookup_reexports = self.header.?.flags & macho.MH_NO_REEXPORTED_DYLIBS == 0; |
| 182 | 175 | ||
| 183 | try self.load_commands.ensureUnusedCapacity(allocator, self.header.?.ncmds); | 176 | try self.load_commands.ensureUnusedCapacity(allocator, self.header.?.ncmds); |
| ... | @@ -198,8 +191,8 @@ fn readLoadCommands(self: *Dylib, allocator: *Allocator, reader: anytype) !void | ... | @@ -198,8 +191,8 @@ fn readLoadCommands(self: *Dylib, allocator: *Allocator, reader: anytype) !void |
| 198 | macho.LC_REEXPORT_DYLIB => { | 191 | macho.LC_REEXPORT_DYLIB => { |
| 199 | if (should_lookup_reexports) { | 192 | if (should_lookup_reexports) { |
| 200 | // Parse install_name to dependent dylib. | 193 | // Parse install_name to dependent dylib. |
| 201 | const id = try Id.fromLoadCommand(allocator, cmd.Dylib); | 194 | var id = try Id.fromLoadCommand(allocator, cmd.Dylib); |
| 202 | try self.dependent_libs.append(allocator, id); | 195 | try dependent_libs.writeItem(id); |
| 203 | } | 196 | } |
| 204 | }, | 197 | }, |
| 205 | else => { | 198 | else => { |
| ... | @@ -341,7 +334,13 @@ const TargetMatcher = struct { | ... | @@ -341,7 +334,13 @@ const TargetMatcher = struct { |
| 341 | } | 334 | } |
| 342 | }; | 335 | }; |
| 343 | 336 | ||
| 344 | pub fn parseFromStub(self: *Dylib, allocator: *Allocator, target: std.Target, lib_stub: LibStub) !void { | 337 | pub fn parseFromStub( |
| 338 | self: *Dylib, | ||
| 339 | allocator: *Allocator, | ||
| 340 | target: std.Target, | ||
| 341 | lib_stub: LibStub, | ||
| 342 | dependent_libs: anytype, | ||
| 343 | ) !void { | ||
| 345 | if (lib_stub.inner.len == 0) return error.EmptyStubFile; | 344 | if (lib_stub.inner.len == 0) return error.EmptyStubFile; |
| 346 | 345 | ||
| 347 | log.debug("parsing shared library from stub '{s}'", .{self.name}); | 346 | log.debug("parsing shared library from stub '{s}'", .{self.name}); |
| ... | @@ -416,8 +415,8 @@ pub fn parseFromStub(self: *Dylib, allocator: *Allocator, target: std.Target, li | ... | @@ -416,8 +415,8 @@ pub fn parseFromStub(self: *Dylib, allocator: *Allocator, target: std.Target, li |
| 416 | 415 | ||
| 417 | log.debug(" (found re-export '{s}')", .{lib}); | 416 | log.debug(" (found re-export '{s}')", .{lib}); |
| 418 | 417 | ||
| 419 | const dep_id = try Id.default(allocator, lib); | 418 | var dep_id = try Id.default(allocator, lib); |
| 420 | try self.dependent_libs.append(allocator, dep_id); | 419 | try dependent_libs.writeItem(dep_id); |
| 421 | } | 420 | } |
| 422 | } | 421 | } |
| 423 | } | 422 | } |
| ... | @@ -521,55 +520,10 @@ pub fn parseFromStub(self: *Dylib, allocator: *Allocator, target: std.Target, li | ... | @@ -521,55 +520,10 @@ pub fn parseFromStub(self: *Dylib, allocator: *Allocator, target: std.Target, li |
| 521 | 520 | ||
| 522 | log.debug(" (found re-export '{s}')", .{lib}); | 521 | log.debug(" (found re-export '{s}')", .{lib}); |
| 523 | 522 | ||
| 524 | const dep_id = try Id.default(allocator, lib); | 523 | var dep_id = try Id.default(allocator, lib); |
| 525 | try self.dependent_libs.append(allocator, dep_id); | 524 | try dependent_libs.writeItem(dep_id); |
| 526 | } | 525 | } |
| 527 | } | 526 | } |
| 528 | } | 527 | } |
| 529 | } | 528 | } |
| 530 | } | 529 | } |
| 531 | |||
| 532 | pub fn parseDependentLibs( | ||
| 533 | self: *Dylib, | ||
| 534 | macho_file: *MachO, | ||
| 535 | syslibroot: ?[]const u8, | ||
| 536 | ) !void { | ||
| 537 | outer: for (self.dependent_libs.items) |id| { | ||
| 538 | if (macho_file.dylibs_map.contains(id.name)) continue :outer; | ||
| 539 | |||
| 540 | const has_ext = blk: { | ||
| 541 | const basename = fs.path.basename(id.name); | ||
| 542 | break :blk mem.lastIndexOfScalar(u8, basename, '.') != null; | ||
| 543 | }; | ||
| 544 | const extension = if (has_ext) fs.path.extension(id.name) else ""; | ||
| 545 | const without_ext = if (has_ext) blk: { | ||
| 546 | const index = mem.lastIndexOfScalar(u8, id.name, '.') orelse unreachable; | ||
| 547 | break :blk id.name[0..index]; | ||
| 548 | } else id.name; | ||
| 549 | |||
| 550 | for (&[_][]const u8{ extension, ".tbd" }) |ext| { | ||
| 551 | const with_ext = try std.fmt.allocPrint(macho_file.base.allocator, "{s}{s}", .{ | ||
| 552 | without_ext, | ||
| 553 | ext, | ||
| 554 | }); | ||
| 555 | defer macho_file.base.allocator.free(with_ext); | ||
| 556 | |||
| 557 | const full_path = if (syslibroot) |root| | ||
| 558 | try fs.path.join(macho_file.base.allocator, &.{ root, with_ext }) | ||
| 559 | else | ||
| 560 | with_ext; | ||
| 561 | defer if (syslibroot) |_| macho_file.base.allocator.free(full_path); | ||
| 562 | |||
| 563 | log.debug("trying dependency at fully resolved path {s}", .{full_path}); | ||
| 564 | |||
| 565 | const did_parse_successfully = try macho_file.parseDylib(full_path, .{ | ||
| 566 | .id = id, | ||
| 567 | .syslibroot = syslibroot, | ||
| 568 | .is_dependent = true, | ||
| 569 | }); | ||
| 570 | if (!did_parse_successfully) continue; | ||
| 571 | } else { | ||
| 572 | log.debug("unable to resolve dependency {s}", .{id.name}); | ||
| 573 | } | ||
| 574 | } | ||
| 575 | } |
src/main.zig+24| ... | @@ -564,6 +564,7 @@ fn buildOutputType( | ... | @@ -564,6 +564,7 @@ fn buildOutputType( |
| 564 | var root_src_file: ?[]const u8 = null; | 564 | var root_src_file: ?[]const u8 = null; |
| 565 | var version: std.builtin.Version = .{ .major = 0, .minor = 0, .patch = 0 }; | 565 | var version: std.builtin.Version = .{ .major = 0, .minor = 0, .patch = 0 }; |
| 566 | var have_version = false; | 566 | var have_version = false; |
| 567 | var compatibility_version: ?std.builtin.Version = null; | ||
| 567 | var strip = false; | 568 | var strip = false; |
| 568 | var single_threaded = false; | 569 | var single_threaded = false; |
| 569 | var function_sections = false; | 570 | var function_sections = false; |
| ... | @@ -1613,6 +1614,29 @@ fn buildOutputType( | ... | @@ -1613,6 +1614,29 @@ fn buildOutputType( |
| 1613 | ) catch |err| { | 1614 | ) catch |err| { |
| 1614 | fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); | 1615 | fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); |
| 1615 | }; | 1616 | }; |
| 1617 | } else if (mem.eql(u8, arg, "-framework") or mem.eql(u8, arg, "-weak_framework")) { | ||
| 1618 | i += 1; | ||
| 1619 | if (i >= linker_args.items.len) { | ||
| 1620 | fatal("expected linker arg after '{s}'", .{arg}); | ||
| 1621 | } | ||
| 1622 | try frameworks.append(linker_args.items[i]); | ||
| 1623 | } else if (mem.eql(u8, arg, "-compatibility_version")) { | ||
| 1624 | i += 1; | ||
| 1625 | if (i >= linker_args.items.len) { | ||
| 1626 | fatal("expected linker arg after '{s}'", .{arg}); | ||
| 1627 | } | ||
| 1628 | compatibility_version = std.builtin.Version.parse(linker_args.items[i]) catch |err| { | ||
| 1629 | fatal("unable to parse -compatibility_version '{s}': {s}", .{ linker_args.items[i], @errorName(err) }); | ||
| 1630 | }; | ||
| 1631 | } else if (mem.eql(u8, arg, "-current_version")) { | ||
| 1632 | i += 1; | ||
| 1633 | if (i >= linker_args.items.len) { | ||
| 1634 | fatal("expected linker arg after '{s}'", .{arg}); | ||
| 1635 | } | ||
| 1636 | version = std.builtin.Version.parse(linker_args.items[i]) catch |err| { | ||
| 1637 | fatal("unable to parse -current_version '{s}': {s}", .{ linker_args.items[i], @errorName(err) }); | ||
| 1638 | }; | ||
| 1639 | have_version = true; | ||
| 1616 | } else { | 1640 | } else { |
| 1617 | warn("unsupported linker arg: {s}", .{arg}); | 1641 | warn("unsupported linker arg: {s}", .{arg}); |
| 1618 | } | 1642 | } |