soplu
soplu

Reputation: 145

Importing non-root module from multiple non-root binaries

I am learning Rust and decided to write a simple client/server program. Both the client and the server will be using a very simple module I've already written. Knowing that this code might grow, I decided to compartmentalize my source for clarity. Right now my current hierarchy looks as follows:

├── Cargo.lock
├── Cargo.toml
├── README.md
├── src
│   ├── client
│   │   └── main.rs
│   ├── common
│   │   ├── communicate.rs
│   │   └── mod.rs
│   ├── lib.rs
│   └── server
│       └── main.rs

Many of the examples I found on Stack Overflow and the net provide great samples for when the main.rs is in the project root directory. Unfortunately I'm trying to do something different as shown above.

communicate.rs contains all of the network code I have written. Eventually I will add other Rust files here and include their public mod statement in mod.rs. Currently common/mod.rs all I have is pub mod communicate;

Focusing on just the client folder, all I have is main.rs as shown. The file "header" lists

extern crate common;

use std::thread;
use std::time;
use std::net;
use std::mem;

use common::communicate;

pub fn main() {
   // ...
}

Besides the fundamental [package] section, all I have in Cargo.toml is

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

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

When I try to build the client binary, the compiler complains that the common crate could not be found.

$ cargo build 
   Compiling clientserver v0.1.0 (file:///home/soplu/rust/RustClientServer)
client/main.rs:1:1: 1:21 error: can't find crate for `common` [E0463]
client/main.rs:1 extern crate common;
                 ^~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
error: Could not compile `clientserver`.

To learn more, run the command again with --verbose.

I think this is because it is looking for a common crate within the client/ folder. I had this same problem when I tried the mod statement instead of extern crate statement.

use std::thread;
use std::time;
use std::net;
use std::mem;

mod common;

Gave me:

client/main.rs:6:5: 6:11 error: file not found for module `common`
client/main.rs:6 mod common;
                     ^~~~~~
client/main.rs:6:5: 12:11 help: name the file either common.rs or common/mod.rs inside the directory "client"

I also tried (using the extern crate...) adding a lib.rs in the client whose contents are pub mod common; but I still get the same error as the first.

One potential solution I found to model it like this project, but this would require a Cargo.toml in every folder, something which I'd like to avoid.

I feel like I am close but am missing something.

Upvotes: 3

Views: 1019

Answers (1)

Francis Gagné
Francis Gagné

Reputation: 65752

You are not building common as a crate right now. The crates being built are the library clientserver (the default name for the library is the package name) and the binaries client and server.

Normally, extern crate clientserver; should work. However, if you want to name your library differently, you can do so by specifying a different name in a [lib] section in Cargo.toml. In this section, you can also specify a different source path for the library's main source file. In your case, it will probably be better, otherwise you'll end up with a crate named common and all of its contents would be in a module named common, so you'd have to access everything as common::common::foo. For example, by adding this to your Cargo.toml:

[lib]
name = "common"
path = "src/common/lib.rs"

you could combine src/lib.rs and src/common/mod.rs into src/common/lib.rs. Then, extern crate common; should work in your binaries.

Upvotes: 1

Related Questions