寝ても覚めてもこんぴうた

プログラム書いたり、ネットワーク設計したり、サーバ構築したり、車いじったり、ゲームしたり。そんなひとにわたしはなりたい。 投げ銭は kyash_id : chidakiyo マデ

Bazelでbuild試してみる(Javaでgetting started)

f:id:chidakiyo:20191024145820j:plain

基本的な内容は 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"
}

出力結果のJSONGraphviz に食わせると以下のような画像化ができます。 これは便利。

f:id:chidakiyo:20191024145927p:plain

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で

discourse.elm-lang.org

databricks.com