A fully-fledged toolchain for Rust on Windows

Published: May 25, 2020   |   Read time:

Tagged:

Rust is a relatively new programming language that aims to be extremely performant and to make use of all the lessons learned by developers over the last 50 years. Initially developed by Mozilla to tackle some performance problems in Firefox, it has rapidly grown in popularity over the last five years, since its inception in 20151.

Stackoverflow Developer Survey 2019 most loved languages -80%

Many cross-platform programming languages tend to work better on certain operating systems than others (e.g. Objective-C, Powershell). But Rust aims to work wherever you need it, on whatever device, and interoperate with whatever you need it to do. It can interact with other languages via foreign function interfaces, and many Rust packages (crates, in Rust lingo) will make use of previously-existing C code.

Getting C code to compile on Windows can sometimes be a struggle, and requiring that you install gigabytes of Visual Studio Build Tools data to do so can feel pretty heavy-handed.

In this post, I’ll detail how to set up a fully-fledged toolchain for developing in Rust on your Windows machine.

Signs that you have a toolchain problem

You can simply ignore this post and follow the installation instructions that Rust provides to install everything on Windows. But even if you think you’ve installed everything correctly, you can often run into problems like this:

# install `bat`, an excellent tool https://github.com/sharkdp/bat
> cargo install bat
    Updating crates.io index
  Downloaded bat v0.15.2
  Downloaded 1 crate (910.7 KB) in 2.96s
  Installing bat v0.15.2
  ...
error: failed to run custom build command for `onig_sys v69.5.0`

Caused by:
  process didn't exit successfully: `C:\Users\james\AppData\Local\Temp\cargo-installzyH5MU\release\build\onig_sys-0407c68cb9873fa0\build-script-build` (exit code: 1)
--- stdout
TARGET = Some("x86_64-pc-windows-gnu")
OPT_LEVEL = Some("3")
HOST = Some("x86_64-pc-windows-gnu")
CC_x86_64-pc-windows-gnu = None
CC_x86_64_pc_windows_gnu = None
HOST_CC = None
CC = None
CFLAGS_x86_64-pc-windows-gnu = None
CFLAGS_x86_64_pc_windows_gnu = None
HOST_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
DEBUG = Some("false")
CARGO_CFG_TARGET_FEATURE = Some("fxsr,sse,sse2")
running: "gcc.exe" "-O3" "-ffunction-sections" "-fdata-sections" "-m64" "-I" "C:\\Users\\james\\AppData\\Local\\Temp\\cargo-installzyH5MU\\release\\build\\onig_sys-0b877317f53023b1\\out" "-I" "oniguruma\\src" "-o" "C:\\Users\\james\\AppData\\Local\\Temp\\cargo-installzyH5MU\\release\\build\\onig_sys-0b877317f53023b1\\out\\oniguruma\\src\\regexec.o" "-c" "oniguruma\\src\\regexec.c"
running: "gcc.exe" "-O3" "-ffunction-sections" "-fdata-sections" "-m64" "-I" "C:\\Users\\james\\AppData\\Local\\Temp\\cargo-installzyH5MU\\release\\build\\onig_sys-0b877317f53023b1\\out" "-I" "oniguruma\\src" "-o" "C:\\Users\\james\\AppData\\Local\\Temp\\cargo-installzyH5MU\\release\\build\\onig_sys-0b877317f53023b1\\out\\oniguruma\\src\\regerror.o" "-c" "oniguruma\\src\\regerror.c"

--- stderr


error occurred: Failed to find tool. Is `gcc.exe` installed? (see https://github.com/alexcrichton/cc-rs#compile-time-requirements for help)

To remedy this problem, we need to install a proper GNU C Compiler and set of development tools.

Installing the toolchain

Install Scoop

Scoop is a command line package manager for Windows. You can install in from PowerShell:

# allow remote signed applications to run
> Set-ExecutionPolicy RemoteSigned -scope CurrentUser
# install scoop
> Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
# ensure scoop installed correctly
> scoop --help

Install Rustup

Rust is installed and managed by the rustup tool. From Rust’s own website,

rustup manages [various Rust] builds in a consistent way on every platform that Rust supports, enabling installation of Rust from the beta and nightly release channels as well as support for additional cross-compilation targets.

Typically, you would install Rust from this site, but you can also install it via scoop2.

> scoop install rustup

Install the Rust stable, GNU toolchain

rustup can manage multiple toolchains to deal with multiple versions of the Rust compiler (think Python virtual environments for building packages). Unless you’re dealing with nightly or beta builds, you’ll only need to deal with the stable compiler. We’re going to use the GNU C Compiler, which needs the GNU toolchain.

# install the toolchain
> rustup toolchain install stable-gnu

# set this toolchain as the default
> rustup set default-host stable-gnu

# or conveniently do both with one line
> rustup default stable-gnu

Once the tools have finished installing, you can check the toolchain is set up correctly.

# if you have a 32 bit system, this will be `stable-i686-pc-windows-gnu`
> rustup toolchain list
stable-x86_64-pc-windows-gnu (default)

Install Msys2

With the toolchain set up, we can now install libraries, download binaries, and develop in Rust as we’d like. However, as mentioned before, many packages need to use a C compiler. While we have Rust set up to use the gcc compiler, we haven’t installed it yet. To do so, and to avoid the heavy Visual Studio Build Tools installer, we will use Msys2 and MinGW. These are tools that bring many tools from the GNU toolchain over to Windows to work in a minimally conflicting way.

We can also install these simply with scoop.

> scoop install msys2
Updating Scoop...
Scoop was updated successfully!
Installing 'msys2' (20190524) [64bit]
msys2-base-x86_64-20190524.tar.xz (62.0 MB) [=====================================================================================] 100%
Checking hash of msys2-base-x86_64-20190524.tar.xz ... ok.
Extracting msys2-base-x86_64-20190524.tar.xz ... done.
Running pre-install script...
Linking ~\scoop\apps\msys2\current => ~\scoop\apps\msys2\20190524
Creating shim for 'msys2'.
Creating shim for 'mingw'.
Creating shim for 'mingw32'.
Creating shim for 'mingw64'.
Creating shortcut for MSYS2 (msys2.exe)
Creating shortcut for MinGW32 (mingw32.exe)
Creating shortcut for MinGW64 (mingw64.exe)
Persisting home
'msys2' (20190524) was installed successfully!
Notes
-----
Please run 'msys2' now for the MSYS2 setup to complete!

> msys2

This opens a Bash-like shell. To install the required tools, we need to use the pacman package manager.

# update package lists
$ pacman -Syu
:: Synchronising package databases...
 mingw32                                                    462.5 KiB   262K/s 00:02 [###############################################] 100%
 mingw32.sig                                                119.0   B  0.00B/s 00:00 [###############################################] 100%
 mingw64                                                    465.1 KiB   403K/s 00:01 [###############################################] 100%
 mingw64.sig                                                119.0   B  0.00B/s 00:00 [###############################################] 100%
 msys                                                       183.3 KiB   182K/s 00:01 [###############################################] 100%
 msys.sig                                                   119.0   B   116K/s 00:00 [###############################################] 100%
:: Starting core system upgrade...
warning: terminate other MSYS2 programs before proceeding
resolving dependencies...
looking for conflicting packages...

Packages (8) bash-4.4.023-2  filesystem-2020.02-2  libzstd-1.4.4-2  mintty-1~3.1.6-1  msys2-runtime-3.1.4-3  pacman-5.2.1-8
             pacman-mirrors-20200329-1  zstd-1.4.4-2

Total Download Size:   19.29 MiB
Total Installed Size:  66.50 MiB
Net Upgrade Size:      -3.22 MiB

:: Proceed with installation? [Y/n]
:: Retrieving packages...
 msys2-runtime-3.1.4-3-x86_64                                 2.7 MiB   312K/s 00:09 [###############################################] 100%
 bash-4.4.023-2-x86_64                                     1934.3 KiB  1452K/s 00:01 [###############################################] 100%
 filesystem-2020.02-2-x86_64                                 44.9 KiB  2.93M/s 00:00 [###############################################] 100%
 mintty-1~3.1.6-1-x86_64                                    678.5 KiB  3.92M/s 00:00 [###############################################] 100%
 pacman-mirrors-20200329-1-any                               20.3 KiB  0.00B/s 00:00 [###############################################] 100%
 libzstd-1.4.4-2-x86_64                                     259.0 KiB  1193K/s 00:00 [###############################################] 100%
 zstd-1.4.4-2-x86_64                                        304.7 KiB  1259K/s 00:00 [###############################################] 100%
 pacman-5.2.1-8-x86_64                                       13.4 MiB  2.98M/s 00:05 [###############################################] 100%
(8/8) checking keys in keyring                                                       [###############################################] 100%
(8/8) checking package integrity                                                     [###############################################] 100%
(8/8) loading package files                                                          [###############################################] 100%
(8/8) checking for file conflicts                                                    [###############################################] 100%
(8/8) checking available disk space                                                  [###############################################] 100%
:: Processing package changes...
(1/8) upgrading msys2-runtime                                                        [###############################################] 100%
(2/8) upgrading bash                                                                 [###############################################] 100%
(3/8) upgrading filesystem                                                           [###############################################] 100%
(4/8) upgrading mintty                                                               [###############################################] 100%
(5/8) upgrading pacman-mirrors                                                       [###############################################] 100%
(6/8) installing libzstd                                                             [###############################################] 100%
(7/8) installing zstd                                                                [###############################################] 100%
(8/8) upgrading pacman                                                               [###############################################] 100%
warning: terminate MSYS2 without returning to shell and check for updates again
warning: for example close your terminal window instead of calling exit

Close the terminal completely, restart your computer, then reopen msys2.

Install developer tools through Msys2

# replace `x86_64` with `i686` if on a 32 bit system
> pacman -S base-devel mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake mingw-w64-x86_64-gcc
# press enter at all the prompts to install the tools
# close the shell when you're done

Add the tools to your PATH

The last thing is to add the msys2 folders to your PATH, so that you can access these tools from your shell. These folders are\path\to\msys2\current\usr\bin and \path\to\msys2\current\mingw64\bin.

You can restart your PowerShell window and be all set. We can check that this is installed correctly by trying to install a crate that requires the C compiler.

> cargo install bat
    Updating crates.io index
  Installing bat v0.15.2
  ...
    Finished release [optimized] target(s) in 13m 57s
  Installing C:\Users\james\scoop\persist\rustup\.cargo\bin\bat.exe
   Installed package `bat v0.15.2` (executable `bat.exe`)

Conclusions

Compiling the same code on a large number of devices is difficult, but Rust does a pretty good job at doing so. Many problems encountered when compiling Rust code can be addressed with ensuring the right toolchain is installed. This can be more easily achieved with with Msys2 and MinGW than by other solutions, and provides a foundation that is easily extensible for other development purposes. Making this process easy on any operating systems ensures that developers of all sorts can use this exciting new programming language to make that happen.

Happy programming.

Footnotes

  1. StackOverflow Developer Survey 2019 

  2. Luke Sampson, the developer behind scoop, got a bit annoyed by the standard installation process back in 2013, and went through the trouble of adding rustup to scoop’s packages. He describes his (possibly outdated) installation process in this blog post