Rustでのパッケージって…
はじめて Rust の crate を crates.io に公開した
はじめに
先日、はじめて Rust で CLI ツールを作って crates.io に公開してみました。
内容はとても簡単で、名前を受け取って Hello, <name>! と出力するだけです。
でも「公開」までの道のりが、思っていたよりもかなりたくさんのポイントがありました。
この記事では、実際にハマった点や、やっていくうちに気づいたことを残しておきます。
プロジェクトの構成
まず、プロジェクト自体はとても小さいです。
cargo new my-cli --bin
で作った後、src/main.rs に clap を使って引数をパースして、それを表示するだけです。
use clap::Parser;
#[derive(Parser)]
struct Cli {
/// 名前を入力
name: String,
}
fn main() {
let args = Cli::parse();
println!("Hello, {}!", args.name);
}
Cargo.toml はこんな感じです。
[package]
name = "call-me-in-cli"
version = "0.1.0"
edition = "2021"
authors = ["a-lost-social-misfit <a.lost.social.misfit@gmail.com>"]
description = "A simple Rust CLI for learning purposes"
license = "MIT"
repository = "https://github.com/a-lost-social-misfit/my-cli"
[dependencies]
clap = { version = "4.3", features = ["derive"] }
crates.io に公開するまでの手順
だいたい以下のような流れでした。
crates.ioに GitHub アカウントでログイン- API トークンを作成(スコープは
publish-newとpublish-updateだけで十分) - ローカルで
cargo loginでトークンを登録 cargo publishで公開
一見シンプルに見えますが、ここで気づきたいことがたくさんありました。
ハマった点と気づき
crate 名は世界で一意にする必要がある
最初は my-cli という名前で公開しようとしたんですが、すでに別の人が同じ名前で公開していて、以下のエラーが出ました。
error: failed to publish my-cli v0.1.0 to registry at https://crates.io
Caused by:
the remote server responded with an error (status 403 Forbidden):
this crate exists but you don't seem to be an owner.
npm のように @scope/package-name のような名前空間はないため、名前をユニークにする必要があります。
最終的に call-me-in-cli に変えて公開できました。
Cargo.lock は CLI なら commit すべき
Cargo.lock を .gitignore に入れていなかったのですが、それが正解でした。
CLI やバイナリの場合は依存関係のバージョンを固定しておくのが推奨されます。
一方、ライブラリの場合は逆に .gitignore に入れるのが一般的です。
公開前に未コミットのファイルがあると失敗する
cargo publish は、git に未コミットのファイルがある場合に以下のようなエラーを出してくれます。
error: 1 files in the working directory contain changes that were not yet committed into git:
Cargo.lock
to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag
これは「crates.io には commit 済みのスナップショットを公開する」という考え方から来ているようです。
--allow-dirty で無視することもできますが、普通は先に commit してから publish するのが正しい流れです。
このエラーは cargo bump patch で バージョンを上げた際にも Cargo.lock が変わるため、毎回出ます。
crate 名を変えると Cargo.lock も変わる
Cargo.toml の name を変えると Cargo.lock も更新されます。
Cargo.lock は現在のプロジェクトの依存関係とバージョンを固定するファイルで、
パッケージ ID が変わると依存解決がやり直されるためです。
edition について迷った
最初 edition = "2024" にしていたのですが、「2024 は nightly じゃないと動かないのでは」と不安になって "2021" に直してしまいました。でも実際には Rust 1.85.0 で "2024" も安定版になっていたので、最終的に "2024" に戻しました。慌てて変えてしまったのは勉強になった経験です。
ログイン済みでもメールアドレスの検証が必要
GitHub アカウントで crates.io にログインしていても、メールアドレスが検証されていないと以下のエラーが出ます。
error: failed to publish my-cli v0.1.0 to registry at https://crates.io
Caused by:
the remote server responded with an error (status 400 Bad Request):
A verified email address is required to publish crates to crates.io.
crates.io のプロフィール設定からメールを登録して検証するだけで解決しました。
API トークンのスコープは最小限にする
トークン作成時にスコープを選ぶ画面があります。
勉強用・個人開発なら publish-new と publish-update の2つだけで十分です。
Rust の文化的にも「最小権限」が基本的な考え方です。
公開した crate の削除には条件がある
かつて crates.io では公開した crate を削除することはできませんでした。 現在は一定の条件を満たせば削除が可能になっています。具体的には、公開から 72 時間以内であるか、オーナーが1人のみで、かつ毎月のダウンロード数が 500 件未満で、他の crate に依存されていない場合に削除できます。 それ以外の場合は依然として削除できないため、公開には注意が必要です。 今回は勉強用なので、そのまま放置しています。
バージョン管理について
Rust では セマンティックバージョニング(semver) を使います。
Cargo.toml の version フィールドで管理し、MAJOR.MINOR.PATCH の形になります。
- PATCH:バグ修正など(
0.1.0→0.1.1) - MINOR:機能追加(
0.1.0→0.2.0) - MAJOR:後方互換性を壊す変更(
0.1.0→1.0.0)
バージョンアップは cargo-bump というツールで簡単にできます。
cargo install cargo-bump
cargo bump patch # 0.1.0 → 0.1.1
その後は通常と同じように commit して publish するだけです。
git add .
git commit -m "Bump version to 0.1.1"
git push origin main
cargo publish
.gitignore について
Rust の .gitignore はとても小さく、最初は以下だけで十分です。
/target/
Cargo.lock は CLI なので commit する側にあります。
ただ、今後プロジェクトが複雑になると、都度追加していくことが出てきます。よくある例としては以下のようなものがあります。
環境変数やシークレットは特に注意が必要です。Rust では Node.js のように .env ファイルを前提にすることは少ないですが、開発中に使うことは出てきます。.env は必ず .gitignore に入れておくべき。
.env
エディタやOS固有のファイルは個人環境に依存するため、必要になったら追加していけば十分です。
# macOS
.DS_Store
# エディタ
.vscode/
.idea/
その他としては、以下のようなものも将来的に出てくることがあります。
# ログやデバッグ用の一時ファイル
*.log
# ビルド成果物やバイナリ(/target/ 以外の場合)
dist/
out/
ただし、Rust の文化的には「設定を増やさないこと」が美徳とされるため、必要になってから足していくのが自然なやり方です。最初から全部書いておくよりも、都度調べて追加していく方が、何が必要で何が不要かの理解も深まります。
まとめ
公開したコード自体は本当に小さかったのですが、「公開」という行程には以上のような多くのポイントがありました。 npm と比べると、crates.io は「履歴の一貫性」や「責任ある公開」を非常に重視している印象でした。 はじめて Rust のパッケージ公開を体験した際には、こうした点に注意していただければ幸いです。