Issue while using `.rlib` . Need help!

Hello,
I am trying to figure out how to use precompiled crate lib aka *.rlib. There is no complete document guide about it, sadly said so. Anyway, please help me why it emits the error. I am stuck. Thank you.

My project structure:

.
└── user_app/
    ├── Cargo.toml
    ├── build.rs
    └── .cargo/
        └── config.toml
    └── libs/
        └── libgreeting.rlib    #The pre-compiled rlib
    └── src/
        └── main.rs

My .cargo/config.toml:

[build]
rustflags = [
    "--extern", "greeting=/absolute_path_to_the_lib/libs/libgreeting.rlib",
    "-L", "native=/absolute_path_to_the_lib/libs"
]

My build.rs:

fn main() {
    println!("cargo:warning=BUILD SCRIPT IS RUNNING!");
    let crate_path = 
	std::path::Path::new("/absolute_path_to_the_lib/libs/libgreeting.rlib")
        .canonicalize()
        .expect("Failed to find libgreeting.rlib");

    println!("cargo:rustc-env=CRATE_MYLIB={}", crate_path.display());
    println!("cargo:rustc-link-lib=static=greeting");
    println!("cargo:rerun-if-changed=libs/libgreeting.rlib");
    println!("cargo:rustc-env=CRATE_MYLIB=/absolute_path_to_the_lib/libs/libgreeting.rlib");
}

My code declaration:

extern crate greeting;
use greeting::morning::GoodMorning;

fn main() {
...
}

cargo build always say:

error: extern location for greeting does not exist: libgreeting.rlib
 --> src/main.rs:1:1
  |
1 | extern crate greeting;
  | ^^^^^^^^^^^^^^^^^^^^^^

If I compile using rustc command then it is ok. But what I want is to use cargo because there will be other things to build as well.

rustc src/main.rs -L /absolute_path_to_the_lib/libs -L libgreeting.rlib

then why not add the crate as a cargo dependency? if you want to mix cargo builds with other build systems, there must be a clear boundary between the two worlds, which are then combined later at link time, and a well-defined ABI must be used (typically C ABI are used, it is possible to use Rust ABI, but not recommended, especially when artifacts from different build systems are mixed).

the --extern flags are managed by cargo itself, you should not manually specify --extern when invoking the compiler through cargo. quoting the section on the rustflags config setting:

It is not recommended to pass in flags that Cargo itself usually manages. For example, the flags driven by profiles are best handled by setting the appropriate profile setting.

Caution: Due to the low-level nature of passing flags directly to the compiler, this may cause a conflict with future versions of Cargo which may issue the same or similar flags on its own which may interfere with the flags you specify. This is an area where Cargo may not always be backwards compatible.

Thank you for the reply.

I try to use *.rlib because I want to test what if we distribute our library in pre-compiled version rather than full source code.

For the issue above, after some tries I came across it. The solution is to remove build.rs use and add one more line into config.toml as following:

"-L", "/absolute_path_to_the_lib/libs/libgreeting.rlib"

Then you'll need to distribute a separate version for every compiler version, at least. Rust ABI is unspecified, so rlibs from one version cannot in general be linked correctly by another one.

Another way, of course, is just to make a normal static library with C-like interface.

1 Like

Yes, it will be a challenge but at least now I know how use .rlib. Thanks.

Also note that the crate metadata leaks a lot of internals of your crate including all source file names + source locations + line widths, all internal types and many internal functions.

1 Like

The .rlib format distributes MIR, I thought? I'm not sure what the stability guarantees are on that, but I believe it's reasonably stable (or in the process of stabilizing).

Not sure about stable MIR, but rlibs contain both MIR (for generic and inlinable functions) and machine code (for non-generic functions).

1 Like

Stable MIR is entirely separate from regular MIR as encoded in the crate metadata. Stable MIR is not suitable for codegen and regular MIR is fully unstable. And the crate metadata contains a ton of other things outside of MIR that are unstable. It is basically a dump of many internal data structures. Rustc will refuse to load any crate metadata from a different rustc version even when there is only a single commit difference.

1 Like