LoginSignup
3
1

More than 3 years have passed since last update.

[Rust] ワークスペースでcargo releaseを使う

Posted at

はじめに

cargo releaseとはpublishにまつわる作業(gitのタグ付けやバージョン書き換えなど)を自動化してくれるcargoのサブコマンドです。2019-07-17リリースの0.12.0にてワークスペースに対応したのですが、いろいろと罠があるのでまとめておきます。

ワークスペースとは

ワークスペースとは複数のクレートを1つのディレクトリにまとめることができる機能です。詳細は"Cargoのワークスペース"を見てください。

使い道ですが、ドキュメントに書いてあるように「大規模なクレートを分割したい」ということはそれほどない気がします。よくあるのが次の2つです。
(これらもまぁ滅多にないといえばないですが…)

  • procedural macro
  • FFI

まずprocedural macroは必ず専用のクレートが必要です。そのためprocedural macroを使ったプロジェクトは(procedural macroのみのクレートでない限り)必ず2つ以上のクレートに分かれることになります。またFFIの場合は、-sysというsuffixの付いたクレートでCの関数を単にRustに変換しただけのものを提供して、別クレートで安全なラッパーを提供する、ということがよく行われます。

大規模なクレートからライブラリを切り出したようなケース(例えばripgrepというgrepツールから汎用ライブラリとしてgrepを切り出したような)は各クレートのバージョンは独立に設定したいと思います。しかし先に挙げたようなケースでは、分かれたクレートは密接に関連していることが多いので、バージョンも同時に上げたいところです。cargo releaseがワークスペースを扱えるようになったことで、複数のクレートのバージョンアップを1コマンドで行えるようになりました。

0.12.0時点の問題点

pre-releaseが使えない

pre-releaseとはバージョンのsuffixに"-alpha.0"や"-rc"などを付けるフローです。これはcargo releaseのデフォルトのフローになっていて、以下のような動作をします。

  • version = "0.1.0-alpha.0"で開発
  • cargo releaseを実行
  • (cargo releaseが)version = "0.1.0" に書き換え
  • (cargo releaseが)コミット
  • (cargo releaseが)タグ付け
  • (cargo releaseが)cargo publish
  • (cargo releaseが)version = "0.1.1-alpha.0" に書き換え

つまり普段の開発はずっとpre-releaseバージョンで行って、cargo release実行の瞬間だけ正式バージョンになる、というフローです。単一クレートの場合はこれで問題ないのですが、ワークスペースで複数クレートになって依存関係があると問題になります。

詳細は細かい話になるので関連するIssueだけ挙げておきます。

これを避けるには、pre-releaseを使わずに正式バージョンだけで運用すれば良いです。ワークスペース直下のrelease.tomlに

release.toml
no-dev-version = true

とするとワークスペース全体でpre-releaseが無効になります。
この状態でcargo release patchとするとパッチバージョンを上げてくれます。
普通にcargo releaseとするとバージョンを上げずにpublishしようとするので注意が必要です。

タグ付けが複数回行われる

gitのタグを付けるようにしている場合、各クレート毎に同じタグを付けようとしてエラーになります。

解決方法ですが、クレート毎のCargo.tomlにて

Cargo.toml
[package.metadata.release]
disable-tag = true

としてタグ付けを無効にして、ワークスペース全体で1回だけタグ付けが発生するように調整するといいでしょう。
タグ付けを有効にするクレートは、ワークスペース内の依存関係的にツリーのルートに位置するクレートがいいと思います。cargo releaseは依存関係ツリーの末端から順に処理していくので、ルートでタグ付けするとちょうど全クレートのバージョンが上がったところでタグ付けできます。

pre-release-replacementsのパス

pre-release-replacementsとはcargo releaseの機能の一つで、README.mdなどに書かれたバージョン番号を上げるのに使います。
ワークスペースを使う場合、これはワークスペース直下のrelease.tomlではなく、各クレートに書く必要があります。
(ワークスペース直下に書いた場合、単に無視されるようです)

さらに、対象となるファイルパスはそのクレートからの相対パスなので、ワークスペース直下のREADME.mdなら../README.mdになります。
現状のcargo releaseはエラー表示がいまいちで、パスを間違えた場合

Fatal: IO Error: No such file or directory (os error 2)

としか出ず、どのtomlファイルのどのパスが間違っているか全くわかりません。
試行錯誤で乗り切りましょう…。(これはそのうち修正PRを出したいです)

ワークスペースのディレクトリ構成

ワークスペースのディレクトリ構成として、公式ドキュメントではワークスペース直下に各クレートのディレクトリを配置する方法が書かれています。しかし、普通のクレートディレクトリ内に別クレートのディレクトリを置いて、ワークスペースとすることもできます。
(例えばripgrepはこのパターンです)

前者と後者ではcargo releaseしたときの挙動が違います。前者はcargo releaseすると全クレートが処理されますが、後者はルートになっているクレートしか処理されません。後者のパターンで全クレート処理したい場合はcargo release --allとする必要があります。

まとめ

ここまでで紹介したworkaroundを適用したプロジェクトが以下になります。具体的な構成例を知りたい方は参考にしてください。

cargo releaseのワークスペース対応はまだ出来たばかりなので、ここに挙げた問題点も仕様なのかバグなのかよく分かりません。
おそらくバージョンアップでいろいろ変わると思いますのでご注意下さい。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1