🦀

C++erのRust入門1:プロジェクトの作成

2023/04/30に公開

Rust をやらないとなーと思いつつ、いつまでたってもやる気にならない。

所有権やライフタイムの所為でC++で慣れてるデータ構造が簡単には Rust で表現できなかったりして、面倒になって放置してたんだよね。

引き出し増やしておかないと取りあえず使う気にもならない言語なので、嫌々試していく。

プロジェクトを作る

とりあえずは以下で main 関数を持つだけのプロジェクトを作成することはできるようだ。

cargo new 名前
cargo init
  • new: 新規にディレクトリが作られる
  • init: 現在のディレクトリをプロジェクトディレクトリとして使うっぽい

個人的には、 mkdir してから cargo init とやるほうが好みかな。

ライブラリを作る場合は --lib をつければよいみたい。

cargo new --lib 名前
cargo init --lib

インデントを絶対に2にする

Rustが一番嫌いなのはインデントが4なこと。世の中エディタの文字を小さくして読める人間ばっかりじゃねぇんだぞ?4って画面のほとんどインデントになるんだよ。

と、いうわけでどれだけ公式が4じゃないと駄目、と言おうと私はガン無視。

そして、フォーマッタは何故.editorconfig を無視する?ちょっとRustさんはお作法なってないんじゃないですかね?

とりあえず、.rustfmt.toml を以下の内容で作成する。

https://github.com/nodamushi/zenn-program/blob/main/src/rust/study/s1/.rustfmt.toml

.editorconfig を以下の内容で作成する。

https://github.com/nodamushi/zenn-program/blob/main/src/rust/study/s1/.editorconfig

適応する際には cargo fmt を実行する。

複数のmain関数

C++なら、CMakeで適当にtargetを生やして、Javaなら普通にstatic main を配置して Eclipse で Runでやってました。Rustでも同じことしたい。複数のプロジェクトに分かれるとVSCodeも複数立ち上げないといけないから面倒くさい。

どうも、 Cargo.toml に [[bin]] を追加することで、1つのプロジェクトに複数のmain関数を配置できるみたい。

https://github.com/nodamushi/zenn-program/blob/3b923af3b89cf83850023b837f6daf6bafb8dc86/src/rust/study/s1/Cargo.toml#L8-L11

hoge を実行するには cargo run --bin hoge で実行する。

通常の main を実行するには cargo run --bin プロジェクト名 (上記のs1プロジェクトは cargo run --bin s1)になる。 --bin が省略できなくなってちょっと面倒。

実行

run で main 関数の実行、 test でテストの実行ができるみたい。

cargo run
cargo run --bin hoge
cargo test
cargo test テスト名(一部だけでも可)

複数の [[bin]] を定義していても、 testcargo test で全部実行してくれるみたい。テスト名を指定する場合は、全部を指定しなくても一部マッチすれば実行される。

リリースビルド

--release をつければリリースビルドになるようだ。

cargo run --release
cargo build --release

テストの書き方

以下のように書くらしい。 #[cfg(test)] はテストビルドのときのみに tests モジュールをコンパイルせよというアノテー…じゃなくて属性(アトリビュート)らしい。

#[cfg(test)]
mod tests {
  #[test]
  fn hogehoge() {
    assert_eq!(2 + 2, 4);
  }
}
  • assert! : true かどうか
  • assert_eq! : 同じかどうか
  • assert_ne! : 一致しないかどうか

失敗時のメッセージは以下のようにして追加できる。

assert!(hoge(value), "hoge(value) return false. value = {}", value);

パニックが起こるかどうかのテストをする場合は、#[should_panic] アノテー…属性で書ける模様。

pub fn my_panic() -> u32 {
  panic!("Panic!");
}

#[cfg(test)]
mod tests {
  use super::*;

  #[test]
  #[should_panic]
  fn panic_test() {
    let x = my_panic();
    println!("x = {}", x);
  }
}

Discussion