3

I'm specifying the -Cpanic=abort and -Zbuild-std=panic_abort when compiling. Why does the linker still say it needs libunwind to compile a program?

I'm experimenting with various ways to cross-compile Rust programs as small as possible (using the min-sized-rust repo as a reference). Right now I'm trying to compile the powerpc64-unknown-linux-musl target and I'm stuck on trying to remove a dependency on libunwind.

Here's my setup:

# 1. Install the Rust std source code
rustup component add rust-src --toolchain nightly
# 2. Setup a simple rust repo
cargo init testing
cd testing
# 3. Download a musl toolchain
wget https://musl.cc/powerpc64-linux-musl-cross.tgz
tar xzf powerpc64-linux-musl-cross.tgz
# 4. Try to compile the project (options on the command line instead of in files for
# maximum obviousness).
# RUSTFLAGS:
#  -Cpanic=abort - abort immediately on panic
#  -Clink-self-contained=no - don't use rustc's builtin libraries and objects (this
#    is needed because powerpc64-unknown-linux-musl is a tier 3 target)
#  -Clink-arg=--sysroot and -Clink-arg=/path/to/sysroot - pass the option to the linker
#    to specify the sysroot of cross-compilation toolchain
# Cargo options:
#  --config target.<triple>.linker - specify the linker to use
#  -Zbuild-std=std,panic_abort - build the standard library from source. Specify
#    panic_abort to make the abort on panic work
RUSTFLAGS="-Cpanic=abort -Clink-self-contained=no -Clink-arg=--sysroot -Clink-arg=powerpc64-linux-musl-cross/powerpc64-linux-musl/" \
cargo +nightly build \
    --config "target.powerpc64-unknown-linux-musl.linker=\"powerpc64-linux-musl-cross/bin/powerpc64-linux-musl-gcc\"" \
    --target powerpc64-unknown-linux-musl -Zbuild-std=panic_abort,std --release

This fails with the following error:

error: linking with `/home/user/Projects/testing/powerpc64-linux-musl-cross/bin/powerpc64-linux-musl-gcc` failed: exit status: 1

<output snipped>

  = note: /home/user/Projects/testing/powerpc64-linux-musl-cross/bin/../lib/gcc/powerpc64-linux-musl/11.2.1/../../../../powerpc64-linux-musl/bin/ld: cannot find -lunwind
irontigran
  • 31
  • 4

1 Answers1

2

From min-size-rust repository: "Even if panic = "abort" is specified in Cargo.toml, rustc will still include panic strings and formatting code in final binary by default. An unstable panic_immediate_abort feature has been merged into the nightly rustc compiler to address this.

To use this, repeat the instructions above to use build-std, but also pass the following -Z build-std-features=panic_immediate_abort option."

Still, you will get "cannot find -lunwind", because the linker still uses libunwind, even though it's truly unneeded,why! I do not know, maybe it's a bug.(Maybe someone with fair knowledge about linkers can easily solve that.I tried a naive solution which is "cargo .... --verbose", copy , remove "libunwind" then relinking which failed)

I verified that is indeed the missing piece by build from source(--target=x86_64-unknown-linux-musl) AND using an old simple trick which is "touch libunwind.a" in the "self-contained" directory inside a target lib folder.(because the linker would still use it even though it's now truly unneeded, then I gave him a dummy libunwind.a)

In your case, I really tried to build it to your target until I got a headache, but couldn't and stopped, but here is possible solutions:

Giving that you're using "-Z build-std-features=panic_immediate_abort" -If you can custom the linking process, then solve it (until what seems to be a bug is solved) -Create a dummy(empty) libunwind.a where it should be in your toolchain

Alyegdry
  • 21
  • 2
  • 1
    And overall users cross-compiling experience would be a piece of cake if Rust would just make direct system calls (like Go, and I think Zig) instead of using libc to do that. – Alyegdry Oct 13 '22 at 18:15
  • And imagine if they do that and fix this libunwind still being used, we would just do (--target=whatever), it's a dream. I'm still waiting for Rust to do that, they will, won't they?! – Alyegdry Oct 13 '22 at 18:17
  • 1
    I forget to mention that when using -Z build-std-features=panic_immediate_abort I got a much smaller size => 34K (and when targeting x86_64-unknown-linux-gnu => 22K), and using utilities like sstrip and UPX I got as small as 17K,12K respectively. uname: Linux Arch 5.19.11-arch1-1 x86_64 GNU/Linux – Alyegdry Oct 13 '22 at 18:25
  • 1
    Ah, good catch on the -Zbuild-std-features=panic_immediate_abort - I found that option a couple days after asking the question and forgot to update the question. – irontigran Oct 14 '22 at 21:27
  • 1
    I tried `touch powerpc64-linux-musl-cross/powerpc64-linux-musl/lib/libunwind.a` and adding `-Zbuild-std-features=panic_immediate_abort`, but got back errors related to undefined symbols, like this: `/home/user/Projects/testing/powerpc64-linux-musl-cross/bin/../lib/gcc/powerpc64-linux-musl/11.2.1/../../../../powerpc64-linux-musl/bin/ld: std.3c071ad7-cgu.3:(.text._ZN3std9backtrace9Backtrace6create28_$u7b$$u7b$closure$u7d$$u7d$17h5eb8fbdbdfa2f8dbE.llvm.4342602629774762248+0x17c): undefined reference to `_Unwind_FindEnclosingFunction'`. So the linker is still trying to resolve libunwind symbols – irontigran Oct 16 '22 at 00:21
  • Then try to modify the linker args, or as I said this may be considerd a bug in the first place. – Alyegdry Oct 16 '22 at 18:24
  • See https://github.com/rust-lang/rust/issues/103673 for the root cause. – Arto Bendiken Feb 15 '23 at 02:46