Rust project template

#rust


My workflow to create a project in Rust and configure a few basic things to get started.

The template already contains the following things:

  • vscode workspace configuration
  • structured logging
  • a script with useful commands which can read environment variables

Prerequisites

Install rust

Create project

You can create a rust project manually or use my rust template on GitHub

Use GitHub template

github.com/juliusunscripted/rust-project-template

  • go to my template repo on GitHub (link above) and click the green button Use this template
  • GitHub will create a new repo with the content of the template
  • adjust your project package name
    • in Cargo.toml
    • in src/utils/logging.rs (adjust the project variable)
  • then you are already ready to run your app

Create project manually

  • alternatively these are the steps to create a new project manually
  • this section only describes a simpler version (only structured logging, cli via clap only part of template repo)

Init cargo project

  • in existing git repo
cargo init .

Visual Studio Code configuration

  • configure your vscode workspace
Recommended extensions
.vscode/extensions.json
{
  "recommendations": [
    "rust-lang.rust-analyzer",
    "yzhang.markdown-all-in-one",
    "tamasfe.even-better-toml",
    "usernamehw.errorlens",
    "vadimcn.vscode-lldb",
    "fill-labs.dependi"
  ]
}
Useful vscode settings
.vscode/settings.json
{
  "files.trimFinalNewlines": true,
  "files.insertFinalNewline": true,
  "[rust]": {
    "editor.detectIndentation": false,
    "editor.insertSpaces": true,
    "editor.tabSize": 4
  },
  "[toml]": {
    "editor.detectIndentation": false,
    "editor.insertSpaces": true,
    "editor.tabSize": 4
  },
  "editor.tabSize": 2,
  "editor.detectIndentation": false,
  "editor.insertSpaces": false,
  // "rust-analyzer.linkedProjects": [
  //   "projects/project-01/Cargo.toml",
  //   "projects/project-02/Cargo.toml",
  //   "projects/project-03/Cargo.toml"
  // ],
  "rust-analyzer.inlayHints.typeHints.enable": false,
  "rust-analyzer.inlayHints.parameterHints.enable": false
}

Configure structured logging

Add dependencies for structured logging
  • add the following to your dependencies
    Cargo.toml
    [dependencies]
    log={ version = "0.4.26", features = ["kv", "kv_serde"] }
    env_logger={ version = "0.11.6", features = ["unstable-kv"] }
    • run cargo check
    • run cargo run
    • everything should still work
Use structured logger
Example project main.rs
  • this example configure a structured logger in main.rs
  • you can control log levels per module via the environment variable RUST_LOG
    • check the provided links in additional resources section for more details
ℹ️
In case you want to copy this example you should set the project variable to your package name.
src/main.rs
use log;
use std::env;
fn main() {
    let mut custom_env_var_rust_log = true;
    if env::var("RUST_LOG").is_err() {
        custom_env_var_rust_log = false;
        // https://rust-lang-nursery.github.io/rust-cookbook/development_tools/debugging/config_log.html
        // simple default: set all to warn
        // let env_var_value = format!("warn");
        // let env_var_value = "warn";
        // project naming: use underscore instead of dash! (example package name: rust-project-template)
        let project = "rust_project_template";
        // set level per module and default to warn
        // let env_var_value = "warn,module_ab=info,{project}::module_xy::sub_module_12=debug";
        // project main ist just {project}
        let env_var_value = format!("warn,{project}=info");
        // ensure that the environment access only happens in single-threaded code.
        unsafe { env::set_var("RUST_LOG", env_var_value) };
    }
    let rust_log = env::var("RUST_LOG").unwrap();
    // env_logger::init();
    env_logger::builder()
        .format_file(true)
        .format_line_number(true)
        .init();
    if !custom_env_var_rust_log {
        log::info!(rust_log; "initialized logger with project default module level configuration");
    } else {
        log::info!(rust_log; "initialized logger with custom  module level configuration (set via environment variable 'RUST_LOG'")
    }
    println!("Hello, world!");
}
Example other module
  • just import the log module and use it
src/example_module/example_submodule.rs
use log;

// your code

Run your app

Basic run command

  • you can run the code via
    cargo run

Extra command for template repo example

  • use cli arguments after two dashes -- when running the program via cargo
    # cli help
    cargo run -- -h
    
    # example run
    cargo run -- --name Julius --count 3

Adjust log levels per module

  • set the environment variable RUST_LOG to configure log levels per module
ℹ️
Do not forget to adapt the module naming according to your package name which is not rust_project_template I suppose.

Set env var inline

RUST_LOG="warn,rust_project_template::example_module::example_submodule=debug" cargo run

Use .env file with bash script

details about ctl.sh script

  • create a file called .env in the root dir of the repo
    RUST_LOG="warn,rust_project_template::example_module::example_submodule=debug"
  • run you app with the following command
    ./ctl.sh cargo:run

Configure debugging

  • install vscode extension CodeLLDB (vadimcn.vscode-lldb)
  • open main.rs file
  • open debug tab
  • click run debug
  • vscode will detect Cargo.toml and provide a default debug configuration
  • now you can add breakpoints and click the debugging button to add a debug session

Additional resources

Logging

rust-analyzer

Debugging with CodeLLDB

  • vscode extension
  • vscode docs info about security stuff
    • use this command to avoid password prompt forever
      sudo DevToolsSecurity --enable
Updated on