Cargo-raze は現在メンテナンスもサポートもされていない製品です。
rules_rust
のcrate_universe
は、同様の目的でサポートおよび保守されている製品です。
crate_universe
cargo-raze でサポートされていたすべての機能をサポートしていると考えられます。ぜひ移行してみることをお勧めします。不足しているサポートやバグを見つけた場合は、 rules_rust
に対して問題を報告するか PR してください。
cargo-raze
PR やそれに対して提出された問題が対処される可能性が低いという現実を反映するためにアーカイブされています。
このプロジェクトのメンテナンスを引き継ぐことに興味がある場合は、Bazel Slack の #rust までご連絡ください。
ワークスペースレベルの Cargo.toml を、rules_rust を使用するコードが直接依存できる BUILD ターゲットに蒸留するための実験的サポート Cargo プラグイン。
これは Google の公式製品 (実験的かどうかにかかわらず) ではなく、Google がたまたま所有しているコードにすぎません。
このプロジェクトは、依存関係解決ロジックと、機能やビルド スクリプトなどの Cargo の機能の一部を、Bazel が Rust クレートをコンパイルするために実行できる実行可能ルールに合成します。標準の rules_rust ルールを使用して Rust コードを最初からコンパイルすることはできますが、依存関係エコシステムの粒度が細かいため、依存関係がほとんどないコードであっても、そのエコシステムに基づいて依存関係ツリーを変換するのは困難になります。
Cargo-raze は、ベンダーまたは非ベンダーの 2 つのモードのいずれかでビルド可能なターゲットを生成できます。ベンダリング モードでは、開発者は共通のcargo vendor
サブコマンドを使用して、ワークスペース Cargo.toml によって示された依存関係をディレクトリに取得し、カーゴ レイズして BUILD ファイルを設定します。非ベンダー モードでは、cargo-raze は BUILD ファイルのフラット リストと、Cargo 自体と同様の方法で依存関係を自動的にプルダウンするために WORKSPACE ファイル内で呼び出すことができるワークスペース レベルのマクロを生成します。
どちらの場合も、最初のステップは、Cargo の依存関係をワークスペース内のどこに配置するかを決定することです。このライブラリは、組織が全員が指す一連の依存関係を決定するモノリポジトリを念頭に置いて設計されました。依存関係の関係者が協力して依存関係をアトミックにアップグレードし、コードベース全体の破損を同時に修正することを目的としています。これが不可能な場合でも、分散シナリオで Cargo-raze を使用することは可能ですが、そのような分離されたリポジトリが現在の実装とうまく相互作用する可能性は低いです。
選択したアプローチに関係なく、rust_rules を WORKSPACE に取り込む必要があります。以下に例を示します。
load ( "@bazel_tools//tools/build_defs/repo:http.bzl" , "http_archive" )
http_archive (
name = "rules_rust" ,
sha256 = "accb5a89cbe63d55dcdae85938e56ff3aa56f21eb847ed826a28a83db8500ae6" ,
strip_prefix = "rules_rust-9aa49569b2b0dacecc51c05cee52708b7255bd98" ,
urls = [
# Main branch as of 2021-02-19
"https://github.com/bazelbuild/rules_rust/archive/9aa49569b2b0dacecc51c05cee52708b7255bd98.tar.gz" ,
],
)
load ( "@rules_rust//rust:repositories.bzl" , "rust_repositories" )
rust_repositories ( edition = "2018" )
Bazel のみのプロジェクトの場合、ユーザーはまず、対象の依存関係を含む標準 Cargo.toml を生成する必要があります。 Cargo がこの模擬クレートのソース ファイルの欠落について文句を言わないように、 [lib]
ディレクティブを含めるように注意してください。以下に例を示します。
[ package ]
name = " compile_with_bazel "
version = " 0.0.0 "
# Mandatory (or Cargo tooling is unhappy)
[ lib ]
path = " fake_lib.rs "
[ dependencies ]
log = " =0.3.6 "
標準の Cargo.toml が配置されたら、次のセクションに従って[package.metadata.raze]
ディレクティブを追加します。
ほとんどすべての正規のカーゴ設定は、 cargo-raze
を使用してインプレースで機能できるはずです。 Cargo ワークスペースが Bazel ワークスペースの下にネストされていると仮定すると、ユーザーは Bazel ファイルの生成に使用する RazeSettings を Cargo.toml ファイルに追加するだけで済みます。
# Above this line should be the contents of your Cargo.toml file
[ package . metadata . raze ]
# The path at which to write output files.
#
# `cargo raze` will generate Bazel-compatible BUILD files into this path.
# This can either be a relative path (e.g. "foo/bar"), relative to this
# Cargo.toml file; or relative to the Bazel workspace root (e.g. "//foo/bar").
workspace_path = " //cargo "
# This causes aliases for dependencies to be rendered in the BUILD
# file located next to this `Cargo.toml` file.
package_aliases_dir = " . "
# The set of targets to generate BUILD rules for.
targets = [
" x86_64-apple-darwin " ,
" x86_64-pc-windows-msvc " ,
" x86_64-unknown-linux-gnu " ,
]
# The two acceptable options are "Remote" and "Vendored" which
# is used to indicate whether the user is using a non-vendored or
# vendored set of dependencies.
genmode = " Remote "
カーゴワークスペースを使用するプロジェクトでは、ユーザーはすべてのraze
設定を、 [workspace]
定義を含む最上位のCargo.toml
ファイルの[workspace.metadata.raze]
フィールドに整理する必要があります。これらの設定は、前のセクションの[package.metadata.raze]
にある設定と同じである必要があります。ただし、クレート設定は引き続きワークスペース メンバーのCargo.toml
ファイルに配置される場合があります。
# Above this line should be the contents of your package's Cargo.toml file
# Note that `some-dependency` is the name of an example dependency and
# `<0.3.0` is a semver version for the dependency crate's version. This
# should always be compaitble in some way with the dependency version
# specified in the `[dependencies]` section of the package defined in
# this file
[ package . metadata . raze . crates . some-dependency . '<0 . 3 . 0' ]
additional_flags = [
" --cfg=optional_feature_a " ,
" --cfg=optional_feature_b " ,
]
# This demonstrates that multiple crate settings may be defined.
[ package . metadata . raze . crates . some-other-dependency . '*' ]
additional_flags = [
" --cfg=special_feature " ,
]
リモート モードでは、ベンダー モードと同様のディレクトリが選択されます。ただし、この場合には、BUILD ファイル、WORKSPACE のベンダーリング命令、および明示的な依存関係のエイリアスのみが含まれています。若干異なる配管が必要です。
これにより、Raze は依存関係がベンダー化されることを期待せず、別のファイルを生成するように指示されます。
まず、cargo-razeをインストールします。
$ cargo install cargo-raze
次に、Cargoディレクトリ内からCargo razeを実行します。
$ cargo raze
最後に、WORKSPACE 内でリモート ライブラリ取得関数を呼び出します。
load ( "//cargo:crates.bzl" , "raze_fetch_remote_crates" )
# Note that this method's name depends on your gen_workspace_prefix setting.
# `raze` is the default prefix.
raze_fetch_remote_crates ()
これにより、依存関係をどこから取得するか、および//cargo
に生成されたファイルを使用して依存関係を構築する方法が Bazel に指示されます。
//cargo:your_dependency_name
に依存することで、Rust ルール内の明示的な依存関係に依存できます。
ベンダー モードでは、ベンダーの依存関係を格納し、それらのビルド ルールへのゲートウェイとなるルートが直接選択されます。 //cargo
従来型ですが、組織のニーズを満たすには//third_party/cargo
方が望ましい場合があります。ルートへの直接ベンダーは、実装固有の特異性のため十分にサポートされていませんが、将来的にはサポートされる可能性があります。これ以降、 //cargo
想定されるディレクトリになります。
まず、BUILDable ターゲットのベンダー化と生成に必要なツールをインストールします。
$ cargo install cargo-raze
その後、cargo/ ディレクトリ内から依存関係をベンダーします。これにより、 Cargo.lock
ファイルも更新されます。
$ cargo vendor --versioned-dirs
最後に、再びcargo/
ディレクトリ内からBUILDファイルを生成します。
$ cargo raze
//cargo:your_dependency_name
に依存することで、Rust ルール内の明示的な依存関係に依存できるようになりました。
Cargo-raze は完全に Bazel で構築でき、ホスト マシンでカーゴをセットアップする必要なく使用できます。これを行うには、プロジェクトの WORKSPACE ファイルに以下を追加するだけです。
load ( "@bazel_tools//tools/build_defs/repo:http.bzl" , "http_archive" )
http_archive (
name = "cargo_raze" ,
sha256 = "c664e258ea79e7e4ec2f2b57bca8b1c37f11c8d5748e02b8224810da969eb681" ,
strip_prefix = "cargo-raze-0.11.0" ,
url = "https://github.com/google/cargo-raze/archive/v0.11.0.tar.gz" ,
)
load ( "@cargo_raze//:repositories.bzl" , "cargo_raze_repositories" )
cargo_raze_repositories ()
load ( "@cargo_raze//:transitive_deps.bzl" , "cargo_raze_transitive_deps" )
cargo_raze_transitive_deps ()
これを設定すると、ユーザーは@cargo_raze//:raze
ターゲットを実行して新しい BUILD ファイルを生成できます。例えば:
bazel run @cargo_raze//:raze -- --manifest-path= $( realpath /Cargo.toml )
現在のところ、 cargo-raze
これを行っていないため、 vendored
genmode を使用しているユーザーは依然として何らかの方法で依存関係をベンダー化する必要があることに注意してください。
一部のクレートは「ビルド スクリプト」を実行します。これは技術的に実行できることに制限はありませんが、通常はいくつかの一般的な処理の 1 つを実行します。
以下に示すすべてのオプションは、src/settings.rs ファイルに列挙されています。
場合によっては、クレートは Rust ソース ファイルを生成するために基本情報のみを使用します。これらのビルド スクリプト ルールは、生成前に Cargo.toml にディレクティブを含めることで、Bazel 内で実際に実行して使用できます。
[ package . metadata . raze . crates . clang-sys . '0 . 21 . 1' ]
gen_buildrs = true
この設定は、cargo-raze に、ビルド スクリプトの Rust_binary ターゲットを生成し、その生成された (OUT_DIR スタイルの) 出力を親クレートに送信するように指示します。
一部のビルド スクリプトは、Cargo が伝達方法を認識しているディレクティブを条件付きで標準出力に出力します。残念ながら、ビルド時に生成される依存関係情報を管理するのはそれほど簡単ではないため、フラグが静的に知られている場合 (おそらくコンパイル ターゲットが静的に知られているため)、次の方法で Cargo.toml 内からフラグを提供できます。
[ package . metadata . raze . crates . unicase . '2 . 1 . 0' ]
additional_flags = [
# Rustc is 1.15, enable all optional settings
" --cfg=__unicase__iter_cmp " ,
" --cfg=__unicase__defauler_hasher " ,
]
この方法で提供されたフラグは、rusc に直接渡されます。発生したビルド スクリプトと stdout ディレクティブを解釈するには、ドキュメントの build-script セクションを参照すると役立つ場合があります。https://doc.rust-lang.org/cargo/reference/build-scripts.html で参照できます。
クレートのコンパイルに必要なシステム ライブラリを提供するには 2 つの方法があります。 1 つ目は、システム ライブラリを直接ベンダーし、そのための BUILD ルールを作成し、対応する-sys
クレートに依存関係を追加することです。 openssl の場合、これは部分的に次のようになります。
[ package . metadata . raze . crates . openssl-sys . '0 . 9 . 24' ]
additional_flags = [
# Vendored openssl is 1.0.2m
" --cfg=ossl102 " ,
" --cfg=version=102 " ,
]
additional_deps = [
" @//third_party/openssl:crypto " ,
" @//third_party/openssl:ssl " ,
]
[ package . metadata . raze . crates . openssl . '0 . 10 . 2' ]
additional_flags = [
# Vendored openssl is 1.0.2m
" --cfg=ossl102 " ,
" --cfg=version=102 " ,
" --cfg=ossl10x " ,
]
場合によっては、ローカル システムの依存関係を直接結び付けることが望ましい場合があります。これを行うには、Bazel ドキュメントのnew_local_repository
セクションを参照してください。 WORKSPACE 内の llvm のプリコンパイル済みバージョンの場合、これは次のようになります。
new_local_repository (
name = "llvm" ,
build_file = "BUILD.llvm.bazel" ,
path = "/usr/lib/llvm-3.9" ,
)
場合によっては、sys クレートを完全にオーバーライドする必要がある場合があります。これは、生成前に Cargo.toml 内の依存関係を削除および補足することで容易に行うことができます。
[ package . metadata . raze . crates . sdl2 . '0 . 31 . 0' ]
skipped_deps = [
" sdl2-sys-0.31.0 "
]
additional_deps = [
" @//cargo/overrides/sdl2-sys:sdl2_sys "
]
一部のクレートは、コンパイル プロセスの一部として使用できる便利なバイナリを提供します。Bindgen はその好例です。 Bindgen は、C または C++ ファイルを処理して Rust ソース ファイルを生成します。 Cargo.toml にディレクティブを追加して、Bazel にそのようなバイナリを公開するように指示できます。
[ package . metadata . raze . crates . bindgen . '0 . 32 . 2' ]
gen_buildrs = true # needed to build bindgen
extra_aliased_targets = [
" cargo_bin_bindgen "
]
Cargo-raze は、バイナリ ターゲットにcargo_bin_
というプレフィックスを付けます。これは、Cargo ではバイナリとライブラリが同じターゲット名を共有することが許可されていますが、Bazel ではこれが許可されていないためです。
現在のところ、Cargo はライブラリを提供しないクレートに関するメタデータを収集しません。これは、 Cargo.toml
ファイルの[dependencies]
セクションでこれらを指定しても、Bazel ターゲットは生成されないことを意味します。 Cargo-raze には、 genmode = "Remote"
使用するときにこれらのクレートを処理するための特別なフィールドがあります。
[ package . metadata . raze . binary_deps ]
wasm-bindgen-cli = " 0.2.68 "
上記のスニペットでは、 wasm-bindgen-cli
クレートはバイナリ依存関係として定義されており、Cargo-raze は、このクレートとここで定義されている他のクレートのメタデータが結果の出力ディレクトリに確実に含まれるようにします。 [package.metadata.raze.binary_deps]
で指定されたターゲットのロックファイルはworkspace_path
で指定されたパス内のlockfiles
ディレクトリに生成されます。
binary_deps
フィールドはワークスペースおよびパッケージのメタデータに含めることができますが、バイナリ依存関係の定義は一度に 1 つだけ存在できることに注意してください。単一のバイナリ依存関係に依存する複数のパッケージがある場合は、その定義をワークスペース メタデータに移動する必要があります。
default_gen_buildrs を true に設定すると、cargo-raze はビルド スクリプトを必要とするすべてのクレートに対してビルド スクリプトを生成します。
[ package . metadata . raze ]
workspace_path = " //cargo "
genmode = " Remote "
default_gen_buildrs = true
この設定は、利便性と正確性の間のトレードオフです。これを有効にすると、フラグを明示的に指定したり、個々のビルド スクリプトを手動で有効にしたりしなくても、多くのクレートが機能することがわかります。ただし、これをオンにすると、使用しているすべてのクレートがビルド時に任意のコードを実行できるようになり、実行されるアクションは密閉的ではなくなる可能性があります。
この設定を有効にしても、いくつかのクレートに追加の設定を提供する必要がある場合があります。たとえば、リング クレートはビルド時にソース ツリーにアクセスする必要があります。
[ package . metadata . raze . crates . ring . '*' ]
compile_data_attr = " glob([ " **/*.der " ]) "
個々のクレートでビルド スクリプトを無効にしたい場合は、次のように実行できます。
[ package . metadata . raze . crates . some_dependency . '*' ]
gen_buildrs = false
Bazel (「速い」、「正しい」、2 つ選択) は、Google が、重複した作業や正確性を損なうことなく、信じられないほど大規模な多言語プロジェクトをコンパイルするために使用する、実戦テストされたビルド システムです。これは、特定のコンパイル オブジェクトが依存関係を検出するために使用できるメカニズムを制限し、ビルド可能なユニットに依存関係の完全なセットを強制的に表現することによって部分的に実現されます。 2 つの同一のビルド ターゲット入力セットがバイトごとに同等の最終結果を生成することを期待します。
その代わりに、ユーザーは、あらゆる種類のコンパイル可能なターゲットをコンパイルし、高速かつ正確な状態を保ちながら、Protobuf オブジェクト、プリコンパイルされたグラフィック シェーダー、生成されたコードなどの「型破りな依存関係」を表現できるカスタマイズ可能で拡張可能なビルド システムを得ることができます。
また、おそらく (まだベンチマークでは実証されていませんが)、Bazel の強みである非常に粒度の高いビルド単位を念頭に置いて構築された大規模なアプリケーションは、より積極的にキャッシュし、反復中にできるだけ多くのコードの再コンパイルを回避できるため、コンパイルが大幅に速くなります。
良くも悪くも、Rust エコシステムは標準ライブラリによく存在する機能を提供するために Cargo クレートに大きく依存しています。これは、安定化への構造化されたプロセス (実験用クレート -> 1.0 クレート -> RFC -> stdlib への組み込み) を説明しているため、言語の進化にとって実際には素晴らしいことですが、このエコシステムにアクセスできない人々は、多くの車輪を再発明します。
それはさておき、Rust 開発者が言語での開発を大幅に加速できる業界標準システムやライブラリと対話するのに役立つ素晴らしいクレートもあります。
Cargo の機能をエミュレートする (可能な限り!) 負担は大きいですが、Bazel がパフォーマンスを維持するために依存している保証 (正確性、再現性) を維持するには、これが唯一の方法のようです。インフライト RFC を使用すると、Cargo がコンパイルに直接使用できるほど柔軟になる可能性が高く、その可能性が高くなります。しかし、現時点では、見かけ上の機能同等性を維持することの方が、実際には、Cargo によって導入される鋭いエッジをすべて回避するよりも簡単であると思われます。 Cargo を Rust コンパイラのように扱います。
少し頑張れば、openssl-sys に依存するプロジェクトを含む、ほぼすべてのものをビルドすることができます。多くの sys クレートでは、ラップするシステム ライブラリを特定し、それをプロジェクトにベンダーするか、システム上のどこに存在するかを Bazel に伝える必要があります。ハードコードされたカーゴ環境変数要件を削除するなど、ソースの軽微な調整が必要な場合もあります。場合によっては修正が重要になる可能性がありますが、最も人気のあるクレートの多くは、https://github.com/acmcarther/cargo-raze-crater から入手できるサンプル リポジトリにビルドされています。
クレート構成を提供する次の例を参照してください。
ベンダー モードの使用:
リモートモードの使用:
OpenSSL のコンパイル:
[package.metadata.raze]
セクションは、impl/src/settings.rs で宣言された構造体から派生します。