Can't use library in minimal workspace project

I am unable to import a library in my binary, even though they are in the same project. I read Chapter 7 of the Rust Book and several posts but I can't make it work.

I can reproduce the problem easily:

  1. cargo new crates_and_modules_snafu
  2. cd crates_and_modules_snafu
  3. echo "[workspace]" >> Cargo.toml
  4. cargo new --lib aaabbbccc (I made sure it does not exist on crates.io)

That last command automatically added aaabbbccc as a member in the workspace section of the root Cargo.toml. I kept the generated code in aaabbbccc/src/lib.rs as-is. I tried to use the add function it contains in src/main.rs with several declarations, they all fail:

Statement cargo build error
use aaabbbccc; no external crate aaabbbccc
use crate::aaabbbccc; no aaabbbccc in the root
use aaabbbccc::add; use of undeclared crate or module aaabbbccc
use crate::aaabbbccc::add; could not find aaabbbccc in the crate root

What use (or mod) statement(s) must I use to reference the function add in the library aaabbbccc of my workspace?

The critical difference here is between having one package with both a library crate and a binary crate, and having two packages, one crate containing a library and the other containing a binary crate.

If you had created a single package, then use aaabbbccc; (which is mostly useless because it doesn't shorten any paths) and use aaabbbccc::add; would have compiled. But since you have created two packages, you must declare the dependency from one package to the other.

In this case, because you have a root package and a library package below it, you need to put the following in crates_and_modules_snafu/Cargo.toml:

[dependencies]
aaabbbccc = { path = "aaabbbccc/" }

I believe the command cargo add --path aaabbbccc will also do this for you, but I haven't tested that.

Once you do that, you can refer to aaabbbccc::add from within crates_and_modules_snafu/src/main.rs.

3 Likes

Thanks, it works! TIL that entries under [workspace] are not automatically added as dependencies.

+For the record, using cargo add --path aaabbbccc also works but it:

  • does not add the trailing backslash
  • pins the current version

Two things to note here:

  • It is actually automatic in the other direction: if you add a path dependency on a subdirectory, then it becomes a workspace member automatically.
  • It can't turn members into dependencies in the general case, because it’s possible that the other member should have a dependency on the root package, rather than vice versa.

Dependency versions actually have no effect as long as path is present. Their purpose is that if you publish both packages to crates.io, then the path will be stripped and the version will be used instead. Of course, when you publish, you do need to make sure the version of the package and in the dependency is set appropriately, and if you aren't planning to publish, it would be better to remove version since it is unnecessary and unused.

3 Likes

I wonder if cargo add should leave off version if publish = false.

You mean cargo add --path specifically, I hope.