From e687c87d691518d63414aed4f355dabbd8565dc3 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Sun, 20 Aug 2023 08:37:44 +0200 Subject: [PATCH 1/3] macho: we no longer need to resolve framework dirs against sysroot --- src/link/MachO.zig | 42 ------------------------------------------ src/link/MachO/zld.zig | 13 ++----------- src/main.zig | 2 +- 3 files changed, 3 insertions(+), 54 deletions(-) diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 4369e3b18a15..0f6859e32afa 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -870,48 +870,6 @@ fn resolveLibSystemInDirs(arena: Allocator, dirs: []const []const u8, out_libs: return false; } -pub fn resolveSearchDir( - arena: Allocator, - dir: []const u8, - syslibroot: ?[]const u8, -) !?[]const u8 { - var candidates = std.ArrayList([]const u8).init(arena); - - if (fs.path.isAbsolute(dir)) { - if (syslibroot) |root| { - const common_dir = if (builtin.os.tag == .windows) blk: { - // We need to check for disk designator and strip it out from dir path so - // that we can concat dir with syslibroot. - // TODO we should backport this mechanism to 'MachO.Dylib.parseDependentLibs()' - const disk_designator = fs.path.diskDesignatorWindows(dir); - - if (mem.indexOf(u8, dir, disk_designator)) |where| { - break :blk dir[where + disk_designator.len ..]; - } - - break :blk dir; - } else dir; - const full_path = try fs.path.join(arena, &[_][]const u8{ root, common_dir }); - try candidates.append(full_path); - } - } - - try candidates.append(dir); - - for (candidates.items) |candidate| { - // Verify that search path actually exists - var tmp = fs.cwd().openDir(candidate, .{}) catch |err| switch (err) { - error.FileNotFound => continue, - else => |e| return e, - }; - defer tmp.close(); - - return candidate; - } - - return null; -} - pub fn resolveLib( arena: Allocator, search_dir: []const u8, diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index 56eee2b5463e..9de287e3e84b 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -3560,17 +3560,8 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr try MachO.resolveLibSystem(arena, comp, options.sysroot, target, options.lib_dirs, &libs); // frameworks - var framework_dirs = std.ArrayList([]const u8).init(arena); - for (options.framework_dirs) |dir| { - if (try MachO.resolveSearchDir(arena, dir, options.sysroot)) |search_dir| { - try framework_dirs.append(search_dir); - } else { - log.warn("directory not found for '-F{s}'", .{dir}); - } - } - outer: for (options.frameworks.keys()) |f_name| { - for (framework_dirs.items) |dir| { + for (options.framework_dirs) |dir| { for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { if (try MachO.resolveFramework(arena, dir, f_name, ext)) |full_path| { const info = options.frameworks.get(f_name).?; @@ -3590,7 +3581,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr if (framework_not_found) { log.warn("Framework search paths:", .{}); - for (framework_dirs.items) |dir| { + for (options.framework_dirs) |dir| { log.warn(" {s}", .{dir}); } } diff --git a/src/main.zig b/src/main.zig index fd220bf17215..01ef0d87bedc 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2566,7 +2566,7 @@ fn buildOutputType( want_native_include_dirs = true; } - // Resolve the library path arguments with respect to sysroot. + // Resolve the library and framework path arguments with respect to sysroot. var lib_dirs = std.ArrayList([]const u8).init(arena); if (sysroot) |root| { for (lib_dir_args.items) |dir| { From 4793dafa0433d758b126f2f97d1de031b99e0fa1 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Sun, 20 Aug 2023 10:43:20 +0200 Subject: [PATCH 2/3] frontend: move framework path resolution from the linker to frontend --- src/Compilation.zig | 14 ++++-- src/link.zig | 1 + src/link/MachO.zig | 22 +-------- src/link/MachO/zld.zig | 44 ++++-------------- src/main.zig | 102 +++++++++++++++++++++++++++++++++++++++-- 5 files changed, 121 insertions(+), 62 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 726862f231a4..80231c91d015 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -507,7 +507,8 @@ pub const InitOptions = struct { c_source_files: []const CSourceFile = &[0]CSourceFile{}, link_objects: []LinkObject = &[0]LinkObject{}, framework_dirs: []const []const u8 = &[0][]const u8{}, - frameworks: std.StringArrayHashMapUnmanaged(Framework) = .{}, + framework_names: []const []const u8 = &.{}, + framework_infos: []const Framework = &.{}, system_lib_names: []const []const u8 = &.{}, system_lib_infos: []const SystemLib = &.{}, /// These correspond to the WASI libc emulated subcomponents including: @@ -830,7 +831,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { // Our linker can't handle objects or most advanced options yet. if (options.link_objects.len != 0 or options.c_source_files.len != 0 or - options.frameworks.count() != 0 or + options.framework_names.len != 0 or options.system_lib_names.len != 0 or options.link_libc or options.link_libcpp or link_eh_frame_hdr or @@ -1446,6 +1447,13 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { system_libs.putAssumeCapacity(lib_name, options.system_lib_infos[i]); } + var frameworks: std.StringArrayHashMapUnmanaged(Framework) = .{}; + errdefer frameworks.deinit(gpa); + try frameworks.ensureTotalCapacity(gpa, options.framework_names.len); + for (options.framework_names, options.framework_infos) |framework_name, info| { + frameworks.putAssumeCapacity(framework_name, info); + } + const bin_file = try link.File.openPath(gpa, .{ .emit = bin_file_emit, .implib_emit = implib_emit, @@ -1465,7 +1473,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .link_libcpp = link_libcpp, .link_libunwind = link_libunwind, .objects = options.link_objects, - .frameworks = options.frameworks, + .frameworks = frameworks, .framework_dirs = options.framework_dirs, .system_libs = system_libs, .wasi_emulated_libs = options.wasi_emulated_libs, diff --git a/src/link.zig b/src/link.zig index 82aeb5dee83f..90a09f8e1123 100644 --- a/src/link.zig +++ b/src/link.zig @@ -37,6 +37,7 @@ pub const SystemLib = struct { pub const Framework = struct { needed: bool = false, weak: bool = false, + path: []const u8, }; pub const SortSection = enum { name, alignment }; diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 0f6859e32afa..92224da63b5f 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -870,7 +870,7 @@ fn resolveLibSystemInDirs(arena: Allocator, dirs: []const []const u8, out_libs: return false; } -pub fn resolveLib( +fn resolveLib( arena: Allocator, search_dir: []const u8, name: []const u8, @@ -889,26 +889,6 @@ pub fn resolveLib( return full_path; } -pub fn resolveFramework( - arena: Allocator, - search_dir: []const u8, - name: []const u8, - ext: []const u8, -) !?[]const u8 { - const search_name = try std.fmt.allocPrint(arena, "{s}{s}", .{ name, ext }); - const prefix_path = try std.fmt.allocPrint(arena, "{s}.framework", .{name}); - const full_path = try fs.path.join(arena, &[_][]const u8{ search_dir, prefix_path, search_name }); - - // Check if the file exists. - const tmp = fs.cwd().openFile(full_path, .{}) catch |err| switch (err) { - error.FileNotFound => return null, - else => |e| return e, - }; - defer tmp.close(); - - return full_path; -} - const ParseDylibError = error{ OutOfMemory, EmptyStubFile, diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index 9de287e3e84b..7987bb4f1d92 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -3512,9 +3512,6 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr try zld.atoms.append(gpa, Atom.empty); // AtomIndex at 0 is reserved as null atom try zld.strtab.buffer.append(gpa, 0); - var lib_not_found = false; - var framework_not_found = false; - // Positional arguments to the linker such as object files and static archives. var positionals = std.ArrayList([]const u8).init(arena); try positionals.ensureUnusedCapacity(options.objects.len); @@ -3557,34 +3554,17 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr for (vals) |v| libs.putAssumeCapacity(v.path.?, v); } - try MachO.resolveLibSystem(arena, comp, options.sysroot, target, options.lib_dirs, &libs); - - // frameworks - outer: for (options.frameworks.keys()) |f_name| { - for (options.framework_dirs) |dir| { - for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { - if (try MachO.resolveFramework(arena, dir, f_name, ext)) |full_path| { - const info = options.frameworks.get(f_name).?; - try libs.put(full_path, .{ - .needed = info.needed, - .weak = info.weak, - .path = full_path, - }); - continue :outer; - } - } - } else { - log.warn("framework not found for '-framework {s}'", .{f_name}); - framework_not_found = true; - } + { + const vals = options.frameworks.values(); + try libs.ensureUnusedCapacity(vals.len); + for (vals) |v| libs.putAssumeCapacity(v.path, .{ + .needed = v.needed, + .weak = v.weak, + .path = v.path, + }); } - if (framework_not_found) { - log.warn("Framework search paths:", .{}); - for (options.framework_dirs) |dir| { - log.warn(" {s}", .{dir}); - } - } + try MachO.resolveLibSystem(arena, comp, options.sysroot, target, options.lib_dirs, &libs); if (options.verbose_link) { var argv = std.ArrayList([]const u8).init(arena); @@ -3731,12 +3711,6 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr if (resolver.unresolved.count() > 0) { return error.UndefinedSymbolReference; } - if (lib_not_found) { - return error.LibraryNotFound; - } - if (framework_not_found) { - return error.FrameworkNotFound; - } if (options.output_mode == .Exe) { const entry_name = options.entry orelse load_commands.default_entry_point; diff --git a/src/main.zig b/src/main.zig index 01ef0d87bedc..3d59308ac184 100644 --- a/src/main.zig +++ b/src/main.zig @@ -746,6 +746,13 @@ const SystemLib = struct { } }; +/// Similar to `link.Framework` except it doesn't store yet unresolved +/// path to the framework. +const Framework = struct { + needed: bool = false, + weak: bool = false, +}; + const CliModule = struct { mod: *Package, /// still in CLI arg format @@ -919,7 +926,7 @@ fn buildOutputType( var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena); var link_objects = std.ArrayList(Compilation.LinkObject).init(arena); var framework_dirs = std.ArrayList([]const u8).init(arena); - var frameworks: std.StringArrayHashMapUnmanaged(Compilation.Framework) = .{}; + var frameworks: std.StringArrayHashMapUnmanaged(Framework) = .{}; // null means replace with the test executable binary var test_exec_args = std.ArrayList(?[]const u8).init(arena); var linker_export_symbol_names = std.ArrayList([]const u8).init(arena); @@ -2566,7 +2573,7 @@ fn buildOutputType( want_native_include_dirs = true; } - // Resolve the library and framework path arguments with respect to sysroot. + // Resolve the library path arguments with respect to sysroot. var lib_dirs = std.ArrayList([]const u8).init(arena); if (sysroot) |root| { for (lib_dir_args.items) |dir| { @@ -2868,6 +2875,65 @@ fn buildOutputType( } // After this point, resolved_system_libs is used instead of external_system_libs. + // We now repeat part of the process for frameworks. + var resolved_frameworks: std.MultiArrayList(struct { + name: []const u8, + framework: Compilation.Framework, + }) = .{}; + + if (frameworks.keys().len > 0) { + var test_path = std.ArrayList(u8).init(gpa); + defer test_path.deinit(); + + var checked_paths = std.ArrayList(u8).init(gpa); + defer checked_paths.deinit(); + + var failed_frameworks = std.ArrayList(struct { + name: []const u8, + checked_paths: []const u8, + }).init(arena); + + framework: for (frameworks.keys(), frameworks.values()) |framework_name, info| { + checked_paths.clearRetainingCapacity(); + + for (framework_dirs.items) |framework_dir_path| { + if (try accessFrameworkPath( + &test_path, + &checked_paths, + framework_dir_path, + framework_name, + )) { + const path = try arena.dupe(u8, test_path.items); + try resolved_frameworks.append(arena, .{ + .name = framework_name, + .framework = .{ + .needed = info.needed, + .weak = info.weak, + .path = path, + }, + }); + continue :framework; + } + } + + try failed_frameworks.append(.{ + .name = framework_name, + .checked_paths = try arena.dupe(u8, checked_paths.items), + }); + } + + if (failed_frameworks.items.len > 0) { + for (failed_frameworks.items) |f| { + const searched_paths = if (f.checked_paths.len == 0) " none" else f.checked_paths; + std.log.err("unable to find framework '{s}'. searched paths: {s}", .{ + f.name, searched_paths, + }); + } + process.exit(1); + } + } + // After this point, resolved_frameworks is used instead of frameworks. + const object_format = target_info.target.ofmt; if (output_mode == .Obj and (object_format == .coff or object_format == .macho)) { @@ -3261,7 +3327,8 @@ fn buildOutputType( .c_source_files = c_source_files.items, .link_objects = link_objects.items, .framework_dirs = framework_dirs.items, - .frameworks = frameworks, + .framework_names = resolved_frameworks.items(.name), + .framework_infos = resolved_frameworks.items(.framework), .system_lib_names = resolved_system_libs.items(.name), .system_lib_infos = resolved_system_libs.items(.lib), .wasi_emulated_libs = wasi_emulated_libs.items, @@ -6336,3 +6403,32 @@ fn accessLibPath( return false; } + +fn accessFrameworkPath( + test_path: *std.ArrayList(u8), + checked_paths: *std.ArrayList(u8), + framework_dir_path: []const u8, + framework_name: []const u8, +) !bool { + const sep = fs.path.sep_str; + + for (&[_][]const u8{ "tbd", "dylib" }) |ext| { + test_path.clearRetainingCapacity(); + try test_path.writer().print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}.{s}", .{ + framework_dir_path, + framework_name, + framework_name, + ext, + }); + try checked_paths.writer().print("\n {s}", .{test_path.items}); + fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { + error.FileNotFound => continue, + else => |e| fatal("unable to search for {s} framework '{s}': {s}", .{ + ext, test_path.items, @errorName(e), + }), + }; + return true; + } + + return false; +} From b73ef342895f00bdb31ea5f947ee83764f235d43 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Mon, 21 Aug 2023 08:07:42 +0200 Subject: [PATCH 3/3] frontend: directly pass resolved frameworks container to the linker We can infer the framework name from the included resolved framework path. Fix hash implementation, and bump linker hash value from 9 to 10. --- src/Compilation.zig | 20 ++++++-------------- src/link.zig | 18 ++++++------------ src/link/Coff/lld.zig | 2 +- src/link/Elf.zig | 2 +- src/link/MachO/zld.zig | 23 +++++++++++------------ src/link/Wasm.zig | 4 ++-- src/main.zig | 19 ++++++------------- 7 files changed, 33 insertions(+), 55 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 80231c91d015..069cc8a2c788 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -507,8 +507,7 @@ pub const InitOptions = struct { c_source_files: []const CSourceFile = &[0]CSourceFile{}, link_objects: []LinkObject = &[0]LinkObject{}, framework_dirs: []const []const u8 = &[0][]const u8{}, - framework_names: []const []const u8 = &.{}, - framework_infos: []const Framework = &.{}, + frameworks: []const Framework = &.{}, system_lib_names: []const []const u8 = &.{}, system_lib_infos: []const SystemLib = &.{}, /// These correspond to the WASI libc emulated subcomponents including: @@ -831,7 +830,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { // Our linker can't handle objects or most advanced options yet. if (options.link_objects.len != 0 or options.c_source_files.len != 0 or - options.framework_names.len != 0 or + options.frameworks.len != 0 or options.system_lib_names.len != 0 or options.link_libc or options.link_libcpp or link_eh_frame_hdr or @@ -1447,13 +1446,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { system_libs.putAssumeCapacity(lib_name, options.system_lib_infos[i]); } - var frameworks: std.StringArrayHashMapUnmanaged(Framework) = .{}; - errdefer frameworks.deinit(gpa); - try frameworks.ensureTotalCapacity(gpa, options.framework_names.len); - for (options.framework_names, options.framework_infos) |framework_name, info| { - frameworks.putAssumeCapacity(framework_name, info); - } - const bin_file = try link.File.openPath(gpa, .{ .emit = bin_file_emit, .implib_emit = implib_emit, @@ -1473,7 +1465,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .link_libcpp = link_libcpp, .link_libunwind = link_libunwind, .objects = options.link_objects, - .frameworks = frameworks, + .frameworks = options.frameworks, .framework_dirs = options.framework_dirs, .system_libs = system_libs, .wasi_emulated_libs = options.wasi_emulated_libs, @@ -2275,7 +2267,7 @@ fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemo /// to remind the programmer to update multiple related pieces of code that /// are in different locations. Bump this number when adding or deleting /// anything from the link cache manifest. -pub const link_hash_implementation_version = 9; +pub const link_hash_implementation_version = 10; fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifest) !void { const gpa = comp.gpa; @@ -2285,7 +2277,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - comptime assert(link_hash_implementation_version == 9); + comptime assert(link_hash_implementation_version == 10); if (comp.bin_file.options.module) |mod| { const main_zig_file = try mod.main_pkg.root_src_directory.join(arena, &[_][]const u8{ @@ -2394,7 +2386,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes // Mach-O specific stuff man.hash.addListOfBytes(comp.bin_file.options.framework_dirs); - link.hashAddFrameworks(&man.hash, comp.bin_file.options.frameworks); + try link.hashAddFrameworks(man, comp.bin_file.options.frameworks); try man.addOptionalFile(comp.bin_file.options.entitlements); man.hash.addOptional(comp.bin_file.options.pagezero_size); man.hash.addOptional(comp.bin_file.options.headerpad_size); diff --git a/src/link.zig b/src/link.zig index 90a09f8e1123..48ad78364cf3 100644 --- a/src/link.zig +++ b/src/link.zig @@ -57,15 +57,11 @@ pub fn hashAddSystemLibs( } } -pub fn hashAddFrameworks( - hh: *Cache.HashHelper, - hm: std.StringArrayHashMapUnmanaged(Framework), -) void { - const keys = hm.keys(); - hh.addListOfBytes(keys); - for (hm.values()) |value| { - hh.add(value.needed); - hh.add(value.weak); +pub fn hashAddFrameworks(man: *Cache.Manifest, hm: []const Framework) !void { + for (hm) |value| { + man.hash.add(value.needed); + man.hash.add(value.weak); + _ = try man.addFile(value.path, null); } } @@ -209,7 +205,7 @@ pub const Options = struct { objects: []Compilation.LinkObject, framework_dirs: []const []const u8, - frameworks: std.StringArrayHashMapUnmanaged(Framework), + frameworks: []const Framework, /// These are *always* dynamically linked. Static libraries will be /// provided as positional arguments. system_libs: std.StringArrayHashMapUnmanaged(SystemLib), @@ -277,7 +273,6 @@ pub const Options = struct { pub fn move(self: *Options) Options { const copied_state = self.*; - self.frameworks = .{}; self.system_libs = .{}; self.force_undefined_symbols = .{}; return copied_state; @@ -643,7 +638,6 @@ pub const File = struct { base.releaseLock(); if (base.file) |f| f.close(); if (base.intermediary_basename) |sub_path| base.allocator.free(sub_path); - base.options.frameworks.deinit(base.allocator); base.options.system_libs.deinit(base.allocator); base.options.force_undefined_symbols.deinit(base.allocator); switch (base.tag) { diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index bd82254e6aed..c0f88704e5c5 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -63,7 +63,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod man = comp.cache_parent.obtain(); self.base.releaseLock(); - comptime assert(Compilation.link_hash_implementation_version == 9); + comptime assert(Compilation.link_hash_implementation_version == 10); for (self.base.options.objects) |obj| { _ = try man.addFile(obj.path, null); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 9d71885e61de..c1cc4355c66a 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1367,7 +1367,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // We are about to obtain this lock, so here we give other processes a chance first. self.base.releaseLock(); - comptime assert(Compilation.link_hash_implementation_version == 9); + comptime assert(Compilation.link_hash_implementation_version == 10); try man.addOptionalFile(self.base.options.linker_script); try man.addOptionalFile(self.base.options.version_script); diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index 7987bb4f1d92..e4dde334530e 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -3396,7 +3396,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr // We are about to obtain this lock, so here we give other processes a chance first. macho_file.base.releaseLock(); - comptime assert(Compilation.link_hash_implementation_version == 9); + comptime assert(Compilation.link_hash_implementation_version == 10); for (options.objects) |obj| { _ = try man.addFile(obj.path, null); @@ -3417,7 +3417,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr man.hash.add(options.strip); man.hash.addListOfBytes(options.lib_dirs); man.hash.addListOfBytes(options.framework_dirs); - link.hashAddFrameworks(&man.hash, options.frameworks); + try link.hashAddFrameworks(&man, options.frameworks); man.hash.addListOfBytes(options.rpath_list); if (is_dyn_lib) { man.hash.addOptionalBytes(options.install_name); @@ -3555,9 +3555,8 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr } { - const vals = options.frameworks.values(); - try libs.ensureUnusedCapacity(vals.len); - for (vals) |v| libs.putAssumeCapacity(v.path, .{ + try libs.ensureUnusedCapacity(options.frameworks.len); + for (options.frameworks) |v| libs.putAssumeCapacity(v.path, .{ .needed = v.needed, .weak = v.weak, .path = v.path, @@ -3664,14 +3663,14 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr try argv.append(try std.fmt.allocPrint(arena, "-L{s}", .{lib_dir})); } - for (options.frameworks.keys()) |framework| { - const info = options.frameworks.get(framework).?; - const arg = if (info.needed) - try std.fmt.allocPrint(arena, "-needed_framework {s}", .{framework}) - else if (info.weak) - try std.fmt.allocPrint(arena, "-weak_framework {s}", .{framework}) + for (options.frameworks) |framework| { + const name = std.fs.path.stem(framework.path); + const arg = if (framework.needed) + try std.fmt.allocPrint(arena, "-needed_framework {s}", .{name}) + else if (framework.weak) + try std.fmt.allocPrint(arena, "-weak_framework {s}", .{name}) else - try std.fmt.allocPrint(arena, "-framework {s}", .{framework}); + try std.fmt.allocPrint(arena, "-framework {s}", .{name}); try argv.append(arg); } diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index f705c18b6970..89c552a3fb2c 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -3193,7 +3193,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l // We are about to obtain this lock, so here we give other processes a chance first. wasm.base.releaseLock(); - comptime assert(Compilation.link_hash_implementation_version == 9); + comptime assert(Compilation.link_hash_implementation_version == 10); for (options.objects) |obj| { _ = try man.addFile(obj.path, null); @@ -4254,7 +4254,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! // We are about to obtain this lock, so here we give other processes a chance first. wasm.base.releaseLock(); - comptime assert(Compilation.link_hash_implementation_version == 9); + comptime assert(Compilation.link_hash_implementation_version == 10); for (wasm.base.options.objects) |obj| { _ = try man.addFile(obj.path, null); diff --git a/src/main.zig b/src/main.zig index 3d59308ac184..5848961052f5 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2876,10 +2876,7 @@ fn buildOutputType( // After this point, resolved_system_libs is used instead of external_system_libs. // We now repeat part of the process for frameworks. - var resolved_frameworks: std.MultiArrayList(struct { - name: []const u8, - framework: Compilation.Framework, - }) = .{}; + var resolved_frameworks = std.ArrayList(Compilation.Framework).init(arena); if (frameworks.keys().len > 0) { var test_path = std.ArrayList(u8).init(gpa); @@ -2904,13 +2901,10 @@ fn buildOutputType( framework_name, )) { const path = try arena.dupe(u8, test_path.items); - try resolved_frameworks.append(arena, .{ - .name = framework_name, - .framework = .{ - .needed = info.needed, - .weak = info.weak, - .path = path, - }, + try resolved_frameworks.append(.{ + .needed = info.needed, + .weak = info.weak, + .path = path, }); continue :framework; } @@ -3327,8 +3321,7 @@ fn buildOutputType( .c_source_files = c_source_files.items, .link_objects = link_objects.items, .framework_dirs = framework_dirs.items, - .framework_names = resolved_frameworks.items(.name), - .framework_infos = resolved_frameworks.items(.framework), + .frameworks = resolved_frameworks.items, .system_lib_names = resolved_system_libs.items(.name), .system_lib_infos = resolved_system_libs.items(.lib), .wasi_emulated_libs = wasi_emulated_libs.items,