メーリングリスト: bazel-go-discuss
Slack: #go on Bazel Slack、#bazel on Go Slack
ルールは開発のベータ段階にあります。彼らは以下をサポートしています:
現在、次のものはサポートされていないか、サポートが制限されています。
Go ルールは、次のホスト プラットフォームでテストされ、サポートされています。
ユーザーは他のいくつかのプラットフォームで成功したと報告していますが、ルールは上記のプラットフォームでのみテストされています。
注: バージョン v0.38.0 以降、rules_go が動作するには Bazel ≥ 5.4.0 が必要です。
master
ブランチは、Bazel の最新バージョンでのみ動作することが保証されています。
Bazel を使用して Go コードをビルドするには、次のものが必要です。
patch
、 cat
、およびPATH
内のその他のいくつかの Unix ツール。通常、Go ツールチェーンをインストールする必要はありません。 Bazel は 1 つをダウンロードします。
Windows 固有のセットアップ手順については、「Windows での rules_go の使用」を参照してください。いくつかの追加ツールをインストールして構成する必要があります。
Bazel の新しい外部依存関係管理システム Bzlmod を使用している場合は、代わりに専用の Go with Bzlmod ガイドを参照してください。
リポジトリの先頭にWORKSPACE
という名前のファイルを作成し、以下のスニペットを追加します (または既存のWORKSPACE
に追加します)。これにより、Bazel に rules_go とその依存関係を取得するように指示されます。 Bazel は、サポートされている最近の Go ツールチェーンをダウンロードし、使用できるように登録します。
load ( "@bazel_tools//tools/build_defs/repo:http.bzl" , "http_archive" )
http_archive (
name = "io_bazel_rules_go" ,
integrity = "sha256-M6zErg9wUC20uJPJ/B3Xqb+ZjCPn/yxFF3QdQEmpdvg=" ,
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.48.0/rules_go-v0.48.0.zip" ,
"https://github.com/bazelbuild/rules_go/releases/download/v0.48.0/rules_go-v0.48.0.zip" ,
],
)
load ( "@io_bazel_rules_go//go:deps.bzl" , "go_register_toolchains" , "go_rules_dependencies" )
go_rules_dependencies ()
go_register_toolchains ( version = "1.23.1" )
http_archive の代わりに git_repository を使用し、最近のコミットを指定することで、 master
で rules_go を使用できます。
BUILD.bazel
という名前のファイルをプロジェクトのルート ディレクトリに追加します。 Go コードを含む各ディレクトリにビルド ファイルが必要ですが、プロジェクトに Go コードがない場合でも、ルート ディレクトリにもビルド ファイルが必要です。 「Hello, world」バイナリの場合、ファイルは次のようになります。
load ( "@io_bazel_rules_go//go:def.bzl" , "go_binary" )
go_binary (
name = "hello" ,
srcs = [ "hello.go" ],
)
このターゲットはbazel build //:hello
を使用してビルドできます。
プロジェクトをgo build
でビルドできる場合は、gazelle を使用してビルド ファイルを自動的に生成および更新できます。
bazel_gazelle
リポジトリとその依存関係をWORKSPACE
に追加します。次のようになります。
load ( "@bazel_tools//tools/build_defs/repo:http.bzl" , "http_archive" ) http_archive ( name = "io_bazel_rules_go" , integrity = "sha256-M6zErg9wUC20uJPJ/B3Xqb+ZjCPn/yxFF3QdQEmpdvg=" , urls = [ "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.48.0/rules_go-v0.48.0.zip" , "https://github.com/bazelbuild/rules_go/releases/download/v0.48.0/rules_go-v0.48.0.zip" , ], ) http_archive ( name = "bazel_gazelle" , integrity = "sha256-12v3pg/YsFBEQJDfooN6Tq+YKeEWVhjuNdzspcvfWNU=" , urls = [ "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.37.0/bazel-gazelle-v0.37.0.tar.gz" , "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.37.0/bazel-gazelle-v0.37.0.tar.gz" , ], ) load ( "@io_bazel_rules_go//go:deps.bzl" , "go_register_toolchains" , "go_rules_dependencies" ) load ( "@bazel_gazelle//:deps.bzl" , "gazelle_dependencies" ) go_rules_dependencies () go_register_toolchains ( version = "1.23.1" ) gazelle_dependencies ()
以下のコードをプロジェクトのルート ディレクトリにあるBUILD.bazel
ファイルに追加します。 prefix
の後の文字列を、プロジェクトに一致するインポート パスのプレフィックスに置き換えます。 go.mod
ファイルがある場合は、モジュール パスと同じである必要があります。
load ( "@bazel_gazelle//:def.bzl" , "gazelle" )
# gazelle:prefix github.com/example/project
gazelle ( name = "gazelle" )
これはgazelle
バイナリ ルールを宣言しており、以下のコマンドを使用して実行できます。
bazel run //:gazelle
これにより、プロジェクト内の各パッケージの go_library、go_binary、および go_test ターゲットを含むBUILD.bazel
ファイルが生成されます。今後、同じコマンドを実行して、新しいソース ファイル、依存関係、およびオプションを使用して既存のビルド ファイルを更新できます。
プロジェクトがgo build
規則に従っていない場合、または gazelle を使用したくない場合は、手動でビルド ファイルを作成できます。
Go コードを含む各ディレクトリに、 BUILD.bazel
という名前のファイルを作成します。使用するルールのファイルの先頭に、 load
ステートメントを追加します。
load ( "@io_bazel_rules_go//go:def.bzl" , "go_binary" , "go_library" , "go_test" )
ライブラリごとに、以下のような go_library ルールを追加します。ソース ファイルはsrcs
属性にリストされます。標準ライブラリ外にインポートされたパッケージは、対応する go_library ルールを参照する Bazel ラベルを使用してdeps
属性にリストされます。ライブラリのインポート パスは、 importpath
属性で指定する必要があります。
go_library (
name = "foo_library" ,
srcs = [
"a.go" ,
"b.go" ,
],
importpath = "github.com/example/project/foo" ,
deps = [
"//tools" ,
"@org_golang_x_utils//stuff" ,
],
visibility = [ "//visibility:public" ],
)
テストの場合は、以下のような go_test ルールを追加します。テストされるライブラリは、 embed
属性にリストされる必要があります。
go_test (
name = "foo_test" ,
srcs = [
"a_test.go" ,
"b_test.go" ,
],
embed = [ ":foo_lib" ],
deps = [
"//testtools" ,
"@org_golang_x_utils//morestuff" ,
],
)
バイナリの場合は、以下のような go_binary ルールを追加します。
go_binary (
name = "foo" ,
srcs = [ "main.go" ],
)
Go リポジトリごとに、以下のような go_repository ルールをWORKSPACE
に追加します。このルールは Gazelle リポジトリから取得されるため、ロードする必要があります。 gazelle update-repos は、go.mod または Gopkg.lock ファイルからこれらのルールを自動的に生成または更新できます。
load ( "@bazel_tools//tools/build_defs/repo:http.bzl" , "http_archive" )
# Download the Go rules.
http_archive (
name = "io_bazel_rules_go" ,
integrity = "sha256-M6zErg9wUC20uJPJ/B3Xqb+ZjCPn/yxFF3QdQEmpdvg=" ,
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.48.0/rules_go-v0.48.0.zip" ,
"https://github.com/bazelbuild/rules_go/releases/download/v0.48.0/rules_go-v0.48.0.zip" ,
],
)
# Download Gazelle.
http_archive (
name = "bazel_gazelle" ,
integrity = "sha256-12v3pg/YsFBEQJDfooN6Tq+YKeEWVhjuNdzspcvfWNU=" ,
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.37.0/bazel-gazelle-v0.37.0.tar.gz" ,
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.37.0/bazel-gazelle-v0.37.0.tar.gz" ,
],
)
# Load macros and repository rules.
load ( "@io_bazel_rules_go//go:deps.bzl" , "go_register_toolchains" , "go_rules_dependencies" )
load ( "@bazel_gazelle//:deps.bzl" , "gazelle_dependencies" , "go_repository" )
# Declare Go direct dependencies.
go_repository (
name = "org_golang_x_net" ,
importpath = "golang.org/x/net" ,
sum = "h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=" ,
version = "v0.23.0" ,
)
# Declare indirect dependencies and register toolchains.
go_rules_dependencies ()
go_register_toolchains ( version = "1.23.1" )
gazelle_dependencies ()
プロトコル バッファからコードを生成するには、 com_google_protobuf
への依存関係をWORKSPACE
に追加する必要があります。
load ( "@bazel_tools//tools/build_defs/repo:http.bzl" , "http_archive" )
http_archive (
name = "com_google_protobuf" ,
sha256 = "535fbf566d372ccf3a097c374b26896fa044bf4232aef9cab37bd1cc1ba4e850" ,
strip_prefix = "protobuf-3.15.0" ,
urls = [
"https://mirror.bazel.build/github.com/protocolbuffers/protobuf/archive/v3.15.0.tar.gz" ,
"https://github.com/protocolbuffers/protobuf/archive/v3.15.0.tar.gz" ,
],
)
load ( "@com_google_protobuf//:protobuf_deps.bzl" , "protobuf_deps" )
protobuf_deps ()
Protoc を構築するには、実行プラットフォーム (Bazel がアクションを実行するプラットフォーム) に登録された C/C++ ツールチェーンが必要です。
proto_library ルールは、 rules_proto
リポジトリによって提供されます。 go proto コンパイラー プラグインであるprotoc-gen-go
は、 com_github_golang_protobuf
リポジトリによって提供されます。どちらも go_rules_dependency によって宣言されます。特に別のバージョンを使用する場合を除き、明示的な依存関係を宣言する必要はありません。別のバージョンを使用する手順については、「依存関係のオーバーライド」を参照してください。
gRPC の依存関係はデフォルトでは宣言されていません (依存関係が多すぎるため)。 go_repository を使用して WORKSPACE で宣言できます。 gazelle update-repos を使用してgo.mod
からインポートすることもできます。
詳細については、「Proto の依存関係」、「gRPC の依存関係」を参照してください。 「競合の回避」も参照してください。
すべての依存関係が登録されたら、proto_library ルールと go_proto_library ルールを宣言して、.proto ファイルから Go コードを生成およびコンパイルできます。
load ( "@rules_proto//proto:defs.bzl" , "proto_library" )
load ( "@io_bazel_rules_go//proto:def.bzl" , "go_proto_library" )
proto_library (
name = "foo_proto" ,
srcs = [ "foo.proto" ],
deps = [ "//bar:bar_proto" ],
visibility = [ "//visibility:public" ],
)
go_proto_library (
name = "foo_go_proto" ,
importpath = "github.com/example/protos/foo_proto" ,
protos = [ ":foo_proto" ],
visibility = [ "//visibility:public" ],
)
go_proto_library
ターゲットは、通常のgo_library
と同様にインポートして依存できます。
rules_go の最新バージョンは APIv1 ( github.com/golang/protobuf
) と APIv2 ( google.golang.org/protobuf
) の両方をサポートしていることに注意してください。デフォルトでは、両方のインターフェイスとの互換性を確保するために、コードはgithub.com/golang/protobuf/cmd/protoc-gen-gen
で生成されます。クライアント コードは、ランタイム ライブラリのいずれかまたは両方を使用してインポートできます。
行く
プロトコルバッファ
依存関係とテスト
はい、しかし直接ではありません。
rules_go は、go_binary およびその他のルールで記述されたターゲットに基づいて、Go コンパイラーとリンカーを直接呼び出します。 Bazel と rules_go は一緒にgo
コマンドと同じ役割を果たすため、Bazel ワークスペースでgo
コマンドを使用する必要はありません。
とはいえ、通常はgo
コマンドで要求される規則に従うことをお勧めします (たとえば、ディレクトリごとに 1 つのパッケージ、パッケージ パスはディレクトリ パスと一致するなど)。 Bazel と互換性のないツールも引き続き機能し、プロジェクトは非 Bazel プロジェクトから依存することができます。
go
コマンドを使用して、Bazel がカバーしていないタスク ( go.mod
への新しい依存関係の追加など) を実行する必要がある場合は、次の Bazel 呼び出しを使用して、Bazel で構成された Go SDK のgo
バイナリを実行できます。
bazel run @io_bazel_rules_go//go -- < args >
Go のバージョンが rules_go で使用されるバージョンと同一であることが保証されるため、 go
直接実行するよりもこれを推奨します。
はい、しかし直接ではありません。 Bazel はgo.mod
ファイルを無視し、すべてのパッケージの依存関係は、go_library およびその他のルールで記述されたターゲットのdeps
属性を通じて表現する必要があります。
gazelle が提供するワークスペース ルールである go_repository を使用して、特定のバージョンの Go モジュールを外部リポジトリとしてダウンロードできます。これにより、ガゼルを使用してビルド ファイルも生成されます。
gazelle update-repos を使用してgo.mod
ファイルから go_repository ルールをインポートできます。
これは、 importpath
属性が使用可能になる前に、 go build
でビルドできるライブラリ内でインポート パスの一貫性を保つために使用されていました。
正しくコンパイルしてリンクするには、rules_go が各ライブラリの Go インポート パス (パッケージをインポートできる文字列) を知っている必要があります。これは、 importpath
属性を使用して明示的に設定されるようになりました。この属性が存在する前は、特別なgo_prefix
ルールとライブラリのパッケージ名およびラベル名からの文字列を連結することによってインポート パスが推測されていました。たとえば、ライブラリ//foo/bar:bar
のgo_prefix
がgithub.com/example/project
の場合、 rules_go はインポート パスをgithub.com/example/project/foo/bar/bar
として推測します。最後のスタッターはgo build
と互換性がないため、ラベル名がgo_default_library
の場合、インポート パスにはそれが含まれません。したがって、ライブラリ//foo/bar:go_default_library
の場合、インポート パスはgithub.com/example/project/foo/bar
になります。
go_prefix
が削除され、 importpath
属性が必須になったため (#721 を参照)、 go_default_library
名は何の役割も果たさなくなりました。将来的にはその使用を中止する可能性があります (#265 を参照)。
コマンドラインで--platforms
フラグを設定することでクロスコンパイルできます。例えば:
$ bazel build --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64 //cmd
デフォルトでは、クロスコンパイル時に cgo は無効になります。 cgo を使用してクロスコンパイルするには、ターゲット プラットフォームに_cgo
サフィックスを追加します。これを機能させるには、クロスコンパイル C/C++ ツールチェーンを Bazel に登録する必要があります。
$ bazel build --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64_cgo //cmd
ビルド タグまたはファイル名のサフィックスを持つプラットフォーム固有のソースは、コンパイル時に自動的にフィルターされます。選択式を使用して、プラットフォーム固有の依存関係をselect
的に含めることができます (Gazelle はこれを自動的に行います)。
go_library (
name = "foo" ,
srcs = [
"foo_linux.go" ,
"foo_windows.go" ,
],
deps = select ({
"@io_bazel_rules_go//go/platform:linux_amd64" : [
"//bar_linux" ,
],
"@io_bazel_rules_go//go/platform:windows_amd64" : [
"//bar_windows" ,
],
"//conditions:default" : [],
}),
)
ターゲット プラットフォームまたは特定の golang SDK バージョンを使用して特定の go_binary ターゲットをビルドするには、go_cross_binary ルールを使用します。これは、単一のビルドでさまざまなプラットフォーム用の複数のバイナリを生成する場合に便利です。
ターゲット プラットフォーム用に特定の go_test ターゲットを構築するには、そのルールにgoos
とgoarch
属性を設定します。
//command_line_option:platforms
での Bazel 構成移行を通じて go_binary または go_test ルールに同等に依存できます (rules_go 0.23.0 より前のこのアプローチには問題があります)。
Bazel はサンドボックス内でテストを実行します。つまり、テストは自動的にファイルにアクセスできません。 data
属性を使用してテスト ファイルを含める必要があります。たとえば、 testdata
ディレクトリ内のすべてを含める場合は、次のようにします。
go_test (
name = "foo_test" ,
srcs = [ "foo_test.go" ],
data = glob ([ "testdata/**" ]),
importpath = "github.com/example/project/foo" ,
)
デフォルトでは、テストは、テストを定義したビルド ファイルのディレクトリで実行されます。これは、リポジトリ ルートで実行される他の言語に従う Bazel 規則ではなく、Go テスト規則に従っていることに注意してください。これは、相対パスを使用してテスト ファイルにアクセスできることを意味します。 rundir
属性を使用してテスト ディレクトリを変更できます。 go_test を参照してください。
testdata
ディレクトリがある場合、Gazelle は上記のようなdata
属性を自動的に追加します。ただし、そこにビルド可能な .go ファイルまたはビルド ファイルが含まれていない限り、 testdata
は通常のパッケージとして扱われます。
Windows では、テスト データ ファイルはシンボリック リンクに依存しており、デフォルトでは Windows では特権のないユーザーがシンボリック リンクを作成できないため、データ ファイルをテストで直接使用できないことに注意してください。 github.com/bazelbuild/rules_go/go/tools/bazel ライブラリを使用してデータ ファイルにアクセスできます。
go_binary
実行可能ファイルを書き込む場所は、rules_go のバージョン間で安定していないため、依存すべきではありません。親ディレクトリの名前には、いくつかの構成データが含まれています。これにより、同じバイナリが異なる構成でビルドされた場合に Bazel のキャッシュが汚染されるのを防ぎます。バイナリのベース名はプラットフォームに依存する場合もあります。Windows では、.exe 拡張子が追加されます。
go_test
ルール内の実行可能ファイルに依存するには、 data
属性で実行可能ファイルを参照し (表示できるようにするため)、 args
内の場所を展開します。実際の場所はコマンド ラインのテストに渡されます。例えば:
go_binary (
name = "cmd" ,
srcs = [ "cmd.go" ],
)
go_test (
name = "cmd_test" ,
srcs = [ "cmd_test.go" ],
args = [ "$(location :cmd)" ],
data = [ ":cmd" ],
)
バイナリにアクセスするテストの完全な例については、//tests/core/cross を参照してください。
あるいは、go_binary のout
属性を特定のファイル名に設定することもできます。 out
が設定されている場合、構成を変更するときにバイナリはキャッシュされないことに注意してください。
go_binary (
name = "cmd" ,
srcs = [ "cmd.go" ],
out = "cmd" ,
)
go_test (
name = "cmd_test" ,
srcs = [ "cmd_test.go" ],
data = [ ":cmd" ],
)
proto ドキュメントの「競合の回避」を参照してください。
これはサポートされていません。 @io_bazel_rules_go//proto:go_grpc
コンパイラで go_proto_library を使用すると、暗黙的な依存関係が@org_golang_google_grpc//:go_default_library
に追加されます。 //vendor/google.golang.org/grpc:go_default_library
またはその他の場所から同じパッケージの別のコピーをリンクすると、コンパイル時または実行時に競合が発生する可能性があります。
プロト ルール生成を有効にして Gazelle を使用している場合、競合を避けるために、 google.golang.org/grpc
のインポートは@org_golang_google_grpc//:go_default_library
に自動的に解決されます。この場合、ベンダーの gRPC は無視する必要があります。
特にベンダーの gRPC パッケージを使用する必要がある場合は、 go_proto_library
の使用を完全に避けることをお勧めします。事前に生成された .pb.go ファイルをチェックインし、 go_library
ルールを使用してビルドできます。 Gazelle は、proto ルールの生成が無効になっている場合にこれらのルールを生成します (ルート ビルド ファイルに# gazelle:proto disable_global
を追加します)。
go_rules_dependency で宣言されたリポジトリをオーバーライドする手順については、「依存関係のオーバーライド」を参照してください。
参考文献:
Travis CI で Bazel テストを実行するには、 before_install
スクリプトで Bazel をインストールする必要があります。上にリンクされている設定ファイルを参照してください。
テスト環境で大量のメモリを消費しないように、Bazel を多数のフラグを指定して実行するとよいでしょう。
--host_jvm_args=-Xmx500m --host_jvm_args=-Xms500m
: JVM ヒープの最大サイズと初期サイズを設定します。同じ状態を維持するということは、JVM がヒープの拡大に時間を費やさないことを意味します。ヒープ サイズの選択はある程度任意です。他の構成ファイルでは、2500m までの制限を推奨しています。値が大きいほどビルドは速くなりますが、OOM 強制終了のリスクが高くなります。--bazelrc=.test-bazelrc
: Travis CI に固有の Bazel 構成ファイルを使用します。残りのオプションのほとんどをここに入れることができます。build --spawn_strategy=standalone --genrule_strategy=standalone
: ビルドのサンドボックス化を無効にします。 mount
システム コールが許可されていないため、Travis のコンテナ内でサンドボックス化が失敗する可能性があります。test --test_strategy=standalone
: テストのサンドボックス化も無効にします。--local_resources=1536,1.5,0.5
: 利用可能な RAM (MB 単位)、コンピューティングに利用可能なコア、および I/O に利用可能なコアに関する Bazel 制限を設定します。値が大きいほどビルドは速くなりますが、競合と OOM 強制終了のリスクが高くなります。--noshow_progress
: クリーンなログの出力で進行状況メッセージを抑制します。--verbose_failures
: より詳細な失敗メッセージを取得します。--test_output=errors
: Travis ログにテストの標準エラー出力を表示します。通常、テスト出力はログ ファイルに書き込まれますが、Travis はこれを保存したりレポートしたりしません。 Travis でのダウンロードは比較的遅い (ネットワークの競合が激しい) ため、ビルド内のネットワーク I/O の量を最小限に抑える必要があります。 Bazel と Go SDK のダウンロードはその大きな部分を占めます。 Go SDK のダウンロードを回避するには、 .travis.yml
ファイルで Go のプレインストール バージョンを含むコンテナーをリクエストし、Travis 固有のWORKSPACE
ファイルでgo_register_toolchains(go_version = "host")
を呼び出します。
Bazel のキャッシュを Travis のキャッシュに入れたいと思うかもしれません。これによりビルドが大幅に高速化されますが、Travis はキャッシュを Amazon に保存するため、転送に非常に長い時間がかかります。実際にはクリーンビルドの方が速いようです。
rules_go は Go SDK の公式リリースのみをサポートします。ただし、 "1.16beta1"
などのversion
go_register_toolchains に渡すことで、ベータ版と RC バージョンをテストすることはできます。 go_download_sdk も参照してください。
load ( "@io_bazel_rules_go//go:deps.bzl" , "go_register_toolchains" , "go_rules_dependencies" )
go_rules_dependencies ()
go_register_toolchains ( version = "1.17beta1" )