こんにちは、田渕です。
いつもは、技術は後追いスタンスなんですが(汗)、今回は少しでも新しい技術に触れてみようと思い、
Bazelを触ってみました。今回はBazelの入門編について紹介しようと思います。
今、私の周辺では何をするにもgradleが全盛です。やっとGradleになれてきたところです(笑)。
Bazelとは、Googleが社内で使用していたビルドツールで、オープンソースとして公開されています。
Bazelの発音ですが、FAQによると、「ベイゼル」が近いようです。
2016年3月現在は、β版での提供となっています。ロードマップがこちらに示されていますが、
安定版は、2016年12月リリースの予定です。安定版では、Windowsもサポートされるようです。
Bazelのドキュメントを見てみると、AndroidやiOSなどのルール(定義)がたくさんあります。
プラットフォーム単位での対応が柔軟に進んでいるようです。
この辺は、マルチプラットフォームを意識したビルドツールを目指しているような感じですね。
また、公式サイトの404ページ、ビルドエラー風メッセージでオシャレ!ですね。

環境の構築
まずは、環境の構築から。
OSのサポートは、今のところMac OS X とLinux(ubuntu)のみ。
ubuntu環境を持っていないので、AWS上にインスタンスを作成しました。
Bazelのインストールマニュアルに沿って、インストールを進めます。
java実行環境のインストール
Bazelは、javaの実行環境1.8以上(1.7はまだサポートされてますが、非推奨)が必要なので、javaをインストールします。
| 1 2 3 | sudo add-apt-repository ppa:webupd8team/java sudo apt-get update sudo apt-get install oracle-java8-installer | 
インストールに必要なコマンドのインストール
| 1 | sudo apt-get install pkg-config zip g++ zlib1g-dev unzip | 
Bazelモジュールをダウンロード
今回は、0.2.0を使用します。
| 1 | wget https://github.com/bazelbuild/bazel/releases/download/0.2.0/bazel-0.2.0-installer-linux-x86_64.sh | 
実行権限をつけます。
| 1 | chmod +x bazel-0.2.0-installer-linux-x86_64.sh | 
インストール
| 1 | ./bazel-version-installer-os.sh --user | 
インストールが完了すると、このようなメッセージが表示されます。
| 1 2 3 4 5 6 7 | Bazel is now installed! Make sure you have "/home/ubuntu/bin" in your path. You can also activate bash completion by adding the following line to your ~/.bashrc: source /home/ubuntu/.bazel/bin/bazel-complete.bash See http://bazel.io/docs/getting-started.html to start a new project! | 
作業フォルダに、binフォルダが作成されます。中身はこのようになっています。
| 1 2 3 | ls -l bin/ total 0 lrwxrwxrwx 1 ubuntu ubuntu 29 Mar  9 10:46 bazel -> /home/ubuntu/.bazel/bin/bazel | 
パスに~/binを追加します。
| 1 2 3 | export PATH="$PATH:$HOME/bin" echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/ubuntu/bin | 
これで、環境構築は完了です。
動かしてみる
実際に動かしてみるために、簡単なプロジェクトを作成します。
Bazelの実行に必要なファイルは、以下の2ファイルです。
・BUILD
・WORKSPACE
BUILDには、コンパイルの詳細設定や、プロジェクト間の依存関係などを記載します。
WORKSPACEには、依存関係や外部ソースの参照などを記載します。
サンプルプロジェクトの構成です。
| 1 2 3 4 5 6 7 8 9 | sample  +---WORKSPACE  +---BUILD  +---src      +---main          +---java              +---com                  +---example                      +---SampleRunner.java | 
SampleRunner.java
| 1 2 3 4 5 6 7 | package com.example; public class SampleRunner {     public static void main(String args[]) {         System.out.println("Hello!!");     } } | 
BUILD
| 1 2 3 4 5 | java_binary(   name = "sample",   srcs = glob(["**/*.java"]),   main_class = "com.example.SampleRunner", ) | 
javaビルドのルール定義を記述しています。
nameはプロジェクト名
srcsはターゲットのソースファイルです。glob関数を使って、ワイルドカードを使用できます。
main_classには、メインクラスを指定します。
ルール定義の詳細はこちら。
WORKSPACEは、今回は依存や外部ソースの参照が必要ないので、空ファイルで問題ありません。
ビルドするには、下記コマンドを実行します。
| 1 | bazel build :sample | 
実行すると、結果がこのように出力されます。
| 1 2 3 4 5 | INFO: Found 1 target... Target //:sample up-to-date:   bazel-bin/sample.jar   bazel-bin/sample INFO: Elapsed time: 10.432s, Critical Path: 2.61s | 
実行後のディレクトリ構成を見てみると、このようになっています。
| 1 2 3 4 5 6 7 8 9 10 11 12 | ls -al total 40 drwxrwxr-x  3 ubuntu ubuntu 4096 Mar 16 03:46 . drwxr-xr-x 10 ubuntu ubuntu 4096 Mar 16 03:46 .. lrwxrwxrwx  1 ubuntu ubuntu  115 Mar 16 03:46 bazel-bin -> /home/ubuntu/.cache/bazel/_bazel_ubuntu/ff8c0dd6bc08ac0c46b3dad0afe9d998/sample/bazel-out/local_linux-fastbuild/bin lrwxrwxrwx  1 ubuntu ubuntu  120 Mar 16 03:46 bazel-genfiles -> /home/ubuntu/.cache/bazel/_bazel_ubuntu/ff8c0dd6bc08ac0c46b3dad0afe9d998/sample/bazel-out/local_linux-fastbuild/genfiles lrwxrwxrwx  1 ubuntu ubuntu   89 Mar 16 03:46 bazel-out -> /home/ubuntu/.cache/bazel/_bazel_ubuntu/ff8c0dd6bc08ac0c46b3dad0afe9d998/sample/bazel-out lrwxrwxrwx  1 ubuntu ubuntu   79 Mar 16 03:46 bazel-sample -> /home/ubuntu/.cache/bazel/_bazel_ubuntu/ff8c0dd6bc08ac0c46b3dad0afe9d998/sample lrwxrwxrwx  1 ubuntu ubuntu  120 Mar 16 03:46 bazel-testlogs -> /home/ubuntu/.cache/bazel/_bazel_ubuntu/ff8c0dd6bc08ac0c46b3dad0afe9d998/sample/bazel-out/local_linux-fastbuild/testlogs -rw-rw-r--  1 ubuntu ubuntu  223 Mar 16 03:46 BUILD drwxrwxr-x  3 ubuntu ubuntu 4096 Mar 14 10:44 src -rw-rw-r--  1 ubuntu ubuntu   84 Mar 14 12:56 WORKSPACE | 
生成物を実行してみます。
| 1 2 | bazel-bin/sample Hello!! | 
生成物をクリアするには、cleanタスクを実行します。
| 1 | bazel clean | 
Mavenリポジトリの依存関係を追加してみる
次に、Mavenリポジトリのライブラリの依存関係を設定してみます。
SampleRunner.javaを以下のように修正します。
| 1 2 3 4 5 6 7 8 9 10 | package com.example; import org.apache.commons.lang3.StringUtils; public class SampleRunner {     public static void main(String args[]) {         System.out.println("Hello!!");         System.out.println(StringUtils.upperCase("bazel"));     } } | 
commons-langのStringUtilsを使用して、bazelを大文字に変換する処理を追加します。
WORKSPACE
| 1 2 3 4 | maven_jar(   name = "commons_lang",    artifact = "org.apache.commons:commons-lang3:3.4" ) | 
nameには、Bazelの内部で使用する名称を指定します。
注意が必要なのは、ここではハイフンは使用できません。ライブラリ名と同じcommons-lang を指定するとこのようなエラーになります。
| 1 2 3 4 | ERROR: /home/ubuntu/sample/WORKSPACE:1:1: maven_jar rule //external:commons-lang's name field must be a legal workspace name. ERROR: Error evaluating WORKSPACE file. ERROR: no such package 'external': Package 'external' contains errors. INFO: Elapsed time: 0.270s | 
BUILD
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | java_binary(   name = "sample",   srcs = glob(["**/*.java"]),   main_class = "com.example.SampleRunner",   deps = ["commons_lang"], ) java_library(   name="commons_lang",   exports = [     "@commons_lang//jar",   ], ) | 
ここで、依存関係を追加します。
java_binaryルールで、depsにcommons_langを指定しています。
commons_langは、java_libraryルールで定義しています。
ここでは、ハイフンは使用できるようです。
ここまでできたら、ビルド、実行してみます。
| 1 2 3 | bazel build :sample Hello!! BAZEL | 
無事動作しました。
最後に
はじめて触ってみた感触ですが、30分もあれば簡単な確認はできると思います。
ただ、Bazelの特色である、高速・柔軟性などを体感するには至っていません。
次回は巨大なプロジェクトをビルドして、Gradleとの比較をしてみたいと思います。

 
						