LibExeObjStep.linkLibC using wrong ELF interpreter
I'm working on a Zig project that dynamically links a C shared library. I'm having an issue where the the Zig binary produced uses the wrong ELF interpreter:
$ file ./zig-out/bin/memflow-shell
./zig-out/bin/memflow-shell: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /nix/store/q29bwjibv9gi9n86203s38n0577w09sx-glibc-2.33-117/lib/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, with debug_info, not stripped
It reports to be using glibc 2.33 for ld-linux which is wrong, it should be using 2.34 since this is what the current github:nixos/nixpkgs/nixos-unstable is using.
Running the executable confirms this:
$ ./zig-out/bin/memflow-shell run --exe ./zig-out/bin/test-exe.exe
./zig-out/bin/memflow-shell: /nix/store/q29bwjibv9gi9n86203s38n0577w09sx-glibc-2.33-117/lib/libc.so.6: version `GLIBC_2.34' not found (required by ./zig-out/bin/memflow-shell)
./zig-out/bin/memflow-shell: /nix/store/q29bwjibv9gi9n86203s38n0577w09sx-glibc-2.33-117/lib/libc.so.6: version `GLIBC_2.34' not found (required by /nix/store/31jas0sifmn3a39jrbmvi55xc4az1p33-memflow-0.2.0-beta5+db06869/lib/libmemflow_ffi.so)
What I really don't understand is the output of ldd when run against the Zig executable and the dynamic library being used:
$ ldd ./zig-out/bin/memflow-shell
linux-vdso.so.1 (0x00007ffd32114000)
libmemflow_ffi.so => /nix/store/31jas0sifmn3a39jrbmvi55xc4az1p33-memflow-0.2.0-beta5+db06869/lib/libmemflow_ffi.so (0x00007fa9e8ab7000)
libc.so.6 => /nix/store/hbvq1160w7k0k0cfpmpd1hn3gf6apika-glibc-2.34-115/lib/libc.so.6 (0x00007fa9e88b8000)
/nix/store/q29bwjibv9gi9n86203s38n0577w09sx-glibc-2.33-117/lib/ld-linux-x86-64.so.2 => /nix/store/hbvq1160w7k0k0cfpmpd1hn3gf6apika-glibc-2.34-115/lib64/ld-linux-x86-64.so.2 (0x00007fa9e8c1a000)
libgcc_s.so.1 => /nix/store/hbvq1160w7k0k0cfpmpd1hn3gf6apika-glibc-2.34-115/lib/libgcc_s.so.1 (0x00007fa9e889e000)
$ ldd /nix/store/31jas0sifmn3a39jrbmvi55xc4az1p33-memflow-0.2.0-beta5+db06869/lib/libmemflow_ffi.so
linux-vdso.so.1 (0x00007fff5432b000)
libgcc_s.so.1 => /nix/store/hbvq1160w7k0k0cfpmpd1hn3gf6apika-glibc-2.34-115/lib/libgcc_s.so.1 (0x00007fad9bdb6000)
libc.so.6 => /nix/store/hbvq1160w7k0k0cfpmpd1hn3gf6apika-glibc-2.34-115/lib/libc.so.6 (0x00007fad9bbb7000)
/nix/store/hbvq1160w7k0k0cfpmpd1hn3gf6apika-glibc-2.34-115/lib64/ld-linux-x86-64.so.2 (0x00007fad9bf33000)
The line /nix/store/q29bwjibv9gi9n86203s38n0577w09sx-glibc-2.33-117/lib/ld-linux-x86-64.so.2 => /nix/store/hbvq1160w7k0k0cfpmpd1hn3gf6apika-glibc-2.34-115/lib64/ld-linux-x86-64.so.2 (0x00007fa9e8c1a000) is confusing, it mentions glibc 2.33 and then points to glibc 2.34 which makes no sense.
I'm not sure if it's this overlay or my build.zig or what but if you have any ideas about this issue I'd appreciate it.
I just ran into the exact same problem and while I don't have a solution, I think I know what the issue is. zig-overlay depends on nixpkgs-unstable while you depend on nixos-unstable. As of this commit on Feb 27 to nixpkgs, glibc was bumped from 2.33-108 to 2.34-115. And as of this commit on Feb 8 it was bumped from 2.33-108 to 2.33-117, which is probably where your specific version came from. Not sure why it went back a version in between but it shouldn't matter. The commit to the new glibc 2.34 hasn't been backported into nixpkgs-unstable yet, so you are depending on glibc 2.34 but this project still has a nixpkgs with only glibc 2.33 in it.
This discrepancy in glibc versions is causing the weird linking, but it actually only got weirder for me from here. Setting my project's nixpkgs to nixpkgs-unstable works, by having both run on glibc 2.33. This obviously isn't optimal because then the rest of my packages will be on the older nixpkgs as well. However forcing zig-overlay to use nixos-unstable (as well as my project using nixos-unstable) still had the original weird behavior of mentioning both glibc 2.33 and glibc 2.34. Even after locally cloning zig-overlay, changing its flake.nix to use nixos-unstable, recreating its lockfile, and using it in my project, it did not want to use glibc 2.34. I do not know why downgrading is the only thing that worked.
I would suspect that if we can't figure out a solution, that some time in the future just running nix flake update and committing that to this repo would fix it.
Workarounds
Downgrading your project to libc 2.33
Match your nixpkgs version with zig-overlay's, by using nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";, as I talked about above.
Build zig from source
The zig package simply in nixpkgs seems to work fine with (either/any) version of glibc. If you need to run on zig master you can do something like this:
{
inputs = {
zig-src = {
url = "github:ziglang/zig";
flake = false;
};
};
...
# now inside `nativeBuildInputs`, for example:
(pkgs.zig.overrideAttrs (x: {
version = "master";
src = inputs.zig-src;
}))
}
This removes the dependency on zig-overlay but is kind of janky because it only works if they don't change the way zig is built upstream, as it just uses the same build steps as however way the current zig version is built on nixpkgs. It also takes a while to build zig from source, so this is really only still a temporary fix until zig-overlay is properly fixed.
Sidenote
I'm pretty sure that this is a nix/zig-overlay issue, and not an upstream issue with zig.
In my flake.nix nixos-unstable is being used transitively throughout all other Flake inputs so I don't see where glibc 2.33 is coming from at all.
nixpkgs/nixos-unstable appears to bring in glibc 2.33 for me, causing this issue. Using nixpkgs/nixos-21.11 instead worked for me.