The Cargo Book https://doc.rust-lang.org/cargo/
- package manager
- パッケージ管理にとどまらず、バイナリを作るための、あらゆる標準コマンドを提供する (-> §4)
- crates.io : packageリポジトリ
# Cargo.toml
[dependencies]
rand = "0.8.3"
- パッケージ名とsemantic versionで依存を指定する
<major>.<minor>.<patch>-<prerelease>+<build>
- https://semver.org/
- 注意
- 言語によって微妙に表記が異なる
- 0.xは開発バージョン. いつでも(破壊的)変更を加えてよい
crates.ioに未公開のバージョンのcrateに依存したいケースがある:
- 手元でbugfixしたcrateを別のcrateから使う
- 他人が作ったcrateの最新版masterを試したい
- majorバージョンをpublish前にintegration testしたい
- git branch指定してoverride
- 書き方は
[patch]
の項を参照
- semver-compatible requirements
- PythonやNodejsで~や^で範囲指定するやつ
- 注意
- 言語によって記号の意味が(結構)異なる
- Caret requirements
- 意味
- 指定したバージョンから、最上位の非ゼロが変わらない限り最新のバージョンまで
^1.2.3 := >=1.2.3, <2.0.0 ^1.2 := >=1.2.0, <2.0.0 ^1 := >=1.0.0, <2.0.0 ^0.2.3 := >=0.2.3, <0.3.0 ^0.2 := >=0.2.0, <0.3.0 ^0.0.3 := >=0.0.3, <0.0.4 ^0.0 := >=0.0.0, <0.1.0 ^0 := >=0.0.0, <1.0.0
- 意味
- ほかのrequirements記法は3.1節を参照
- Rustでのお約束
- 省略すると^ (caret) がつく.
time = "1.2.3"
とtime = "^1.2.3"
は同じ - なるべくゆるく範囲指定する
- 省略すると^ (caret) がつく.
-
依存ライブラリ群のバージョンを決定する方法
- 制約充足問題 厳密解を得るのはNP困難 らしい
- なのでパッケージマネージャごとに異なるヒューリスティクスが使われる
-
cargoでは、複数のパッケージが、共通のパッケージの別バージョンに依存する場合
- semver compatibleなら、compatibility rangeを満たす最新のバージョン1つに決定
- semver incompatibleなら、それぞれ別々のバージョンに依存する
- 後者では version-incompatibility hazardsが起きる可能性がある
-
version-incompatibility hazards
- https://doc.rust-lang.org/cargo/reference/resolver.html#version-incompatibility-hazards
- 問題
- 依存グラフにあるクレートの異なるバージョンが含まれると、それらの公開型を、それらの利用パッケージが(再)公開する場合に、衝突する
A --> B --> C==2.0.0 `--> D --> C==1.2.3
- 例えばB,Dの公開APIが、C::Floatを使う場合が該当する?
- 対策:semver trick
- 簡単に言うと、非互換リリースをするとき(例 1.xが広く使われている状況で2.0.0をリリース)、新しいバージョンの型を旧バージョンでもre-exportしたポイントリリースを同時に発行する
-
dev-dependency, build-dependencyもある
-
manifest (3.2)
- Cargo.toml
- よくでてくるTOML記法: tableとarray of tables
- tableはmapのこと
- pythonのdict, JSONのobject
- tableはmapのこと
# packageという名前のmap [package] name = "hello_world" version = "0.1.0" # 上と次の行は同じ package = { name = "hello_world", version = "0.1.0"} # # [[ ]] は mapのリスト # = array of tables [[bin]] name = "cool-tool" test = false bench = false [[bin]] name = "frobnicator" required-features = ["frobnicate"]
-
workspace (3.3)
- Cargo.lockをシェアするパッケージ群
- npm workspace, goのmoduleみたいな
-
features (3.4)
- 条件付きコンパイル
cfg(features = "std")
- featureごとにdependencyを分けられる
-
profiles (3.5)
- ビルド(コンパイル)の設定を変える. 最適化、デバッグシンボル有無などなど
- Cargo has 4 built-in profiles: dev, release, test, and bench
- --release, --debugフラグ
-
configuration (3.6)
- config.tomlにcargoの挙動を変える設定をかく
-
environment variables (3.7)
-
build script (3.8)
- Makefile的な
build.rs
rustc
以外のコマンドを呼ぶときにつかう (例:Cのリンカを呼ぶ、code generatorを呼ぶ)
- Makefile的な
-
external tools (3.12)
- cargoコマンドの出力をJSON形式にするオプションあり
cargo metadata
- cargo-xxxという名のバイナリにパスを通せばサブコマンドxxxがつくれる (gitみたい)
- nodeのnpm, rubyのRubygemsのような中央リポジトリ
- documentation
- ドキュメンテーションコメント(3連スラッシュ)をレンダリングしてくれる
- doctestもできる
- 深い階層のモジュールは見づらい
- -> トップレベルにre-export (
pub use
) すると見やすい
- -> トップレベルにre-export (
- crates.ioにひとたび公開したら削除できない(
取り下げ
はできる)- 秘密の情報publishしたらまずい