I have three files in src/, like so:
lib.rs
pub mod first
first.rs
fn hello() {}
main.rs
pub mod lib
This gives me an error saying:
error[E0583]: file not found for module `first`
--> src/lib.rs:1:9
|
1 | pub mod first;
| ^^^^^
|
= help: name the file either lib/first.rs or lib/first/mod.rs inside the directory "src"
Now, if I remove pub mod lib from main.rs, everything compiles fine.
I don't understand why this is happening.
The help that compiler says is very meaningful.
When you write pub mod first; inside of a lib.rs it checks for the first.rs file or first folder inside a lib folder and a mod.rs file.
Please note that mod.rs usages are changed with Rust 2018. Reference
Now, if I remove pub mod lib from main.rs, everything compiles fine.
When you remove pub mod lib; from your main,
You basically say that this code will not be used in production therefore it is not needed to compile even. So basically the code will not included to compile.
This is why it works when you remove the pub mod lib;
Related
I'm using Dev-c++. My main.cpp calling functions in both a.dll and b.dll which works perfectly. Now, new requirement I need b.dll call function foo() in a.dll.
I included a.header file in bmain.cpp, Put lib file of a in linker. re-build b.dll successfully.
Next, I included both a.header & b.header in main.cpp, put lib files of both a & b in linker. After compile, I got error message "undefined reference to foo()". How to solve this situation?
tried merge tow .dll, but got multi definition error.
I'm trying to call a function belonging to some module from another module (for code factoring, organization, etc).
Here is my crate structure:
➜ mod_test git:(master) ✗ tree
.
├── Cargo.lock
├── Cargo.toml
└── src
├── bin
│ └── one.rs
├── lib
│ └── two.rs
└── main.rs
3 directories, 5 files
In main I declare:
pub mod bin {
pub mod one;
}
pub mod lib {
pub mod two;
}
and all these files simply contain a trivial pub fn main() {println!("hello");}.
At this point, everything is okay.
Now, is it possible to call lib::two::main from bin/one.rs?
None of use crate::lib::two;, use super::lib::two;, use self::super::lib::two; added in bin/one.rs work.
edit: I have: rustc 1.42.0 (b8cedc004 2020-03-09) installed on Linux 5.3.0-45-generic, for what it's worth.
edit 2: whenever using the super keyword, I get this mysterious error from rustc:
error[E0433]: failed to resolve: there are too many leading `super` keywords
and I can't find any troubleshooting about this anywhere.
edit 3: adding a lib.rs file in src declaring the lib module structure, and writing use mod_test::lib::two; in one.rs works, but:
1) it defeats the idea of not multiplying "dumb module declaration files" in my crate.
2) I have to literally copy the exact same information at two different places (in main.rs and in lib.rs)
3) use mod_test::lib::two; is the only working syntax, using crate or super keywords still result in arcane compiler errors
src/bin is a special directory name to Cargo. Files in this directory are compiled as standalone binaries when you run cargo build. When compiled as binaries, they aren't part of the crate structure defined in main.rs or lib.rs.
If you just want to use bin::one as a module inside main.rs, what you have works already! You're getting error messages from compiling one.rs as a standalone binary, not from compiling main.rs with bin::one as a module. If you run cargo run --bin <name-of-project>, compilation will succeed and it will run the program in main.rs.
To tell Cargo not to compile one.rs by itself, I would suggest renaming the bin directory. This not only solves the technical problem, but also is less likely to confuse other programmers reading the project, who will expect bin to contain binaries. There may be some way to prevent Cargo from treating bin specially in this way; however, renaming it is probably the best option.
If you do want one.rs to be compiled to a separate executable that uses two, you must create a lib.rs file in the same directory as main.rs. This is also a special file to Cargo and it defines the module structure for the library crate.
// lib.rs
pub mod lib { /* note: this lib is not related to lib.rs; just unfortunately named */
pub mod two;
}
Then inside one.rs, write use <crate-name>::lib::two;
// bin/one.rs
use mod_test::lib::two;
crate::lib::two does not work, as files inside the bin directory are compiled as standalone binaries, not as crate members; therefore, you have to call the crate by its "external" name.
adding a lib.rs file in src declaring the lib module structure, and writing use mod_test::lib::two; in one.rs works, but:
1) it defeats the idea of not multiplying "dumb module declaration files" in my crate.
2) I have to literally copy the exact same information at two different places (in main.rs and in lib.rs)
main.rs and lib.rs are two different crate roots. They are allowed to have different structure. You don't need both unless you want to generate both the binary and the library. If you want to use the library crate from inside any binary (including main.rs), it's just a use away:
use mod_test;
See also
Rust modules confusion when there is main.rs and lib.rs
Rust package with both a library and a binary?
I have troubles resolving my module imports. Here is my file structure:
.
|-- scenes
| |-- libs
| | |-- mod.rs
| | `-- components.rs
| |-- mod.rs
| `-- scene.rs
`-- main.rs
I can't import the module libs in scene.rs. I think I don't get it the module logical. Any help would be very appreciable.
if I try to do mod libs; in scene.rs
error[E0583]: file not found for module `libs`
--> src/scenes/scene.rs:2:5
|
2 | mod libs;
| ^^^^
|
= help: name the file either scene/libs.rs or scene/libs/mod.rs inside the directory "src/scenes"
Contents files:
main.rs
mod scenes;
let sc = scenes::scene::Scene{};
scenes/scene.rs
mod libs; // errors
pub struct Sphere {
pub center: libs::components::Point
}
pub struct Scene {}
scenes/mod.rs
pub mod scene;
pub mod libs;
scenes/libs/components.rs
pub struct Point {}
scenes/libs/mod.rs
pub mod components;
Instead of mod libs, write use crate::scenes::libs.
The Rust 2018 Edition has changed the module system slightly to help clarify situations such as this.
Your directory should be restructured like so:
main.rs
scenes.rs
scenes
| libs.rs
| libs
| | components.rs
| scene.rs
The main difference here is that mod.rs files are now extracted from their folder and named appropriately.
PRE-RUST-2018 - NOV 2018
Instead of mod libs, write use scenes::libs.
The error message is telling you is you're trying to declare the existence of a submodule of scene that does not exist. Instead, you want to import (with use) the libs module which is accessed by scenes::libs from the crate root.
I have Rust project with both integration tests (in the /tests dir) and benchmarks (in the /benches dir). There are a couple of utility functions that I need in tests and benches, but they aren't related to my crate itself, so I can't just put them in the /utils dir.
What is idiomatic way to handle this situation?
Create a shared crate (preferred)
As stated in the comments, create a new crate. You don't have to publish the crate to crates.io. Just keep it as a local unpublished crate inside your project and mark it as a development-only dependency.
This is best used with version 2 of the Cargo resolver. For better performance, consider using a Cargo workspace.
.
├── Cargo.toml
├── src
│ └── lib.rs
├── tests
│ └── integration.rs
└── utilities
├── Cargo.toml
└── src
└── lib.rs
Cargo.toml
# ...
[dev-dependencies]
utilities = { path = "utilities" }
utilities/src/lib.rs
pub fn shared_code() {
println!("I am shared code");
}
tests/integration.rs
extern crate utilities;
#[test]
fn a_test() {
utilities::shared_code();
}
A test-only module
You could place a module inside your crate that is only compiled when a specific feature is passed. This is the same concept used for unit tests. This has the advantage that it can access internals of your library code. It has the disadvantage that you need to pass the flag each time you run the code.
This is best used with version 2 of the Cargo resolver.
Cargo.toml
# ...
[features]
test-utilities = []
src/lib.rs
#[cfg(feature = "test-utilities")]
pub mod test_utilities {
pub fn shared_code() {
println!("I'm inside the library")
}
}
tests/integration.rs
extern crate the_library;
#[test]
fn a_test() {
the_library::test_utilities::shared_code();
}
execution
cargo test --features=test-utilities
This is best used with version 2 of the Cargo resolver.
Use a module from an arbitrary file path
This is just ugly to me, and really goes out of the normal path.
utilities.rs
pub fn shared_code() {
println!("This is just sitting out there");
}
tests/integration.rs
#[path = "../utilities.rs"]
mod utilities;
#[test]
fn a_test() {
utilities::shared_code();
}
See also:
Where should I put test utility functions in Rust?
You could add those utility-functions to a pub-module inside your main crate and use the #[doc(hidden)] or #![doc(hidden)] attribute to hide them from the docs-generator. Extra comments will guide the reader to why they are there.
Whilst this doesn't help for benchmarks, I came here looking for a way to do this with multiple integration tests, and later found that you can do the following for integration tests:
Modules with common code follow the ordinary modules rules, so it's ok to create common module as tests/common/mod.rs.
Source: https://doc.rust-lang.org/rust-by-example/testing/integration_testing.html
I have Rust project with both integration tests (in the /tests dir) and benchmarks (in the /benches dir). There are a couple of utility functions that I need in tests and benches, but they aren't related to my crate itself, so I can't just put them in the /utils dir.
What is idiomatic way to handle this situation?
Create a shared crate (preferred)
As stated in the comments, create a new crate. You don't have to publish the crate to crates.io. Just keep it as a local unpublished crate inside your project and mark it as a development-only dependency.
This is best used with version 2 of the Cargo resolver. For better performance, consider using a Cargo workspace.
.
├── Cargo.toml
├── src
│ └── lib.rs
├── tests
│ └── integration.rs
└── utilities
├── Cargo.toml
└── src
└── lib.rs
Cargo.toml
# ...
[dev-dependencies]
utilities = { path = "utilities" }
utilities/src/lib.rs
pub fn shared_code() {
println!("I am shared code");
}
tests/integration.rs
extern crate utilities;
#[test]
fn a_test() {
utilities::shared_code();
}
A test-only module
You could place a module inside your crate that is only compiled when a specific feature is passed. This is the same concept used for unit tests. This has the advantage that it can access internals of your library code. It has the disadvantage that you need to pass the flag each time you run the code.
This is best used with version 2 of the Cargo resolver.
Cargo.toml
# ...
[features]
test-utilities = []
src/lib.rs
#[cfg(feature = "test-utilities")]
pub mod test_utilities {
pub fn shared_code() {
println!("I'm inside the library")
}
}
tests/integration.rs
extern crate the_library;
#[test]
fn a_test() {
the_library::test_utilities::shared_code();
}
execution
cargo test --features=test-utilities
This is best used with version 2 of the Cargo resolver.
Use a module from an arbitrary file path
This is just ugly to me, and really goes out of the normal path.
utilities.rs
pub fn shared_code() {
println!("This is just sitting out there");
}
tests/integration.rs
#[path = "../utilities.rs"]
mod utilities;
#[test]
fn a_test() {
utilities::shared_code();
}
See also:
Where should I put test utility functions in Rust?
You could add those utility-functions to a pub-module inside your main crate and use the #[doc(hidden)] or #![doc(hidden)] attribute to hide them from the docs-generator. Extra comments will guide the reader to why they are there.
Whilst this doesn't help for benchmarks, I came here looking for a way to do this with multiple integration tests, and later found that you can do the following for integration tests:
Modules with common code follow the ordinary modules rules, so it's ok to create common module as tests/common/mod.rs.
Source: https://doc.rust-lang.org/rust-by-example/testing/integration_testing.html