Bazel入門
Bazelとは
Googleが内部で利用していたビルドツールのオープンソース版として提供されているものです。
Bazel - a fast, scalable, multi-language and extensible build system" - Bazel
ビルドやテストの高速化を目指して作られています。
C++やJavaだけでなく、iOSやAndroidアプリのビルドにも対応しています。
今後のロードマップにはAndroid Studioとの統合も入っています。
Bazelを導入する理由
- Gradleよりも構造的な設計になっていて、各アクションが何をするかが正確に理解しやすい構成になっている(らしい)。
- すでに、ローカルでのキャッシュ、並列実行、依存性解析の最適化などが行われており高速に動作する。 さらに、分散キャッシュの仕組みも今絶賛入ろうとしていることろのなので、ビルドの高速化という意味では期待ができそう。
Bazelの公式ページも参照ください。
Bazelのinstall
Installing Bazel on macOS - Bazel
homebrewでinstallすると最後に補完スクリプトのパスが表示されるのでそれを利用してzshの補完の設定をします。
Bash completion has been installed to: /usr/local/etc/bash_completion.d zsh completions have been installed to: /usr/local/share/zsh/site-functions
fpath[1,0]=~/.zsh/completion/ mkdir -p ~/.zsh/completion/ cp scripts/zsh_completion/_bazel ~/.zsh/completion rm -f ~/.zcompdump; compinit # This way the completion script does not have to parse Bazel's options # repeatedly. The directory in cache-path must be created manually. zstyle ':completion:*' use-cache on zstyle ':completion:*' cache-path ~/.zsh/cache
Bazelでビルド
まずは簡単なチュートリアルを試してみます。
WORKSPACEファイル
Bazelは、ビルドしたいソースコードとビルド成果物を含むworkspaceというディレクトリでビルドを行います。
必要に応じて、1つのworkspaceを複数のプロジェクトで共有することができます。
workspaceはどこでもよいのですが、トップディレクトリにWORKSPACE
ファイルを必ず置く必要があります。
このWORKSPACE
ファイルに外部の依存性の定義を行います。
依存がなければ空ファイルでも大丈夫です。
touch WORKSPACE
BUILDファイル
Bazelは、プロジェクト内でのビルドターゲットを知るために、BUILD
ファイルを使います。
BUILD
ファイルはPythonに似たBazelのビルド用言語で記述します。
BUILD
ファイルにいろいろなルールを書いていきます。
各ルールは、入力、出力、および入力からの出力を計算する方法を指定します。
genrule
について
シェルコマンドを呼び出すgenrule
は、Makefileを使っている人たちにおなじみのルールです。
genrule
の詳細は下記ページにまとまっています。
今回は単純にecho
コマンドで標準出力に出した内容をリダイレクトしてファイルに書き込むルールを作ってみます。
genrule
では、 cmd
で指定したコマンドが実行されます。
genrule( name = "hello", outs = ["hello_world.txt"], cmd = "echo Hello World > $@", )
今回、cmd
の中で使われている$@
はBazelの中で使える変数で、outs
が一つの場合において、outs
の内容が展開されます。
利用可能な変数の一覧は Make variables にまとまっています。
ターゲットは、ルールの中で設定しているname
によって指定されるlabel
になります。
また、Bazelの成果物はソースツリーを汚染しないようにするために、ソースツリーとは別のbazel-genfiles
ディレクトリに格納されます。
1回目
% bazel build :hello .................... INFO: Found 1 target... Target //:hello up-to-date: bazel-genfiles/hello_world.txt INFO: Elapsed time: 7.322s, Critical Path: 0.01s
2回目
% bazel build :hello INFO: Found 1 target... Target //:hello up-to-date: bazel-genfiles/hello_world.txt INFO: Elapsed time: 0.155s, Critical Path: 0.00s % cat bazel-genfiles/hello_world.txt Hello World
BUILD
ファイルにouts
を複数して$@
を利用するとビルドエラーになります。
genrule( name = "hello", outs = ["hello_world.txt", "hello_world2.txt"], cmd = "echo Hello World > $@", )
% bazel build :hello ERROR: /Users/hoge/BazelTest/SampleEcho/BUILD:4:9: in cmd attribute of genrule rule //:hello: variable '$@' : more than one output file. ERROR: Analysis of target '//:hello' failed; build aborted. INFO: Elapsed time: 0.161s
ルールは、他のルールの出力を入力として利用できます。
生成したsrc
はlabelから参照できます。
$<
はsrc
のファイルの変数です。
genrule( name = "hello", outs = ["hello_world.txt"], cmd = "echo Hello World > $@", ) genrule( name = "double", srcs = [":hello"], outs = ["double_hello.txt"], cmd = "cat $< $< > $@", )
% bazel build :double INFO: Found 1 target... Target //:double up-to-date: bazel-genfiles/double_hello.txt INFO: Elapsed time: 0.396s, Critical Path: 0.04s % cat bazel-genfiles/double_hello.txt Hello World Hello World
genrule
ですが、通常利用するためのものではないです。
それぞれの言語に特化したルールがあるので、それを使ったほうがよいです。