about
10/21/2024
Rust Tooling

Rust Tooling

development tools for Rust: cargo, clippy, fmt, doc + VS Code, git

About
click header to toggle Rust Explorer
Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.
- Jamie Zawinski

Synopsis:

The Rust code development infrastructure is well designed and easy to use. We focus here on combining Rust build tools with Visual Studio Code and git code management.
In this post we look at processes for building programs and software systems using Rust. The intent is to provide build processes for both Windows and Linux platforms. One major ingredient is to use Visual Studio Code as a code editor on both OS platforms. VS Code supports plugins for Rust that provide intellisense and error flags. It also provides a contained terminal window we will use to initiate builds from the command line and executions of successful build products.

2. Visual Studio Code Editor:

Figure 1. VS Code IDE Installation: Download Visual Studio Code, a.k.a. VS Code. This works for Windows, Linux, and macOS. Then run installer from Downloads folder. IDE Setup: There are three things you may wish to change in the default configuration:
  1. The terminal panel, Figure 1 on the right, is placed by default at the bottom of the IDE window. It works better for me to have in on the right. You can place it wherever you like with settings (click Gear icon at left bottom -> settings):
    Settings -> User -> search for "Panel Default Location"
  2. By default the IDE shows a code Minimap on the right of the code editing panel. You can disable that with:
    Settings -> User -> TextEditor -> Minimap
  3. You may wish to change the default terminal used by VS Code:
    Settings -> Search for Terminal
    Terminal -> Integrated -> Default profile
    right click to see list: Command Prompt, PowerShell, Git Bash, ...
You will find it convenient to use the keyboard shortcuts:
  • "ctrl /" to toggle comments on selected lines
  • "ctrl [ and ctrl ]" to control indenting of selected lines
  • Also, to open integrated terminal in any folder, click top menu File, select "Open Folder" and right click any file in the folder. Then select "Open in Integrated Terminal". This is particularly useful when you open a workspace folder (any folder with .vscode subfolder).
Other Settings: To change other settings:
  • "settings -> Editor -> uncheck Accept Suggestion on Commit Character" to avoid many spurious insertions of unwanted suggestions.
  • "settings -> search for menu -> select Menu Bar Visibility" to show/hide top menu
  • "F11" to toggle full screen mode
  • "View -> Command Palette -> .Net: Generate Assets for Build and Debug" enables Run -> Start Debugging of .Net programs. Have to have editor open in project directory.
  • "ctrl K, ctrl T -> select editor theme" to select one of many alternatives
  • "settings -> workbench -> appearance -> color customizations" to set terminal colors
  • "File -> Preferences -> Settings" to change lots of defaults
  • "File -> Preferences -> Settings -> user -> Features -> Terminal" to change Terminal defaults
  • "View -> Command Pallet -> Preferences: Open Settings (JSON)" to edit any user setting manually
Settings Details
Figure 4. VS Code Project launch Settings Figure 5. VS Code User Settings The settings you will manage most often are local settings for each project, found in a .vscode folder at the top level of your project. Initially that folder doesn't exist, and you don't need to explicitly create it. VS Code creates it for you the first time you click on the Run or Terminal -> Run Task menus. You will be asked if you want to configure and, when you affirm by selecting a configuration, the folder is created and populated. That will happen as long as you have selected one or more plugins (see below). The C#, C++, and Rust plugins supply configurations for debugging. You can then edit them if you wish to modify the way debugging or builds happen. I do all builds in the terminal, so only have a launch.json file, no tasks.json file for building. VS Code settings are stored in three places:
  1. local project settings:
    Debugging settings in launch.json and build settings in tasks.json
    Find in project's .vscode folder, as JSON files launch.json and tasks.json
    Access by opening json file in code editor
  2. user settings:
    Hundreds of settings for Terminal, Keyboard mappings, ...
    Find in C:\Users\[userid]\AppData\Roaming\Code\User\settings.json
    Access: View -> Command Pallet -> Preferences -> Open Settings(JSON)
  3. default settings:
    All available settings (most of which you don't want to change)
    Doesn't appear to be a physical json file.
    Access: View -> Command Pallet -> Preferences -> Open Default Settings(JSON)
You can get to forms for changing preferences from Manage icon (gear) at left bottom of IDE.
Setup for Editing, Building, and Debugging Code: VS Code, as delivered has a very good code editor, but does not have the ability to build, execute, and debug code for the languages of interest to us here. You get those by adding plugins from the plugin selector on the left. Figure 2. VS Code Plugins If you click on the plugins icon on the left border of the IDE you will see something like the view shown in Figure 2. That shows that I have installed plugins for C++, C#, CMake, and Rust. The C++ plugin provides intellisense for the code view and for building and debugging. The plugin uses MsBuild, but the path to that needs to be configured, and you can't easily configure the terminal to use MsBuild if it isn't on your path. For that, CMake is an excellent alternative. You may wish to look at my CMakeDemo repository for a use example. You build the project target by running CMake in the attached terminal. Then run or debug using the Run menu at the top of the IDE. The C# plugin provides intellisense. You need to build your project target in the attached terminal by issuing a "dotnet build" command. Then you can run or debug using the Run menu. The Rust plugin provides intellisense and the ability to build and run the resulting executable from the Run menu. Usually I do all building in the terminal window and run from there as well, as shown in Figure 4. I just use the VS Code run menu to start Rust debugging. Debugging: Figure 3. VS Code Debugging Debugging Rust in VS Code (pdf) One final remark: you get finer control over the debugging process by selecting the debug option on the left border of the IDE, just above the plugin selector. That allows you to select one of multiple debug configurations if you have them defined in launch.json (you find that inside the .vscode folder). You also can view local variables, set watches, and look at machine registers. If you expand Figure 3. by clicking on the image body, you will see the debug control bar at the top which provides controls for single stepping, step-into, step-outof, restart, and quit. The first button on the control bar is a continue button that will move to the next available breakpoint. You set those by clicking in the left margin of the edit window, just to the left of the line numbers. Platforms: All of the above works almost identically on both Windows and Linux. I've used VS Code on macOS, but haven't yet done much development there, but expect that all of these observations carry over to that platform as well. Complementing all of this with a github account makes it easy to move code between platforms, and use virtually the same development processes on each.

3.0 Cargo Package Manager

Visual Studio Code is an effective tool for adding files and editing code. Opening a terminal panel in the editor supports command line builds, execution, formatting, and testing using the Cargo package manager. Figure 4. VS Code with Terminal Common cargo commands are:
  • cargo new mypkg
    Create directory with cargo.toml file and src directory
  • cargo run
    Build and execute binary created from src::main.rs
  • cargo test
    Run unit tests associated with src::lib.rs
  • cargo run --example test1
    Execute examples::test1.rs built with src::lib.rs
  • cargo clippy
    Evaluate package's code style and complexity
  • cargo fmt
    Reformat local source code files according to Rust community accepted rules.
Cargo is powerful but still quite easy to use, especially within a VS Code terminal panel, as shown in Figure 4. For the last two years I've used VS Code and Cargo to build virtually all of the code shown in my github repositories. That includes projects with multiple packages and remote crates from crates.io. The Cargo.toml file provides a declarative interface to define dependencies on muliple local libraries as well as remote crates. You can view more details about cargo commands in the dropdown below.
Cargo Commands 
Cargo Command Action
Selection of frequently used cargo commands and options. To see all: use cargo help
new Create a new package in a new folder. Folder contains cargo.toml file and src directory.
syntax:  cargo new name [options] [path]
options: --bin, --lib, --name, (-v, --verbose), (-q, --quiet), (-h, --help)
example: cargo new mypkg --bin
Creates new package in subdirectory mypkg. src contains code for hello world executable.
init Create a new package in an existing folder. Folder contains cargo.toml file and src directory.
syntax:  cargo init name [options] [path]
options: --bin, --lib, --name, (-v, --verbose), (-q, --quiet), (-h, --help)
example: cargo init mypkg --lib
Creates new package in existing subdirectory mypkg. src contains code for library.
build, b Compile local packages and all their dependencies that have changed since last build.
syntax:  cargo build [options]
options: (-d, --debug), (-r, --release), --example name, (-v, --verbose), (-q, --quiet)
example: cargo build --example test1
Builds test1.rs in examples subdirectory (sibling of src)
check, c Same as build but omits code generation.
run, r Build local packages and their dependencies that have changed since last build and execute bin file.
syntax:  cargo run [options] [--args]
options: (-d, --debug), (-r, --release), --example name, (-v, --verbose), (-q, --quiet)
example: cargo run
Builds main.rs in src subdirectory and its dependencies, and runs binary
example: cargo run --example test1
Builds lib.rs and its dependencies in src subdirectory, test1.rs in examples subdirectory (sibling of src) and runs binary
test, t Execute package unit, integration, and documentation tests.
syntax:  cargo test [testname] [--test-options]
options: Use cargo help test
example: cargo test
clean Remove build products
syntax: cargo clean [options]
options: Use cargo help clean
doc, d Build documentation for local package and all dependencies.
syntax: cargo doc [options]
options: Use cargo help doc
clippy Style and complexity checker. Guidance to write idiomatic code.
syntax: cargo clippy [options]
options: Use cargo help clippy
fmt Runs rustfmt on all bin and lib files in current package.
syntax: cargo fmt
common option: create rustfmt.toml file with tab_spaces = 2 to change indent width
PowerShell Commands  If you use the integrated PowerShell terminal (default for VS Code in Windows) this table will help you work productively from the command line.
Command Action
Selection of frequently used PowerShell commands and options. To see all: use PowerShell -help
ls, dir, gci, Get-ChildItem list directory contents
syntax:  ls [options] [path]
options: -Force, -(R)ecurse, -Name, -File, -Directory, -Filter, -Include, -Exclude, -Depth, -Attributes
example: ls -Filter *.zip
display all zip files in current working directory
example: ls -Hidden
display all hidden files in current working directory
example: ls -File | Select-String "Rust" | Select-Object -First 10
display first ten files containing string "Rust" - may also use regex
example: ls -Path ..
display all files and directories in parent directory
cd change current working directory
example: cd ../PostDemos
sets sibling PostDemos as current working directory
pwd, gl, Get-Location display current working directory
rm, del, Remove-Item delete file or directory
syntax: rm [options]
options: -Include, -Exclude, -Confirm, -Force, -WhatIf
example: rm foodir
removes directory foodir
example: rm foo.txt
removes file foo.txt
cls, clear clear contents of terminal
cat, type, gc, Get-Content display text representation of object on terminal
syntax: cat [options]
options: -Path, -(Head, H, First, TotalCount), -Tail, -Encoding, -Delimiter -Raw
example: cat index.html -TotalCount 10
write,
write-output,
write-host,
write-error,
echo,
Write-Output
write to pipeline, stdout, stderr
syntax: write [options]
options: -Object, -ForegroundColor, -BackgroundColor, ...
example: write-host -ForegroundColor green "this is a string" "and another" "and a final"
md, mkdir, New-Item create new directory
syntax: md [options]
options: -Name, -Path, -ItemType, -Value, -Force, -NoClobber, -Credential, -WhatIf, -Confirm
example: md foo -ItemType Directory
ni, New-Item create new object
syntax: ni [options]
options: -Name, -Path, -ItemType, -Value, -Force, -NoClobber, -Credential, -WhatIf, -Confirm
example: ni foobar.txt or ni -Name foobar.txt
creates file foobar.txt in current working directory
example: ni LinkToFoo -ItemType SymbolicLink -Target foo.txt
makes symbolic link to foo.txt
man, help, Get-Help show help text
syntax: man [options]
options: ls, cat, ...
example: man ls

4.0 Rust Development Process:

The table below captures a process for developing code using VS Code and Cargo.
Topic Rust
Installation Rust: cargo, rustc, clippy
Download Rust.
That includes rustc - the rust compiler, cargo - a package manager, and other tools like clippy. This works for Windows and Linux.
Install Rust pluggin, RLS, from the pluggin dropdown in VSCode's left menu bar. That supports intellisence and debugging. If you have any problems with that, this tutorial may help: VSCode with Rust.
Work Flow
[ Example: Bin Project ].
[ Example: Lib Project ].
Creating Projects:
In VS Code, open the parent folder where you want to create a new Rust project.

You create a binary project with the terminal command:
cargo new TestPkg --name test_pkg
That creates a new directory TestPkg with a cargo.toml metadata file and /src folder with hello world Rust code in main.rs. Rust uses the naming conventions:
  1. snake_case:
    Rust wants project names, test_pkg, and data names, my_data, to be snake_case, e.g., all lower case, words separated with an underscore.
  2. CamelCase:
    Rust wants type names Vec<String>, MyPoint, ... to be CamelCase, e.g. each word in a name is capitalized with all the other characters lower case.
That's why the new command ends with --name test_pkg. If you don't use a snake_case name you will repeatedly get warnings about naming formats.
Now you can open the new folder from the File menu and run or start debugging. when you don't need to debug just issue the command:
cargo run test_pkg
in the terminal.

You create a library with the terminal command:
cargo new TestLib --lib --name test_lib
cargo builds the library starter code with test fixtures for unit tests. Once you have some library code and corresponding tests, you run tests with the terminal command:
cargo test

If you manually create an /examples folder as a sibling to the /src folder, you can put demonstration code that uses the library and displays results on the termianl. To do that use the command:
cargo run --example test1
where test1.rs is the demonstration code inside /examples. Two things to note here:
  1. The directory name is examples (plural) but the option is --example (singular).
  2. The file name is test1.rs but the option value is test1 (no extension).
Building Applications Figure 4. Application Structure When you build applications, you will probably factor them into several libraries and an executive. Figure 4. presents an example.
Each library has:
  1. A library directory containing a cargo.toml file, a src directory containing library code, and an examples directory containing one or more test and demonstration files, each with a main function.
  2. Cargo.toml file contains metadata about the library and a list of dependencies, if any. That dependency list helps cargo automatically bind dependencies to the library.
  3. lib.rs file that contains source code for the library and usually a set of configured tests checking that the library maintains its design invariants.
    You run those tests with the command:
    cargo test
    Run from the terminal in the library project directory (where the cargo.toml file resides).
  4. One or more test and demonstration files, each with a main function, test1.rs, ... placed in an "examples" directory, a sibling of "src". These files bind to the library and provide visual evidence that library's operations are as expected. You run demonstration tests with the command:
    cargo run --example test1
The Application has an Executive directory with:
  1. A cargo.toml file listing the dependencies of the executive on Lib #1 and Lib #2.
    [dependencies]
    lib1_name = { Path = "../Lib1" }
    lib2_name = { Path = "../Lib2" }
  2. An executive file with a main function and, at the top:
    use lib1_name::*;
    use lib2_name::*;
    This gives executive code access to all the public facilities in both libraries.
The Cargo book has examples of this with several additional options.
Managing code with git git is a distributed version control system. It manages versions of code with one or more branches.
Typical commands are:
  • git init
    create a git repository
  • git status
    list all files in a managed directory tree that have been changed since last git update
  • git -A
    add all changed files to staging area
  • git commit -m"<message>"
    add staged files to git repository
  • git push origin branch-name
    send updates to remote repository
  • git pull origin branch-name
    pull updates from remote repository and save locally
  • git checkout -b branch-name
    create new branch
  • git checkout branch-name
    switch to existing branch
Collaborate using github
Create (free) account if you don't have one.
Submit pull request:
  • Fork remote repository if you don't have push access
    • Open remote repository in github.com and click fork button. That creates a copy of repository in your account.
    • Clone forked repository to your local machine.
  • Navigate into local repository.
  • create a new branch:
    • git checkout -b my-proposed-changes
  • Make changes and commit:
    • git add -A
    • git commit -m"change-summary"
  • Push to your forked github repo:
    • git remote add origin url-to-your-remote-github-repo
    • git push origin my-proposed-changes
  • Create pull request on original github repo
    • Go to forked repository on your github account
    • click "Compare & pull" request
    • Provide a title and description in PR form
    • choose main branch of original repo
    • click Create pull request
  Next Prev Pages Sections About Keys