This question already has answers here:
What are the valid path roots in the use keyword?
(2 answers)
Closed 4 years ago.
I want to separate the application logic to keep my main.rs file clean. I am using diesel for a simple project and I have the following files inside /src folder
main.rs
lib.rs
models.rs
schema.rs
I tried declaring the modules inside main.rs file and using them in the lib.rs file but that produces the following error:
unresolved import models; no models external crate [E0432]
main.rs looks like this:
pub mod lib;
pub mod schema;
pub mod models;
lib.rs produces error with this:
pub use models;
pub use schema::sent_sms;
I do not understand why things need to be so awfully complicated in this language, or maybe I am too stupid to understand it.
Please help me understand.
The main part of this answer was moved to the duplicate question!
So your problem is that use models; looks for models relative to the current module (lib). But models is not a sub module of lib, but of main. So the correct way to refer to these top level modules is like that:
use crate::{
models,
schema::sent_sms,
};
Additional notes:
If you have a executable project and just need a module to have some utility functions in, you usually wouldn't call it lib as that name is the default name for library crates' roots.
This use statement behavior changed with Rust 2018 (≥ 1.31))
Read this guide for more information about use statements and how they changed in Rust 2018
Related
So I want to have some modules defined in lib.rs but not make them public but only available for use within the project.
in my lib.rs, if I have the definition as this:
pub mod args;
in my main.rs, I can use the args modules this way:
use my_lib::args::Cli;
where my_lib is defined in Cargo.tml as
[lib]
name = "my_lib"
path = "src/lib.rs"
but I don't want pub mod args;. I tried changing to pub(crate) mod args; but this leads to compilation error that the args module cannot be found.
How do I make a module like args defined in lib.rs available without have to give it the most permissive visibility?
Since Rust separates the library lib.rs and binary main.rs into separate crates there is no simple way to include things that are in lib.rs and not pub from main.rs.
I suggest you follow the way of big crates (serde comes to mind) and add a pub mod __private; which conveys the meaning. You can additionaly annotate it with #[doc(hidden)] to hide it from the documentation making it even more obvious.
I'm looking for a convenience method to include all the Rust files in a given folder into my mod.rs file automatically. My folder structure looks like the following:
views/
mod.rs
view1.rs
view2.rs
view3.rs
Is there something like pub mod ** which would be equivalent to writing pub mod view1.rs, pub mod view2.rs and pub mod view3.rs? Just trying to save a little extra time here, since any rs file I put in this folder I want to be included in that module.
There is no build in language feature for implicitly picking up all files in a folder. You could write a procedural macro iterating over directory entries and generating use viewX statements, but I would dis-advice invoking that much magic, for a bit of convenience.
On another node. Rust does allow you to declare the module in a views.rs file which would be located next to the views folder in the hierarchy.
Is it possible to call a function defined in main.rs (like main itself) from lib.rs? If yes, how? The only information that I found was this from more than a year ago:
However it does appear that the importing behavior doesn't work the
other way. I.e. if you declare some public module in src/main.rs, you
can't import it into the src/lib.rs crate even when you specify the
name of the crate. I couldn't find documentation describing this
behavior but by testing it in Rust 1.37.0, it does appear to be the
case.
This question already has answers here:
How do I do a basic import/include of a function from one module to another in Rust 2015?
(3 answers)
Split a module across several files
(7 answers)
How can I include a module from another file from the same project?
(6 answers)
Closed 5 years ago.
How do I include a file with the full path my_project/src/include_me.rs in main.rs?
I've checked the dependencies guide, and all of them appear to be including a binary. I've also checked "The Book", but none of the examples there end in ".rs" either.
How do I make include_me.rs compile with the rest of the project?
There are basically two (main) ways in Rust to include code from somewhere else:
1. "Including" internal code
If your include_me.rs belongs to your project, you should move it to the same folder main.rs lies in:
└── src
├── include_me.rs
└── main.rs
Then you can write this in your main.rs:
mod include_me;
fn main() {
// Call a function defined in the other file (module)
include_me::some_function();
}
A mod declaration makes the Rust compiler look for the corresponding .rs files automatically!
So everything that belongs to your project, belongs in the same folder (or a subfolder thereof) as the folder where main.rs (or lib.rs) is lying. The files are then "included" via the module system. To read a good introduction into modules, please read the chapter on modules in the Rust book. You could also check out Rust by Example on that topic. The module system is pretty central and thus important to learning Rust.
2. "Including" external code
If your include_me.rs is something that doesn't belong to your actual project, but is rather a collection of useful things you are using in multiple projects, it should be seen as a library. To include code of such external libraries, you have to include it as an extern crate. And to make your life easier, you really want to use Cargo!
So let's prepare your include_me.rs as Cargo library project. You need the following file structure (which is automatically generated by cargo new my_library --lib):
. my_library
├── Cargo.toml
└── src
└── lib.rs
Now copy all the contents from include_me.rs into lib.rs (it is just convention to call the root file of a library project lib.rs). Let's say that the my_library folder's full path is ~/code/my_library.
Now let's prepare your main project's Cargo project. It has a similar file
structure (but a main.rs instead of lib.rs, because it's a executable-project, not a library-project):
. my_project
├── Cargo.toml
└── src
└── main.rs
To declare your dependency on my_library, you have to put this into your Cargo.toml:
[package]
name = "my_project"
version = "0.1.0"
authors = ["you"]
edition = "2018"
[dependencies]
my_library = { path = "~/code/my_library" }
You can also use relative paths ("../my_library"), but it only makes sense if you know that the two projects always stay where they are, relative to one another (like if they are both managed in the same repository).
Now you can, in your main.rs, write:
use my_library::some_function;
fn main() {
// Call a function defined in the other file (extern crate)
some_function();
}
If you want to upload any of those two projects, you have to interact with crates.io (or another crates registry, if your company has one), but this is another topic.
(Note: some time ago, it was necessary to write extern crate my_library; inside main.rs. This is not necessary anymore, but you might find old code with extern crate declarations.)
Any other ways?
Yes, but you shouldn't use those. There is the include!() macro which allows you to verbatim include other files, just like the #include from C-land. However, it is strongly discouraged to use this in situations where the module system would be able to solve your problem. include!() is only useful in very special situations, often linked to a more complex build system which generates code.
I'm trying to read the code of servo. As an example, I'm looking at this code in layout_task.rs:
use url::Url;
..and I want to know which code this refers to (the answer is rust-url).
Per the Rust reference §6.1.2.2 Use declarations,
the paths contained in use items are relative to the crate root [...]
It is also possible to use self and super at the beginning of a use item to refer to the current and direct parent modules respectively.
All rules regarding accessing declared modules in use declarations apply to both module declarations and extern crate declarations.
The reference (§5 Crates and source files) does not explicitly say what a "crate root" is, but it does share that:
A crate contains a tree of nested module scopes. The top level of this tree is a module that is anonymous [...] The Rust compiler is always invoked with a single source file as input, and always produces a single output crate. The processing of that source file may result in other source files being loaded as modules.
So it seems that to find the crate root that the current file (layout_task.rs) belongs to, we need to figure out what source file rustc is invoked with when building the crate. With Cargo this is specified in Cargo.toml and defaults to src/lib.rs:
[lib]
path = "src/lib.rs"
In my case, here's Cargo.toml and the lib.rs has:
extern crate url;
pub mod layout_task;
So far so good. To find out what the extern crate refers to, we need to look at Cargo.toml again:
[dependencies.url]
version = "0.2"
The cargo docs claim that "Dependencies from crates.io are not declared with separate sections", but apparently they can be... So we look the package up on crates.io: https://crates.io/crates/url