Rust Bite: Tooling

code development tools

1. Prologue

This Bite examines processes for building Rust programs and software systems. The goal is to support build processes on both Windows and Linux platforms. Visual Studio Code serves as the code editor on both OS platforms. VS Code supports Rust plugins that supply intellisense and error flags. It also hosts a contained terminal window that initiates builds from the command line and runs successful build products.

2. Visual Studio Code Editor:

Figure 1. VS Code IDE
Installation: Download Visual Studio Code, a.k.a. VS Code. It runs on Windows, Linux, and macOS. Then run the installer from the Downloads folder. IDE Setup: Consider changing two items in the default configuration:
  1. The IDE places the terminal panel, shown in Figure 1, at the bottom of the window by default. I prefer it on the right. Move it wherever you like through settings (click the Gear icon at the lower left, then select settings):
    Settings -> User -> Workbench -> Panel Default Location
  2. The IDE shows a code Minimap on the right of the code editing panel by default. Disable it with:
    Settings -> User -> TextEditor -> Minimap
These keyboard shortcuts prove convenient: Other Settings: To change other settings:
Settings Details
Figure D1. VS Project launch Settings
Figure D2. VS Code User Settings
Local settings for each project sit in a .vscode folder at the top level of the project. You manage these most often. The folder does not exist initially, and you do not need to create it. VS Code creates it the first time you click the Run or Terminal -> Run Task menus. VS Code asks whether to configure the project, and once you select a configuration it creates and populates the folder. That happens as long as you have selected one or more plugins (see below). The C#, C++, and Rust plugins supply configurations for debugging. Edit them to modify the way debugging or builds run. I run all builds in the terminal, so I keep only a launch.json file and 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 do not want to change)
    Does not appear to be a physical json file.
    Access: View -> Command Pallet -> Preferences -> Open Default Settings(JSON)
Reach the forms for changing preferences through the Manage icon (gear) at the lower left of the IDE.
Setup for Editing, Building, and Debugging Code: VS Code ships with an excellent code editor but does not build, execute, or debug code for the languages of interest here. Add those capabilities through the plugin selector on the left.
Figure 2. VS Code Plugins
Click the plugins icon on the left border of the IDE to see a view like Figure 2. It shows that I have installed plugins for C++, C#, CMake, and Rust. The C++ plugin supplies intellisense for the code view and for building and debugging. The plugin uses MsBuild, but you must configure the path to it, and configuring the terminal to use MsBuild proves difficult when MsBuild is not on your path. CMake serves as an excellent alternative. See my CMakeDemo repository for a use example. Build the project target by running CMake in the attached terminal. Then run or debug through the Run menu at the top of the IDE. The C# plugin supplies intellisense. Build the project target in the attached terminal by issuing a "dotnet build" command. Then run or debug through the Run menu. The Rust plugin supplies intellisense and builds and runs the resulting executable from the Run menu. I do all the building in the terminal window and run from there as well. I use the VS Code Run menu only to start Rust debugging. Debugging:
Figure 3. VS Code Debugging
Debugging Rust in VS Code (pdf) One final remark: select the debug option on the left border of the IDE, just above the plugin selector, for finer control over the debugging process. That lets you select one of multiple debug configurations defined in launch.json (found inside the .vscode folder). You can also view local variables, set watches, and inspect machine registers. Expand Figure 3 by clicking on the image body to 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 moves execution to the next available breakpoint. Set breakpoints 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 have used VS Code on macOS but have not yet done much development there. I expect these observations to carry over to that platform as well. A github account complements this setup, letting you move code between platforms and use essentially the same development processes on each.

3. Development Process:

Topic Rust
Installation Rust: cargo, rustc, clippy
Download Rust.
The download includes rustc - the Rust compiler, cargo - a package manager, and other tools like clippy. It runs on Windows and Linux.
Install the Rust plugin, RLS, from the plugin dropdown in VS Code's left menu bar. It supports intellisense and debugging. If you run into problems, this tutorial may help: VSCode with Rust.
Work Flow Creating Projects:
In VS Code, open the parent folder where you want to create a new Rust project. In the terminal issue the command:
cargo new TestPkg --name test_pkg
That creates a new directory TestPkg with a cargo.toml metadata file and a /src folder that holds hello world Rust code in main.rs. Rust uses these naming conventions:
  1. snake_case:
    Rust expects project names, test_pkg, and data names, my_data, to use snake_case, e.g., all lower case with words separated by an underscore.
  2. CamelCase:
    Rust expects type names Vec<String>, MyPoint, ... to use CamelCase, e.g. each word in a name starts with a capital letter and the remaining characters are lower case.
That is why the new command ends with --name test_pkg. Without a snake_case name you will repeatedly get warnings about naming formats.
Open the new folder from the File menu and run or start debugging. When you do not need to debug, issue the command:
cargo run test_pkg
in the terminal.

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 add library code and corresponding tests, run them with the terminal command:
cargo test

Create an /examples folder as a sibling to the /src folder to hold demonstration code that uses the library and displays results on the terminal. Run it with 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 You will typically factor applications into several libraries and an executive. Figure 4 presents an example.
Each library has:
  1. A library directory that contains a cargo.toml file, a src directory that holds library code, and an examples directory that holds one or more test and demonstration files, each with a main function.
  2. A cargo.toml file that contains metadata about the library and a list of dependencies, if any. That dependency list lets cargo bind dependencies to the library automatically.
  3. A lib.rs file that holds source code for the library and usually a set of configured tests that check that the library maintains its design invariants.
    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, ... These files bind to the library and provide visual evidence that the library's operations behave as expected. Run demonstration tests with the command:
    cargo run --example test1
The Application has an Executive directory with:
  1. A cargo.toml file that lists the executive's dependencies 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 presents examples of this pattern with several additional options.

4. Epilogue

The following pages present discussions and code examples for most of the important Rust features.