Unresolved import when importing from a local crate with a main.rs file - rust

I have included a library as a submodule in my program. The structure looks like this:
.
├── my_lib/
├── Cargo.toml
└── src/
├── lib/
├── mod.rs
└── foo.rs
└── main.rs
├── src/
└── main.rs
└── Cargo.toml
In my program's Cargo.toml file I have added the dependency following this answer:
[dependencies]
my_lib = { path = "./my_lib" }
However I'm not able to use this library inside my program, I'm a bit new to Rust and this import system is very confusing to me. I've tried this in main.rs:
use my_lib::foo;
But I get an unresolved import 'my_lib' error.

A crate can be either a library or an executable, not both. Your my_lib contains a main.rs file, which means Cargo will treat it as an executable file. You cannot import from an executable.
You will need to restructure your code. Perhaps you actually meant for my_lib to be a library, in which case it should have a top-level lib.rs. You probably want to:
delete my_lib/src/main.rs
move my_lib/src/lib/mod.rs to my_lib/src/lib.rs
move my_lib/src/lib/foo.rs to my_lib/src/foo.rs
See also:
Rust package with both a library and a binary?

Related

error[E0601]: `main` function not found in crate for utilitary file for a custom binary

I have a custom binary called cli.rs and a file clap.rs with some utilities for clap.rs:
src
bin
cli.rs
clap.rs
where clap.rs just provides me with the clap definitions:
pub fn get_matches() -> ArgMatches {
}
fn main() {}
so I can import them into cli.rs.
However if I take out fn main from clap.rs I get
error[E0601]: `main` function not found in crate `clap`
I don't want clap.rs to have a main function, I just it to simply be a utils file for the binary cli.rs
From the cargo book about package layout:
Cargo uses conventions for file placement to make it easy to dive into a new Cargo package:
.
// ...
├── src/
| | // ...
│ └── bin/
│ ├── named-executable.rs
│ ├── another-executable.rs
│ └── multi-file-executable/
│ ├── main.rs
│ └── some_module.rs
| // ...
[...]
The default executable file is src/main.rs.
Other executables can be placed in src/bin/.
[...]
If a binary, example, bench, or integration test consists of multiple source files, place a main.rs file along with the extra modules within a subdirectory of the src/bin, examples, benches, or tests directory. The name of the executable will be the directory name.
By putting both cli.rs and clap.rs into bin/, you told Cargo that you have two binaries: One named cli, one named clap.
This package layout should work for you:
src
bin
cli
main.rs (that's your cli.rs)
clap.rs
Alternatively, you could also put clap.rs into a lib crate (by putting it inside lib/ and then putting pub mod clap; inside lib.rs). Note however that you then need to reference get_matches() as <your_package_name>::clap::get_matches() so that the compiler knows you are not referencing something from your binary crate, but something from your library crate.

Correct place for private module to be used by multiple executables

Two executables' sources, foo.rs and bar.rs, are located in src/bin.
Private common functionality exists in src/bin/common.rs.
foo.rs and bar.rs include this functionality with:
mod common;
use common::{Bish, Bash, Bosh};
This works, but src/bin/common.rs doesn't feel like the right path for something which isn't going to be built into an executable.
Moving common.rs to src or src/lib stops foo.rs and bar.rs from seeing it.
Where should I put common.rs and how do I then import it?
A common approach to store shared parts at lib.rs and use these in binaries. Its usage, though, is a bit different than simply mod + use. In fact, library is a separate crate, so you need to access it via crate name (defined in Cargo.toml).
Cargo.toml:
[package]
name = "crate-name"
# ... the rest
src/bin/foo.rs:
fn main() {
crate_name::fun();
}
src/lib.rs:
pub fn fun() {}
example
├── Cargo.toml
└── src
├── bin
│   ├── bar.rs
│   └── foo.rs
├── common.rs
└── lib.rs
foo.rs and bar.rs:
#[path = "../common.rs"]
mod common;
use common::{Bish, Bash, Bosh};
also see: How can I use a module from outside the src folder in a binary project, such as for integration tests or benchmarks?

What's the difference between binary and library in Rust? [duplicate]

This question already has an answer here:
What is the difference between library crates and normal crates in Rust?
(1 answer)
Closed 2 years ago.
What's the difference between binary and library in Rust?
I read The Cargo Book, but couldn't understand it well.
I generated two folders using cargo new a --bin and cargo new b --lib, however, both of them look the same inside. What are the purposes of --bin and --lib? And what are the difference between them?
A binary crate should generate an executable (or multiple) that can be installed in the user's path and can be executed as usual.
The purpose of a library crate on the other hand is not to create executables but rather provide functionality for other crates to depend on and use.
Also they do differ in their structure:
✦2 at [22:50:27] ➜ cargo new --bin somebinary
✦2 at [22:50:29] ➜ cargo new --lib somelib
Created library `somelib` package
✦2 at [22:50:34] ➜ tree somebinary/
somebinary/
├── Cargo.toml
└── src
└── main.rs
1 directory, 2 files
✦2 at [22:50:41] ➜ tree somelib/
somelib/
├── Cargo.toml
└── src
└── lib.rs
You can also find more information in this rust-lang forum thread: https://users.rust-lang.org/t/what-is-the-difference-between-cargo-new-lib-and-cargo-new-bin/19009
One creates an src/main.rs and other creates src/lib.rs. They are different in the nature of the files which are created. Differences lies in whether you are interested in creating a library or interested in creating a binary
Are you sure you ran those exact same commands?
(ins)temp->tree
.
├── a
│   ├── Cargo.toml
│   └── src
│   └── main.rs
└── b
├── Cargo.toml
└── src
└── lib.rs

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.
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.

How do I tell Cargo to build files other than main.rs?

Here is my directory structure:
lowks#lowkster ~/src/rustlang/gettingrusty $ tree .
.
├── Cargo.lock
├── Cargo.toml
├── foo.txt
├── src
│   ├── boolean_example.rs
│   ├── function_goodbye_world.rs
│   ├── listdir.rs
│   ├── looping.rs
│   ├── main.rs
│   ├── pattern_match.rs
│   └── write_to_file.rs
└── target
├── build
├── deps
├── examples
├── gettingrusty
└── native
6 directories, 11 files
When I run 'cargo build', it seems to only build main.rs. How should I change Cargo.toml to build the rest of the files too?
Put other.rs file into bin subfolder of src folder (./src/bin/other.rs). And run cargo build --bin other or cargo run --bin other
The Rust compiler compiles all the files at the same time to build a crate, which is either an executable or a library. To add files to your crate, add mod items to your crate root (here, main.rs) or to other modules:
mod boolean_example;
mod function_goodbye_world;
mod listdir;
mod looping;
mod pattern_match;
mod write_to_file;
To access items defined in another module from your crate root, you must qualify that item with the module name. For example, if you have a function named foo in module looping, you must refer to it as looping::foo.
You can also add use statements to import names in the module's scope. For example, if you add use looping::foo;, then you can just use foo to refer to looping::foo.
For more information, see Separating Modules into Different Files in The Rust Programming Language.
There are a few different types of binaries or targets that cargo recognizes:
binaries
libraries
benchmarks
integration tests
examples
For example, if the file boolean_example.rs is a standalone example that you want to run you can put in inside an examples directory and tell cargo about it like so:
[[example]]
name = "boolean" # examples/boolean.rs
This lets you invoke your example with cargo run --example boolean
Read the cargo book's page on package layout as well to see how these target directories can be structured.
you can include your testing in the main.rs file as following >>
Filename: src/main.rs
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn this_test_will_pass() {
let value = 4;
assert_eq!(4, value);
}
#[test]
fn this_test_will_fail() {
let value = 8;
assert_eq!(5, value);
}
}
Or call them from your tests file.
then run them using test command: cargo test
from filename: lib/tests.rs
mod tests;
tests::run();
in this case main.rs will be built but only tests.rs file will be
executed.
more prove:

Resources