How does rustc (not cargo) finds the external library file's name?

extern crate my_crate
fn main() {
  my_crate::run();
}

When compiling this code using rustc (and not cargo), lets say we invoke rustc using rustc --out-dir ./build main.rs -Ldeps, and the my_crate could be anything (rlib/dylib/cdylib), how would rustc know the exact filename of the specified crate? picture showing output of commands
I tested it with rlib and here are my observations:

Code:

// File: lib.rs
#![crate_type = "rlib"]
#![crate_name = "my_lib"]

pub fn run() {
    println!("Working!")
}
// File: main.rs
extern crate my_lib;

fn main() {
    my_lib::run();
}

Commands I used to compile these files (on windows):

C:/Users/Me/Desktop/Rust/Test> rustc lib.rs
C:/Users/Me/Desktop/Rust/Test> rustc main.rs -L.

Observations:

  1. Compiling the lib.rs file gave me a new file named libmy_lib.rlib.
  2. If I rename this file to libsomething.rlib, and in main.rs, I use extern crate something, the compilation fails.
  3. If I rename this file to libsomething.rlib, and leave everything else the same, the compilation still fails.

Basically if I keep the compiler generated name, and I have used the crate_name attribute while compiling the library, the compilation is successful, otherwise it would give compilation error.

The .rlib file is an ar archive. One of the files in the archive is a .rmeta file with information about the crate including its name. I believe rustc scans this metadata when searching for libraries. For more details, see: Libraries and Metadata - Rust Compiler Development Guide

You can use the --extern option to override the name in the metadata. For example, if you want extern crate something to refer to libsomething.rlib even though it originally had a different crate name, run:

rustc main.rs --extern something=./libsomething.rlib
1 Like

Makes sense. But then why does changing the rlib file name breaks the compilation?

When there is no explicit file provided via --extern, it seems the compiler starts by looking at the filenames of libraries in its search paths. Libraries with potentially-matching filenames are then scanned for matching metadata. According to this comment, the filename match is a heuristic to reduce the number of files the compiler needs to open and scan: