bazelでWORKSPACEにGo言語のライブラリを追加する楽なやり方

Go言語のプロジェクトをビルドシステムbazelを用いて管理しているとする。そのとき、新しくライブラリの依存を追加する場合のやりかた

困ること

bazelはプロジェクトで使うパッケージはbazel自身が取ってくる。つまり、Goのパッケージ管理システムを使わない。 そbazelはgit_repository もしくは http_archive で取得したディレクトリ( goの場合は go_repositoryも)に ひとつのプロジェクト(e.g. github.com/keizo042/go-something )として扱い、それぞれのディレクトリには使いたいプロジェクトにつけた名前(e.g. com_github_keizo042_go_something)からの絶対パス ( "//utils"_を用いて依存関係を一意にする。

これで何がおこるかというと、bazelが依存したライブラリを見つけられずにビルドが失敗する。 そしてその依存関係を解決を手で記述するのがめんくさいため、なるべくコマンドに自動生成してもらうやり方を書いた。

使うもの

  • bazel
  • gazelle
  • Go言語のパッケージ管理システム(ここではGo Moduleを例に使う)

やりかた

1. Go言語のソースコードに新しく依存したいパッケージを追加する

package sample

import (
 "github.com/keizo042/go-something/utils"
)

2. Go言語のパッケージ管理システムを使い依存関係ファイルを作る

Go111MODULE=on go mod init && go mod tidy

3. gazelle を持ちいて依存関係ファイルからWORKSPACEとBUILD.bazelを生成する

bazel run //:gazelle update-repo -- -from_file=go.mod

4. だいたいこんな感じになる

WORKSPACE

go_repository(
  importpath = "github.com/keizo042/go-something",
  name = "com_github_keizo042_go_something"
  tags = "v1.0.0",
)

BUILD.bazel

go_package(

  deps = [
   "com_github_keizo042_go_something//utils",
  ]
)

なんでこうするのか

bazelのGo言語サポート用コマンドgazelleには、Go言語のパッケージマネージャの依存関係ファイルからWORKSPACEを自動生成する機能がついている。 そのため、Go Module or depに依存関係の解析をさせたのち、gazelle update-repo コマンドでその結果を取り込むことができる。 こうすれば、自分でファイルを書き換えずに依存関係を解決できる。

さらに、gazelle updateでWORKSPACE以下のGo言語のファイルからimportしているライブラリを読み取ってWORKSPACEにあるパッケージ照らし合わせてBUILD.bazelを更新することもできる。 bazel管理のプロジェクトにおいて、 ライブラリを追加した後、

GO111MODULE=on go mod init && go mod tidy && bazel run //:gazelle update-repos -- -from_file=go.mod && bazel run //:gazelle update 

としておくといい感じにライブラリの依存関係を管理できる。