1

I want to find the libc.so file that's being used in a Rust build so that I can query it with --version. (Some libcs expose their version information via C macros, so an alternative for them would be to use the cc crate in a build script. But others like musl don't.)

I can figure out which libstd-*.so file a rust binary or library will be linked against. When this libstd.so is linked against the host's libc, then running ldd on it shows that libc.so. But when the host system is using glibc and the targeted environment is musl, this doesn't work ("Invalid ELF header"). Instead of ldd, I could instead use readelf -d or objdump -p on the libstd.so. But these only show the filename of the libc.so file it uses, not its full path. And that libc.so isn't at any of the directories in LD_LIBRARY_PATH. (I do know where it is on my own systems, but I'm trying to find it programmatically on arbitrary systems.)

Running ldconfig -p only gives me information about the libc for the host system.

It would be great if there were a rustc equivalent of gcc's and clang's -print-file-name=libc.so, so that I could do something like rustc --target=$TARGET --print-file-name=libc.so.

Other ideas about how I could get this information?

dubiousjim
  • 4,722
  • 1
  • 36
  • 34

1 Answers1

2

You can pass linker arguments to rustc like so:

rustc -C link-args=...

To find out which libc.so is used, I believe the following command should suffice:

rustc -C link-args=-Wl,-t ...

From man ld:

  -t
  --trace
       Print the names of the input files as ld processes them. ...

Update:

This didn't work: rustc "eats up" the output from the linker.

I was able to get the desired output indirectly:

echo 'fn main() { println!("")}' | rustc -C link-args=-Wl,-Map=map.out -o foo -
grep 'libc\.so' map.out
libc.so.6                     /usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-f25e49a311b0f577.rlib(std-f25e49a311b0f577.std.cy8lhng1-cgu.2.rcgu.o) (setuid@@GLIBC_2.2.5)
LOAD /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc.so
LOAD /lib/x86_64-linux-gnu/libc.so.6
Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • Hmm. `echo 'fn main() { println!("")}' | rustc -C link-args=-t -o foo --target=$TARG0 -` gives no output to stderr or stdout, though the resulting binary is linked against libc.so.6. (In fact, the body of main can be empty and it's still linked against libc.) – dubiousjim Apr 25 '20 at 19:45
  • @dubiousjim It sounds like `rustc` is "eating up" the linker output. You may need to add a `--verbose` or similar flag. – Employed Russian Apr 25 '20 at 20:03
  • Thanks! Here's a bit more minimized: `echo 'fn main() {}' | rustc -C link-args=-Wl,-Map=map.out -o /dev/null - && egrep '^LOAD .*/libc[-._]so' map.out`. I tried writing the map to `/dev/stdout`, but that didn't work. – dubiousjim Apr 25 '20 at 20:22
  • Unfortunately, though, if you add a `--target` flag to the `rustc` command, the resulting map file doesn't have any `.so` files in it. Even if the explicit target is the same as one's host system. Still, I think this is some progress and I appreciate even achieving that. – dubiousjim Apr 25 '20 at 20:28
  • Sorry, I was wrong. If the explicit target is the same as the host system, the `libc.so` is there in the map file. But not when the target is different, which is the case I'm seeking a solution for. – dubiousjim Apr 25 '20 at 21:14
  • [It appears](https://github.com/rust-lang/rust/pull/40113#issuecomment-284500764) that when the host is glibc rustc can only statically link musl targets. So neither the binary nor the map points to the musl libc. The `libstd-*.so` in `.../rustlib/$TARGET/lib` directory seems to be linked against the libc, but as I said in the initial Q, the tools I'm able to use to query it don't report a full path to that libc. Somehow I need to find out what library search path rustc is using when a `--target` is specified. It's not the value that's exposed to the file being built as `LD_LIBRARY_PATH`. – dubiousjim Apr 25 '20 at 22:37
  • For anyone who comes here later looking to do this too, I [opened an issue](https://github.com/rust-lang/rust/issues/71564) for rustc. Discussion there tells me that rustc's `x86_64-unknown-linux-musl` target doesn't use the system MUSL, but bundles its own copy/version. – dubiousjim Apr 26 '20 at 14:11