For newcomers to Rust, after setting up the development environment, the next step is to become familiar with the tools. Having effective tools will significantly accelerate the learning process. The principle of "to make good work, one must first sharpen one's tools" applies here.
As a beginner, the ability to execute a single Rust script without the need to create a full project or run it within a heavy IDE is highly desirable. This allows for quick experimentation with basic Rust concepts.
The online repository crates.io hosts a variety of tools. Two notable ones for this purpose are:
cargo-script: This utility has not been updated since 2017, so it's best to focus on understanding its primary functionalities rather than relying on it for modern development.rust-script: This tool is actively maintained and is the recommended choice for running single Rust scripts.
With these tools, learning fundamental Rust code becomes straightforward, even without a full IDE setup.
For brevity, "script" or "script command" will be used interchangeably below.
Installing Scripting Tools
Installation is simple using Cargo:
cargo install cargo-scriptcargo install rust-script
Relevant project links:
cargo-script: GitHub - DanielKeep/cargo-scriptrust-script: GitHub - fornwall/rust-script, rust-script.org
Note: Its highly recommended to focus on the rust-script tool as detailed in the later sections of this article.
Be aware of a tool simply named script, which is different from cargo-script.
Understanding cargo-script
The primary function of cargo-script can be inferred from its command-line help:
cargo help script
Note: This command will only appear if cargo-script is installed.
Key options and flags are available:
-d: Add an external dependency.-D: Add a macro dependency.-x: Inject an external crate.-t: Use a template.-l: Read script from standard input and execute line by line.-: Execute the script as a literal expression.
cargo-script Examples
Running a Single .rs File Without Dependencies
This is the most common usage and is ideal for practicing basic Rust syntax when no external crates are needed.
cargo script your_script.rs
Alternatively, you can use:
cargo-script your_script.rs
The former is often more concise.
Adding/Injecting Dependencies
Consider the following script example (e.g., guessGame.rs):
/**
* cargo script -d rand 2.1guessGame.rs
*/
extern crate rand;
use std::io;
use rand::{thread_rng, Rng};
use std::cmp::Ordering;
fn main(){
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1..101);
println!("Please input your guess.");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Failed to read line");
let guess: u32 = guess.trim().parse().expect("Please type a number!");
// ... rest of the game logic
}
To compile and run this script with the rand dependency, use:
cargo script -d rand guessGame.rs
The -d flag specifies an external dependency. The -x flag can be used to inject an external crate.
Using rust-script
Getting Help
rust-script provides extensive help:
rust-script --help
rust-script shares similarities with cargo-script, as it is a fork and successor.
Running a Script Without External Dependencies
Execute a script file directly:
rust-script your_script.rs
Execution is reasonably fast for scripts without external dependencies.
Running a Script with External Dependencies
Similar to cargo-script, use the -d flag for dependencies:
rust-script -d rand your_script.rs
The first invocation might seem slow because rust-script generates and builds a temporary Cargo project. Subsequent runs of the same script will be fast due to caching. The documentation states:
Under the hood, a Cargo project will be generated and built (with the Cargo output hidden unless compilation fails or the -c/--cargo-output option is used). The first invocation of the script will be slower as the script is compiled. Subsequent invocations of unmodified scripts will be fast as the built executable is cached.
To add multiple external packages, repeat the -d flag:
rust-script -d libc -d encoding_rs your_script.rs
Executing Expressions Directly
For quick evaluation of small code snippets, use the -e flag:
rust-script -e "println!(\"Hello from expression!\");"
The -e option can be combined with other flags, such as -d, to inject modules:
rust-script -d time -e "time::util::is_leap_year(2024)"
This command would output true.
For multi-line expressions, use curly braces:
rust-script -e "{ let a = 10; let b = 20; a + b }"
This would output 30.
Using the Rust Playground
The Rust Playground (play.rust-lang.org) is a valuable online tool for testing and validating code snippets. However, it has limitations:
- It may not offer persistent storage for test code, hindering structured learning.
- Features like autocompletion are typically unavailable.
The Playground allows for real-time code execution and output visualization, makinng it suitable for quick script-like tasks.
Beyond simply running code, the Playground offers insights into the Rust compilation process:
- Build: Compiles the code.
- Test: Runs tests.
- Asm: Displays generated assembly code.
- LLVM IR: Shows the Low-Level Virtual Machine Intermediate Representation.
- MIR: Displays the Mid-level Intermediate Representation, a control-flow graph representation used for type checking and optimizations.
- HIR: Represents the High-level Intermediate Representation, which simplifies complex syntax into more basic compiler-friendly forms.
- Wasm: Compiles code to WebAssembly.
The general Rust compilation pipeline can be visualized as:
AST -> HIR -> THIR -> MIR -> LLVM IR -> Machine Code
AST (Abstract Syntax Tree): The initial tree-like representation of the source code generated by the compiler's front-end after lexical and syntax analysis.
THIR (Typed HIR): An intermediate representation that adds type information to HIR, facilitating the generation of MIR.
Conclusion
While cargo-script offers convenient features, its outdated status makes rust-script the preferred tool for executing single Rust scripts. For scenarios not requiring complex debugging, rust-script is an excellent choice.