お金をかけずにサーバーの勉強をしよう

Rustインストール

2024年1月17日

メニューへ戻る

開発言語 Rustを Ubuntu 22.04にインストールします。

Linuxカーネル 6.1より Rustで作成された機能の取り込みが始まりました。
まだ C・C++に取って代わるわけではないですが、段々とその地位を上げいくだろうと見られていますね。

これまで Cや C++での開発をしてきていない人には余り興味のない開発言語かも知れませんが、勢力を増してきているものではあるので、ここでは Rustの環境を作ってみることにします。

Rustの本家サイトはこちら。
Rust


1.環境

2024年1月17日現在の最新バージョンは、1.75.0です。

Ubuntu Server 22.04.3にインストールをしますが、Desktop版でも何も変わらないでしょう。

Ubuntu Serverのインストールについては、
Ubuntu Linux Serverをインストール」 及び
Ubuntu Serverの初期設定」 に書いています。


2.インストール

前提があって、gccがインストールされていなければなりませんので、やっておきます。

subro@UbuntuServer2204-1:~$ sudo apt -y install gcc
〜〜〜 省略 〜〜〜

Rustのインストール手順はこちらです。
Rustをインストール
では、手順に沿ってやっていきましょう。

Rustも最近流行りのホームディレクトリ配下のディレクトリにインストールされるタイプですので、sudoは使いません。

subro@UbuntuServer2204-1:~$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
info: downloading installer

iWelcome 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:

  /home/subro/.rustup

This can be modified with the RUSTUP_HOME environment variable.

The Cargo home directory is located at:

  /home/subro/.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:

  /home/subro/.cargo/bin

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

  /home/subro/.profile
  /home/subro/.bashrc

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

Current installation options:


   default host triple: x86_64-unknown-linux-gnu
     default toolchain: stable (default)
  modify PATH variable: yes
               profile: default

1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
>1  ← 見づらいですがここで「1」と入力しています。

info: profile set to 'default'
info: default host triple is x86_64-unknown-linux-gnu
info: syncing channel updates for 'stable-x86_64-unknown-linux-gnu'
info: latest update on 2023-12-28, rust version 1.75.0 (82e1608df 2023-12-21)
info: downloading component 'cargo'
info: downloading component 'clippy'
info: downloading component 'rust-docs'
 14.3 MiB /  14.3 MiB (100 %)  11.0 MiB/s in  1s ETA:  0s
info: downloading component 'rust-std'
 23.6 MiB /  23.6 MiB (100 %)  11.2 MiB/s in  2s ETA:  0s
info: downloading component 'rustc'
 61.4 MiB /  61.4 MiB (100 %)  11.1 MiB/s in  5s ETA:  0s
info: downloading component 'rustfmt'
info: installing component 'cargo'
info: installing component 'clippy'
info:installing component 'rust-docs'
 14.3 MiB /  14.3 MiB (100 %)   3.2 MiB/s in  4s ETA:  0s
info: installing component 'rust-std'
 23.6 MiB /  23.6 MiB (100 %)   8.9 MiB/s in  2s ETA:  0s
info: installing component 'rustc'
 61.4 MiB /  61.4 MiB (100 %)   9.7 MiB/s in  6s ETA:  0s
info: installing component 'rustfmt'
info: default toolchain set to 'stable-x86_64-unknown-linux-gnu'

  stable-x86_64-unknown-linux-gnu installed - rustc 1.75.0 (82e1608df 2023-12-21)


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, run:
source "$HOME/.cargo/env"

難なくインストールできました。

[~/.bashrc]ファイルと [~/.profile]ファイルに次の 1行が勝手に加えられていて、Rustのコマンドにパスが通るようになっていました。

. "$HOME/.cargo/env"

これを有効化しましょう。

subro@UbuntuServer2204-1:~$ . .bashrc

[~/.cargo]ディレクトリがインストール先ですが、何ができたか見てみましょう。

subro@UbuntuServer2204-1:~$ tree .cargo
.cargo
├── bin
│   ├── cargo
│   ├── cargo-clippy
│   ├── cargo-fmt
│   ├── cargo-miri
│   ├── clippy-driver
│   ├── rls
│   ├── rust-analyzer
│   ├── rust-gdb
│   ├── rust-gdbgui
│   ├── rust-lldb
│   ├── rustc
│   ├── rustdoc
│   ├── rustfmt
│   └── rustup
└── env

1 directory, 15 files

[~/cargo/bin/rustc]ファイルが Rustのコンパイラです。
Javaみたいです。

バージョンを確認します。

subro@UbuntuServer2204-1:~$ rustc --version
rustc 1.75.0 (82e1608df 2023-12-21)

問題ないようです。


3.チュートリアルのプロジェクトをやってみる

Rustは一度も書いたことがないので、次のチュートリアルに従ってプロジェクトを作って実行してみます。
はじめに

ここの下の方に「新しいプロジェクトを作成する」という段落がありますので、それに沿って進めます。

[hello-rust]プロジェクトを作ります。

以下、[~/work/rust]ディレクトリで作業します。

subro@UbuntuServer2204-1:~/work/rust$ cargo new hello-rust
     Created binary (application) `hello-rust` package

中身はこんな風になってます。

subro@UbuntuServer2204-1:~/work/rust$ tree -a hello-rust
hello-rust
├── .git
│   ├── HEAD
│   ├── config
│   ├── description
│   ├── hooks
│   │   ├── applypatch-msg.sample
│   │   ├── commit-msg.sample
│   │   ├── fsmonitor-watchman.sample
│   │   ├── post-update.sample
│   │   ├── pre-applypatch.sample
│   │   ├── pre-commit.sample
│   │   ├── pre-merge-commit.sample
│   │   ├── pre-push.sample
│   │   ├── pre-rebase.sample
│   │   ├── pre-receive.sample
│   │   ├── prepare-commit-msg.sample
│   │   ├── push-to-checkout.sample
│   │   └── update.sample
│   ├── info
│   │   └── exclude
│   ├── objects
│   │   ├── info
│   │   └── pack
│   └── refs
│       ├── heads
│       └── tags
├── .gitignore
├── Cargo.toml
└── src
    └── main.rs

10 directories, 20 files

[hello-rust]プロジェクトを実行します。

subro@UbuntuServer2204-1:~/work/rust/hello-rust$ cd hello-rust

subro@UbuntuServer2204-1:~/work/rust/hello-rust$ cargo run
   Compiling hello-rust v0.1.0 (/home/subro/work/rust/hello-rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.54s
     Running `target/debug/hello-rust`
Hello, world!

実行されて「Hello, world!」が表示されました。

どんなファイルが生成されたか見てみます。

subro@UbuntuServer2204-1:~/work/rust/hello-rust$ tree -a
.
├── .git
│   ├── HEAD
│   ├── config
│   ├── description
│   ├── hooks
│   │   ├── applypatch-msg.sample
│   │   ├── commit-msg.sample
│   │   ├── fsmonitor-watchman.sample
│   │   ├── post-update.sample
│   │   ├── pre-applypatch.sample
│   │   ├── pre-commit.sample
│   │   ├── pre-merge-commit.sample
│   │   ├── pre-push.sample
│   │   ├── pre-rebase.sample
│   │   ├── pre-receive.sample
│   │   ├── prepare-commit-msg.sample
│   │   ├── push-to-checkout.sample
│   │   └── update.sample
│   ├── info
│   │   └── exclude
│   ├── objects
│   │   ├── info
│   │   └── pack
│   └── refs
│       ├── heads
│       └── tags
├── .gitignore
├── Cargo.lock
├── Cargo.toml
├── src
│   └── main.rs
└── target
    ├── .rustc_info.json
    ├── CACHEDIR.TAG
    └── debug
        ├── .cargo-lock
        ├── .fingerprint
        │   └── hello-rust-6f2dcfb780e161d5
        │       ├── bin-hello-rust
        │       ├── bin-hello-rust.json
        │       ├── dep-bin-hello-rust
        │       └── invoked.timestamp
        ├── build
        ├── deps
        │   ├── hello_rust-6f2dcfb780e161d5
        │   └── hello_rust-6f2dcfb780e161d5.d
        ├── examples
        ├── hello-rust
        ├── hello-rust.d
        └── incremental
            └── hello_rust-g8w9s3gqxor3
                ├── s-gsj98dtfct-blafz-7l7qn7o2la57ylhg29z11odbk
                │   ├── 13k5r5v27idane3m.o
                │   ├── 178h8f4ydwd4q1yr.o
                │   ├── 1p5ngs5xgmmm89ex.o
                │   ├── 2i27kdxvhvrpa2mx.o
                │   ├── 3ag8rghmvnp3rdqa.o
                │   ├── 3o1gdudxfaic4lll.o
                │   ├── dep-graph.bin
                │   ├── query-cache.bin
                │   └── work-products.bin
                └── s-gsj98dtfct-blafz.lock

20 directories, 42 files

ピンク色の [hello-rust]ファイルができあがった実行ファイルです。

プロジェクトのディレクトリ構成としては、最近はやりのパターンで C#もこんな感じでした。


引き続き「依存関係を追加する」という段落以降をやってみます。

ここでは、パッケージ(「クレート」と呼ぶ)を利用しています。
手順通り [Cargo.toml]ファイルににピンクの行を追加しました。

[package]
name = "hello-rust"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
ferris-says = "0.3.1"

プロジェクトをビルドします。

subro@UbuntuServer2204-1:~/work/rust/hello-rust$ cargo build
    Updating crates.io index
  Downloaded smawk v0.3.2
  Downloaded textwrap v0.13.4
  Downloaded unicode-width v0.1.11
  Downloaded smallvec v1.12.0
  Downloaded ferris-says v0.3.1
  Downloaded 5 crates (124.0 KB) in 0.82s
   Compiling unicode-width v0.1.11
   Compiling smawk v0.3.2
   Compiling smallvec v1.12.0
   Compiling textwrap v0.13.4
   Compiling hello-rust v0.1.0 (/home/subro/work/rust/hello-rust)
    Finished dev [unoptimized + debuginfo] target(s) in 2.14s
   Compiling ferris-says v0.3.1

ビルドできました。

何か盛んにダウンロードしてましたので、パッケージ関連のファイルがこのディレクトリにできると思いましたが、そうでもない様子。

subro@UbuntuServer2204-1:~/work/rust/hello-rust$ tree -a
.
├── .git
│   ├── HEAD
│   ├── config
│   ├── description
│   ├── hooks
│   │   ├── applypatch-msg.sample
│   │   ├── commit-msg.sample
│   │   ├── fsmonitor-watchman.sample
│   │   ├── post-update.sample
│   │   ├── pre-applypatch.sample
│   │   ├── pre-commit.sample
│   │   ├── pre-merge-commit.sample
│   │   ├── pre-push.sample
│   │   ├── pre-rebase.sample
│   │   ├── pre-receive.sample
│   │   ├── prepare-commit-msg.sample
│   │   ├── push-to-checkout.sample
│   │   └── update.sample
│   ├── info
│   │   └── exclude
│   ├── objects
│   │   ├── info
│   │   └── pack
│   └── refs
│       ├── heads
│       └── tags
├── .gitignore
├── Cargo.lock
├── Cargo.toml
├── src
│   └── main.rs
└── target
    ├── .rustc_info.json
    ├── CACHEDIR.TAG
    └── debug
        ├── .cargo-lock
        ├── .fingerprint
        │   ├── ferris-says-dabbec653d22d461
        │   │   ├── dep-lib-ferris_says
        │   │   ├── invoked.timestamp
        │   │   ├── lib-ferris_says
        │   │   └── lib-ferris_says.json
        │   ├── hello-rust-6f2dcfb780e161d5
        │   │   ├── bin-hello-rust
        │   │   ├── bin-hello-rust.json
        │   │   ├── dep-bin-hello-rust
        │   │   └── invoked.timestamp
        │   ├── hello-rust-dd7172e3794ae4de
        │   │   ├── bin-hello-rust
        │   │   ├── bin-hello-rust.json
        │   │   ├── dep-bin-hello-rust
        │   │   └── invoked.timestamp
        │   ├── smallvec-bdc725b5ee2eaf08
        │   │   ├── dep-lib-smallvec
        │   │   ├── invoked.timestamp
        │   │   ├── lib-smallvec
        │   │   └── lib-smallvec.json
        │   ├── smawk-8ebeab629f8845e9
        │   │   ├── dep-lib-smawk
        │   │   ├── invoked.timestamp
        │   │   ├── lib-smawk
        │   │   └── lib-smawk.json
        │   ├── textwrap-4233a5741c9d163d
        │   │   ├── dep-lib-textwrap
        │   │   ├── invoked.timestamp
        │   │   ├── lib-textwrap
        │   │   └── lib-textwrap.json
        │   └── unicode-width-a645f17db2f885de
        │       ├── dep-lib-unicode-width
        │       ├── invoked.timestamp
        │       ├── lib-unicode-width
        │       └── lib-unicode-width.json
        ├── build
        ├── deps
        │   ├── ferris_says-dabbec653d22d461.d
        │   ├── hello_rust-6f2dcfb780e161d5
        │   ├── hello_rust-6f2dcfb780e161d5.d
        │   ├── hello_rust-dd7172e3794ae4de
        │   ├── hello_rust-dd7172e3794ae4de.d
        │   ├── libferris_says-dabbec653d22d461.rlib
        │   ├── libferris_says-dabbec653d22d461.rmeta
        │   ├── libsmallvec-bdc725b5ee2eaf08.rlib
        │   ├── libsmallvec-bdc725b5ee2eaf08.rmeta
        │   ├── libsmawk-8ebeab629f8845e9.rlib
        │   ├── libsmawk-8ebeab629f8845e9.rmeta
        │   ├── libtextwrap-4233a5741c9d163d.rlib
        │   ├── libtextwrap-4233a5741c9d163d.rmeta
        │   ├── libunicode_width-a645f17db2f885de.rlib
        │   ├── libunicode_width-a645f17db2f885de.rmeta
        │   ├── smallvec-bdc725b5ee2eaf08.d
        │   ├── smawk-8ebeab629f8845e9.d
        │   ├── textwrap-4233a5741c9d163d.d
        │   └── unicode_width-a645f17db2f885de.d
        ├── examples
        ├── hello-rust
        ├── hello-rust.d
        └── incremental
            ├── hello_rust-2jc152hmmykou
            │   ├── s-gsj9fqrl5y-7k0z5-8wh6sx8ojsi70yjinl8dkpb8c
            │   │   ├── 12yvux6qt58x2oqa.o
            │   │   ├── 20261ju3k9eq9m4o.o
            │   │   ├── 3e43k7u4mn0hoee2.o
            │   │   ├── bk6w2sv10dd1ph8.o
            │   │   ├── capifntweoa87sq.o
            │   │   ├── dep-graph.bin
            │   │   ├── query-cache.bin
            │   │   ├── s26cakyhnp1efy1.o
            │   │   └── work-products.bin
            │   └── s-gsj9fqrl5y-7k0z5.lock
            └── hello_rust-g8w9s3gqxor3
                ├── s-gsj98dtfct-blafz-7l7qn7o2la57ylhg29z11odbk
                │   ├── 13k5r5v27idane3m.o
                │   ├── 178h8f4ydwd4q1yr.o
                │   ├── 1p5ngs5xgmmm89ex.o
                │   ├── 2i27kdxvhvrpa2mx.o
                │   ├── 3ag8rghmvnp3rdqa.o
                │   ├── 3o1gdudxfaic4lll.o
                │   ├── dep-graph.bin
                │   ├── query-cache.bin
                │   └── work-products.bin
                └── s-gsj98dtfct-blafz.lock

28 directories, 93 files

このパターンは、ホームディレクトリの下にあった [~/.cargo]ディレクトリにできているに違いない。

subro@UbuntuServer2204-1:~/work/rust/hello-rust$ tree -a ~/.cargo
/home/subro/.cargo
├── .package-cache
├── .package-cache-mutate
├── bin
│   ├── cargo
│   ├── cargo-clippy
│   ├── cargo-fmt
│   ├── cargo-miri
│   ├── clippy-driver
│   ├── rls
│   ├── rust-analyzer
│   ├── rust-gdb
│   ├── rust-gdbgui
│   ├── rust-lldb
│   ├── rustc
│   ├── rustdoc
│   ├── rustfmt
│   └── rustup
├── env
└── registry
    ├── CACHEDIR.TAG
    ├── cache
    │   └── index.crates.io-6f17d22bba15001f
    │       ├── ferris-says-0.3.1.crate
    │       ├── smallvec-1.12.0.crate
    │       ├── smawk-0.3.2.crate
    │       ├── textwrap-0.13.4.crate
    │       └── unicode-width-0.1.11.crate
    ├── index
    │   └── index.crates.io-6f17d22bba15001f
    │       ├── .cache
    │       │   ├── fe
    │       │   │   └── rr
    │       │   │       └── ferris-says
    │       │   ├── sm
    │       │   │   ├── al
    │       │   │   │   └── smallvec
    │       │   │   └── aw
    │       │   │       └── smawk
    │       │   ├── te
    │       │   │   └── xt
    │       │   │       └── textwrap
    │       │   └── un
    │       │       └── ic
    │       │           └── unicode-width
    │       └── config.json
    └── src
        └── index.crates.io-6f17d22bba15001f
            ├── ferris-says-0.3.1
            │   ├── .cargo-ok
            │   ├── .cargo_vcs_info.json
            │   ├── .gitignore
            │   ├── .travis.yml
            │   ├── CODE-OF-CONDUCT.md
            │   ├── CONTRIBUTING.md
            │   ├── Cargo.toml
            │   ├── Cargo.toml.orig
            │   ├── LICENSE-APACHE
            │   ├── LICENSE-MIT
            │   ├── README.md
            │   ├── appveyor.yml
            │   ├── src
            │   │   └── lib.rs
            │   └── tests
            │       └── integration_test.rs
            ├── smallvec-1.12.0
            │   ├── .cargo-ok
            │   ├── .cargo_vcs_info.json
            │   ├── .github
            │   │   └── workflows
            │   │       └── main.yml
            │   ├── .gitignore
            │   ├── Cargo.toml
            │   ├── Cargo.toml.orig
            │   ├── LICENSE-APACHE
            │   ├── LICENSE-MIT
            │   ├── README.md
            │   ├── benches
            │   │   └── bench.rs
            │   ├── debug_metadata
            │   │   ├── README.md
            │   │   └── smallvec.natvis
            │   ├── scripts
            │   │   └── run_miri.sh
            │   ├── src
            │   │   ├── arbitrary.rs
            │   │   ├── lib.rs
            │   │   ├── specialization.rs
            │   │   └── tests.rs
            │   └── tests
            │       ├── debugger_visualizer.rs
            │       └── macro.rs
            ├── smawk-0.3.2
            │   ├── .cargo-ok
            │   ├── .cargo_vcs_info.json
            │   ├── Cargo.toml
            │   ├── Cargo.toml.orig
            │   ├── LICENSE
            │   ├── README.md
            │   ├── dprint.json
            │   ├── rustfmt.toml
            │   ├── src
            │   │   ├── brute_force.rs
            │   │   ├── lib.rs
            │   │   ├── monge.rs
            │   │   └── recursive.rs
            │   └── tests
            │       ├── agreement.rs
            │       ├── complexity.rs
            │       ├── monge.rs
            │       ├── random_monge
            │       │   └── mod.rs
            │       └── version-numbers.rs
            ├── textwrap-0.13.4
            │   ├── .cargo-ok
            │   ├── .cargo_vcs_info.json
            │   ├── CHANGELOG.md
            │   ├── Cargo.lock
            │   ├── Cargo.toml
            │   ├── Cargo.toml.orig
            │   ├── LICENSE
            │   ├── README.md
            │   ├── src
            │   │   ├── core
            │   │   │   └── optimal_fit.rs
            │   │   ├── core.rs
            │   │   ├── indentation.rs
            │   │   ├── lib.rs
            │   │   └── splitting.rs
            │   └── tests
            │       ├── indent.rs
            │       └── version-numbers.rs
            └── unicode-width-0.1.11
                ├── .cargo-ok
                ├── .cargo_vcs_info.json
                ├── .github
                │   └── workflows
                │       └── rust.yml
                ├── .gitignore
                ├── .travis.yml
                ├── COPYRIGHT
                ├── Cargo.toml
                ├── Cargo.toml.orig
                ├── LICENSE-APACHE
                ├── LICENSE-MIT
                ├── README.md
                ├── scripts
                │   └── unicode.py
                └── src
                    ├── lib.rs
                    ├── tables.rs
                    └── tests.rs

42 directories, 109 files

やはりこちらにキャッシュされてるようです。
これで別なプロジェクトなんかで同じクレートを使うときは、ダウンロードはされずキャッシュを読むようになってるんですね。
これもオーソドックスな形です。

続けて「小さいRustアプリケーション」という段落に進みます。

[src/main.rs]ファイルを手順の通り以下のように書き換えました。

use ferris_says::say; // from the previous step
use std::io::{stdout, BufWriter};

fn main() {
    let stdout = stdout();
    let message = String::from("Hello fellow Rustaceans!");
    let width = message.chars().count();

    let mut writer = BufWriter::new(stdout.lock());
    say(&message, width, &mut writer).unwrap();
}

手順に従ってプロジェクトを実行します。

subro@UbuntuServer2204-1:~/work/rust/hello-rust$ cargo run
   Compiling hello-rust v0.1.0 (/home/subro/work/rust/hello-rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.47s
     Running `/home/subro/work/rust/hello-rust/target/debug/hello-rust`
 __________________________
< Hello fellow Rustaceans! >
 --------------------------
        \
         \
            _~^~^~_
        \) /  o o  \ (/
          '_   -   _'
          / '-----' \

出ましたね、カニが。
Rust界隈でカニカニ言ってた謎がこれで氷解しました。

チュートリアルはこれで終わりです。


==========
私は Rustの文法も何も知りませんが、このプロジェクト作成から実行までの手順やソースを見るに、Javaや C#をやってた人なら取っつき易い言語なんじゃないかと思います。
何をしているのか私でも予想がつくくらいなので。

高効率言語(?)として Goとの戦いが信者同士の間で勃発していたようですが、2023年は C#に人気をさらわれてしまったようです。

Goについては「Goインストール」に書きました。

私は C言語上がりの人間なので Cでも良いと思うんですが、メモリ管理がより安全なんだそうで、Linuxカーネルは今後どんどん Rustに置き換わっていくのかも知れません。


これからオライリーの新刊も出るようですし、刊行される日本語書籍の数からしても勢いがすごいですね。