rustlinear-algebrarust-cargolapack

Why does using `extern` allow for runtime linking?


I have this code snippet:

    extern crate blas;
    extern crate openblas_src;
    pub fn eigen_decompose_symmetric_tri_diagonal(
        main_diag: &Vec<f64>,
        sub_diag: &Vec<f64>,
    )
    {
     /* code */
    lapack::dsteqr(/* args */);
    /* code */
    }

That uses a lapack binding. What I don't understand is, if I comment out the two extern statements I get a linker error where dsteqr is not found. I would like to understand why this happens.


Solution

  • The compiler will not end up linking a dependency if it thinks it is unused.

    In the rustc book on the --extern parameter (which is how Cargo provides dependencies):

    Specifying --extern has one behavior difference from extern crate: --extern merely makes the crate a candidate for being linked; it does not actually link it unless it's actively used. In rare occasions you may wish to ensure a crate is linked even if you don't actively use it from your code: for example, if it changes the global allocator or if it contains #[no_mangle] symbols for use by other programming languages. In such cases you'll need to use extern crate.

    So adding extern crate openblas_src; ensures it will link to the openblas system library.

    This isn't normally a problem that you need to worry about though. If you add a cargo dependency and simply don't use it its probably best that it doesn't require that runtime linkage. And even if you don't directly use a -sys crate, using a crate that itself depends on and uses it will consider it "used" and automatically be linked.

    Encountering this error is fairly unique to blas/lapack because there are competing system libraries (accelerate, blis, intel-mkl, netlib, openblas) that provide the functionality that the higher-level libraries rely on. The blas/lapack crates rely on their -sys counterparts, but those are only function declarations and are lacking links= to a particular system library. Thus they simply rely on global symbols to tie them at link-time, which as indicated above, won't be guaranteed unless extern crate is added by the end-user for one of the -src implementation crates. A bit more info on their blas-lapack-rs wiki.