I have a Rust project consisting of two binary sources sharing the same library:
Cargo.toml:
<...>
[[bin]]
name = "quoter_xml"
path = "src/quoter_xml.rs"
[[bin]]
name = "quoter"
path = "src/quoter.rs"
<...>
src/quoter_xml.rs:
use <...>
fn main() {
<...>
}
src/quoter.rs:
use <...>
fn main() {
<...>
}
src/lib.rs:
pub mod <...>
When I compile it, I get two binaries: quoter_xml and quoter_xml.
When I generate doc using cargo doc, I get independent doc files doc/quoter_xml/index.html and doc/quoter/index.html.
What I want is to add some description texts to the top of these doc files.
I've tried to add "//!"-type comments to binary sources, for example:
src/quoter_xml.rs:
use <...>
//! quoter_xml - this binary is for <..>
fn main() {
<...>
}
But if I compile project after it, I get an error:
error[E0753]: expected outer doc comment
--> src/quoter_xml.rs:10:1
|
10 | //! quoter_xml - this binary is for <..>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
help: you might have meant to write a regular comment
|
10 - //! quoter_xml - this binary is for <..>
10 + // quoter_xml - this binary is for <..>
|
Compiler consider to use regular comments, but I don't want it: I need comments that will get to the top of doc pages, "//!"-type comments.
I've search Internet and found recommendation to place these type of comments in src/lib.rs file, but this is not what I want. I want to have independent top-level comments in doc for each binary file.
Any suggestion?
I believe you simply need to move your comment above the use statement in quoter_xml.rs.
//! quoter_xml - this binary is for <..>
use <...>
// Crate level doc comment cannot be after any code.
fn main() {
<...>
}
Related
I have a Cargo project set up with a library and a binary. The library is meant to be used on many platforms, including Android, while the binary is only meant to be used on Linux. As such, the binary contains a bunch of Linux-specific code that does not compile when I target Android. Is there a way to specify (without using features) that the binary should only be compiled on Linux?
I tried putting #![cfg(target_os = "linux")] in the main.rs of my binary, but then I got this error:
error[E0601]: `main` function not found in crate `server`
--> src/bin/server/main.rs:1:1
|
1 | / #![cfg(target_os = "linux")]
2 | |
3 | | use anyhow::{self, Context};
4 | |
... |
36 | | }
37 | | }
| |_^ consider adding a `main` function to `src/bin/server/main.rs`
I had exactly the same problem. The official Rust docs do not seem to mention how to solve it. But I found a solution.
The trick is to specify two main() functions in the file main.rs. The first one contains the code you want to execute when you are on Linux. The second one remains empty. With the help of conditional compilation, you tell the compiler which of the two main() functions to compile.
// within main.rs
#[cfg(target_os = "linux")]
fn main() {
// Your Linux-specific code goes here...
}
#[cfg(not(target_os = "linux"))]
fn main() {} // remains empty for all other OS
If you have OS-specific imports or other code at the top-level, just wrap it inside a module and use conditional compilation for it as well.
#[cfg(target_os = "linux")]
mod linux {
use anyhow::{self, Context};
// ...
}
The below link has related information that should help you in terms of target selection and selective compilation https://doc.rust-lang.org/cargo/commands/cargo-build.html#target-selection
Main Question
How to use code from helper1.rs in main.rs.
// main.rs
mod lib;
use lib::lib_function;
use lib::public_library;
mod module_a;
mod module_b;
use module_a::{helper1::helper1_function, mod_a_function};
use module_b::{helper2, helper3, mod_b_function};
fn main() {
println!("Hello, world from main!");
lib_function();
public_library::public_library_mod_function();
helper1_function();
mod_a_function();
helper2::helper2_function();
helper3::helper3_function();
mod_b_function();
}
// module_b/mod.rs
pub mod helper2;
pub mod helper3;
pub fn mod_a_function() {
println!("Printing from module_b/mod.rs");
}
// module_b/helper2.rs
pub fn helper2_function() {
println!("Hello from Helper 2!!");
}
I get the error:
error: couldn't read src\module_b\mod.rs: stream did not contain valid UTF-8
--> src\main.rs:14:1
|
14 | mod module_b;
| ^^^^^^^^^^^^^
error: could not compile `rust_modules_cheat_sheet` due to previous error
I'm not sure what non-utf-8 character is in module_b but isn't in module_a.
Cheat Sheet for modules and importing in Rust
I've seen a lot of tutorials online that kind of say the same thing, but it's not complete or sophisticated for other cases. I wanted to ask the community as well as research how to use code from various situations and modules in rust. If you would like to comment below for the two cases I am unsure of right now, that would be appreciated.
Example Directory
/src
| main.rs
| lib.rs
| other.rs
|- module_a/
| | mod.rs
| | helper1.rs
|- module_b/
| | mod.rs
| | helper2.rs
| | helper3.rs
Various Situation
Using code from other.rs in main.rs (Understood)
Using code from lib.rs in main.rs (Understood)
Using code from mod.rs in lib.rs (Understood)
Using code from helper1.rs in main.rs (Understood)
Using code from helper2.rs in helper3.rs (Unsure)
Using code from module_a/mod.rs in module_b/mod.rs (use crate::module_a)
Github Repo for Future Reference
Link to repo
Hopefully, this helps others in the future. I know I need it.
Thanks
This is not from a misunderstanding of Rust's module system. Your module_b\mod.rs file is UTF-16 encoded instead of UTF-8 encoded as Rust is expecting.
If you're using VS Code: Change the encoding of a file in Visual Studio Code You can change the encoding by clicking on the UTF-16 LE part of the bottom status bar and selecting Save with encoding and then selecting UTF-8.
If using Vim: How can I change a file's encoding with vim?
I'm trying out the "Using Derive Macros" example on the index page for the latest beta version of clap:
// (Full example with detailed comments in examples/01d_quick_example.rs)
//
// This example demonstrates clap's full 'custom derive' style of creating arguments which is the
// simplest method of use, but sacrifices some flexibility.
use clap::{AppSettings, Parser};
/// This doc string acts as a help message when the user runs '--help'
/// as do all doc strings on fields
#[derive(Parser)]
#[clap(version = "1.0", author = "Kevin K. <kbknapp#gmail.com>")]
struct Opts {
/// Sets a custom config file. Could have been an Option<T> with no default too
#[clap(short, long, default_value = "default.conf")]
config: String,
/// Some input. Because this isn't an Option<T> it's required to be used
input: String,
/// A level of verbosity, and can be used multiple times
#[clap(short, long, parse(from_occurrences))]
verbose: i32,
#[clap(subcommand)]
subcmd: SubCommand,
}
...
Unfortunately it fails to compile:
$ cargo build
Compiling ex v1.0.0-SNAPSHOT (/home/hwalters/git/home/ex)
error: cannot find derive macro `Parser` in this scope
--> src/main.rs:5:10
|
5 | #[derive(Parser)]
| ^^^^^^
|
note: `Parser` is imported here, but it is only a trait, without a derive macro
--> src/main.rs:1:25
|
1 | use clap::{AppSettings, Parser};
| ^^^^^^
error: cannot find attribute `clap` in this scope
--> src/main.rs:6:3
|
6 | #[clap(version = "1.0", author = "Kevin K. <kbknapp#gmail.com>")]
| ^^^^
|
= note: `clap` is in scope, but it is a crate, not an attribute
...
I tried to find the full example file "examples/01d_quick_example.rs" in the tar file for this GitHub tag, but it does not seem exist there.
I appreciate this is a beta version, but is this functionality expected to work, or am I doing something wrong?
Thanks!
In clap, use features = [ "derive" ] in Cargo.toml to enable the ability to derive :)
update
#stein below makes a good point of expanding the answer:
To "use" means: in the [dependencies] section, specify clap with a
line similar to: clap = { version = "3.1.0", features = ["derive"]} –
Stein Feb 19 at 13:00
Please +1 their comment :-).
This means, in your Cargo.toml
[dependencies]
# ...
clap = { version = "3", features = ["derive"]}
I am trying to build a single Rust binary executable. In the src directory I have four files:
main.rs:
use fasta_multiple_cmp::get_filenames;
fn main() {
get_filenames();
}
mod.rs:
pub mod fasta_multiple_cmp;
pub mod build_sequences_matrix;
fasta_multiple_cmp.rs:
pub mod fasta_multiple_cmp {
...
pub fn get_filenames() {
let args: Vec<String> = env::args().collect();
...
build_sequences_matrix.rs:
pub mod build_sequences_matrix {
use simple_matrix::Matrix;
...
Cargo told me:
src/main.rs:3:5
|
3 | use fasta_multiple_cmp::get_filenames;
| ^^^^^^^^^^^^^^^^^^ use of undeclared crate or module `fasta_multiple_cmp
I believed I understood some little things, but ther I'm lost. What is going on?
Thaks for any hint!
Your original code wasn't working because Rust's use is looking for a crate to import from, not just a file in the same directory.
If you want to separate logic into other files, you will need to break apart your project into both a binary and into a library (aka - a crate that your binary can use for imports).
This can be done in your Cargo.toml as:
[package]
edition = "2018"
name = "my_project"
version = "1.2.3"
... your other settings ...
[[bin]]
edition = "2018"
name = "whatever_name_for_binary"
path = "src/main.rs"
This means that your binary will be compiled into a file called "whatever_name_for_binary" in your target folder. It also means your non-binary files act as a library, and can be imported by your binary by using use my_project::some_module;
Because your project will now contain both a library and binary, you will need to specify when you want to run/compile the binary.
You do this by running: cargo run --bin whatever_name_for_binary
For more information, see the Rust Book's Chapter on Modules.
I am trying to output the contents of a syn::Expr to the console, but get the following error:
error[E0599]: no method named `to_string` found for type `&syn::Expr` in the current scope
--> derive/src/lib.rs:165:40
|
165 | println!("Expression: {:#?}", expr.to_string());
| ^^^^^^^^^
|
= note: the method `to_string` exists but the following trait bounds were not satisfied:
`syn::Expr : std::string::ToString`
`&syn::Expr : std::string::ToString`
`syn::Expr : std::string::ToString`
It is not clear to me what "trait bounds" are or how to satisfy them. Are there any easy ways to output the contents of this variable?
syn::Expr is documented as implementing the Debug trait, so you use the Debug formatter:
extern crate syn; // 0.15.4
fn example(expr: syn::Expr) {
println!("{:#?}", expr);
}
However, all Debug implementations in syn are guarded by the Cargo feature extra-traits. So in order to use those Debug impls, you have to specifically enable that feature in your Cargo.toml:
[dependencies]
syn = { version = "0.15", features = ["extra-traits"] }
You can read more about syn's optional Cargo features in their README.
See also:
How do I print variables in Rust and have it show everything about that variable, like Ruby's .inspect?
What is the difference between println's format styles?
Should I implement Display or ToString to render a type as a string?
Does println! borrow or own the variable?