bazelで別projectにあるprotobufを参照してGo言語をビルドする

bazelはv0.24.1でためした。 あと走り書きなので、わからなかったら @keizo042まで気軽に聞いてほしい。推敲の参考にする。

TL;DR;

  • bazelを使うとprotobufが生成する中間コードを管理する必要がなくなる
  • protobufが示すgoのimport pathと実際のファイル構造に少し差があってもbazelが吸収してくれる
  • そのかわりpb.goはまったく手に入らなくなる。

bazelの軽い紹介

bazelというビルドシステムが存在する。概念としてはmakefileを置き換えるものであり、Googleが主導して開発している。 特徴として

  • 宣言的に実装する
  • targetごとにrule(pluginみたいなの)を実装することができる
  • ビルドに必要なものはランタイムからすべてダウンロードして実行する

あたりかな。

bazel.build

こまったこと

以下の環境が存在するとする

  • git repositoryとして提供されるprotobuf
  • protbufをビルドするbazelが書かれている
  • bazelはgo言語としてビルドすることができる状態にある
  • 開発しているプロダクトのソースコードは別のrepositoryとして管理している

この状況でどうやってprotobuf repoを利用したらいいのかわからなかった

解決

自分のrepositoryのWORKSPACEに対象のprotobuf repoを引っ張ってくるgit_repository を宣言する name は慣例的に github.com/xxxx/common-protoを com_github_xxx_common_proto みたいな感じで変換しているようなので倣うことにする

# WORKSPACE
load("@bazel_tools//tools/build_defs/repo:gitbzl", "git_repository")

git_repository(
  name = "com_github_xxx_common_proto
  tag = "v0.0.1"
)

次にprotobufを使用したいディレクトリのBUILD.bazelのgo_libraryのdepsのところに一行追加する ここのcom_github_xxx_common_protoはgit_repositoryのnameで宣言した文字列である必要がある。 また//path/to/protoはprotoファイルの存在するディレクトリに対する実際のパスである。 go_default_librarはprotobuf repoのBUILD.bazelで宣言したruleのnameである。 goのプロジェクトにbazelを用いるときgo_default_libraryを示すことでGoのパッケージ扱いにする合意があるらしい。

go_library(
  name = com_github_keizo042_goproj_client
 deps = [
 "@com_github_xxx_common_proto//path/to/proto:go_default_library"
)

gazelle updateでgolangのimportpathに書きかられてしまうばあいのワークアラウンド

resolve ディレクティブでパスの解決順を変更できる

# gazelle:resolve go @com_github_common_proto/path/to/proto:go_default_library path/to/proto