Docker & Rust & mold で良さげな環境作ってみる

# 目的

- hello world ができること。
- GUI でテストと debug ができること。完成イメージ↓
  ![スクリーンショット 2022-12-23 1.16.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2327661/133ccab3-7efd-765f-2482-823b9308bd32.png)


# 説明しないこと
ツールの説明とかはあまりしない予定です。
参照リンクはこまめに貼るので、必要であればそちらを参照ください。

# エディタ
- [VS Code](https://azure.microsoft.com/ja-jp/products/visual-studio-code/)

※ 全て VS Code の拡張機能で完結するようになってます。

# install しておく拡張機能

- [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)

※ 使い方に関してはドキュメントを参照してください。（初めての方でもすぐ使えるはず）

# ディレクトリ構成
```
.
├── .devcontainer
│   └── devcontainer.json
├── app
│   ├── .cargo
│   │   └── config.toml
│   ├── .gitignore
│   ├── .vscode
│   │   ├── launch.json
│   │   └── settings.json
│   └── Makefile.toml
├── docker
│   └── rust
│       └── Dockerfile
└── docker-compose.yml
```

# 各ディレクトリとファイルの内容

## `docker-compose.yml`

```docker-compose.yml
version: '3.7'
services:
  app:
    container_name: rust_app
    build: ./docker/rust
    tty: true
    volumes:
      - ./app:/app
    environment:
      - CARGO_TARGET_DIR=/app/target
      - DEBIAN_FRONTEND=noninteractive
      - LC_CTYPE=ja_JP.utf8
      - LANG=ja_JP.utf8

```

## `.devcontainer/`

```devcontainer.json
{
    "name": "app",
    "dockerComposeFile": [
        "../docker-compose.yml"
    ],
    "service": "app",
    "workspaceFolder": "/app",
    "settings": {},
    "extensions": [
        "editorconfig.editorconfig",
        "rust-lang.rust-analyzer",
        "vadimcn.vscode-lldb",
        "bungcip.better-toml",
        "serayuzgur.crates",
        "dustypomerleau.rust-syntax",
        "jscearcy.rust-doc-viewer",
        "mooman219.rust-assist",
        "swellaby.vscode-rust-test-adapter"
    ]
}
```

## `app/`

[cargo-make](https://crates.io/crates/cargo-make/0.3.54) の設定ファイル（お好みで）
```Makefile.toml
[tasks.watch]
run_task = [
    { name = ["clippy", "test"] }
]
watch = true

[tasks.clippy]
command = "cargo"
args = ["clippy"]

[tasks.test]
command = "cargo"
args = ["test"]

[tasks.run]
command = "cargo"
args = ["watch", "-x", "run"]

[tasks.run-release]
command = "cargo"
args = ["run", "--release"]

```

### `.cargo/`
[mold](https://github.com/rui314/mold) を使えるようにするための設定を記述
[Actix](https://actix.rs/) をお試しで使った時にコンパイル遅かったので今回入れてみました〜
```config.toml
[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=/usr/bin/mold"]
```

### `.vscode/`

ブレークポイントとか貼ってデバッグできるようにする設定です
```launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "lldb",
            "request": "launch",
            "name": "Debug",
            "program": "${workspaceFolder}/**/*.rs",
            "args": [],
            "cwd": "${workspaceFolder}",
        }
    ]
}
```

ファイル保存時に、自動フォーマット（お好みで）
```settings.json
{
    "editor.formatOnSave": true,
}
```

### `docker/rust/`

[sqlx](https://github.com/launchbadge/sqlx) は今回使う予定はないですが、今後使いたいので先に入れました

```Dockerfile

FROM rust:latest

RUN apt-get update \
  && apt-get install -y clang git \
  && echo "install rust tools" \
  && rustup component add rust-src \
  && rustup component add rustfmt \
  && rustup component add clippy \
  && cargo install cargo-watch cargo-make sqlx-cli

# see https://github.com/rui314/mold#compile-mold
RUN git clone https://github.com/rui314/mold.git \
  && mkdir /mold/build \
  && cd /mold/build \
  && git checkout v1.7.1 \
  && ../install-build-deps.sh \
  && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=/usr/bin/c++ .. \
  && cmake --build . -j $(nproc) \
  && cmake --install .

WORKDIR /app

```

# setup
1. ファイルとディレクトリの準備ができたら、以下コマンドを実行してコンテナを立ち上げましょう
    15 分くらいかかるので、tea time.
    ```bash
    $ docker compose up -d
    ```

2. 立ち上がったら、[Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) を使ってコンテナの中に入ります
    VS Code の拡張機能読み込むのに時間かかるかも

3. コンテナに入ったら、以下コマンドを実行して、プロジェクトを作成します
    ```bash
    $ cargo init
    ```

4. プロジェクトができたらさらに以下コマンドを実行しましょう
    ```bash
    $ cargo run
    ```
    or
    ```bash
    $ mold -run cargo run
    ```
    "hello world" の文字列が表示されたら OK です
    ![スクリーンショット 2022-12-23 1.03.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2327661/2e2f3078-88fb-3169-932f-cda3d8fc3218.png)

# まとめ

とりあえず目的は達成できたので ok
テストも GUI から実行できるようにしてあるので、開発もスムーズに進むんじゃないだろうか
image size 大きいのと、image build に時間かかるのがちょっと課題ですが、後々チューニングできたらなと思います（そもそも[`rust`](https://hub.docker.com/_/rust)のベースイメージが結構でかい...）
それでは良い Rust Lifi を！