How can I use shared logic from different files? - rust

Having shared logic in:
// euler/shared/lib.rs
pub fn foo() {
println!("shared::foo()");
}
How can I use it from different files:
// euler/001/main.rs
use super::shared; // error: unresolved import `super::shared`
fn main() {
shared::foo(); // how to access it?
}
// euler/002/main.rs
use super::shared; // error: unresolved import `super::shared`
fn main() {
shared::foo(); // how to access it?
}

mdup's answer is correct, but I'd encourage you to use Cargo, Rust's package manager. It will do two very important things for you here:
Set up the correct command line arguments to rustc.
Automatically rebuild the dependent libraries when they change.
Use cargo new shared and cargo new --bin euler-001 to generate the right directory structure. Move your shared code to shared/src/lib.rs and your binaries to euler-001/src/main.rs:
.
├── euler-001
│   ├── Cargo.toml
│   └── src
│   └── main.rs
└── shared
├── Cargo.toml
└── src
└── lib.rs
Then, edit euler-001/Cargo.toml and add the dependencies section:
[dependencies.shared]
path = "../shared"
And tweak your main.rs to know about the crate:
extern crate shared;
fn main() {
shared::foo();
}
Now, you can simply type cargo run in the euler-001 directory:
$ cargo run
Compiling shared v0.1.0 (file:///private/tmp/play/euler-001)
Compiling euler-001 v0.1.0 (file:///private/tmp/play/euler-001)
Running `target/debug/euler-001`
shared::foo()
Note that you don't have to remember command line arguments and things are compiled for you! Having a built-in package manager is great!

One solution is to create a library out of the shared code. This will allow you to use an extern crate declaration.
// euler/shared/shared.rs
pub fn foo() {
println!("shared::foo()");
}
To compile the lib:
$ cd euler/shared
$ rustc --crate-type=lib shared.rs
$ ls -l libshared.rlib
-rw-r--r-- 1 mdup wheel 6758 May 17 14:38 libshared.rlib
Here is how you use it in "client" code:
// euler/001/main.rs
extern crate shared;
fn main() {
shared::foo();
}
The compile the client:
$ cd euler/001
$ rustc -L ../shared main.rs
$ ls -l main
-rwxr-xr-x 1 mdup wheel 291420 May 17 14:42 main
$ ./main
shared::foo()
More info in Rust By Example, section "Crates", pages "Library" and "extern crate".

Related

Failed to resolve module with a use statement, but the module can be used when specifying scope

In Rust, I have the following folder structure:
├── Cargo.toml
└── src
├── bin
│ └── main.rs
└── lib.rs
This is as recommended in this answer.
This is the (relevant) contents of the Cargo.toml file:
[package]
name = "devinit"
...
And this is the contents of my lib.rs file:
pub mod testmod {
pub fn testfunc() {
println!("Hello world");
}
}
When trying to use the function testfunc() in main.rs, I can refer to it by specifying its scope:
fn main() {
devinit::testmod::testfunc();
}
This compiles and executes successfully. However, if I were to actually 'use' it, as seen below...
use devinit::testmod::testfunc;
fn main() {
testfunc();
}
...the compilation fails. The following code fails to compile with the error 'failed to resolve: maybe a missing crate `devinit`?'
Why is this happening? Looking at the aforementioned answer's author's project (linked in previous edits of the answer), the structure seems to be the same...
I'm pretty new to Rust, so maybe I missed something?

How Rust finds its dependencies [duplicate]

By following this guide I created a Cargo project.
src/main.rs
fn main() {
hello::print_hello();
}
mod hello {
pub fn print_hello() {
println!("Hello, world!");
}
}
which I run using
cargo build && cargo run
and it compiles without errors. Now I'm trying to split the main module in two but cannot figure out how to include a module from another file.
My project tree looks like this
├── src
├── hello.rs
└── main.rs
and the content of the files:
src/main.rs
use hello;
fn main() {
hello::print_hello();
}
src/hello.rs
mod hello {
pub fn print_hello() {
println!("Hello, world!");
}
}
When I compile it with cargo build I get
error[E0432]: unresolved import `hello`
--> src/main.rs:1:5
|
1 | use hello;
| ^^^^^ no `hello` external crate
I tried to follow the compiler's suggestions and modified main.rs to:
#![feature(globs)]
extern crate hello;
use hello::*;
fn main() {
hello::print_hello();
}
But this still doesn't help much, now I get this:
error[E0463]: can't find crate for `hello`
--> src/main.rs:3:1
|
3 | extern crate hello;
| ^^^^^^^^^^^^^^^^^^^ can't find crate
Is there a trivial example of how to include one module from the current project into the project's main file?
You don't need the mod hello in your hello.rs file. Code in any file but the crate root (main.rs for executables, lib.rs for libraries) is automatically namespaced in a module.
To include the code from hello.rs in your main.rs, use mod hello;. It gets expanded to the code that is in hello.rs (exactly as you had before). Your file structure continues the same, and your code needs to be slightly changed:
main.rs:
mod hello;
fn main() {
hello::print_hello();
}
hello.rs:
pub fn print_hello() {
println!("Hello, world!");
}
If you wish to have nested modules...
Rust 2018
It's no longer required to have the file mod.rs (although it is still supported). The idiomatic alternative is to name the file the name of the module:
$ tree src
src
├── main.rs
├── my
│   ├── inaccessible.rs
│   └── nested.rs
└── my.rs
main.rs
mod my;
fn main() {
my::function();
}
my.rs
pub mod nested; // if you need to include other modules
pub fn function() {
println!("called `my::function()`");
}
Rust 2015
You need to put a mod.rs file inside your folder of the same name as your module. Rust by Example explains it better.
$ tree src
src
├── main.rs
└── my
├── inaccessible.rs
├── mod.rs
└── nested.rs
main.rs
mod my;
fn main() {
my::function();
}
mod.rs
pub mod nested; // if you need to include other modules
pub fn function() {
println!("called `my::function()`");
}
I really like Gardener's response. I've been using the suggestion for my module declarations.
./src
├── main.rs
├── other_utils
│ └── other_thing.rs
└── utils
└── thing.rs
File main.rs
#[path = "utils/thing.rs"] mod thing;
#[path = "other_utils/other_thing.rs"] mod other_thing;
fn main() {
thing::foo();
other_thing::bar();
}
File utils/thing.rs
pub fn foo() {
println!("foo");
}
File other_utils/other_thing.rs
#[path = "../utils/thing.rs"] mod thing;
pub fn bar() {
println!("bar");
thing::foo();
}
In a non main.rs (or lib.rs) file if you want to include from a file in the same directory then the code below works. The key is to use the word super:: for the include. (This is how I rewrote the answer of rodo without using path.)
Directory tree:
src
├── main.rs
├── my.rs
└── my
├── a.rs
└── b.rs
To include a.rs in b.rs:
File src/my/a.rs
pub fn function() {
println!("src/my/a.rs/function()");
}
File src/my/b.rs
use super::b::function;
fn f2() {
function();
}
File src/my.rs
mod a;
mod b;
File src/main.rs
mod my;
As of 2022
├── src
├── main.rs
├── scripts
│ └── func.rs
└── scripts.rs
If I want to call the functions from the func.rs file (which are inside the scripts folder), I created a so-called "linking" file in the root directory the same as the folder's name (it's not necessary to have the linking file name and the folder name the same).
Content of file scripts/func.rs:
pub fn sayHello(){
println!("Hello, World!");
}
In the scripts.rs file I have:
pub(crate) mod func;
Then in my main.rs file I have called the sayHello() function as below:
mod scripts;
fn main() {
scripts::func::sayHello();
}
its a faily simple approach in solving this, you need to add mod into the main.rs file, for its to be accessible throughout the file tree

"unresolved import -- maybe a missing extern" When extern declaration exists

I have a small project which built with no issues when it was all in one big .rs file. I wanted to make it easier to work with, so I broke it up into modules, and the project is now structured like this:
├── GameState
│   ├── ballstate.rs
│   ├── collidable.rs
│   ├── gamestate.rs
│   ├── mod.rs
│   └── playerstate.rs
├── lib.rs
└── main.rs
In ballstate.rs, I need to use the rand crate. Here's an abbreviated version of the file:
extern crate rand;
pub struct BallState {
dir: Point,
frame: BoundingBox
}
impl BallState {
fn update_dir(&mut self) {
use rand::*;
let mut rng = rand::thread_rng();
self.dir.x = if rng.gen() { Direction::Forwards.as_float() } else { Direction::Backwards.as_float() };
self.dir.y = if rng.gen() { Direction::Forwards.as_float() } else { Direction::Backwards.as_float() };
}
}
However, when I run cargo build from the top level directory, I get the following error:
GameState/ballstate.rs:42:9: 42:13 error: unresolved import rand::*. Maybe a missing extern crate rand?
When I just had the extern crate declaration in my main.rs file, this worked. What's changed now that it's in a separate module?
To quote from the Crates and Modules chapter of the Rust book:
[...] use declarations are absolute paths, starting from your crate root. self makes that path relative to your current place in the hierarchy instead.
The compiler is correct; there is no such thing as rand, because you've put it inside a module, so the correct path to it would be GameState::ballstate::rand, or self::rand from within the GameState::ballstate module.
You need to either move extern crate rand; to the root module or use self::rand within the GameState::ballstate module.
You need to put the extern crate rand; line in you main.rs and/or lib.rs file. No need to put it in the other files.
Perhaps it is related to this bug.

How to access a symbol defined in nested module?

I am using rustc 1.0.0 (a59de37e9 2015-05-13) (built 2015-05-14)
src
├── main.rs
└── core
├── mod.rs
└── expressionType.rs
main.rs:
mod core;
use core::expressionType;
fn main() {
let t = expressionType::ExpressionType.Integer;
println!("Hello, world!")
}
expressionType.rs:
pub enum ExpressionType {
Integer,
List(Box<ExpressionType>),
Function(Box<ExpressionType>, Box<ExpressionType>)
}
mod.rs:
pub mod expressionType;
from src, when I try to do rustc main.rs, I get
main.rs:5:13: 5:43 error: unresolved name `expressionType::ExpressionType`
main.rs:5 let t = expressionType::ExpressionType.Integer;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
I also tried core::expressionType::ExpressionType and expressionType.ExpressionType
Am I missing something? Why can't I access enum from expressionType.rs
UPD1: I also tried to add
pub use self::expressionType::ExpressionType;
to mod.rs, but after that in main.rs neither core::ExpressionType, nor expressionType::ExpressionType become available.
You need to write ExpressionType::Integer rather than ExpressionType.Integer (:: instead of .). In the latter case, the compiler is looking for a value, such as a variable or constant, named ExpressionType.

How can I include a module from another file from the same project?

By following this guide I created a Cargo project.
src/main.rs
fn main() {
hello::print_hello();
}
mod hello {
pub fn print_hello() {
println!("Hello, world!");
}
}
which I run using
cargo build && cargo run
and it compiles without errors. Now I'm trying to split the main module in two but cannot figure out how to include a module from another file.
My project tree looks like this
├── src
├── hello.rs
└── main.rs
and the content of the files:
src/main.rs
use hello;
fn main() {
hello::print_hello();
}
src/hello.rs
mod hello {
pub fn print_hello() {
println!("Hello, world!");
}
}
When I compile it with cargo build I get
error[E0432]: unresolved import `hello`
--> src/main.rs:1:5
|
1 | use hello;
| ^^^^^ no `hello` external crate
I tried to follow the compiler's suggestions and modified main.rs to:
#![feature(globs)]
extern crate hello;
use hello::*;
fn main() {
hello::print_hello();
}
But this still doesn't help much, now I get this:
error[E0463]: can't find crate for `hello`
--> src/main.rs:3:1
|
3 | extern crate hello;
| ^^^^^^^^^^^^^^^^^^^ can't find crate
Is there a trivial example of how to include one module from the current project into the project's main file?
You don't need the mod hello in your hello.rs file. Code in any file but the crate root (main.rs for executables, lib.rs for libraries) is automatically namespaced in a module.
To include the code from hello.rs in your main.rs, use mod hello;. It gets expanded to the code that is in hello.rs (exactly as you had before). Your file structure continues the same, and your code needs to be slightly changed:
main.rs:
mod hello;
fn main() {
hello::print_hello();
}
hello.rs:
pub fn print_hello() {
println!("Hello, world!");
}
If you wish to have nested modules...
Rust 2018
It's no longer required to have the file mod.rs (although it is still supported). The idiomatic alternative is to name the file the name of the module:
$ tree src
src
├── main.rs
├── my
│   ├── inaccessible.rs
│   └── nested.rs
└── my.rs
main.rs
mod my;
fn main() {
my::function();
}
my.rs
pub mod nested; // if you need to include other modules
pub fn function() {
println!("called `my::function()`");
}
Rust 2015
You need to put a mod.rs file inside your folder of the same name as your module. Rust by Example explains it better.
$ tree src
src
├── main.rs
└── my
├── inaccessible.rs
├── mod.rs
└── nested.rs
main.rs
mod my;
fn main() {
my::function();
}
mod.rs
pub mod nested; // if you need to include other modules
pub fn function() {
println!("called `my::function()`");
}
I really like Gardener's response. I've been using the suggestion for my module declarations.
./src
├── main.rs
├── other_utils
│ └── other_thing.rs
└── utils
└── thing.rs
File main.rs
#[path = "utils/thing.rs"] mod thing;
#[path = "other_utils/other_thing.rs"] mod other_thing;
fn main() {
thing::foo();
other_thing::bar();
}
File utils/thing.rs
pub fn foo() {
println!("foo");
}
File other_utils/other_thing.rs
#[path = "../utils/thing.rs"] mod thing;
pub fn bar() {
println!("bar");
thing::foo();
}
In a non main.rs (or lib.rs) file if you want to include from a file in the same directory then the code below works. The key is to use the word super:: for the include. (This is how I rewrote the answer of rodo without using path.)
Directory tree:
src
├── main.rs
├── my.rs
└── my
├── a.rs
└── b.rs
To include a.rs in b.rs:
File src/my/a.rs
pub fn function() {
println!("src/my/a.rs/function()");
}
File src/my/b.rs
use super::b::function;
fn f2() {
function();
}
File src/my.rs
mod a;
mod b;
File src/main.rs
mod my;
As of 2022
├── src
├── main.rs
├── scripts
│ └── func.rs
└── scripts.rs
If I want to call the functions from the func.rs file (which are inside the scripts folder), I created a so-called "linking" file in the root directory the same as the folder's name (it's not necessary to have the linking file name and the folder name the same).
Content of file scripts/func.rs:
pub fn sayHello(){
println!("Hello, World!");
}
In the scripts.rs file I have:
pub(crate) mod func;
Then in my main.rs file I have called the sayHello() function as below:
mod scripts;
fn main() {
scripts::func::sayHello();
}
its a faily simple approach in solving this, you need to add mod into the main.rs file, for its to be accessible throughout the file tree

Resources