GolangのビルドにBazel + Gazelleを使ってみたのでメモです。

環境

各ソフトウェアのバージョンです。

  • Ubuntu 20.04
  • Bazel 7.1.1
  • gazelle v0.35.0
  • Golang 1.22.2

ビルドするプロジェクトは以下としました。

コードの内容は関係ないので割愛しますが、Wireguardのclientのプロファイルを自動生成するツールです。こちらをBazelでビルドできるようにします。

インストール

まずは、BazelとGazelleをインストールします。

BazelはBazeliskのReleaseページからbinaryをダウンロードします。

Gazelleは以下のコマンドでインストール可能です。

go install github.com/bazelbuild/bazel-gazelle/cmd/gazelle@latest

WORKSPACEファイルの作成

プロジェクトのルートフォルダに WORKSPACEファイルを作成します。

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "io_bazel_rules_go",
    sha256 = "80a98277ad1311dacd837f9b16db62887702e9f1d1c4c9f796d0121a46c8e184",
    urls = [
        "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.46.0/rules_go-v0.46.0.zip",
        "https://github.com/bazelbuild/rules_go/releases/download/v0.46.0/rules_go-v0.46.0.zip",
    ],
)

http_archive(
    name = "bazel_gazelle",
    integrity = "sha256-MpOL2hbmcABjA1R5Bj2dJMYO2o15/Uc5Vj9Q0zHLMgk=",
    urls = [
        "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.35.0/bazel-gazelle-v0.35.0.tar.gz",
        "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.35.0/bazel-gazelle-v0.35.0.tar.gz",
    ],
)

load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")

############################################################
# Define your own dependencies here using go_repository.
# Else, dependencies declared by rules_go/gazelle will be used.
# The first declaration of an external repository "wins".
############################################################

go_rules_dependencies()

go_register_toolchains(version = "1.22.2")

gazelle_dependencies()

rules_goとgazelleのarchiveをdownloadして必要なルールをloadしています。ご利用のバージョンが異なる場合は、sha256の値が異なったりしますので、各パッケージの公式ドキュメントをご確認ください。

Gazelleの実行

以下2つのコマンドを実行します。まず、各ソースコードのパッケージごとにBUILD.bazelファイルを作成します。-go_prefixはご自身のプロジェクトに変更してご利用ください。

gazelle -go_prefix github.com/tanan/wg-config-generator

実行後、出来上がったBUILD.bazelファイルを見ると、ビルドやテストに必要なgo_librarygo_binarygo_testのルールが記載されていると思います。

続いて、依存パッケージのリポジトリを定義するために、以下のコマンドを実行します。このコマンドは、-from_fileに記載のgo.modを読み取って、-to_macroで指定するdeps.bzlファイルにgo_dependenciesというmacroを作成します。

gazelle update-repos -from_file=go.mod -to_macro=deps.bzl%go_dependencies -prune

このコマンドを実行すると、以下のdeps.bzlが作成されます。

load("@bazel_gazelle//:deps.bzl", "go_repository")

def go_dependencies():
    go_repository(
        name = "com_github_armon_go_metrics",
        importpath = "github.com/armon/go-metrics",
        sum = "h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=",
        version = "v0.4.1",
    )
    go_repository(
        name = "com_github_coreos_go_semver",
        importpath = "github.com/coreos/go-semver",
        sum = "h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=",
        version = "v0.3.0",
    )
...

これでBazelを実行する準備が整いました。

Bazelの実行

いくつかコマンドを実行します。

### query (targetの表示)
$ bazel query //...
//:wg-config-generator
//:wg-config-generator_lib
//cmd:cmd
//config:config
//config:config_test
//handler:handler
//handler:handler_test
//model:model
//util:util

### test
$ bazel test //config:config_test
INFO: Analyzed target //config:config_test (0 packages loaded, 0 targets configured).
INFO: Found 1 test target...
Target //config:config_test up-to-date:
  bazel-bin/config/config_test_/config_test
INFO: Elapsed time: 0.229s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
//config:config_test                                            (cached) PASSED in 0.1s

Executed 0 out of 1 test: 1 test passes.

### build
$ bazel build //...
INFO: Analyzed 9 targets (0 packages loaded, 0 targets configured).
INFO: Found 9 targets...
INFO: Elapsed time: 0.262s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action

### run
$ bazel run //:wg-config-generator
Usage:
  wgconf [command]
...

実行できることが確認できました。ちなみに、buildの成果物はbazel-outに出力されますので、以下のように実行することも可能です。

$ ./bazel-out/k8-fastbuild/bin/wg-config-generator_/wg-config-generator
wgconf is a CLI to generate server and client configrations.

Usage:
  wgconf [command]

...