Nice example! Here is the reason why linkage fails:
$ nm -D /nix/store/ajyzs6yvw923wa3phimy56cid5y62szi-glibc-2.17/lib/libpthread.so | fgrep pthread_atfork
000000000000e370 T pthread_atfork@GLIBC_2.2.5
$ nm -D /nix/store/ajyzs6yvw923wa3phimy56cid5y62szi-glibc-2.17/lib/libpthread.so | fgrep sem_init
000000000000e4b0 T sem_init@@GLIBC_2.2.5
Note the presence and lack of @@
which signifies the default version of a symbol (the one should be used when no version is specified). This means default version of pthread_atfork
should come from somewhere else. In glibc-2.17
case it is libpthread_nonshared.a
:
$ nm /nix/store/ajyzs6yvw923wa3phimy56cid5y62szi-glibc-2.17/lib/libpthread_nonshared.a
pthread_atfork.oS:
0000000000000000 T pthread_atfork
...
If you add a -Wl,-t
to your linker command you will see that libpthread_nonshared.a
does not get pulled in:
--- a/flake.nix
+++ b/flake.nix
@@ -78,7 +78,7 @@
n=$out/bin/$name
mkdir -p "$(dirname "$n")"
mv "$codePath" code.c
- $CC -pthread code.c -o "$n"
+ $CC -pthread code.c -o "$n" -Wl,-t
'';
});
link-pthread-atfork> /nix/store/ajyzs6yvw923wa3phimy56cid5y62szi-glibc-2.17/lib/crt1.o
link-pthread-atfork> /nix/store/ajyzs6yvw923wa3phimy56cid5y62szi-glibc-2.17/lib/crti.o
link-pthread-atfork> /nix/store/h5kvfrjmpw792v8jg7nrzfkffmn0iyy8-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/crtbegin.o
link-pthread-atfork> /build/ccDarPNX.o
link-pthread-atfork> /nix/store/h5kvfrjmpw792v8jg7nrzfkffmn0iyy8-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/libgcc.a
link-pthread-atfork> /nix/store/xq05361kqwzcdamcsxr4gzg8ksxrb8sg-gcc-12.3.0-lib/lib/libgcc_s.so
link-pthread-atfork> /nix/store/xq05361kqwzcdamcsxr4gzg8ksxrb8sg-gcc-12.3.0-lib/lib/libgcc_s.so.1
link-pthread-atfork> /nix/store/h5kvfrjmpw792v8jg7nrzfkffmn0iyy8-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/libgcc.a
link-pthread-atfork> /nix/store/ajyzs6yvw923wa3phimy56cid5y62szi-glibc-2.17/lib/libpthread.so
link-pthread-atfork> /nix/store/ajyzs6yvw923wa3phimy56cid5y62szi-glibc-2.17/lib/libc.so
link-pthread-atfork> /nix/store/ajyzs6yvw923wa3phimy56cid5y62szi-glibc-2.17/lib/libc.so.6
link-pthread-atfork> /nix/store/ajyzs6yvw923wa3phimy56cid5y62szi-glibc-2.17/lib/libc_nonshared.a
link-pthread-atfork> /nix/store/ajyzs6yvw923wa3phimy56cid5y62szi-glibc-2.17/lib/ld-linux-x86-64.so.2
link-pthread-atfork> /nix/store/ajyzs6yvw923wa3phimy56cid5y62szi-glibc-2.17/lib/libc_nonshared.a
link-pthread-atfork> /nix/store/ajyzs6yvw923wa3phimy56cid5y62szi-glibc-2.17/lib/ld-linux-x86-64.so.2
link-pthread-atfork> /nix/store/h5kvfrjmpw792v8jg7nrzfkffmn0iyy8-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/libgcc.a
link-pthread-atfork> /nix/store/xq05361kqwzcdamcsxr4gzg8ksxrb8sg-gcc-12.3.0-lib/lib/libgcc_s.so
link-pthread-atfork> /nix/store/xq05361kqwzcdamcsxr4gzg8ksxrb8sg-gcc-12.3.0-lib/lib/libgcc_s.so.1
link-pthread-atfork> /nix/store/h5kvfrjmpw792v8jg7nrzfkffmn0iyy8-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/libgcc.a
link-pthread-atfork> /nix/store/h5kvfrjmpw792v8jg7nrzfkffmn0iyy8-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/crtend.o
link-pthread-atfork> /nix/store/ajyzs6yvw923wa3phimy56cid5y62szi-glibc-2.17/lib/crtn.o
link-pthread-atfork> /nix/store/74y3751gsixaz9797ib0hp7c658sp1y5-binutils-2.40/bin/ld: /build/ccDarPNX.o: in function `main':
link-pthread-atfork> code.c:(.text.startup+0x5): undefined reference to `pthread_atfork'
link-pthread-atfork> collect2: error: ld returned 1 exit status
Normally libpthread_nonshared.a
is expected to be supplied via libpthread.so
(it should be a linker script). Just like libc_nonshared.a
is provided via libc.so
linker script.
But glibc-2.38
derivation in nixpkgs
clobbers it for you with a backwards compatibility symlink:
# Backwards-compatibility to fix e.g.
# "configure: error: Pthreads are required to build libgomp" during `gcc`-build
# because it's not actually needed anymore to link against `pthreads` since
# it's now part of `libc.so.6` itself, but the gcc build breaks if
# this doesn't work.
ln -sf $out/lib/libpthread.so.0 $out/lib/libpthread.so
ln -sf $out/lib/librt.so.1 $out/lib/librt.so
ln -sf $out/lib/libdl.so.2 $out/lib/libdl.so
ln -sf $out/lib/libutil.so.1 $out/lib/libutil.so
touch $out/lib/libpthread.a
You need to remove all of that block. I’ll remove just the symlink to illustrate the difference. Example hack:
--- a/packages/glibc/default.nix
+++ b/packages/glibc/default.nix
@@ -18,9 +18,11 @@ let
./fix-configure.patch
];
in
-glibc.overrideAttrs (_: {
+glibc.overrideAttrs (oa: {
inherit (glibc-2_17) name src configureFlags postPatch;
version = "2.17";
patches = oldPatches ++ backportPatches ++ localPatches;
+ # remove harmful compat symlink hacks
+ postInstall = lib.replaceStrings ["ln -sf $out/lib/libpthread.so.0 $out/lib/libpthread.so"] [""] oa.postInstall;
})
That way the linker script is restored and you get the linkage succeeded:
link-pthread-atfork> /nix/store/ppny4fbad8rsq2dywl7cgs092j58h7fx-glibc-2.17/lib/crt1.o
link-pthread-atfork> /nix/store/ppny4fbad8rsq2dywl7cgs092j58h7fx-glibc-2.17/lib/crti.o
link-pthread-atfork> /nix/store/h5kvfrjmpw792v8jg7nrzfkffmn0iyy8-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/crtbegin.o
link-pthread-atfork> /build/ccPZwXYG.o
link-pthread-atfork> /nix/store/h5kvfrjmpw792v8jg7nrzfkffmn0iyy8-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/libgcc.a
link-pthread-atfork> /nix/store/xq05361kqwzcdamcsxr4gzg8ksxrb8sg-gcc-12.3.0-lib/lib/libgcc_s.so
link-pthread-atfork> /nix/store/xq05361kqwzcdamcsxr4gzg8ksxrb8sg-gcc-12.3.0-lib/lib/libgcc_s.so.1
link-pthread-atfork> /nix/store/h5kvfrjmpw792v8jg7nrzfkffmn0iyy8-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/libgcc.a
link-pthread-atfork> /nix/store/ppny4fbad8rsq2dywl7cgs092j58h7fx-glibc-2.17/lib/libpthread.so
link-pthread-atfork> /nix/store/ppny4fbad8rsq2dywl7cgs092j58h7fx-glibc-2.17/lib/libpthread.so.0
link-pthread-atfork> /nix/store/ppny4fbad8rsq2dywl7cgs092j58h7fx-glibc-2.17/lib/libpthread_nonshared.a
link-pthread-atfork> /nix/store/ppny4fbad8rsq2dywl7cgs092j58h7fx-glibc-2.17/lib/libpthread_nonshared.a
link-pthread-atfork> /nix/store/ppny4fbad8rsq2dywl7cgs092j58h7fx-glibc-2.17/lib/libc.so
link-pthread-atfork> /nix/store/ppny4fbad8rsq2dywl7cgs092j58h7fx-glibc-2.17/lib/libc.so.6
link-pthread-atfork> /nix/store/ppny4fbad8rsq2dywl7cgs092j58h7fx-glibc-2.17/lib/libc_nonshared.a
link-pthread-atfork> /nix/store/ppny4fbad8rsq2dywl7cgs092j58h7fx-glibc-2.17/lib/ld-linux-x86-64.so.2
link-pthread-atfork> /nix/store/ppny4fbad8rsq2dywl7cgs092j58h7fx-glibc-2.17/lib/libc_nonshared.a
link-pthread-atfork> /nix/store/ppny4fbad8rsq2dywl7cgs092j58h7fx-glibc-2.17/lib/ld-linux-x86-64.so.2
link-pthread-atfork> /nix/store/h5kvfrjmpw792v8jg7nrzfkffmn0iyy8-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/libgcc.a
link-pthread-atfork> /nix/store/xq05361kqwzcdamcsxr4gzg8ksxrb8sg-gcc-12.3.0-lib/lib/libgcc_s.so
link-pthread-atfork> /nix/store/xq05361kqwzcdamcsxr4gzg8ksxrb8sg-gcc-12.3.0-lib/lib/libgcc_s.so.1
link-pthread-atfork> /nix/store/h5kvfrjmpw792v8jg7nrzfkffmn0iyy8-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/libgcc.a
link-pthread-atfork> /nix/store/h5kvfrjmpw792v8jg7nrzfkffmn0iyy8-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/crtend.o
link-pthread-atfork> /nix/store/ppny4fbad8rsq2dywl7cgs092j58h7fx-glibc-2.17/lib/crtn.o
Note the presence of libpthread_nonshared.a
in the trace now.
Hope that helps a bit.