Accessing a library from an additional executable

I've a project set up as follows:

# Cargo.toml
[package]
name = "rstest"
version = "0.1.0"

// src/mylib.rs
pub fn hello() -> String {
    "Hello, world!".to_string()
}
// src/lib.rs
mod mylib;

#[cfg(test)]
mod tests {
    use mylib::*;

    #[test]
    fn test_hello() {
        let s = hello();
        assert_eq!(s, "Hello, world!".to_string());
    }
}

With this set up, cargo test runs as expected. I now want to add an additional executable:

// src/bin/app.rs
fn main() {
    use std::io::{stdin,stdout,Write};
    use self::hello;

    println!("{}", hello());
    println!("Goodbye, world!");
}

This fails to compile:

error[E0432]: unresolved import `self::hello`
 --> src/bin/app.rs:3:9
  |
3 |     use self::hello;
  |         ^^^^^^^^^^^ no `hello` in the root

This is no doubt a dumb question for most of you, but what form of use statement is needed to get app.rs to compile? I also tried super without success.

Thanks and regards,

Vinay Sajip

Did you tried use rstest::hello;?
IIRC, executables in src/bin is treated as independent crate from lib.rs.

(If you are using edition 2015 (i.e. Cargo.toml does not contain edition = "2018"), you may also need extern crate rstest;.)

Thanks for the tip. I used use rstest::mylib::hello; and it compiled and ran OK. I'm surprised that one can't use some sort of relative reference, though - if I were to rename the crate, it would require changes in two places now for everything to work.

Regards,

Vinay Sajip

right: binaries and examples are considered separate crates for the sake of compilation, so using from the library has to be done by its full crate name

there could be a special keyword for this, but there isn't; as you say, this is a disadvantage when renaming, the advantage is that separating out the binary/example code to a new crate is easier

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.