aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-01-13 17:57:56 +0100
committerJakub Konka <kubkon@jakubkonka.com>2022-01-13 20:02:11 +0100
commit5cde5f947fa12440463f684d9417ac00c8b9790a (patch)
tree4cc1ba8e54327060e7009a923e2c79faddf5d29e
parenta8564df9ed510f572732b8179844299fc3d3c11b (diff)
downloadzig-5cde5f947fa12440463f684d9417ac00c8b9790a.tar.gz
zig-5cde5f947fa12440463f684d9417ac00c8b9790a.zip
Introduce LinkObject with must_link field
-rw-r--r--src/Compilation.zig19
-rw-r--r--src/link.zig12
-rw-r--r--src/link/Coff.zig12
-rw-r--r--src/link/Elf.zig12
-rw-r--r--src/link/MachO.zig31
-rw-r--r--src/link/Wasm.zig12
-rw-r--r--src/main.zig19
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(),