Cargo vs go build: CIにおけるRustとGoのビルド
Cargoとgo buildはそれぞれの言語のネイティブツールです。CIで本当に問われるのはコンパイル時間と、それぞれがどれだけうまくキャッシュを効かせられるかです。
CargoはRustのビルドツール兼パッケージマネージャーで、lockfileと豊富な依存関係グラフを備えています。go build(go modulesを使用)は、シンプルな依存関係モデルと積極的なbuild cacheによってGoを高速にコンパイルします。本記事は言語を選ぶのではなく、2つのエコシステムのCIでの挙動を比較します。
| Cargo (Rust) | go build (Go) | |
|---|---|---|
| Lockfile | Cargo.lock | go.sum + go.mod |
| 典型的なコンパイル時間 | 長め(LLVM、単相化) | 高速 |
| Build cache | target/ + registry cache | GoのBuild cache(非常に効果的) |
| インクリメンタルビルド | あり | あり(キャッシュ駆動) |
| CIのキャッシュキー | Cargo.lockのハッシュ | go.sumのハッシュ |
CIでは
Goのビルドは通常高速で、Goのbuild cacheによって、いったんキャッシュされれば繰り返しのCIコンパイルは非常に安価になります。RustのコンパイルはLLVMのコード生成やgenericsの単相化のため遅くなりがちなので、Cargoのtarget/ディレクトリとregistry cacheをキャッシュすることが大きく効いてきます。sccacheのようなツールでさらに改善できます。どちらのツールも「優れている」わけではなく、各言語のコンパイルモデルを反映しているだけです。
どちらも高速化するには
Rustでは、~/.cargo/registryとプロジェクトのtarget/をCargo.lockをキーにキャッシュし、共有コンパイルキャッシュとしてsccacheを検討しましょう。Goでは、Goのbuild cacheとmodule cacheをgo.sumをキーにキャッシュします。キャッシュはどちらにとっても最大のCIの武器です。
結論
これらは言語ネイティブのツールであり、置き換え可能な選択肢ではありません。RustにはCargoを、Goにはgo buildを使いましょう。CIの観点でのポイントは、Rustは積極的なbuild cacheの恩恵を最も受ける一方、Goは最初から高速で、build cacheによってさらに速くなるということです。