zig
zig copied to clipboard
`-lc` doesn't link `c_nonshared`
$ cat a.c
extern char __libc_single_threaded;
int main(void) {
return __libc_single_threaded;
}
$ clang a.c
$ zig build-exe a.c -lc
ld.lld: error: undefined symbol: __libc_single_threaded
>>> referenced by a.c:3
>>> /home/vexu/.cache/zig/o/00d791557252b46f5ed6668a930dc12a/a.o:(main)
error: LLDReportedFailure
Not sure how this works on other targets but on Arch Linux it means that building stage2 with system LLVM requires this patch:
diff --git a/build.zig b/build.zig
index 5896ab1a8..fb821ccf4 100644
--- a/build.zig
+++ b/build.zig
@@ -550,6 +550,7 @@ fn addCmakeCfgOptionsToExe(
else => |e| return e,
};
exe.linkSystemLibrary("unwind");
+ exe.linkSystemLibrary("c_nonshared");
} else if (exe.target.isFreeBSD()) {
try addCxxKnownPath(b, cfg, exe, "libc++.a", null, need_cpp_includes);
exe.linkSystemLibrary("pthread");
Arch uses glibc 2.35.
Looking through recent glibc changes related to c_nonshared I found https://github.com/bminor/glibc/commit/1a2f44a848663036c8a14671fe0faa3fed0b2a25. I wonder if this means that linking pthread previously implied c_nonshared, but it doesn't any more.
The proper fix is probably adding -lc_nonshared to libcFullLinkFlags() in src/target.zig if targeting glibc. I would like to understand exactly what's happening here though before doing that.
At least for me a default build of glibc contains libc_nonshared.a, but srcglibc.zig` does not contain it in the library list:
// The order of the elements in this array defines the linking order.
pub const libs = [_]Lib{
.{ .name = "m", .sover = 6 },
.{ .name = "pthread", .sover = 0 },
.{ .name = "c", .sover = 6 },
.{ .name = "dl", .sover = 2 },
.{ .name = "rt", .sover = 1 },
.{ .name = "ld", .sover = 2 },
.{ .name = "util", .sover = 1 },
};
Nevertheless, libc_nonshared.a is generated during building stage1.
How is Zig picking up the correct paths to the libcs etc in .cache? rg glibc inside the build folder of stage1 shows no results. Is the path picked up from calculating/combining some hashes?
Note that zig is perfectly capable of providing libc_nonshared.a... but in the case of native builds we don't do it because we want to actually integrate with system libc. So we're stuck figuring out what the various systems want from us.
On my glibc 2.32 void linux system /usr/lib/libc.so appears to be a linker script which pulls in libc_nonshared.a:
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /usr/lib64/libc.so.6 /usr/lib64/libc_nonshared.a AS_NEEDED ( /usr/lib64/ld-linux-x86-64.so.2 ) )
This might help explain things, in particular why I wasn't seeing any reference to libc_nonshared.a in gcc -v output on my system.
Ok, on my glibc 2.35 gentoo system cat /usr/lib/libc.so:
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf32-i386)
GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux.so.2 ) )
cat /usr/lib64/libc.so:
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /lib64/libc.so.6 /usr/lib64/libc_nonshared.a AS_NEEDED ( /lib64/ld-linux-x86-64.so.2 ) )
On Arch its similar
cat /usr/lib/libc.so
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /usr/lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /usr/lib/ld-linux-x86-64.so.2 ) )
cat /usr/lib64/libc.so
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /usr/lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /usr/lib/ld-linux-x86-64.so.2 ) )
file /usr/lib/ld-linux.so.2 symlinking to /usr/lib32/ld-linux.so.2 should not make a difference in this context.
$ cat a.c extern char __libc_single_threaded; int main(void) { return __libc_single_threaded; } $ clang a.c $ zig build-exe a.c -lc ld.lld: error: undefined symbol: __libc_single_threaded >>> referenced by a.c:3 >>> /home/vexu/.cache/zig/o/00d791557252b46f5ed6668a930dc12a/a.o:(main) error: LLDReportedFailure
Ah, and __libc_single_threaded was introduced in glibc 2.32
On my system, Zig is in fact providing libc_nonshared.a, but the symbol is still missing:
$ ./zig-linux-x86_64-0.9.1/zig build-exe test.c -lc --verbose-link
ld.lld -error-limit=0 -O0 -z stack-size=16777216 --gc-sections -m elf_x86_64 -o test /home/topolarity/.cache/zig/o/3bb4baaa7fdbd4d420aa2c0ea0b25896/Scrt1.o /home/topolarity/.cache/zig/o/f01eecd9f532c366e29902dc433e6bbc/crti.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 /home/topolarity/.cache/zig/o/4f097214eb5219ae4350051529af36b2/test.o /home/topolarity/.cache/zig/o/8e947370e0e9a95237b40481a6c38c41/libcompiler_rt.a --as-needed /home/topolarity/.cache/zig/o/b61716bae4d350e69e284aa7d351fe5d/libm.so.6 /home/topolarity/.cache/zig/o/b61716bae4d350e69e284aa7d351fe5d/libpthread.so.0 /home/topolarity/.cache/zig/o/b61716bae4d350e69e284aa7d351fe5d/libc.so.6 /home/topolarity/.cache/zig/o/b61716bae4d350e69e284aa7d351fe5d/libdl.so.2 /home/topolarity/.cache/zig/o/b61716bae4d350e69e284aa7d351fe5d/librt.so.1 /home/topolarity/.cache/zig/o/b61716bae4d350e69e284aa7d351fe5d/libld.so.2 /home/topolarity/.cache/zig/o/b61716bae4d350e69e284aa7d351fe5d/libutil.so.1 /home/topolarity/.cache/zig/o/fa5988d449df15a0a124339ef2635cc7/libc_nonshared.a /home/topolarity/.cache/zig/o/b569a0eace5a24dad59f9ea9da18f67d/crtn.o
ld.lld: error: undefined symbol: __libc_single_threaded
>>> referenced by test.c:3
>>> /home/topolarity/.cache/zig/o/4f097214eb5219ae4350051529af36b2/test.o:(main)
error: LLDReportedFailure
$
If I request a system library so that Zig integrates with system libc, the example actually works:
$ ./zig-linux-x86_64-0.9.1/zig build-exe test.c -lc -lz --verbose-link
ld.lld -error-limit=0 -O0 -z stack-size=16777216 --gc-sections -m elf_x86_64 -o test /usr/lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../lib/crt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../lib/crti.o -rpath /lib64 -rpath /lib -rpath /usr/lib64 -rpath /usr/lib -L /usr/local/lib64 -L /usr/local/lib -L /usr/lib/x86_64-linux-gnu -L /lib64 -L /lib -L /usr/lib64 -L /usr/lib -L /lib/x86_64-linux-gnu -L /usr/lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../lib -dynamic-linker /lib64/ld-linux-x86-64.so.2 /home/topolarity/.cache/zig/o/93bdf25300a52e9361dec6260fcb51e3/test.o /home/topolarity/.cache/zig/o/8e947370e0e9a95237b40481a6c38c41/libcompiler_rt.a --as-needed -lz -lm -lpthread -lc -ldl -lrt -lutil /usr/lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../lib/crtn.o
$
On my system, Zig is in fact providing
libc_nonshared.a, but the symbol is still missing:$ ./zig-linux-x86_64-0.9.1/zig build-exe test.c -lc --verbose-link ld.lld -error-limit=0 -O0 -z stack-size=16777216 --gc-sections -m elf_x86_64 -o test /home/topolarity/.cache/zig/o/3bb4baaa7fdbd4d420aa2c0ea0b25896/Scrt1.o /home/topolarity/.cache/zig/o/f01eecd9f532c366e29902dc433e6bbc/crti.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 /home/topolarity/.cache/zig/o/4f097214eb5219ae4350051529af36b2/test.o /home/topolarity/.cache/zig/o/8e947370e0e9a95237b40481a6c38c41/libcompiler_rt.a --as-needed /home/topolarity/.cache/zig/o/b61716bae4d350e69e284aa7d351fe5d/libm.so.6 /home/topolarity/.cache/zig/o/b61716bae4d350e69e284aa7d351fe5d/libpthread.so.0 /home/topolarity/.cache/zig/o/b61716bae4d350e69e284aa7d351fe5d/libc.so.6 /home/topolarity/.cache/zig/o/b61716bae4d350e69e284aa7d351fe5d/libdl.so.2 /home/topolarity/.cache/zig/o/b61716bae4d350e69e284aa7d351fe5d/librt.so.1 /home/topolarity/.cache/zig/o/b61716bae4d350e69e284aa7d351fe5d/libld.so.2 /home/topolarity/.cache/zig/o/b61716bae4d350e69e284aa7d351fe5d/libutil.so.1 /home/topolarity/.cache/zig/o/fa5988d449df15a0a124339ef2635cc7/libc_nonshared.a /home/topolarity/.cache/zig/o/b569a0eace5a24dad59f9ea9da18f67d/crtn.o ld.lld: error: undefined symbol: __libc_single_threaded >>> referenced by test.c:3 >>> /home/topolarity/.cache/zig/o/4f097214eb5219ae4350051529af36b2/test.o:(main) error: LLDReportedFailure $If I request a system library so that Zig integrates with system libc, the example actually works:
$ ./zig-linux-x86_64-0.9.1/zig build-exe test.c -lc -lz --verbose-link ld.lld -error-limit=0 -O0 -z stack-size=16777216 --gc-sections -m elf_x86_64 -o test /usr/lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../lib/crt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../lib/crti.o -rpath /lib64 -rpath /lib -rpath /usr/lib64 -rpath /usr/lib -L /usr/local/lib64 -L /usr/local/lib -L /usr/lib/x86_64-linux-gnu -L /lib64 -L /lib -L /usr/lib64 -L /usr/lib -L /lib/x86_64-linux-gnu -L /usr/lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../lib -dynamic-linker /lib64/ld-linux-x86-64.so.2 /home/topolarity/.cache/zig/o/93bdf25300a52e9361dec6260fcb51e3/test.o /home/topolarity/.cache/zig/o/8e947370e0e9a95237b40481a6c38c41/libcompiler_rt.a --as-needed -lz -lm -lpthread -lc -ldl -lrt -lutil /usr/lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../lib/crtn.o $
Can you please share output of ./zig-linux-x86_64-0.9.1/zig build-exe --show-builtin?
On my glibc 2.32 void linux system
/usr/lib/libc.soappears to be a linker script which pulls inlibc_nonshared.a:/* GNU ld script Use the shared library, but some functions are only in the static library, so try that secondarily. */ OUTPUT_FORMAT(elf64-x86-64) GROUP ( /usr/lib64/libc.so.6 /usr/lib64/libc_nonshared.a AS_NEEDED ( /usr/lib64/ld-linux-x86-64.so.2 ) )This might help explain things, in particular why I wasn't seeing any reference to
libc_nonshared.aingcc -voutput on my system.
I guess this will be fixed when https://github.com/ziglang/zig/issues/6469 will be fixed:
./zig targets | jq .native.triple: "x86_64-linux.5.18.14...5.18.14-gnu.2.19"
ldd --version: ldd (Gentoo 2.35-r8 p9) 2.35
./zig build-exe a.c -lc:
LLD Link... ld.lld: error: undefined symbol: __libc_single_threaded
>>> referenced by a.c:3 (/home/bratishkaerik/zig/build/a.c:3)
>>> /home/bratishkaerik/.cache/zig/o/ba6cf5a0f60a803a3277d1158d1d817f/a.o:(main)
./zig build-exe a.c -lc -target x86_64-linux.5.18.14...5.18.14-gnu.2.32 (and higher, like 2.34): no error
./zig build-exe a.c -lc -target x86_64-linux.5.18.14...5.18.14-gnu.2.35:
error: zig does not yet provide glibc version 2.35, the max provided version is 2.34
error: unable to build glibc shared objects: InvalidTargetGLibCVersion
Can you please share output of
./zig-linux-x86_64-0.9.1/zig build-exe --show-builtin?
Indeed, the wrong version of glibc is detected:
pub const os = std.Target.Os{
.tag = .linux,
.version_range = .{ .linux = .{
.range = .{
.min = .{
.major = 5,
.minor = 10,
.patch = 102,
},
.max = .{
.major = 5,
.minor = 10,
.patch = 102,
},
},
.glibc = .{
.major = 2,
.minor = 19,
.patch = 0,
},
}},
};
that's tracked separately in 6469
Could I get someone affected by this issue to check whether #12788 solves it?
Duplicate of #6469 since the example works as expected with -target native-native-gnu.2.34.