C native library linking issue for Rust

Hi, I have a C native library linking issue for Rust. Let's say I have the following setup in a Linux system:

  1. A native C library (Lib A) which uses a custom build system
  2. A Rust wrapper (FFI) library (Lib B) to exports the functions of the above C library, a build.rs script is there to find the Lib A and link to Lib A statically
  3. A Rust library (Lib C) to use the Lib B and other libs for its work
  4. A binary (Bin D) which use Lib C to do its work

When I build the Bin D, I got the Undefined Reference error. The undefined references are just the functions in Lib A.

My question is, why the symbols that Bin D use are not linked to Lib B statically? I expect Lib B has all the required symbols and code, so all dependencies (Lib C and Bin D) can just use Lib B to work. What's the solution for this problem?

What does your build.rs script for Lib B look like?

That's common expectation but that's not how static libraries work on POSIX platforms. If you use library B and it depends on library A then you have to specify -lB -lA (in that order) in the command-line of the linker.

You may find approximately bazillion partial solutions on stackoverflow. Typical solution is to use pkgconfig or libtool but there are lots of other half-solutions.

But they are just the different ways to satisfy the basic requirement outlined above.

That issue is the reason C libraries often vendor in third-party code instead of using external libraries.

It looks like the following, but uses a special method to find path of Lib A.

println!("cargo:rustc-link-search={Lib A path}");

Lib A is the only native library, Lib B and Lib C are rust libraries, so seems it's not "-lB -lA" problem.

Are you using an absolute or relative path for {Lib A path}? I can't reproduce the issue if I use an absolute path.

I'm using absolute path for Lib A. The problem seems the Lib A is not linked to Lib B. I see there is a note for linking in Using C libraries in Rust: make a sys crate (kornel.ski), seems the static linking works in a very weird way.

The extern crate is implied by Lib C using any symbols from Lib B, and from Bin D using any symbols from Lib C.

It's odd that it isn't linking, though. What's the full output that you get from cargo build -v following a full cargo clean, including the rustc invocations?

Seems the problem is the system setup. When building Bin D, the path for Lib A is inaccessible somehow. I have to embed the Lib A into the Lib B, so it can always be found. The problem solved.

This raises another question. Is it possible to let a crate (Bin D) to use the compiled form (rlib, etc.) of its dependency (Lib B), so the crate (Bin D) won't need the original native library (Lib A) during linking?

I can't give you a conclusive answer, because I still have no clue what your setup looks like. But you might want to look into the --extern flag, which allows you to add additional rlibs to the compilation that you can import with extern crate B;. Note that if you're using static linking, then the object files from Lib A should be copied into the rlib in Lib B.