Skip to content

Commit a9c4677

Browse files
a-khabarovchrisirhc
authored andcommitted
link: make zig cc pass -l/-L like Clang/GCC for ELF
1 parent b7656de commit a9c4677

File tree

2 files changed

+33
-14
lines changed

2 files changed

+33
-14
lines changed

src/link.zig

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,6 +1609,8 @@ pub const Input = union(enum) {
16091609
needed: bool,
16101610
weak: bool,
16111611
reexport: bool,
1612+
name: ?[]const u8,
1613+
lib_directory: Directory,
16121614
};
16131615

16141616
pub const DsoExact = struct {
@@ -1661,6 +1663,8 @@ pub fn hashInputs(man: *Cache.Manifest, link_inputs: []const Input) !void {
16611663
man.hash.add(dso.needed);
16621664
man.hash.add(dso.weak);
16631665
man.hash.add(dso.reexport);
1666+
man.hash.addOptionalBytes(dso.name);
1667+
man.hash.addOptionalBytes(dso.lib_directory.path);
16641668
},
16651669
.dso_exact => |dso_exact| {
16661670
man.hash.addBytes(dso_exact.name);
@@ -1936,7 +1940,7 @@ fn resolveLibInput(
19361940
else => |e| fatal("unable to search for tbd library '{f}': {s}", .{ test_path, @errorName(e) }),
19371941
};
19381942
errdefer file.close();
1939-
return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query);
1943+
return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query, name_query.name, lib_directory);
19401944
}
19411945

19421946
{
@@ -1949,11 +1953,11 @@ fn resolveLibInput(
19491953
},
19501954
}),
19511955
};
1952-
try checked_paths.writer(gpa).print("\n {f}", .{test_path});
1953-
switch (try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, .{
1956+
try checked_paths.writer(gpa).print("\n {}", .{test_path});
1957+
switch (try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, lib_directory, target, .{
19541958
.path = test_path,
19551959
.query = name_query.query,
1956-
}, link_mode, color)) {
1960+
}, link_mode, color, name_query.name)) {
19571961
.no_match => {},
19581962
.ok => return .ok,
19591963
}
@@ -1974,7 +1978,7 @@ fn resolveLibInput(
19741978
}),
19751979
};
19761980
errdefer file.close();
1977-
return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query);
1981+
return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query, name_query.name, lib_directory);
19781982
}
19791983

19801984
// In the case of MinGW, the main check will be .lib but we also need to
@@ -1990,7 +1994,7 @@ fn resolveLibInput(
19901994
else => |e| fatal("unable to search for static library '{f}': {s}", .{ test_path, @errorName(e) }),
19911995
};
19921996
errdefer file.close();
1993-
return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query);
1997+
return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query, name_query.name, lib_directory);
19941998
}
19951999

19962000
return .no_match;
@@ -2002,6 +2006,8 @@ fn finishResolveLibInput(
20022006
file: std.fs.File,
20032007
link_mode: std.builtin.LinkMode,
20042008
query: UnresolvedInput.Query,
2009+
name: ?[]const u8,
2010+
lib_directory: Directory,
20052011
) ResolveLibInputResult {
20062012
switch (link_mode) {
20072013
.static => resolved_inputs.appendAssumeCapacity(.{ .archive = .{
@@ -2016,6 +2022,8 @@ fn finishResolveLibInput(
20162022
.needed = query.needed,
20172023
.weak = query.weak,
20182024
.reexport = query.reexport,
2025+
.name = name,
2026+
.lib_directory = lib_directory,
20192027
} }),
20202028
}
20212029
return .ok;
@@ -2035,8 +2043,8 @@ fn resolvePathInput(
20352043
color: std.zig.Color,
20362044
) Allocator.Error!?ResolveLibInputResult {
20372045
switch (Compilation.classifyFileExt(pq.path.sub_path)) {
2038-
.static_library => return try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, pq, .static, color),
2039-
.shared_library => return try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, pq, .dynamic, color),
2046+
.static_library => return try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, Directory.cwd(), target, pq, .static, color, null),
2047+
.shared_library => return try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, Directory.cwd(), target, pq, .dynamic, color, null),
20402048
.object => {
20412049
var file = pq.path.root_dir.handle.openFile(pq.path.sub_path, .{}) catch |err|
20422050
fatal("failed to open object {f}: {s}", .{ pq.path, @errorName(err) });
@@ -2072,10 +2080,12 @@ fn resolvePathInputLib(
20722080
resolved_inputs: *std.ArrayListUnmanaged(Input),
20732081
/// Allocated via `gpa`.
20742082
ld_script_bytes: *std.ArrayListUnmanaged(u8),
2083+
lib_directory: Directory,
20752084
target: *const std.Target,
20762085
pq: UnresolvedInput.PathQuery,
20772086
link_mode: std.builtin.LinkMode,
20782087
color: std.zig.Color,
2088+
name: ?[]const u8,
20792089
) Allocator.Error!ResolveLibInputResult {
20802090
try resolved_inputs.ensureUnusedCapacity(gpa, 1);
20812091

@@ -2100,7 +2110,7 @@ fn resolvePathInputLib(
21002110
const buf = ld_script_bytes.items[0..n];
21012111
if (mem.startsWith(u8, buf, std.elf.MAGIC) or mem.startsWith(u8, buf, std.elf.ARMAG)) {
21022112
// Appears to be an ELF or archive file.
2103-
return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query);
2113+
return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query, name, lib_directory);
21042114
}
21052115
const stat = file.stat() catch |err|
21062116
fatal("failed to stat {f}: {s}", .{ test_path, @errorName(err) });
@@ -2166,7 +2176,7 @@ fn resolvePathInputLib(
21662176
}),
21672177
};
21682178
errdefer file.close();
2169-
return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query);
2179+
return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query, name, lib_directory);
21702180
}
21712181

21722182
pub fn openObject(path: Path, must_link: bool, hidden: bool) !Input.Object {
@@ -2189,6 +2199,8 @@ pub fn openDso(path: Path, needed: bool, weak: bool, reexport: bool) !Input.Dso
21892199
.needed = needed,
21902200
.weak = weak,
21912201
.reexport = reexport,
2202+
.name = null,
2203+
.lib_directory = Directory.cwd(),
21922204
};
21932205
}
21942206

src/link/Lld.zig

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,10 +1179,17 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {
11791179
}
11801180

11811181
// By this time, we depend on these libs being dynamically linked
1182-
// libraries and not static libraries (the check for that needs to be earlier),
1183-
// but they could be full paths to .so files, in which case we
1184-
// want to avoid prepending "-l".
1185-
argv.appendAssumeCapacity(try dso.path.toString(arena));
1182+
// libraries and not static libraries (the check for that needs to be earlier).
1183+
if (dso.name) |name| {
1184+
if (dso.lib_directory.path) |path| {
1185+
argv.appendAssumeCapacity("-L");
1186+
argv.appendAssumeCapacity(path);
1187+
}
1188+
argv.appendAssumeCapacity(if (dso.weak) "-weak-l" else "-l");
1189+
argv.appendAssumeCapacity(name);
1190+
} else {
1191+
argv.appendAssumeCapacity(try dso.path.toString(arena));
1192+
}
11861193
},
11871194
};
11881195

0 commit comments

Comments
 (0)