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.
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
You need to make it public if you want it callable outside the sub module: pub fn sub() {...} . As for rustc, you can run cargo with a verbose flag (e.g. cargo build -v ... ) and then look at how it invokes rustc . error: Could not compile hello . To learn more, run the command again with --verbose.
To import the module, we use the keyword mod , followed by the file name without the . rs extension. When a module is imported, it allows us to use any code that's marked as public in the file we're importing the module from. Note that the module must be imported before we use any of its code.
Rust provides a powerful module system that can be used to hierarchically split code in logical units (modules), and manage visibility (public/private) between them. A module is a collection of items: functions, structs, traits, impl blocks, and even other modules.
Keyword crate A Rust binary or library. The primary use of the crate keyword is as a part of extern crate declarations, which are used to specify a dependency on a crate external to the one it's declared in. Crates are the fundamental compilation unit of Rust code, and can be seen as libraries or projects.
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With