link.Lld: fix linking ELF shared libraries with -l on Windows

In Zig 0.17.0, we started lowering these to `-L/ -l:/path/to/lib.so` in
the LLD invocation, but that obviously doesn't work on Windows. Luckily,
LLD's, uh, curious approach to path concatenation means that we can just
pass `-L ""` instead of `-L/` and everything works.

Resolves: https://codeberg.org/ziglang/zig/issues/37257
This commit is contained in:
Matthew Lugg authored and mlugg committed 2026-10-26 10:26:58 +01:00
1 parent 94661e1cca
commit 8d6c05f8ec
2 files changed
+49 -1

No files matched your search

+4 -1
View File
@@ -1163,7 +1163,10 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {
// object, we pass it on the CLI as "-l:/absolute/path/to/libfoo.so". This will treat
// the given path not actually as an absolute path, but as relative to the library
// search path, so the root directory must therefore be the only library search path.
try argv.append("-L/");
switch (builtin.os.tag) {
.windows => try argv.appendSlice(&.{ "-L", "" }),
else => try argv.append("-L/"),
}
for (base.comp.link_inputs) |link_input| switch (link_input) {
.res => unreachable, // Windows-only
+45
View File
@@ -2484,6 +2484,51 @@ pub fn addCliTests(b: *std.Build) *Step {
step.dependOn(&run_test.step);
}
{
// Test (cross-)compiling for Linux using `-l` syntax. The build system only uses `-l` for
// system libraries (and therefore only for native builds), but it is possible and legal to
// use it when cross-compiling.
const tmp_path = b.tmpPath();
const build_libfoo = b.addSystemCommand(&.{
b.graph.zig_exe,
"build-lib",
"-target",
"x86_64-linux",
"-dynamic",
});
const libfoo = build_libfoo.addOutputFileArg2("libfoo.so", .{ .prefix = "-femit-bin=" });
build_libfoo.setCwd(tmp_path);
build_libfoo.setName("zig build-lib libfoo.so");
build_libfoo.expectStdOutEqual("");
build_libfoo.expectStdErrEqual("");
const build_libbar = b.addSystemCommand(&.{
b.graph.zig_exe,
"build-lib",
"-target",
"x86_64-linux",
"-dynamic",
});
build_libbar.addDirectoryArg2(libfoo.dirname(), .{ .prefix = "-L" });
build_libbar.addArg("-lfoo");
const libbar = build_libbar.addOutputFileArg2("libbar.so", .{ .prefix = "-femit-bin=" });
build_libbar.setCwd(tmp_path);
build_libbar.setName("zig build-lib libbar.so");
build_libbar.expectStdOutEqual("");
build_libbar.expectStdErrEqual("");
// We mainly just want to make sure the build commands complete successfully, but we may as
// well double-check that the output is a valid ELF file.
const check_libbar = b.addCheckFile(libbar, .{
.expected_matches = &.{"\x7fELF"},
});
step.dependOn(&check_libbar.step);
}
return step;
}