基本的な内容は Getting Started with Bazel をなぞってます。
Bazelとはなにか
Googleが開発したBuildツール。 もともとはGoogleが社内で使っているツール(の思想?)をベースに開発されているようですね。
makeを置き換えれるもの的な説明を見かけたが、もっと嬉しいことがありそう 実行時にディレクトリを汚染しない(サンドボックス内で実行する)や、並列ビルドが行えるなどがある
Bazelのインストール
ここ からインストール用の情報が確認できる。
今回はMac上で試すので、homebrew(tap)で入れてしまいます。
brew tap bazelbuild/tap brew install bazelbuild/tap/bazel
一応インストール確認
bazel --version
bazel 1.0.0
と返ってくるのでリリースされたばかりの1.0.0がインストールされました(2019/10/18現在)
ちなみに こちら にあるようにIDEとの連携も可能なようです。 IntelliJを使って開発しているのでそのうち時間があるときに試してみようと思います。
また、Dockerコンテナを利用して試したい方には こちら のコンテナを利用できます。
BuildのTutorialの実行(Java)
ひとまず こちら のJavaのチュートリアルをやってみようと思います
事前に必要なもの
- bazelのインストール
- JDKのインストール
- JDK8をインストールするように書いてありますが、JDK13でやってみます
サンプルプロジェクトの取得
以下を実行し、サンプルプロジェクトを取得します
git clone https://github.com/bazelbuild/examples/
Bazelを利用してBuildする
workspaceをセットアップする
ワークスペースはプロジェクトのソースファイルとBazelの生成ファイルが置かれます。 Bazelの特別なファイルも置かれます。 WORKSPACEファイルはディレクトリ構造のrootに置く必要があります。 BUILDファイルも配置する必要がありますが、BUILDファイルを配置するディレクトリはパッケージとなります。
Bazel workspaceとして指定するディレクトリに 空の WORKSPACE というファイル
を配置します。
Bazelがビルドする際の依存ファイルはすべて同一のワークスペース内に存在する必要があります (外部のワークスペースとリンクするという概念もあるようです)
java-tutorial パッケージをBuildしてみる
java-tutorial ディレクトリ配下のBUILDファイルを利用してBuildしてみます。
ディレクトリに移動してBuildコマンドを実行します。
cd java-tutorial
bazel build //:ProjectRunner
//
はプロジェクトルートからの相対的なBUILDファイルの位置で、 ProjectRunner
はBUILDファイル内で名付けられたターゲットです。
Buildが成功すると、ワークスペースのrootにあるbazel-binディレクトリにビルドの出力を配置します。
bazel-bin/ProjectRunner
のコマンドを実行することで動作確認が行なえます。
bazel-binのディレクトリをlsすると
$ ls bazel-bin
ProjectRunner ProjectRunner.runfiles libgreeter-native-header.jar
ProjectRunner.jar ProjectRunner.runfiles_manifest libgreeter.jar
ProjectRunner.jar-0.params _javac libgreeter.jar-0.params
ProjectRunner.jar-1.params external libgreeter.jar-1.params
ProjectRunner.jar_manifest_proto libgreeter-hjar.jar libgreeter.jar_manifest_proto
ProjectRunner.jdeps libgreeter-hjar.jdeps libgreeter.jdeps
という感じで大量にファイルが生成されているようです。
依存グラフを参照する
BUILDファイルで定義した依存関係を表示します。
以下のコマンドを実行します
$ bazel query --noimplicit_deps "deps(//:ProjectRunner)" --output graph
チュートリアルでは --notool_deps
オプションも付けていますが、それをつけるとうまく動きません。
出力結果はこんな感じ
digraph mygraph { node [shape=box]; "//:ProjectRunner" "//:ProjectRunner" -> "//:greeter" "//:ProjectRunner" -> "//:src/main/java/com/example/ProjectRunner.java" "//:src/main/java/com/example/ProjectRunner.java" "//:greeter" "//:greeter" -> "//:src/main/java/com/example/Greeting.java" "//:src/main/java/com/example/Greeting.java" }
出力結果のJSONを Graphviz に食わせると以下のような画像化ができます。 これは便利。
build targetを読む
java-tutorial/BUILD
を以下のように複数に分割されています。
java_binary( name = "ProjectRunner", srcs = ["src/main/java/com/example/ProjectRunner.java"], main_class = "com.example.ProjectRunner", deps = [":greeter"], ) java_library( name = "greeter", srcs = ["src/main/java/com/example/Greeting.java"], )
このような構成にすると ProjectRunner
を実行する前に greeter
が実行されます。
depsで greeter
が指定されています。
以下のコマンドでBuildを実行してみます
bazel build //:ProjectRunner
Buildが成功したら以下のコマンドで生成したバイナリのテストを行えます。
bazel-bin/ProjectRunner
ProjectRunner.javaを変更するとBazelはその変更されたファイルのみを再度コンパイルします。
まとめ
チュートリアルの流れ的には、単一のグラフになっているBUILDファイルを、Bazelを改善するという流れで複数に分割するという流れになってるのですが、実際にgithubから取得したexampleはすでに複数に分割されているようなので、流れが違っています。
とりあえずチュートリアル動かした、というレベルであまり良くわかってないっすw
今後やりたい
- ScalaをBazelで
- ElmをBazelで