diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-01-13 17:57:56 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-01-13 20:02:11 +0100 |
| commit | 5cde5f947fa12440463f684d9417ac00c8b9790a (patch) | |
| tree | 4cc1ba8e54327060e7009a923e2c79faddf5d29e | |
| parent | a8564df9ed510f572732b8179844299fc3d3c11b (diff) | |
| download | zig-5cde5f947fa12440463f684d9417ac00c8b9790a.tar.gz zig-5cde5f947fa12440463f684d9417ac00c8b9790a.zip | |
Introduce LinkObject with must_link field
| -rw-r--r-- | src/Compilation.zig | 19 | ||||
| -rw-r--r-- | src/link.zig | 12 | ||||
| -rw-r--r-- | src/link/Coff.zig | 12 | ||||
| -rw-r--r-- | src/link/Elf.zig | 12 | ||||
| -rw-r--r-- | src/link/MachO.zig | 31 | ||||
| -rw-r--r-- | src/link/Wasm.zig | 12 | ||||
| -rw-r--r-- | src/main.zig | 19 |
7 files changed, 74 insertions, 43 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig index 7a3279445e..833e3b39ca 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -654,6 +654,11 @@ pub const ClangPreprocessorMode = enum { pub const SystemLib = link.SystemLib; pub const CacheMode = link.CacheMode; +pub const LinkObject = struct { + path: []const u8, + must_link: bool = false, +}; + pub const InitOptions = struct { zig_lib_directory: Directory, local_cache_directory: Directory, @@ -698,8 +703,7 @@ pub const InitOptions = struct { lib_dirs: []const []const u8 = &[0][]const u8{}, rpath_list: []const []const u8 = &[0][]const u8{}, c_source_files: []const CSourceFile = &[0]CSourceFile{}, - link_objects: []const []const u8 = &[0][]const u8{}, - must_link_objects: []const []const u8 = &[0][]const u8{}, + link_objects: []LinkObject = &[0]LinkObject{}, framework_dirs: []const []const u8 = &[0][]const u8{}, frameworks: []const []const u8 = &[0][]const u8{}, system_lib_names: []const []const u8 = &.{}, @@ -1057,7 +1061,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { if (options.system_lib_names.len != 0) break :x true; for (options.link_objects) |obj| { - switch (classifyFileExt(obj)) { + switch (classifyFileExt(obj.path)) { .shared_library => break :x true, else => continue, } @@ -1460,7 +1464,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { if (options.c_source_files.len >= 1) { hash.addBytes(options.c_source_files[0].src_path); } else if (options.link_objects.len >= 1) { - hash.addBytes(options.link_objects[0]); + hash.addBytes(options.link_objects[0].path); } const digest = hash.final(); @@ -1536,7 +1540,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .link_libcpp = link_libcpp, .link_libunwind = link_libunwind, .objects = options.link_objects, - .must_link_objects = options.must_link_objects, .frameworks = options.frameworks, .framework_dirs = options.framework_dirs, .system_libs = system_libs, @@ -2267,7 +2270,11 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes try man.addOptionalFile(comp.bin_file.options.linker_script); try man.addOptionalFile(comp.bin_file.options.version_script); - try man.addListOfFiles(comp.bin_file.options.objects); + + for (comp.bin_file.options.objects) |obj| { + _ = try man.addFile(obj.path, null); + man.hash.add(obj.must_link); + } for (comp.c_object_table.keys()) |key| { _ = try man.addFile(key.src.src_path, null); diff --git a/src/link.zig b/src/link.zig index ea12292d22..3dc75c77e8 100644 --- a/src/link.zig +++ b/src/link.zig @@ -155,8 +155,7 @@ pub const Options = struct { soname: ?[]const u8, llvm_cpu_features: ?[*:0]const u8, - objects: []const []const u8, - must_link_objects: []const []const u8, + objects: []Compilation.LinkObject, framework_dirs: []const []const u8, frameworks: []const []const u8, system_libs: std.StringArrayHashMapUnmanaged(SystemLib), @@ -756,7 +755,10 @@ pub const File = struct { // We are about to obtain this lock, so here we give other processes a chance first. base.releaseLock(); - try man.addListOfFiles(base.options.objects); + for (base.options.objects) |obj| { + _ = try man.addFile(obj.path, null); + man.hash.add(obj.must_link); + } for (comp.c_object_table.keys()) |key| { _ = try man.addFile(key.status.success.object_path, null); } @@ -793,8 +795,8 @@ pub const File = struct { var object_files = try std.ArrayList([*:0]const u8).initCapacity(base.allocator, num_object_files); defer object_files.deinit(); - for (base.options.objects) |obj_path| { - object_files.appendAssumeCapacity(try arena.dupeZ(u8, obj_path)); + for (base.options.objects) |obj| { + object_files.appendAssumeCapacity(try arena.dupeZ(u8, obj.path)); } for (comp.c_object_table.keys()) |key| { object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.object_path)); diff --git a/src/link/Coff.zig b/src/link/Coff.zig index ea9c457716..26b8c78a28 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -943,7 +943,10 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { comptime assert(Compilation.link_hash_implementation_version == 1); - try man.addListOfFiles(self.base.options.objects); + for (self.base.options.objects) |obj| { + _ = try man.addFile(obj.path, null); + man.hash.add(obj.must_link); + } for (comp.c_object_table.keys()) |key| { _ = try man.addFile(key.status.success.object_path, null); } @@ -1005,7 +1008,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { // build-obj. See also the corresponding TODO in linkAsArchive. const the_object_path = blk: { if (self.base.options.objects.len != 0) - break :blk self.base.options.objects[0]; + break :blk self.base.options.objects[0].path; if (comp.c_object_table.count() != 0) break :blk comp.c_object_table.keys()[0].status.success.object_path; @@ -1110,7 +1113,10 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{lib_dir})); } - try argv.appendSlice(self.base.options.objects); + try argv.ensureUnusedCapacity(self.base.options.objects.len); + for (self.base.options.objects) |obj| { + argv.appendAssumeCapacity(obj.path); + } for (comp.c_object_table.keys()) |key| { try argv.append(key.status.success.object_path); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 36fe97f69b..d0f9d7851d 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1384,7 +1384,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { try man.addOptionalFile(self.base.options.linker_script); try man.addOptionalFile(self.base.options.version_script); - try man.addListOfFiles(self.base.options.objects); + for (self.base.options.objects) |obj| { + _ = try man.addFile(obj.path, null); + man.hash.add(obj.must_link); + } for (comp.c_object_table.keys()) |key| { _ = try man.addFile(key.status.success.object_path, null); } @@ -1469,7 +1472,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { // build-obj. See also the corresponding TODO in linkAsArchive. const the_object_path = blk: { if (self.base.options.objects.len != 0) - break :blk self.base.options.objects[0]; + break :blk self.base.options.objects[0].path; if (comp.c_object_table.count() != 0) break :blk comp.c_object_table.keys()[0].status.success.object_path; @@ -1678,7 +1681,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { } // Positional arguments to the linker such as object files. - try argv.appendSlice(self.base.options.objects); + try argv.ensureUnusedCapacity(self.base.options.objects.len); + for (self.base.options.objects) |obj| { + argv.appendAssumeCapacity(obj.path); + } for (comp.c_object_table.keys()) |key| { try argv.append(key.status.success.object_path); diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 8ba2ac973c..90981da0ee 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -499,7 +499,10 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { comptime assert(Compilation.link_hash_implementation_version == 1); - try man.addListOfFiles(self.base.options.objects); + for (self.base.options.objects) |obj| { + _ = try man.addFile(obj.path, null); + man.hash.add(obj.must_link); + } for (comp.c_object_table.keys()) |key| { _ = try man.addFile(key.status.success.object_path, null); } @@ -571,8 +574,9 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { // here. TODO: think carefully about how we can avoid this redundant operation when doing // build-obj. See also the corresponding TODO in linkAsArchive. const the_object_path = blk: { - if (self.base.options.objects.len != 0) - break :blk self.base.options.objects[0]; + if (self.base.options.objects.len != 0) { + break :blk self.base.options.objects[0].path; + } if (comp.c_object_table.count() != 0) break :blk comp.c_object_table.keys()[0].status.success.object_path; @@ -679,19 +683,20 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { // the relocatable object files. self.invalidate_relocs = true; - // Unpack must-link archives - var must_link_archives = std.StringArrayHashMap(void).init(arena); - try must_link_archives.ensureTotalCapacity(@intCast(u32, self.base.options.must_link_objects.len)); - for (self.base.options.must_link_objects) |lib| { - _ = must_link_archives.getOrPutAssumeCapacity(lib); - } - // Positional arguments to the linker such as object files and static archives. var positionals = std.ArrayList([]const u8).init(arena); try positionals.ensureUnusedCapacity(self.base.options.objects.len); + + var must_link_archives = std.StringArrayHashMap(void).init(arena); + try must_link_archives.ensureUnusedCapacity(self.base.options.objects.len); + for (self.base.options.objects) |obj| { - if (must_link_archives.contains(obj)) continue; - _ = positionals.appendAssumeCapacity(obj); + if (must_link_archives.contains(obj.path)) continue; + if (obj.must_link) { + _ = must_link_archives.getOrPutAssumeCapacity(obj.path); + } else { + _ = positionals.appendAssumeCapacity(obj.path); + } } for (comp.c_object_table.keys()) |key| { @@ -899,7 +904,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { try argv.append("dynamic_lookup"); } - for (self.base.options.must_link_objects) |lib| { + for (must_link_archives.keys()) |lib| { try argv.append(try std.fmt.allocPrint(arena, "-force_load {s}", .{lib})); } diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 99311b8441..34723cdb27 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -1128,7 +1128,10 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { comptime assert(Compilation.link_hash_implementation_version == 1); - try man.addListOfFiles(self.base.options.objects); + for (self.base.options.objects) |obj| { + _ = try man.addFile(obj.path, null); + man.hash.add(obj.must_link); + } for (comp.c_object_table.keys()) |key| { _ = try man.addFile(key.status.success.object_path, null); } @@ -1181,7 +1184,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { // build-obj. See also the corresponding TODO in linkAsArchive. const the_object_path = blk: { if (self.base.options.objects.len != 0) - break :blk self.base.options.objects[0]; + break :blk self.base.options.objects[0].path; if (comp.c_object_table.count() != 0) break :blk comp.c_object_table.keys()[0].status.success.object_path; @@ -1346,7 +1349,10 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { } // Positional arguments to the linker such as object files. - try argv.appendSlice(self.base.options.objects); + try argv.ensureUnusedCapacity(self.base.options.objects.len); + for (self.base.options.objects) |obj| { + argv.appendAssumeCapacity(obj.path); + } for (comp.c_object_table.keys()) |key| { try argv.append(key.status.success.object_path); diff --git a/src/main.zig b/src/main.zig index 335ca21142..c924b14b69 100644 --- a/src/main.zig +++ b/src/main.zig @@ -705,12 +705,9 @@ fn buildOutputType( var c_source_files = std.ArrayList(Compilation.CSourceFile).init(gpa); defer c_source_files.deinit(); - var link_objects = std.ArrayList([]const u8).init(gpa); + var link_objects = std.ArrayList(Compilation.LinkObject).init(gpa); defer link_objects.deinit(); - var must_link_objects = std.ArrayList([]const u8).init(gpa); - defer must_link_objects.deinit(); - var framework_dirs = std.ArrayList([]const u8).init(gpa); defer framework_dirs.deinit(); @@ -1241,7 +1238,7 @@ fn buildOutputType( } } else switch (Compilation.classifyFileExt(arg)) { .object, .static_library, .shared_library => { - try link_objects.append(arg); + try link_objects.append(.{ .path = arg }); }, .assembly, .c, .cpp, .h, .ll, .bc, .m, .mm => { try c_source_files.append(.{ @@ -1312,7 +1309,7 @@ fn buildOutputType( switch (file_ext) { .assembly, .c, .cpp, .ll, .bc, .h, .m, .mm => try c_source_files.append(.{ .src_path = it.only_arg }), .unknown, .shared_library, .object, .static_library => { - try link_objects.append(it.only_arg); + try link_objects.append(.{ .path = it.only_arg }); }, .zig => { if (root_src_file) |other| { @@ -1756,7 +1753,10 @@ fn buildOutputType( if (i >= linker_args.items.len) { fatal("expected linker arg after '{s}'", .{arg}); } - try must_link_objects.append(linker_args.items[i]); + try link_objects.append(.{ + .path = linker_args.items[i], + .must_link = true, + }); } else { warn("unsupported linker arg: {s}", .{arg}); } @@ -1851,7 +1851,7 @@ fn buildOutputType( const basename = fs.path.basename(c_source_files.items[0].src_path); break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; } else if (link_objects.items.len >= 1) { - const basename = fs.path.basename(link_objects.items[0]); + const basename = fs.path.basename(link_objects.items[0].path); break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; } else if (emit_bin == .yes) { const basename = fs.path.basename(emit_bin.yes); @@ -2054,7 +2054,7 @@ fn buildOutputType( test_path.items, @errorName(e), }), }; - try link_objects.append(try arena.dupe(u8, test_path.items)); + try link_objects.append(.{ .path = try arena.dupe(u8, test_path.items) }); break; } else { var search_paths = std.ArrayList(u8).init(arena); @@ -2447,7 +2447,6 @@ fn buildOutputType( .rpath_list = rpath_list.items, .c_source_files = c_source_files.items, .link_objects = link_objects.items, - .must_link_objects = must_link_objects.items, .framework_dirs = framework_dirs.items, .frameworks = frameworks.items, .system_lib_names = system_libs.keys(), |
