ヴェズルフェルニルの研究ノート

座右の銘「ただ一人犀の角のように歩め」的な研究活動ノート

Rustのインストールと開発環境の構築

本業仕事で新しいIoTプロジェクトに関わっている。このプロジェクトのターゲット機はRaspberry Piを搭載しており、小生はファームウェアの開発を行っているが、そのプログラミング言語としてRustを使っている。

本格的にRustを使ってソフトウェア開発を行うのがこれが初めてだ。ハード制御を行うファームウェアC/C++を使って開発するのが一般的だが(最近は組み込みもPythonやNode.jsを使って開発できないこともないが、速度的制約をクリアしなければならなかったり細かなハード制御が必要だったりすると、やはりC/C++の方が実現し易い)、Rustを使っても同様の目的が達成できるんじゃないかと思っていた。実際にRustによるLinux稼働ファームウェアの開発を進めていて、この選択は正解だったと実感している。

RustはC/C++よりプログラミング・コストが低く、発達したエコシステムにより豊富なライブラリが揃っており、それらを使うとハード寄りのディープな目的もほとんど達成できる。速度面でもC/C++に劣らず、細やかな非同期処理、スレッド制御、メモリ管理も可能だ。

最近登場している開発系ツールはRustで書かれているものが多い。Rustを使ってWeb開発もできるし、PythonやNode.jsより応答性能の高いものが作れる。Rust用機械学習ライブラリも登場しているし、Rustで書かれたリアルタイムOSやESP32などのマイコン開発用フレームワークも存在する。組み込み開発もいまはRustでやるのが最適解なのかもしれない。あらゆる分野でRustが使われるトレンドが起きているようだ。

今回のプロジェクトだけでなく、自己研究でのIoTやエッジ・組み込みLinux利用開発でも積極的にRustを使っていくつもりだ。

自分の備忘録として、MacUbuntu機へRustの開発環境を構築する手順を書き残しておく。

Rustのインストール

Rustのインストール方法として、公式サイトではrustupを使うことが推薦されている。

www.rust-lang.org

asdfを使ってRustをインストールすることもできるが、asdfによって導入できるのはrustc(Rustコンパイラ)だけで、rustupは使えない。rustupを使うと複数のバージョンのRustをインストールでき(asdfのような言語バージョン管理ツールの機能も兼ね備えている)、cargoというパッケージマネージャも一緒に導入できる。Rustでのパッケージ管理はこのcargoを使うことが前提となる。

現状、Rustのインストールはrustupを使って行うのが最良の方法と言えるだろう。

% brew install rustup
% echo 'export PATH="/usr/local/opt/rustup/bin:$PATH"' >> ~/.zshrc
% source ~/.zshrc

bashの場合は、"~/.zshrc" の部分を "~/.bashrc" に変える。

$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

本インストール・コマンドの実行時に後述の "rustup-init" コマンドも一緒に実行される。

Rustの初期設定

rustupをインストールしたら、最初に下のコマンドを実行して、Rust環境の初期設定を行っておく。

% rustup-init

Welcome to Rust!

This will download and install the official compiler for the Rust
programming language, and its package manager, Cargo.

Rustup metadata and toolchains will be installed into the Rustup
home directory, located at:

  /Users/LOGNAME/.rustup

This can be modified with the RUSTUP_HOME environment variable.

The Cargo home directory is located at:

  /Users/LOGNAME/.cargo

This can be modified with the CARGO_HOME environment variable.

The cargo, rustc, rustup and other commands will be added to
Cargo's bin directory, located at:

  /Users/LOGNAME/.cargo/bin

This path will then be added to your PATH environment variable by
modifying the profile files located at:

  /Users/LOGNAME/.profile
  /Users/LOGNAME/.zshenv

You can uninstall at any time with rustup self uninstall and
these changes will be reverted.

Current installation options:


   default host triple: x86_64-apple-darwin
     default toolchain: stable (default)
               profile: default
  modify PATH variable: yes

1) Proceed with standard installation (default - just press enter)
2) Customize installation
3) Cancel installation
>

info: profile set to 'default'
info: default host triple is x86_64-apple-darwin
info: syncing channel updates for 'stable-x86_64-apple-darwin'
info: latest update on 2024-06-13, rust version 1.79.0 (129f3b996 2024-06-10)
info: downloading component 'cargo'
  6.9 MiB /   6.9 MiB (100 %)   4.8 MiB/s in  1s ETA:  0s
info: downloading component 'clippy'
info: downloading component 'rust-docs'
 15.4 MiB /  15.4 MiB (100 %)   4.8 MiB/s in  3s ETA:  0s
info: downloading component 'rust-std'
 23.4 MiB /  23.4 MiB (100 %)   6.7 MiB/s in  3s ETA:  0s
info: downloading component 'rustc'
 55.5 MiB /  55.5 MiB (100 %)   5.1 MiB/s in  9s ETA:  0s
info: downloading component 'rustfmt'
info: installing component 'cargo'
info: installing component 'clippy'
info: installing component 'rust-docs'
 15.4 MiB /  15.4 MiB (100 %)   2.5 MiB/s in  5s ETA:  0s
info: installing component 'rust-std'
 23.4 MiB /  23.4 MiB (100 %)   9.8 MiB/s in  2s ETA:  0s
info: installing component 'rustc'
 55.5 MiB /  55.5 MiB (100 %)  10.6 MiB/s in  5s ETA:  0s
info: installing component 'rustfmt'
info: default toolchain set to 'stable-x86_64-apple-darwin'

  stable-x86_64-apple-darwin installed - rustc 1.79.0 (129f3b996 2024-06-10)


Rust is installed now. Great!

To get started you may need to restart your current shell.
This would reload your PATH environment variable to include
Cargo's bin directory ($HOME/.cargo/bin).

To configure your current shell, you need to source
the corresponding env file under $HOME/.cargo.

This is usually done by running one of the following (note the leading DOT):
. "$HOME/.cargo/env"            # For sh/bash/zsh/ash/dash/pdksh
source "$HOME/.cargo/env.fish"  # For fish

※上はIntel Mac上での "rustup-init" コマンドの実行例。他のプラットホーム上では "x86_64-apple-darwin" などの表示が変わってくる。

"rustup-init" コマンドによる初期設定が済んだら、下のような記述を.zshrcbashの場合は.bashrc)に追加した上で、それを有効にする。

% vi ~/.zshrc
. "$HOME/.cargo/env"
% source ~/.zshrc

その上で、コマンド "rustc" と "cargo" が利用できることを確認しておく。

% rustc --version
rustc 1.79.0 (129f3b996 2024-06-10)
% cargo --version
cargo 1.79.0 (ffa9cf99a 2024-06-03)

rustupによってインストールしたRust環境のファイル群はディレクト$HOME/.cargoの中に格納されている。

補足情報

Macで "rustup-init" コマンドを実行したときに、下のような警告が表示されることがある。

% rustup-init
warning: it looks like you have an existing installation of Rust at:
warning: /usr/local/bin
warning: It is recommended that rustup be the primary Rust installation.
warning: Otherwise you may have confusion unless you are careful with your PATH
warning: If you are sure that you want both rustup and your already installed Rust
warning: then please reply `y' or `yes' or set RUSTUP_INIT_SKIP_PATH_CHECK to yes
warning: or pass `-y' to ignore all ignorable checks.
error: cannot install while Rust is installed

Continue? (y/N)

Homebrewによってすでにrustパッケージが導入済みときに、この警告が表示される。

この場合は、以下のコマンドによってrustパッケージが存在することを確認し、それをアンインストールしてから、 "rustup-init" コマンドを再度実行すれば良い。

% which rustc
/usr/local/bin/rustc
% brew info rust
==> rust: stable 1.79.0 (bottled), HEAD
Safe, concurrent, practical language
https://www.rust-lang.org/
Installed
/usr/local/Cellar/rust/1.78.0 (3,320 files, 294.3MB) *
  Poured from bottle using the formulae.brew.sh API on 2024-06-07 at 08:29:53
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/r/rust.rb
License: Apache-2.0 or MIT
==> Dependencies
Required: libgit2 ✔, libssh2 ✔, llvm ✘, openssl@3 ✘, pkg-config ✔
==> Requirements
Required: macOS >= 10.12 (or Linux) ✔
==> Options
--HEAD
    Install HEAD version
==> Caveats
zsh completions have been installed to:
  /usr/local/share/zsh/site-functions
==> Analytics
install: 36,888 (30 days), 122,724 (90 days), 431,118 (365 days)
install-on-request: 26,090 (30 days), 89,554 (90 days), 325,780 (365 days)
build-error: 346 (30 days)
% brew uninstall rust

Rustによるプロジェクト作成とビルド

Rustによるプロジェクト(プログラム)の作成とビルドができることを確認しておこう。

プロジェクトの作成

新しいRustプロジェクトの作成は、以下のような "cargo" コマンドを使って行える。

プロジェクト・ディレクトリを新規作成する場合

% cargo new hello_rust
   Creating binary (application) `hello_rust` package
note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

既存ディレクトリ内でプロジェクトを作成する場合

% mkdir hello_rust
% cd hello_rust
% cargo init
    Creating binary (application) package
note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Rustプロジェクトを作成すると、一緒にCargo.tomlというファイルも生成され、この中にプロジェクトの依存パッケージ情報が記述されている(Rustでは、パッケージを "Crate" と呼称する)。

プロジェクト・ソースの作成

コマンド "cargo new PROJECT_NAME" や "cargo init" によってプロジェクトを作成すると、プロジェクト・ディレクトリ内にsrcというディレクトリが生成されており、Rustプログラムのソースファイルはこのディレクトリの中に作成していくことが決まり事になっている。

また、下のような一つのソースファイルも自動的に生成される。

  • src/main.rs
fn main() {
    println!("Hello, world!");
}

プロジェクトのビルドと実行

プロジェクト・ディレクトリ内で下のコマンドを実行することで、そのプロジェクトのビルドが行える。

% cargo build
   Compiling hello_rust v0.1.0 (/Users/LOGNAME/hello_rust)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.18s

下のコマンドによって、プロジェクト・プログラムを起動・実行することができる。

% cargo run
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/hello_rust`
Hello, world!

コマンド "cargo run" はプロジェクトのビルドと実行を続けて行っている。

Rust開発環境の整備

Rustによるプログラム開発に有益なツールが多く在るが、その中から厳選してみた。それらのインストール方法を以下に記しておく。

追加コンポーネントのインストール

% rustup component add rls rust-analysis rust-src rust-analyzer

コンポーネントの機能は以下のとおり。

  • rls 旧版のRust Language Server(古いバージョンのRustで使われる)
  • rust-analysis Rust標準ライブラリのメタデータ
  • rust-src Rust標準ライブラリのソースコードのローカルコピー(rlsrust-analyzerなどで参照される)
  • rust-analyzer 新版のRust Language Server(最近のバージョンのRustでは、こちらが使われる)

以下のコンポーネントも有益だが、本記事執筆時点のRustの最新バージョンでは、これらは "rustup-init" コマンドによる初期設定時にインストール済みになっていた。

  • clippy Rust公式のリンター(変数名ルールなどの静的解析を行う)
  • rust-docs 公式Rustドキュメントのローカルコピー("rustup doc" コマンド実行時に、ローカルの公式ドキュメントを参照できるようになる)
  • rustfmt コード・フォーマッタ(ソースコードの可読性整形を行う)

インストール済みのRustコンポーネントは下のコマンドによって確認できる。

% rustup component list
cargo-x86_64-apple-darwin (installed)
clippy-x86_64-apple-darwin (installed)
llvm-bitcode-linker-x86_64-apple-darwin
llvm-tools-x86_64-apple-darwin
rls-x86_64-apple-darwin
rust-analysis-x86_64-apple-darwin
rust-analyzer-x86_64-apple-darwin
rust-docs-x86_64-apple-darwin (installed)
rust-src
rust-std-aarch64-apple-darwin
rust-std-aarch64-apple-ios
rust-std-aarch64-apple-ios-sim
rust-std-aarch64-linux-android
rust-std-aarch64-pc-windows-gnullvm
rust-std-aarch64-pc-windows-msvc
rust-std-aarch64-unknown-fuchsia
rust-std-aarch64-unknown-linux-gnu
rust-std-aarch64-unknown-linux-musl
rust-std-aarch64-unknown-linux-ohos
rust-std-aarch64-unknown-none
rust-std-aarch64-unknown-none-softfloat
rust-std-aarch64-unknown-uefi
rust-std-arm-linux-androideabi
rust-std-arm-unknown-linux-gnueabi
rust-std-arm-unknown-linux-gnueabihf
rust-std-arm-unknown-linux-musleabi
rust-std-arm-unknown-linux-musleabihf
rust-std-armebv7r-none-eabi
rust-std-armebv7r-none-eabihf
rust-std-armv5te-unknown-linux-gnueabi
rust-std-armv5te-unknown-linux-musleabi
rust-std-armv7-linux-androideabi
rust-std-armv7-unknown-linux-gnueabi
rust-std-armv7-unknown-linux-gnueabihf
rust-std-armv7-unknown-linux-musleabi
rust-std-armv7-unknown-linux-musleabihf
rust-std-armv7-unknown-linux-ohos
rust-std-armv7a-none-eabi
rust-std-armv7r-none-eabi
rust-std-armv7r-none-eabihf
rust-std-i586-pc-windows-msvc
rust-std-i586-unknown-linux-gnu
rust-std-i586-unknown-linux-musl
rust-std-i686-linux-android
rust-std-i686-pc-windows-gnu
rust-std-i686-pc-windows-gnullvm
rust-std-i686-pc-windows-msvc
rust-std-i686-unknown-freebsd
rust-std-i686-unknown-linux-gnu
rust-std-i686-unknown-linux-musl
rust-std-i686-unknown-uefi
rust-std-loongarch64-unknown-linux-gnu
rust-std-loongarch64-unknown-none
rust-std-loongarch64-unknown-none-softfloat
rust-std-nvptx64-nvidia-cuda
rust-std-powerpc-unknown-linux-gnu
rust-std-powerpc64-unknown-linux-gnu
rust-std-powerpc64le-unknown-linux-gnu
rust-std-riscv32i-unknown-none-elf
rust-std-riscv32im-unknown-none-elf
rust-std-riscv32imac-unknown-none-elf
rust-std-riscv32imafc-unknown-none-elf
rust-std-riscv32imc-unknown-none-elf
rust-std-riscv64gc-unknown-linux-gnu
rust-std-riscv64gc-unknown-none-elf
rust-std-riscv64imac-unknown-none-elf
rust-std-s390x-unknown-linux-gnu
rust-std-sparc64-unknown-linux-gnu
rust-std-sparcv9-sun-solaris
rust-std-thumbv6m-none-eabi
rust-std-thumbv7em-none-eabi
rust-std-thumbv7em-none-eabihf
rust-std-thumbv7m-none-eabi
rust-std-thumbv7neon-linux-androideabi
rust-std-thumbv7neon-unknown-linux-gnueabihf
rust-std-thumbv8m.base-none-eabi
rust-std-thumbv8m.main-none-eabi
rust-std-thumbv8m.main-none-eabihf
rust-std-wasm32-unknown-emscripten
rust-std-wasm32-unknown-unknown
rust-std-wasm32-wasi
rust-std-wasm32-wasip1
rust-std-wasm32-wasip1-threads
rust-std-x86_64-apple-darwin (installed)
rust-std-x86_64-apple-ios
rust-std-x86_64-fortanix-unknown-sgx
rust-std-x86_64-linux-android
rust-std-x86_64-pc-solaris
rust-std-x86_64-pc-windows-gnu
rust-std-x86_64-pc-windows-gnullvm
rust-std-x86_64-pc-windows-msvc
rust-std-x86_64-unknown-freebsd
rust-std-x86_64-unknown-fuchsia
rust-std-x86_64-unknown-illumos
rust-std-x86_64-unknown-linux-gnu
rust-std-x86_64-unknown-linux-gnux32
rust-std-x86_64-unknown-linux-musl
rust-std-x86_64-unknown-linux-ohos
rust-std-x86_64-unknown-netbsd
rust-std-x86_64-unknown-none
rust-std-x86_64-unknown-redox
rust-std-x86_64-unknown-uefi
rustc-x86_64-apple-darwin (installed)
rustc-dev-aarch64-apple-darwin
rustc-dev-aarch64-pc-windows-msvc
rustc-dev-aarch64-unknown-linux-gnu
rustc-dev-aarch64-unknown-linux-musl
rustc-dev-arm-unknown-linux-gnueabi
rustc-dev-arm-unknown-linux-gnueabihf
rustc-dev-armv7-unknown-linux-gnueabihf
rustc-dev-i686-pc-windows-gnu
rustc-dev-i686-pc-windows-msvc
rustc-dev-i686-unknown-linux-gnu
rustc-dev-loongarch64-unknown-linux-gnu
rustc-dev-powerpc-unknown-linux-gnu
rustc-dev-powerpc64-unknown-linux-gnu
rustc-dev-powerpc64le-unknown-linux-gnu
rustc-dev-riscv64gc-unknown-linux-gnu
rustc-dev-s390x-unknown-linux-gnu
rustc-dev-x86_64-apple-darwin
rustc-dev-x86_64-pc-windows-gnu
rustc-dev-x86_64-pc-windows-msvc
rustc-dev-x86_64-unknown-freebsd
rustc-dev-x86_64-unknown-illumos
rustc-dev-x86_64-unknown-linux-gnu
rustc-dev-x86_64-unknown-linux-musl
rustc-dev-x86_64-unknown-netbsd
rustc-docs-x86_64-unknown-linux-gnu
rustfmt-x86_64-apple-darwin (installed)

追加パッケージのインストール

% cargo install cargo-edit
% cargo install cargo-watch
$ sudo apt install -y libssl-dev
$ cargo install cargo-edit
$ cargo install cargo-watch
  • cargo-edit (Rustでのプロジェクトの依存パッケージ変更はCargo.tomlを編集することで行うが)Rustパッケージ(Crate)の追加/削除を "cargo add CRATE_NAME" や "cargo rm CRATE_NAME" というコマンドで行えるようになる
  • cargo-watch ソースファイルの変更を検知して、"cargo run" コマンドを自動的に実行してくれる

インストール済みのRustパッケージは下のコマンドによって確認できる。

% cargo install --list
cargo-edit v0.12.3:
    cargo-add
    cargo-rm
    cargo-set-version
    cargo-upgrade
cargo-watch v8.5.2:
    cargo-watch

Visual Studio Code拡張機能のインストール

VSCodeでのRustプログラム開発に有益な拡張機能として、rust-analyzerをインストールしておくことを薦める。

これは上述のコンポーネントrust-analyzerVSCode版だ。

少し前までRust(Rust言語対応ユーティリティ機能)とrust-analyzer(Language Support Server)という2つの拡張機能が存在しており、この両方をインストールすることが推薦されていたが、現在この2つはrust-analyzerの一つに統合されている。本記事執筆時点では、VSCodeのRust用拡張機能として最低限rust-analyzerだけをインストールしておけば良いだろう。

【追記】〔2024-07-23〕

VSCodeのRust用拡張機能として、CodeLLDBもインストールする必要があるのを書き忘れていた。

これはVSCode上でのRustソースコードデバッグ実行に使われるものだ。

小生のVSCode環境にはSwiftという拡張機能が導入済みで、このSwiftCodeLLDBに依存しており、すでにCodeLLDBがインストール済みだったので上のことに気づかなかった。

【追記】〔2024-07-24〕

備忘録として、cargoコマンドの使い方も書いておく。

新規プロジェクトの作成

cargo new PROJECT_NAME

本コマンドは通常パッケージ用プロジェクトを作成する。

コマンド "cargo new --bin PROJECT_NAME" によって、バイナリパッケージ用プロジェクトを作成できる。

既存ディレクトリ上でのプロジェクトの作成

cd PROJECT_DIR
cargo init

プロジェクトのビルド

cargo build

オプションなし(または--debugオプション付き)で本コマンドを実行すると、Debug用実行可能ファイルがビルドされる。コマンド "cargo build --relaese" だと、Relaese用実行可能ファイルがビルドされる。

コマンド "cargo build --example EXAMPLE_NAME" によって、examplesディレクトリ内の指定サンプルプログラムをビルドできる。

プロジェクトのビルドと実行

cargo run

コマンド "cargo run --example EXAMPLE_NAME" によって、examplesディレクトリ内の指定サンプルプログラムをビルド・実行できる。

プロジェクトのビルド可能確認

cargo check

本コマンドによってプロジェクトのビルドは行われず、コンパイル確認だけが行われる。

プロジェクトのビルド削除(クリーン)

cargo clean

パッケージ(Crate)のインストール

cargo add CRATE_NAME

cargo-editがインストールされている場合に使えるコマンド

パッケージ(Crate)のアンインストール

cargo rm CRATE_NAME

cargo-editがインストールされている場合に使えるコマンド

パッケージ(Crate)の検索

cargo search CRATE_NAME

Rust Crateの公式配布サイトcrates.ioから、指定した名前を含むCrateが検索される。

crates.io

依存Crateの更新

cargo update

本コマンドによって、プロジェクトの全依存Crateが最新版へ更新される。

テストの実行

cargo test

ディレクトtests内にプロジェクトの単体テスト用ソースファイルが作成されている場合に、本コマンドによってそれらがビルド・実行される。

プロジェクト・ドキュメントの作成

cargo doc

プロジェクトのファイル群からドキュメントを生成する。

ソースファイル中に一定のルールに則って記述されたコメントが、本コマンドによるドキュメント情報収集の対象となる。

バイナリパッケージのインストール

cargo install PACKAGE_NAME

バイナリパッケージのアンインストール

cargo uninstall PACKAGE_NAME

【参照リンク】

qiita.com

zenn.dev

code.visualstudio.com