Bazelで複数のパッケージを使う

2020/03/06

BAZEL C/C++ Googleサービス Linux RandomGrid Ubuntu 技術

t f B! P L
さて、導入ドキュメントもあと2項目というところまで来ました。

今回の記事で2項目一気に説明してしまいます。

導入ドキュメントが出来上がった後は、今度は Common C++ Build Use Cases について同様の作業をやっていく予定です。

cc_libraryルールのオプションに関する翻訳はどっか時間が空いたらかな。

さて、お気づきの方も多いと思いますが当翻訳作業では自動翻訳を一切使用しておりません。だからこうして一日に何記事も挙げれるっていう部分もあります。

というのもドキュメント自体は読みやすいのですが、BUILDとかルールの属性名とか、そういった固有名詞が多分に含まれたドキュメントなので、自動翻訳をすると語順が変化して意味の通らない文になる→英語で表示し直して読む→日本語の文にする。

という作業の手間がかえって増えます。難しい単語も全く出てこないドキュメントなので、
「それであれば読みながらテキストエディタに訳文書いていった方が早いやぁ」
というわけで独断と偏見と愛と汗と涙と希望のこれらの記事が出来上がっているわけです。



複数のパッケージを使用する

 それではプロジェクトを複数のパッケージに分割していきましょう。
サンプルプロジェクトはstage3、格納場所は cpp-tutorial/stage3 です。

└──stage3
   ├── main
   │   ├── BUILD
   │   ├── hello-world.cc
   │   ├── hello-greet.cc
   │   └── hello-greet.h
   ├── lib
   │   ├── BUILD
   │   ├── hello-time.cc
   │   └── hello-time.h
   └── WORKSPACE
このプロジェクトは2つのサブディレクトリに分割されており、これらのサブディレクトリは独立した BUILD ファイルをそれぞれ配置されています。
まずは lib/BUILD の内容を確認してみましょう。
cc_library(
    name = "hello-time",
    srcs = ["hello-time.cc"],
    hdrs = ["hello-time.h"],
    visibility = ["//main:__pkg__"],
)
ライブラリをビルドするルールだけが記載されています。
注目すべきは visibility 属性です。
これは // で表されるワークスペースの下の、 main パッケージ内のモジュールからは参照できることを表しています。
では main/BUILD の内容はどうなっているでしょうか。
cc_library(
    name = "hello-greet",
    srcs = ["hello-greet.cc"],
    hdrs = ["hello-greet.h"],
)

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
    deps = [
        ":hello-greet",
        "//lib:hello-time",
    ],
)
main パッケージの中で cc_binary ルールで記載された hello-world ターゲットから、
lib パッケージで記載された hello-time ターゲットへの参照が、
deps 属性に設定されていることがわかります。

これまで同様に Bazel には deps 属性によって依存関係が教示されています。

visibility 属性に自ターゲットを参照出来るパッケージを設定しない場合、 デフォルトでは Bazel は同一パッケージ内のターゲット同士でしか依存関係を解決しようとしません。

Bazel はターゲットだけを周囲のパッケージから参照できるようにすることで、 実装の詳細がライブラリなどの公開 API に漏洩してしまうことを防いでいます。

それでは実際にビルドを実行してみましょう。
ビルドコマンドはこれまでと全く変わりません。
bazel build //main:hello-world

ビルド結果も一緒です。
Starting local Bazel server and connecting to it...
INFO: Analyzed target //main:hello-world (14 packages loaded, 53 targets configured).
INFO: Found 1 target...
Target //main:hello-world up-to-date:
  bazel-bin/main/hello-world
INFO: Elapsed time: 2.639s, Critical Path: 0.40s
INFO: 4 processes: 4 linux-sandbox.
INFO: Build completed successfully, 8 total actions

実行の仕方と結果も一緒
bazel-bin/main/hello-world
Hello world
Fri Mar  6 15:10:48 2020

しかし前回に引き続きグラフを表示すると、プロジェクトの構造は全く異なることがわかります。

 stage1:

 stage2:

 stage3:

 ラベルを使用した外部ターゲットの参照 


Bazel は、BUILD ファイルとコマンドラインでラベルと呼ばれるターゲットへの参照識別子を使用します。
これまでビルドコマンドや、cc_binary ルールの中に記載してきた、//main:hello-worldy や、stage3の cc_library ルールの中に記載した //lib:hello-time がラベルに当たります。 

ラベルの文法として特異に覚えておくべき内容は以下です。

// 

ワークスペースルートを表します。
//:main であればワークスペースルートにある main ターゲットを表すラベルです。

通常のパスと同じようにディレクトリ階層を表します。
 実際の文法は以下のように記載してパッケージとターゲットの探索を実行します。
//path/to/package:target-name
パッケージへのパス:ターゲット名 という形です。 

また、ワークスペースルートに直接ターゲットを置いている場合は、// は省略することが可能です。

つまり、//:target-name は :target-name と同じ意味になります。 

まあ実際には汎用的にプロジェクト構造を作って、それぞれのフォルダの中にソース追加する運用が現実的ですけどね……

Translate

ページビューの合計

注意書き

基本的にごった煮ブログですので、カテゴリから記事を参照していただけると読みやすいかと存じます。

ADBlocker等を使用していると、Twitterやアクセスカウンタが表示されません。

記事を読むには差し支えませんが、情報を参照したい場合には一時例外にしていただけると全てご参照いただけます。

Featured Post

ボイドラDICEの攻略法

QooQ