Cargo.toml で Rust のパッケージを管理する

Tauri 2 の src-tauri/Cargo.toml を節ごとに解説。[lib] の crate-type、tauri の features、tauri-build、プラグインの追加、[profile.release] の最適化。

環境構築 対象: Tauri 2.x 更新日: 読了目安: 約7分 env-015
目次
  1. 1. 生成される Cargo.toml の全体像
  2. [package] と [lib]
  3. [build-dependencies] の tauri-build
  4. 2. tauri クレートの features
  5. 3. プラグインクレートを追加する
  6. 4. [profile.release] の最適化
  7. 動作確認
  8. よくあるエラーと対処法
  9. error[E0433]: failed to resolve: use of unresolved module or unlinked crate 'tauri_plugin_fs'
  10. error[E0432]: unresolved import 'tauri::tray' など、モジュールが見つからない
  11. current package believes it's in a workspace when it's not
  12. 注意点
  13. 関連レシピ

フロントエンドの package.json に相当するのが src-tauri/Cargo.toml です。ただし Tauri のものは一般的な Rust プロジェクトと少し違い、[lib] 節がある、tauri クレートの features で機能を有効化する、build.rs 用に tauri-build が必要、という特徴があります。create-tauri-app が生成するファイルを上から読み解き、その後で「クレートを足す」「features を切り替える」「リリースビルドを最適化する」といった日常的な編集を整理します。

1. 生成される Cargo.toml の全体像

[package]
name = "my-app"
version = "0.1.0"
description = "A Tauri App"
authors = ["you"]
edition = "2021"

[lib]
name = "my_app_lib"
crate-type = ["staticlib", "cdylib", "rlib"]

[build-dependencies]
tauri-build = { version = "2", features = [] }

[dependencies]
tauri = { version = "2", features = [] }
tauri-plugin-opener = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"

[profile.release]
codegen-units = 1
lto = true
opt-level = 3
panic = "abort"
strip = true

[package] と [lib]

[package] name は実行ファイル名 (my-app.exe / my-app) になります。Tauri 2 はアプリ本体を lib.rs (ライブラリ) に置き、main.rs はそれを呼ぶだけの薄い皮です。crate-type の 3 つは、rlib がデスクトップ用 (main.rs が静的リンク)、staticlib が iOS 用、cdylib が Android 用で、デスクトップ専用でも残しておいて害はありません。[lib] name に _lib を付けているのはバイナリ名との衝突を避けるためで、main.rs の my_app_lib::run() はこの名前に対応しています。片方だけ変えるとコンパイルエラーになります。

[build-dependencies] の tauri-build

build.rs の tauri_build::build() が、tauri.conf.json の読み込み、アイコンやマニフェストの埋め込み (Windows のリソース)、capabilities/ からの権限スキーマ生成 (src-tauri/gen/schemas/) を担当します。ビルド時にしか使わないので [build-dependencies] に置きます。tauri クレートと同じマイナーに揃えておく必要があります。

[dependencies] の serde / serde_json はコマンドの引数・戻り値を JSON 化するために必須です。tauri-plugin-opener は不要なら削除して構いませんが、lib.rs の .plugin(tauri_plugin_opener::init()) と capabilities/default.json の opener:default も一緒に消します。

2. tauri クレートの features

Tauri 本体はコンパイル時間と実行ファイルサイズを抑えるため、多くの機能を feature フラグの後ろに置いています。

feature有効になるもの
devtoolsリリースビルドでも WebView のインスペクタを開けるようにする (デバッグビルドでは常に有効)
tray-iconシステムトレイ API (tauri::tray)
image-png / image-icoImage::from_path などで PNG / ICO をデコード。アイコンを実行時に読み込むときに必要
protocol-assetasset:// プロトコルでローカルファイルを WebView に表示
macos-private-api透明ウィンドウなど macOS のプライベート API
config-json5 / config-tomltauri.conf.json5 / Tauri.toml を設定ファイルとして使う (tauri-build にも同じ feature が必要)

追加は Cargo.toml の features = ["tray-icon", "image-png"] を直接編集するか、cargo add で行います。

cd src-tauri
cargo add tauri --features tray-icon,image-png

3. プラグインクレートを追加する

公式プラグインは CLI で追加するのが確実です。

npm run tauri add fs

このコマンドが行うのは次の 4 つで、手動で追加するときも同じことをします。

  1. src-tauri/Cargo.toml の [dependencies] に tauri-plugin-fs = "2" を追加 (内部で cargo add)
  2. src-tauri/src/lib.rs の Builder に .plugin(tauri_plugin_fs::init()) を挿入
  3. package.json に @tauri-apps/plugin-fs を追加 (内部で npm install)
  4. capabilities/default.json に fs:default を追加

デスクトップ専用のプラグイン (global-shortcut, updater, single-instance など) は、モバイルビルドから除外するために [target] 付きの節へ入ります。

[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
tauri-plugin-global-shortcut = "2"

4. [profile.release] の最適化

雛形の設定は「速度重視」です。公式のサイズ削減ガイドは opt-level = "s" (サイズ優先) を勧めています。

[profile.release]
codegen-units = 1   # 並列コンパイルを捨てて最適化の余地を増やす
lto = true          # クレートをまたいだリンク時最適化
opt-level = "s"     # 3 = 速度優先 / "s" = サイズ優先 / "z" = さらにサイズ優先
panic = "abort"     # パニック時の巻き戻し処理を省く
strip = true        # デバッグシンボルを除去

[profile.dev]
incremental = true  # 開発時は差分コンパイルを優先

codegen-units = 1 と lto = true はリリースビルドの時間を大きく伸ばします (小規模アプリでも 2〜3 倍)。CI でビルド時間が問題になるなら lto = "thin" が妥協点です。

動作確認

cargo add や手編集の後は src-tauri で cargo check を実行すると、依存解決とコンパイルエラーだけを素早く確認できます。npm run tauri dev が通り、追加した feature の API (例: tauri::tray::TrayIconBuilder) が use できれば完了です。

よくあるエラーと対処法

error[E0433]: failed to resolve: use of unresolved module or unlinked crate 'tauri_plugin_fs'

lib.rs に .plugin(tauri_plugin_fs::init()) を書いたのに Cargo.toml に依存を足していない状態です。cargo add tauri-plugin-fs を src-tauri で実行します。

error[E0432]: unresolved import 'tauri::tray' など、モジュールが見つからない

feature を有効にしていません。tauri::tray なら tray-icon、Image::from_path なら image-png が必要です。docs.rs のページで該当項目に表示される feature 名を確認してください。

current package believes it's in a workspace when it's not

リポジトリのルートなど親ディレクトリに [workspace] を持つ Cargo.toml があると、src-tauri がそのメンバーとみなされます。親の members に "src-tauri" を加えるか、src-tauri/Cargo.toml に空の [workspace] 節を書いて独立させます。

注意点

  • Cargo.lock は必ずコミットします。ロックがないと CI と手元で別バージョンが解決され、再現しないビルドエラーの原因になります。
  • version = "2" は ^2 の意味で、cargo update で 2.x 系の最新へ上がります。tauri・tauri-build・各 tauri-plugin-* は同じマイナーに揃えるのが原則です。更新手順は Tauri CLI を最新版にアップグレードする を参照してください。

関連レシピ

参考リンク(公式ドキュメント)

Web Ninja

この記事を書いた人

Web Ninja ウェブエンジニア (Web Engineer)

会社員ネットワークエンジニアから独立してかれこれ 25 年以上 Web エンジニアとして活動中。普段は JavaScript と Node.js を自在に操り、時には C++ や Perl といった古流の技も嗜みます。近年は Tauri × Rust という新たな武器を手に、デスクトップアプリ開発の最前線を駆け抜けています。「作りたい」を「作れる」に変えるための、実践的な「技」をお届けします。

お問い合わせ: tauri.ninja@gmail.com

内容の誤り・動かないコードを報告する