FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://sites.google.com/site/fpgadevelopindex/

BazelのBUILDファイルとWORKSPACEファイルの関係性

f:id:msyksphinz:20160529232134p:plain

Bazelをひたすら試行して、Bazelの小難しい環境がなんとなく分かってきた。特に注意しなければならないのは、Bazelに含まれるBUILDファイルとWORKSPACEファイルの関係性だ。ここを理解するのには、かなり時間がかかった。

例として、以下のようなプロジェクトを作ってテストしてみた。

github.com

Bazelのプロジェクト内に、2つのアプリケーション(app1:実行ファイル、app2: ライブラリ)を用意した。 app1はapp2を使用するが、まずはapp2をライブラリとして作成し、それをリンクする。

. # bazel_test
├── app1
│   ├── app1.cpp
│   └── BUILD
├── app2
│   ├── app2.cpp
│   ├── app2.hpp
│   └── BUILD
└── WORKSPACE

このとき、WORKSPACEファイルは、各アプリケーションのディレクトリに配置されるのではなく、app1とapp2の上位ディレクトリに存在する。

これにより、コンパイルが開始されるときのルートディレクトリがどこになるのかが決定する。ちょっと見てみよう。少しエラーを仕込んで、Bazelが何をやっているのかを確認する。

$ cd app1
$ bazel build :app1 --verbose_failures
INFO: Found 1 target...
ERROR: /home/vagrant/work/sicp_exercise/bazel_test/app1/BUILD:1:1: C++ compilation of rule '//app1:app1' failed: namespace-sandbox failed: error executing command
  (cd /home/vagrant/.cache/bazel/_bazel_vagrant/bf6184562b9de4efbf42ada266fc0899/bazel_test && \
  exec env - \

ふむ。app1のディレクトリにいるはずなのに、Bazelが移動したのはそれより上のディレクトリ、bazel_testディレクトリだ。つまり、ビルドを開始するときは、BazelはBUILDディレクトリの存在する場所ではなく、WORKSPACEディレクトリの存在する場所に移動する。

したがって、BUILDファイルの書き方も少しトリッキーだ。

  • app1/BUILD
cc_binary (
  name = "app1",
  srcs = ["app1.cpp"],
  deps = ["//app2"],
  copts = ["-Iapp2"],
)

ソースファイルは、BUILDファイルの存在するapp1ディレクトリからの相対パスで指定してよい(厳密にはファイル名ではなくラベル名だが)。 depsで記述している依存パッケージはWORKSPACEディレクトリが存在する場所からの相対ディレクトリ、さらにcoptsでg++に渡されるオプションも、WORKSPACEディレクトリが存在する場所からの相対パスを記述すべきだ。

  • app2/BUILD
cc_library (
  name = "app2",
  srcs = ["app2.cpp"],
  hdrs = ["app2.hpp"],
  visibility = ["//visibility:public"],
)

ビルドには成功する。

$ bazel build :app1 --verbose_failures
INFO: Found 1 target...
Target //app1:app1 up-to-date:
  bazel-bin/app1/app1
INFO: Elapsed time: 0.237s, Critical Path: 0.03s