rust

【Rust】「実践Rustプログラミング入門」のつまずきメモ【clap編】

【追記】公式Githubで修正版あり

追記です。本記事はchap4のclapクレートのビルドがコケた件の解決方法についてのメモです。しかし、後ほど確認したら、Githubで修正済みコードがありました。先に確認しましょう(殴)(https://github.com/forcia/rustbook/blob/master/ch04/4-1/samplecli-derivemacro/src/main.rs)

別のところでGithubのサンプルでもビルドがコケるとの情報があり、後回しにしたのが良くなかったです。反省ですね。

ところで、「実践Rustプログラミング入門」の10-2章でビルドの再現性について記載がありました。ビルドを再現するために必要な情報は以下の2つのファイルのようです。

  • Cargo.lock(依存クレートの正確なバージョンを保持)
  • rust-toolchain(rustコンパイラのバージョンを保持)

今後も勉強していく上で〇〇のビルドが通らない件的なトラブルは直面すると思うので、このあたりも並行して勉強していきたいですね。それにしてもC/C++ではGCC,CMake,GDB,etcと環境を管理しているのに比べCargoの優秀さをしみじみ感じますね。

概要:clapクレートのビルドがコケる【Chapter4】

書籍の「実践Rustプログラミング入門」のChap4でポーランド記法の数式計算アプリを作成するサンプルを実装していたところ、コマンド引数クレートのclapでビルドエラーが出たため、原因を調べました。

検証環境は以下です。

  • M2MacBookAir (2022)
  • MacOS Ventura 13.1
  • Docker v4.15.0 (Rust環境はUbuntu22.04 Arm64コンテナ上に構築)
  • rustc 1.66.1 (90743e729 2023-01-10)

Cargo.toml↓

[package]
name = "samplecli"
version = "0.1.0"
edition = "2021"

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

[dependencies]
clap = "3.0.0-beta.2"

ビルドエラー

エラーが出るソースとエラー内容は以下になります。

(略)...
error[E0432]: unresolved import `clap::Clap`
 --> src/main.rs:1:5
  |
1 | use clap::Clap;
  |     ^^^^^^^^^^ no `Clap` in the root

error: cannot determine resolution for the derive macro `Clap`
 --> src/main.rs:3:10
  |
3 | #[derive(Clap, Debug)]
  |          ^^^^
  |
  = note: import resolution is stuck, try simplifying macro imports

error: cannot find attribute `clap` in this scope
 --> src/main.rs:4:3
  |
4 | #[clap(
  |   ^^^^
  |
  = note: `clap` is in scope, but it is a crate, not an attribute

error: cannot find attribute `clap` in this scope
  --> src/main.rs:12:7
   |
12 |     #[clap(short, long)]
   |       ^^^^
   |
   = note: `clap` is in scope, but it is a crate, not an attribute
(略)...

解決方法

現行最新のrustc 1.66.1でビルドが通るようにします。手順は以下です。

  1. Cargo.toml内のclapのfeatureフラグ =”derive”を加える。
  2. ソースのclapのトレイト名”Clap”を”Parser”に変更する

①変更後のCargo.toml。(ちなみに最新2023/1/23時点のclap v4.1.1でもビルド可)

[package]
name = "samplecli"
version = "0.1.0"
edition = "2021"

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

[dependencies]
clap = { version = "3.0.0-beta.2", features = ["derive"] }

②変更後のソース。1と3行目を修正

原因考察

書籍の開発環境と比較し、Toolchainのrustc バージョンが書籍より上がっているのが原因と考え、プロジェクトフォルダトップに”rustc-toolchain”ファイルを作成し、rustc 1.44.0に変更。

しかし、Cargo.tomlのeditionが2021に対応していないとエラーがでたため、2018にダウングレードしようとするが、やり方が分からず断念(toml内の”2021″を直接書き換えると、tomlが読み込めなくなりビルドも修復も不可になりました)。

書籍の開発環境に合わせる方針を一旦諦め、clapの公式チュートリアル(https://docs.rs/clap/latest/clap/_derive/_tutorial/index.html)を読み漁ると”This requires enabling the derive feature flag.“と記載があり、原因の1つと仮定しました。

2つ目の原因である”Clap”トレイトはベータ版で消滅していました。

他も変更した部分はありましたが、根本原因の検証をした結果、原因はこの2つでした。

また、QiitaやZennを拝見すると、clapv3系とv4系で書き方が違うご様子でした。後方互換性はほとんどは確保されているとは思いますが、追いかけるのは大変そうです。

感想

  • ビルドエラーは丁寧な説明がでてくるので良き
  • クレートの公式チュートリアルの説明がしっかりしている印象
  • rustは高度成長期のため、web上の情報は少なくかつ賞味期限は短し、公式Docは友達
  • C/C++系人間としては便利なクレート(ライブラリ)が豊富で楽しい
ABOUT ME
sh-goto
組込エンジニア. 最近の遊びはLinuxの低レイヤいじりとXilinxのZynqとFPGAを使った電子工作