BazelでJavaのプロジェクトをビルドする

2015年12月時点でのインストール手順はこちら

概要

  • Bazelを実際に使って見るためにインストールとサンプルプロジェクトのビルドを試してみる。

Bazel?

f:id:horie1024:20150512211627p:plain

BazelはGoogleで使われているビルドツールBlazeのOSS版。巨大なソースコードのビルド、テストおよびリリースの要件を満たすように設計されたビルドツールで、迅速かつ確実に巨大なソースコードをビルドすることが可能ならしい。現在α版。

Bazelの特徴

  • Fast
    • キャッシュと並列処理でビルドを高速化
  • Reproducible
    • ビルドサーバ、開発機問わずbitwise-identicalなバイナリをビルド
  • Flexible
    • 他言語サポート、同じコードベースでサーバ、クライアント両方のビルドに対応

なぜBazelを試してみるのか

  • AndroidでのGradleの次のビルドシステム(と勝手に思っている)
  • Androidのビルドが高速化される可能性
    • AndroidのビルドがBazelを使うことで高速になるかもしれない
    • もし高速化されれば開発効率が大幅にアップ
  • Jakeが言及していた。

Bazel実行環境の用意

Ubuntu環境の構築

MacでDockerを利用するための環境を構築

boot2dockerのインストール

  • homebrewでもインストールできるようだが公式サイトのやり方でインストールする
  • osx-installerを開く
  • Boot2Docker-1.6.0.pkgを実行しインストール f:id:horie1024:20150512211757p:plain

  • 起動方法がコマンドラインとApplicationの2通りあるのでコマンドラインから起動する

  • Boot2Docker VMの作成
$ boot2docker init
  • boot2docker VMの起動
$ boot2docker start
  • Dockerクライアント用の環境変数が表示される
$ boot2docker start
Waiting for VM and Docker daemon to start...
...........................oooooooooooooooo
Started.
Writing /Users/horie1024/.boot2docker/certs/boot2docker-vm/ca.pem
Writing /Users/horie1024/.boot2docker/certs/boot2docker-vm/cert.pem
Writing /Users/horie1024/.boot2docker/certs/boot2docker-vm/key.pem
To connect the Docker client to the Docker daemon, please set:
export DOCKER_HOST=tcp://192.168.59.103:2376
export DOCKER_CERT_PATH=/Users/horie1024/.boot2docker/certs/boot2docker-vm
export DOCKER_TLS_VERIFY=1
  • shellの設定ファイルに以下を記述。手動でexportしても問題は無い。
eval "$(boot2docker shellinit)"
  • hello-worldコンテナを起動
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from hello-world
・
・
・
Hello from Docker.
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (Assuming it was not already locally available.)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

For more examples and ideas, visit:
http://docs.docker.com/userguide/
$ boot2docker ssh
                        ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /"""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/
 _                 _   ____     _            _
| |__   ___   ___ | |_|___ \ __| | ___   ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|   <  __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
Boot2Docker version 1.6.0, build master : a270c71 - Thu Apr 16 19:50:36 UTC 2015
Docker version 1.6.0, build 4749651

Ubuntuコンテナを起動してみる

  • dockerコマンドで起動
$ docker run -it ubuntu bash
  • 起動できた
$ docker run -it ubuntu bash
Unable to find image 'ubuntu:latest' locally
Pulling repository ubuntu
b7cf8f0d9e82: Download complete
706766fe1019: Download complete
a62a42e77c9c: Download complete
2c014f14d3d9: Download complete
Status: Downloaded newer image for ubuntu:latest
root@3kdi85o3d:/#
  • Ubuntuのバージョンを確認
root@3kdi85o3d:/# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.2 LTS"

Bazelのインストール

バイナリインストールのサポートはまだ無い(後日サポートするらしい)。http://bazel.io/docs/install.htmlを参考に進める

$ sudo add-apt-repository ppa:webupd8team/java
sudo: add-apt-repository: command not found

add-apt-repositoryが無いと言われ失敗。

  • software-properties-commonをインストールすると解決
$ sudo apt-get install software-properties-common
  • apt-getをアップデート
$ sudo apt-get update
  • Java8のインストール
$ sudo apt-get install oracle-java8-installer
  • JAVA_HOMEの設定
$ export JAVA_HOME=/usr/lib/jvm/java-8-oracle
  • 必要なパッケージのインストール
$ sudo apt-get install libarchive-dev pkg-config zip g++ zlib1g-dev
  • Bazelをダウンロード
$ git clone https://github.com/google/bazel/
  • Bazelのインストール
$ cd bazel
$ ./compile.sh
  • PATHを通す
$ export PATH="$PATH:$HOME/bazel/output"
  • インストールできた
$ bazel
Extracting Bazel installation...
Apr 25, 2015 7:15:15 AM com.google.devtools.build.lib.runtime.BlazeRuntime batchMain
INFO: Running Blaze in batch mode with startup args [--batch, --install_base=/root/.cache/bazel/_bazel_root/install/e3f3e466c8e7784303e1f835508f8561, --output_base=/root/.cache/bazel/_bazel_root/d41d8cd98f00b204e9800998ecf8427e, --workspace_directory=, --nofatal_event_bus_exceptions, --option_sources=]
                                                     [bazel development version]
Usage: bazel <command> <options> ...

Available commands:
  analyze-profile     Analyzes build profile data.
  build               Builds the specified targets.
  canonicalize-flags  Canonicalizes a list of bazel options.
  clean               Removes output files and optionally stops the server.
  doc_ext             Prints help for commands, or the index.
  help                Prints help for commands, or the index.
  info                Displays runtime info about the bazel server.
  query               Executes a dependency graph query.
  run                 Runs the specified target.
  shutdown            Stops the bazel server.
  test                Builds and runs the specified test targets.
  version             Prints version information for bazel.

Getting more help:
  bazel help <command>
                   Prints help and options for <command>.
  bazel help startup_options
                   Options for the JVM hosting bazel.
  bazel help target-syntax
                   Explains the syntax for specifying targets.
  bazel help info-keys
                   Displays a list of keys used by the info command.
  • versionをみてみる
$ bazel version
Apr 25, 2015 7:20:22 AM com.google.devtools.build.lib.runtime.BlazeRuntime batchMain
INFO: Running Blaze in batch mode with startup args [--batch, --install_base=/root/.cache/bazel/_bazel_root/install/e3f3e466c8e7784303e1f835508f8561, --output_base=/root/.cache/bazel/_bazel_root/d41d8cd98f00b204e9800998ecf8427e, --workspace_directory=, --nofatal_event_bus_exceptions, --option_sources=]
ERROR: Version information not available.

ERRORでた・・

サンプルプロジェクトのビルド

インストールが正常に行われたか確認うるためにサンプルプロジェクトをビルドする。

  • プロジェクトディレクトリの作成
$ mkdir my-project
  • WORKSPACEファイルを作成
$ cd my-project
$ touch WORKSPACE
  • bazelインストール時にcloneしてきたディレクトリからexampleをコピー
$ cp -r $HOME/bazel/examples .
  • ビルドの実行

初回実行時にbazel-binやbazel-outといったリンクが作られる。

$ bazel build examples/java-native/src/main/java/com/example/myproject:hello-world
INFO: Found 1 target...
Target //examples/java-native/src/main/java/com/example/myproject:hello-world up-to-date:
  bazel-bin/examples/java-native/src/main/java/com/example/myproject/hello-world.jar
  bazel-bin/examples/java-native/src/main/java/com/example/myproject/hello-world
INFO: Elapsed time: 3.269s, Critical Path: 1.21s
  • ビルド成果物の実行

ビルドによって作成されたバイナリはbazel-bin/以下に配置される。

$ bazel-bin/examples/java-native/src/main/java/com/example/myproject/hello-world
Hello world

実行できた。Androidのビルドに対応したらまた試したい。

Docker Hubに登録

登録した。

https://registry.hub.docker.com/u/horie1024/bazel/registry.hub.docker.com

参考

OpenBRをインストールしてみる

概要

ちょっと興味があったのでOpenBRをビルドして動かしてみる。

OpenBR

OpenBRはOSSの生体識別ライブラリで、顔写真から年齢や性別を判別したりできる。最近だとMicrosoftのProjectOxfordで公開されたデモが話題になっていた。

OpenBRのインストール

installationをみてみると現状ソースコードからビルドするしかないようだった。Macにインストールはしたくないので適当なUbuntu環境を用意してビルドする。

DockerでUbuntu環境を用意

boo2dockerを起動

boo2dockerのVMが起動していないなら起動

$ boot2docker up

コンテナを起動

$ docker run --name openbr -i -t ubuntu /bin/bash

Ubuntuのバージョンを確認

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.2 LTS"

OpenBRをビルド

installationに沿って作業を進める。

GCCのインストール

$ sudo apt-get update
$ sudo apt-get install build-essential

CMakeのインストール

$ sudo apt-get install cmake cmake-curses-gui

OpenCVのインストール

ビデオのデコードに問題出たらここ参考にしてねとあるが、取り敢えず手順通りに進める。手順ではOpenCVのバージョンが2.4.5になってるが2.4.11で試す。

OpenCVここからダウンロードしてきてコンテナにボリュームをマウントするなりして渡す。

$ sudo apt-get install unzip
$ unzip opencv-2.4.11.zip
$ cd opencv-2.4.11
$ mkdir build
$ cd build
$ cmake -DCMAKE_BUILD_TYPE=Release ..
$ make -j4
$ sudo make install
$ cd ../..
$ rm -rf opencv-2.4.11

/usr/local/lib以下にインストールされた。

Qtのインストール

$ sudo apt-get install qt5-default libqt5svg5-dev qtcreator

OpenBRのビルド

$ git clone https://github.com/biometrics/openbr.git
$ cd openbr
$ git checkout 0.5
$ git submodule init
$ git submodule update
$ mkdir build
$ cd build
$ cmake -DCMAKE_BUILD_TYPE=Release ..

ここでなぜかOpenCVがインストールされて無いと言われたので、再度OpenCVをインストール後再度cmakeを実行。

$ cmake -DCMAKE_BUILD_TYPE=Release ..
$ make -j4
$ sudo make install

バージョンを確認

$ br -version
0.5.0

インストールできた。

動かしてみる

OpenBRのトップページにあるAge Estimationを実行してみる。実行例だと写真を2枚使用しているが一枚でも問題ないようだった。(metadata.csvの中身を見る限る)

$ br -algorithm AgeEstimation -enroll me.jpg metadata.csv

metadata.csvに結果が出力されるので見てみる。

File,Affine_0_X,Affine_0_Y,Affine_1_X,Affine_1_Y,Age,Confidence,DFFS,FTE,First_Eye_X,First_Eye_Y,FrameNumber,FrontalFace_X,FrontalFace_Y,FrontalFace_Width,FrontalFace_Height,PossibleFTE,Second_Eye_X,Second_Eye_Y
me.jpg,88,74,116,73,35.2215,1,737.614,false,88,74,0,66,47,74,74,false,116,73

35.2215歳か・・

Docker imageを作成

OpenBRをインストールできたのでimageを作成しておく。

$ docker commit -m 'OpenBRをインストール' <コンテナID> horie1024/openbr_0.5

作成されているか確認。

$ docker images
REPOSITORY             TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
horie1024/openbr_0.5   latest              12abc56def        About a minute ago   5.000 GB

作成できた。

Docker Hubにimageを登録する

Docker Hubに登録

https://hub.docker.com/account/signup/から登録する。

f:id:horie1024:20150511105359p:plain

コマンドラインからログイン

$ docker login

以下のようなエラーが出てdocker loginに失敗する場合、boot2docker restartすればok。

FATA[0034] Error response from daemon: Server Error: Post https://index.docker.io/v1/users/: dial tcp: lookup index.docker.io on 192.168.13.1:50: read udp 192.168.13.1:50: i/o timeout

Docker Hubに作成したimageを登録

先ほど作成したimageをpush。

$ docker push horie1024/openbr_0.5

登録できた。

registry.hub.docker.com

使用する場合は、docker pull後にdocker runすればok。

追記

Node.jsのバインディングがあった。https://www.npmjs.com/package/openbr

参考

ReactNativeを試してみる

概要

ReactNativeを試してみた。現在iOSのみサポート。Androidサポートはcoming soonらしい。

準備

Getting Startedを参考に進める。

Node.jsのインストール

  • HomebrewでもインストールできるがNodebrewやnvmを使った方が良いと思う。
  • nodevbrew
  • nvm

watchmanとflowのインストール

$ brew install watchman
$ brew install flow

watchmanとflowはサンプルを動かすだけならインストールしなくても問題ないと思う。

ReactNativeクライアントのインストール

$ npm install -g react-native-cli

サンプルプロジェクトの作成

$ react-native init AwesomeProject

xcodeでプロジェクトを読み込む

サンプルを編集してみる

  • index.ios.jsをエディタで開く
  • Welcome to React Native!の後ろにHello World!を追記してみる。
var AwesomeProject = React.createClass({
  render: function() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to React Native! Hello World!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit index.ios.js{'\n'}
          Press Cmd+R to reload
        </Text>
      </View>
    );
  }
});
  • 保存してcmd+R

f:id:horie1024:20150327032648p:plain

変更が反映される。

デバッグ

  • Xcode上でcmd+Rを押すとChromeのタブが開く
  • タブ上でReactNativeのJSコードが実行されているらしく、Chromeのdeveloperツールデバッグできるようだった。 f:id:horie1024:20150327033129p:plain

感想

思ってた以上に簡単にサンプルを動かせた。デバッガの使い方がよく分かってないので、もう少し触ってみようと思う。

build.gradleからの環境変数の参照

build.gradleからの環境変数の参照

CIサーバなどで以下のように環境変数を定義する。

export ORG_GRADLE_PROJECT_TEST="hoge"

ORG_GRADLE_PROJECT_propertyと定義すると、propertyという変数名でbuild.gradleから参照できる。

apply plugin: 'com.android.application'

// 環境変数ORG_GRADLE_PROJECT_TESTの内容をTESTで参照できる。
println(TEST)

android {
    compileSdkVersion 22
    buildToolsVersion "22"

    defaultConfig {
    }
    buildTypes {
        debug {
        }

        release {
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

実行すると参照できていることがわかる。

$ ./gradlew aR

・
・
・
'hoge'
・
・
・

参考

GradleでJavaDocを出力する

ターミナルからコマンドでJavaDocを出力できるようにしてみる。

build.gradleの修正

JavaDocを出力したい対象(moduleとか)のbuild.gradleに以下を追加。

android.libraryVariants.all { variant ->

    if (variant.name == "debug") {
        return
    }

    task("generateJavadoc", type: Javadoc) {
        title = "My JavaDoc"
        description "Generates JavaDoc."
        source = variant.javaCompile.source
        ext.androidJar =
                "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar"
        classpath = files(variant.javaCompile.classpath.files) + files(ext.androidJar)
        options.links("http://docs.oracle.com/javase/7/docs/api/");
        options.links("http://d.android.com/reference/");
        exclude '**/BuildConfig.java'
        exclude '**/R.java'
    }
}

確認

tasksで確認。「Other tasks」にgenerateJavadocが追加されてる。

./gradlew tasks
Other tasks
-----------
generateJavadoc - Generates JavaDoc.

出力

コマンドを実行して出力する。

./gradlew generateJavadoc

文字化けを直す

charsetをutf-8にしてやる。optionsのcharSetを使えば良い。

android.libraryVariants.all { variant ->

    if (variant.name == "debug") {
        return
    }

    task("generateJavadoc", type: Javadoc) {
        title = "My JavaDoc"
        description "Generates Javadoc"
        source = variant.javaCompile.source
        ext.androidJar =
                "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar"
        classpath = files(variant.javaCompile.classpath.files) + files(ext.androidJar)
        options.links("http://docs.oracle.com/javase/7/docs/api/");
        options.links("http://d.android.com/reference/");
        options.charSet("utf-8")
        exclude '**/BuildConfig.java'
        exclude '**/R.java'
    }
}

出力先

デフォルトでは、build/docs/javadoc以下に出力される。destinationDirを指定すれば任意の出力先を指定できる。

自動化

コマンドで完結するので自動化できる。masterにマージされるとJavaDocを出力して、GitHubPagesとかに上げるまで自動化すると良さそう。

追記

publicのクラス、メソッドのみJavaDocに出力したいので、showFromPublicを追加してみた。

android.libraryVariants.all { variant ->

    if (variant.name == "debug") {
        return
    }

    task("generateJavadoc", type: Javadoc) {
        title = "My JavaDoc"
        description "Generates Javadoc"
        source = variant.javaCompile.source
        ext.androidJar =
                "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar"
        classpath = files(variant.javaCompile.classpath.files) + files(ext.androidJar)
        options.links("http://docs.oracle.com/javase/7/docs/api/");
        options.links("http://d.android.com/reference/");
        options.charSet("utf-8")
        options.showFromPublic()
        exclude '**/BuildConfig.java'
        exclude '**/R.java'
    }
}

これでpublicのクラス、メソッドのみ出力できた。

参考

Golangでネットワークプログラミングの勉強

Whispering Gophers を読みながらネットワークプログラミングの勉強をしてる。 part2は標準入力で受けた文字をjsonに変換してlocalhost内でtcpを使って送るというもの。 JavaScriptとか書いてて個人的に未知の領域だったのだけど、こんな簡単に書けるんですね。

c, _ := net.Dial("tcp", "localhost:8000")

enc := json.NewEncoder(c)

enc.Encode("Hello World")

通信を受ける側はdump.go - whispering-gophers - Whispering Gophers - Google Project Hosting を使えとサンプルコードにコメントがあったのでこれを使えばおk。