Phoenix
Phoenix

Reputation: 1788

Refactoring to workspace structure causes extern crate imports to not work

I need different parts of my project to use different versions of the same extern crate so I'm refactoring my Rust project to be divided into multiple packages via the workspaces system using this as a guide. Doing so is causing all my pub extern crate imports to not work.

This post is very similar to one I created very recently and then deleted - this version contains a minimal, complete, and verifiable example.

Here's my project structure

workspace_test/
  root/
    src/
      main.rs
    Cargo.toml
  Cargo.toml

workspace_test/Cargo.toml:

[package]
name = "workspace_test"
version = "0.1.0"
authors = ["Phoenix <[email protected]>"]

[workspace]
members = [
    "root"
]

[[bin]]
name = "root"
path = "root/src/main.rs"

workspace_test/root/Cargo.toml:

[package]
name = "root"
version = "0.1.0"
authors = ["Phoenix <[email protected]>"]

[dependencies]
time = "0.1"

workspace_test/root/src/main.rs:

pub extern crate time;

fn main() {
    println!("Hello, world!");
}

This is also on github, so it can easily be cloned and cargo run'd.

This is the error:

error[E0463]: can't find crate for `time`
 --> root/src/main.rs:1:1
  |
1 | pub extern crate time;
  | ^^^^^^^^^^^^^^^^^^^^^^ can't find crate

error: aborting due to previous error

error: Could not compile `workspace_test`.

Upvotes: 0

Views: 1789

Answers (1)

Tim Diekmann
Tim Diekmann

Reputation: 8486

In workspace_test/Cargo.toml you create a package with the binary root. If you execute cargo run, it runs the main.rs, but since you didn't state the dependencies in this manifest file, the error occurs. The dependency is only specified in workspace_test/root/Cargo.toml, which is not used at this point.

I assume you want to use the workspaces proposed by the RFC. You can create a workspace with virtual manifests, which must neither specify a [package] nor [[bin]], so just remove them. workspace_test/Cargo.toml now looks like this:

[workspace]
members = [
    "root"
]

If you only have one executable, you can now pass the package: -p/--package

cargo run -p root

or specify the manifest path manually:

cargo run --manifest-path root/Cargo.toml

If root/Cargo.toml contains multiple targets, you can just append the --lib or --bin flags as usual. E.g. this would execute the abc-binary specified in workspace_test/root/Cargo.toml:

cargo run -p root --bin abc

Upvotes: 2

Related Questions