@@ -104,8 +104,19 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?
if (module_obj_path) |path| try positionals.append(.{ .path = path });
for (positionals.items) |obj| {
// TODO: parse for archive meaning don't unpack objects
_ = obj;
parsePositional(macho_file, obj.path) catch |err| switch (err) {
error.MalformedObject,
error.MalformedArchive,
error.InvalidCpuArch,
error.InvalidTarget,
=> continue, // already reported
error.UnknownFileType => try macho_file.reportParseError(obj.path, "unknown file type for an object file", .{}),
else => |e| try macho_file.reportParseError(
obj.path,
"unexpected error: parsing input file failed with error {s}",
.{@errorName(e)},
),
};
}
if (comp.link_errors.items.len > 0) return error.FlushFailure;
@@ -241,6 +252,75 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?
if (comp.link_errors.items.len > 0) return error.FlushFailure;
}
fn parsePositional(macho_file: *MachO, path: []const u8) MachO.ParseError!void {
const tracy = trace(@src());
defer tracy.end();
if (try Object.isObject(path)) {
try parseObject(macho_file, path);
} else if (try fat.isFatLibrary(path)) {
const fat_arch = try macho_file.parseFatLibrary(path);
if (try Archive.isArchive(path, fat_arch)) {
try parseArchive(macho_file, path, fat_arch);
} else return error.UnknownFileType;
} else if (try Archive.isArchive(path, null)) {
try parseArchive(macho_file, path, null);
} else return error.UnknownFileType;
}
fn parseObject(macho_file: *MachO, path: []const u8) MachO.ParseError!void {
const tracy = trace(@src());
defer tracy.end();
const gpa = macho_file.base.comp.gpa;
const file = try std.fs.cwd().openFile(path, .{});
errdefer file.close();
const handle = try macho_file.addFileHandle(file);
const mtime: u64 = mtime: {
const stat = file.stat() catch break :mtime 0;
break :mtime @as(u64, @intCast(@divFloor(stat.mtime, 1_000_000_000)));
};
const index = @as(File.Index, @intCast(try macho_file.files.addOne(gpa)));
macho_file.files.set(index, .{ .object = .{
.path = try gpa.dupe(u8, path),
.file_handle = handle,
.mtime = mtime,
.index = index,
} });
try macho_file.objects.append(gpa, index);
const object = macho_file.getFile(index).?.object;
try object.parseAr(macho_file);
}
fn parseArchive(macho_file: *MachO, path: []const u8, fat_arch: ?fat.Arch) MachO.ParseError!void {
const tracy = trace(@src());
defer tracy.end();
const gpa = macho_file.base.comp.gpa;
const file = try std.fs.cwd().openFile(path, .{});
errdefer file.close();
const handle = try macho_file.addFileHandle(file);
var archive = Archive{};
defer archive.deinit(gpa);
try archive.parse(macho_file, path, handle, fat_arch);
var has_parse_error = false;
for (archive.objects.items) |extracted| {
const index = @as(File.Index, @intCast(try macho_file.files.addOne(gpa)));
macho_file.files.set(index, .{ .object = extracted });
const object = &macho_file.files.items(.data)[index].object;
object.index = index;
object.parseAr(macho_file) catch |err| switch (err) {
error.InvalidCpuArch => has_parse_error = true,
else => |e| return e,
};
try macho_file.objects.append(gpa, index);
}
if (has_parse_error) return error.MalformedArchive;
}
fn markExports(macho_file: *MachO) void {
if (macho_file.getZigObject()) |zo| {
zo.asFile().markExportsRelocatable(macho_file);
@@ -733,6 +813,7 @@ fn writeHeader(macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void {
const assert = std.debug.assert;
const build_options = @import("build_options");
const eh_frame = @import("eh_frame.zig");
const fat = @import("fat.zig");
const link = @import("../../link.zig");
const load_commands = @import("load_commands.zig");
const log = std.log.scoped(.link);
@@ -748,4 +829,5 @@ const Atom = @import("Atom.zig");
const Compilation = @import("../../Compilation.zig");
const File = @import("file.zig").File;
const MachO = @import("../MachO.zig");
const Object = @import("Object.zig");
const Symbol = @import("Symbol.zig");