Import a module from my crate in a Criterion benchmark [duplicate] - rust

My project's path structure is as follows:
demo
├── benches
│   └── crypto_bench.rs
├── src
│   ├── main.rs
│   └── crypto.rs
├── Cargo.lock
└── Cargo.toml
crypto.rs contains a struct Crypto with implementation.
crypto.rs is referred to from main.rs using mod crypto;
How can I use crypto.rs from crypto_bench.rs inside the benches folder?
I have tried all kinds of variations of extern crate, mod, super and use.
All examples I could find online are for library projects with a lib.rs and those "imports" don't work when using a project with a main.rs file.

Here's a literal answer, but don't actually use this!
#![feature(test)]
extern crate test;
#[path = "../src/foo.rs"] // Here
mod foo;
#[bench]
fn bencher(_: &mut test::Bencher) {
println!("{:?}", foo::Thang);
}
In fact, it's very likely that this won't work because your code in foo.rs needs supporting code from other files that won't be included.
Instead of doing this, just create a library. You have the pure definition of a library - a piece of code that wants to be used in two different executables. You don't have to give up having an executable or even create separate directories (see Rust package with both a library and a binary?), but creating reusable code is a key component of making good code.
Your end state would look something like:
demo
├── Cargo.lock
├── Cargo.toml
├── benches
│   └── crypto_bench.rs
├── benchmarks
└── src
├── bin
│   └── main.rs
├── crypto.rs
└── lib.rs
Move the reusable code to a library:
src/lib.rs
pub mod crypto;
src/crypto.rs
pub struct Crypto;
impl Crypto {
pub fn secret() {}
}
Then import your library from the benchmark and the binary:
benches/crypto_bench.rs
#![feature(test)]
extern crate test;
use demo::crypto::Crypto;
use test::Bencher;
#[bench]
fn speedy(b: &mut Bencher) {
b.iter(|| Crypto::secret());
}
src/bin/main.rs
use demo::crypto::Crypto;
fn main() {
Crypto::secret();
eprintln!("Did the secret thing!");
}
You can then run it in different ways:
$ cargo build
Compiling demo v0.1.0 (/private/tmp/example)
Finished dev [unoptimized + debuginfo] target(s) in 0.51s
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/main`
Did the secret thing!
$ cargo +nightly bench
Compiling demo v0.1.0 (/private/tmp/example)
Finished release [optimized] target(s) in 0.70s
Running target/release/deps/my_benchmark-5c9c5716763252a0
running 1 test
test speedy ... bench: 1 ns/iter (+/- 0)
test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out
See also:
Rust package with both a library and a binary?
What is an idiomatic way to have shared utility functions for integration tests and benchmarks?
Can I make an object public for integration tests and/or benchmarks only?
Cannot import a module in an integration test

Related

Can't find local crate specified in Cargo.toml even though main.rs exists [duplicate]

My project's path structure is as follows:
demo
├── benches
│   └── crypto_bench.rs
├── src
│   ├── main.rs
│   └── crypto.rs
├── Cargo.lock
└── Cargo.toml
crypto.rs contains a struct Crypto with implementation.
crypto.rs is referred to from main.rs using mod crypto;
How can I use crypto.rs from crypto_bench.rs inside the benches folder?
I have tried all kinds of variations of extern crate, mod, super and use.
All examples I could find online are for library projects with a lib.rs and those "imports" don't work when using a project with a main.rs file.
Here's a literal answer, but don't actually use this!
#![feature(test)]
extern crate test;
#[path = "../src/foo.rs"] // Here
mod foo;
#[bench]
fn bencher(_: &mut test::Bencher) {
println!("{:?}", foo::Thang);
}
In fact, it's very likely that this won't work because your code in foo.rs needs supporting code from other files that won't be included.
Instead of doing this, just create a library. You have the pure definition of a library - a piece of code that wants to be used in two different executables. You don't have to give up having an executable or even create separate directories (see Rust package with both a library and a binary?), but creating reusable code is a key component of making good code.
Your end state would look something like:
demo
├── Cargo.lock
├── Cargo.toml
├── benches
│   └── crypto_bench.rs
├── benchmarks
└── src
├── bin
│   └── main.rs
├── crypto.rs
└── lib.rs
Move the reusable code to a library:
src/lib.rs
pub mod crypto;
src/crypto.rs
pub struct Crypto;
impl Crypto {
pub fn secret() {}
}
Then import your library from the benchmark and the binary:
benches/crypto_bench.rs
#![feature(test)]
extern crate test;
use demo::crypto::Crypto;
use test::Bencher;
#[bench]
fn speedy(b: &mut Bencher) {
b.iter(|| Crypto::secret());
}
src/bin/main.rs
use demo::crypto::Crypto;
fn main() {
Crypto::secret();
eprintln!("Did the secret thing!");
}
You can then run it in different ways:
$ cargo build
Compiling demo v0.1.0 (/private/tmp/example)
Finished dev [unoptimized + debuginfo] target(s) in 0.51s
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/main`
Did the secret thing!
$ cargo +nightly bench
Compiling demo v0.1.0 (/private/tmp/example)
Finished release [optimized] target(s) in 0.70s
Running target/release/deps/my_benchmark-5c9c5716763252a0
running 1 test
test speedy ... bench: 1 ns/iter (+/- 0)
test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out
See also:
Rust package with both a library and a binary?
What is an idiomatic way to have shared utility functions for integration tests and benchmarks?
Can I make an object public for integration tests and/or benchmarks only?
Cannot import a module in an integration test

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?

"Unresolved import" when linking with [lib] in Cargo.toml [duplicate]

I'm trying to create a module in Rust and then use it from a different file. This is my file structure:
matthias#X1:~/projects/bitter-oyster$ tree
.
├── Cargo.lock
├── Cargo.toml
├── Readme.md
├── src
│   ├── liblib.rlib
│   ├── lib.rs
│   ├── main.rs
│   ├── main.rs~
│   └── plot
│   ├── line.rs
│   └── mod.rs
└── target
└── debug
├── bitter_oyster.d
├── build
├── deps
├── examples
├── libbitter_oyster.rlib
└── native
8 directories, 11 files
This is Cargo.toml:
[package]
name = "bitter-oyster"
version = "0.1.0"
authors = ["matthias"]
[dependencies]
This is main.rs:
extern crate plot;
fn main() {
println!("----");
plot::line::test();
}
This is lib.rs:
mod plot;
this is plot/mod.rs
mod line;
and this is plot/line.rs
pub fn test(){
println!("Here line");
}
When I try to compile my program using: cargo run I get:
Compiling bitter-oyster v0.1.0 (file:///home/matthias/projects/bitter-oyster)
/home/matthias/projects/bitter-oyster/src/main.rs:1:1: 1:19 error: can't find crate for `plot` [E0463]
/home/matthias/projects/bitter-oyster/src/main.rs:1 extern crate plot;
How do I compile my program? As far as I can tell from online documentations this should work, but it doesn't.
To add to the given answers, a library compiled as a cdylib (docs) can generate this error when you try to reference it in another project. I solved it by separating the code I wished to reuse in a regular lib project.
If you see this error:
error[E0463]: can't find crate for `PACKAGE`
|
1 | extern crate PACKAGE;
| ^^^^^^^^^^^^^^^^^^^^^ can't find crate
it could be that you haven't added the desired crate to the dependencies list in your Cargo.toml:
[dependencies]
PACKAGE = "1.2.3"
See specifying dependencies in the Cargo docs.
You have the following problems:
you have to use extern crate bitter_oyster; in main.rs, because the produced binary uses your crate, the binary is not a part of it.
Also, call bitter_oyster::plot::line::test(); in main.rs instead of plot::line::test();. plot is a module in the bitter_oyster crate, such as line. You are referring to the test function with its fully qualified name.
Make sure, that every module is exported in the fully qualified name. You can make a module public with the pub keyword, like pub mod plot;
You can find more information about Rust's module system here: https://doc.rust-lang.org/book/crates-and-modules.html
A working copy of your module structure is as follows:
src/main.rs:
extern crate bitter_oyster;
fn main() {
println!("----");
bitter_oyster::plot::line::test();
}
src/lib.rs:
pub mod plot;
src/plot/mod.rs:
pub mod line;
src/plot/line.rs :
pub fn test(){
println!("Here line");
}
I got this issue when I had imported my crate in [dev-dependencies] instead of [dependencies]
This can also happen when you don't enable certain "feature flags" for specific crates. Unfortunately, these feature flags can sometimes be undocumented. When feature flags are missing when required, they show the same error ("Can't find crate")
I was using diesel, and was trying to use BigInteger:
Wrong
diesel = { version = "2.0.3", features = ["postgres", "chrono", "r2d2", "serde_json", "biginteger"] }
Correct:
diesel = { version = "2.0.3", features = ["postgres", "chrono", "r2d2", "serde_json", "numeric"] }

How can I use a module from outside the src folder in a binary project, such as for integration tests or benchmarks?

My project's path structure is as follows:
demo
├── benches
│   └── crypto_bench.rs
├── src
│   ├── main.rs
│   └── crypto.rs
├── Cargo.lock
└── Cargo.toml
crypto.rs contains a struct Crypto with implementation.
crypto.rs is referred to from main.rs using mod crypto;
How can I use crypto.rs from crypto_bench.rs inside the benches folder?
I have tried all kinds of variations of extern crate, mod, super and use.
All examples I could find online are for library projects with a lib.rs and those "imports" don't work when using a project with a main.rs file.
Here's a literal answer, but don't actually use this!
#![feature(test)]
extern crate test;
#[path = "../src/foo.rs"] // Here
mod foo;
#[bench]
fn bencher(_: &mut test::Bencher) {
println!("{:?}", foo::Thang);
}
In fact, it's very likely that this won't work because your code in foo.rs needs supporting code from other files that won't be included.
Instead of doing this, just create a library. You have the pure definition of a library - a piece of code that wants to be used in two different executables. You don't have to give up having an executable or even create separate directories (see Rust package with both a library and a binary?), but creating reusable code is a key component of making good code.
Your end state would look something like:
demo
├── Cargo.lock
├── Cargo.toml
├── benches
│   └── crypto_bench.rs
├── benchmarks
└── src
├── bin
│   └── main.rs
├── crypto.rs
└── lib.rs
Move the reusable code to a library:
src/lib.rs
pub mod crypto;
src/crypto.rs
pub struct Crypto;
impl Crypto {
pub fn secret() {}
}
Then import your library from the benchmark and the binary:
benches/crypto_bench.rs
#![feature(test)]
extern crate test;
use demo::crypto::Crypto;
use test::Bencher;
#[bench]
fn speedy(b: &mut Bencher) {
b.iter(|| Crypto::secret());
}
src/bin/main.rs
use demo::crypto::Crypto;
fn main() {
Crypto::secret();
eprintln!("Did the secret thing!");
}
You can then run it in different ways:
$ cargo build
Compiling demo v0.1.0 (/private/tmp/example)
Finished dev [unoptimized + debuginfo] target(s) in 0.51s
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/main`
Did the secret thing!
$ cargo +nightly bench
Compiling demo v0.1.0 (/private/tmp/example)
Finished release [optimized] target(s) in 0.70s
Running target/release/deps/my_benchmark-5c9c5716763252a0
running 1 test
test speedy ... bench: 1 ns/iter (+/- 0)
test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out
See also:
Rust package with both a library and a binary?
What is an idiomatic way to have shared utility functions for integration tests and benchmarks?
Can I make an object public for integration tests and/or benchmarks only?
Cannot import a module in an integration test

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