Milis: bazel-go-diskusi
Kendur: #pergi di Bazel Slack, #bazel di Go Slack
Aturannya masih dalam tahap pengembangan beta. Mereka mendukung:
Mereka saat ini tidak mendukung atau memiliki dukungan terbatas untuk:
Aturan Go diuji dan didukung pada platform host berikut:
Pengguna telah melaporkan keberhasilan di beberapa platform lain, namun aturannya hanya diuji pada platform yang tercantum di atas.
Catatan: Sejak versi v0.38.0, Rules_go memerlukan Bazel ≥ 5.4.0 agar dapat berfungsi.
Cabang master
hanya dijamin berfungsi dengan Bazel versi terbaru.
Untuk membuat kode Go dengan Bazel, Anda memerlukan:
patch
, cat
, dan beberapa alat Unix lainnya di PATH
.Biasanya Anda tidak perlu menginstal rantai alat Go. Bazel akan mengunduhnya.
Lihat Menggunakan Rules_go di Windows untuk petunjuk pengaturan khusus Windows. Beberapa alat tambahan perlu diinstal dan dikonfigurasi.
Jika Anda menggunakan sistem manajemen ketergantungan eksternal baru Bazel, Bzlmod, lihat panduan khusus Go with Bzlmod.
Buat file di bagian atas repositori Anda bernama WORKSPACE
, dan tambahkan cuplikan di bawah (atau tambahkan ke WORKSPACE
Anda yang sudah ada). Ini memberitahu Bazel untuk mengambil rule_go dan dependensinya. Bazel akan mengunduh toolchain Go terbaru yang didukung dan mendaftarkannya untuk digunakan.
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" )
Anda dapat menggunakan rule_go di master
dengan menggunakan git_repository alih-alih http_archive dan menunjuk ke komit terbaru.
Tambahkan file bernama BUILD.bazel
di direktori root proyek Anda. Anda memerlukan file build di setiap direktori dengan kode Go, namun Anda juga memerlukannya di direktori root, meskipun proyek Anda tidak memiliki kode Go di sana. Untuk biner "Halo, dunia", filenya akan terlihat seperti ini:
load ( "@io_bazel_rules_go//go:def.bzl" , "go_binary" )
go_binary (
name = "hello" ,
srcs = [ "hello.go" ],
)
Anda dapat membangun target ini dengan bazel build //:hello
.
Jika proyek Anda dapat dibangun dengan go build
, Anda dapat membuat dan memperbarui file build Anda secara otomatis menggunakan gazelle.
Tambahkan repositori bazel_gazelle
dan dependensinya ke WORKSPACE
Anda. Seharusnya terlihat seperti ini:
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 ()
Tambahkan kode di bawah ini ke file BUILD.bazel
di direktori root proyek Anda. Ganti string setelah prefix
dengan awalan jalur impor yang cocok dengan proyek Anda. Ini harus sama dengan jalur modul Anda, jika Anda memiliki file go.mod
.
load ( "@bazel_gazelle//:def.bzl" , "gazelle" )
# gazelle:prefix github.com/example/project
gazelle ( name = "gazelle" )
Ini mendeklarasikan aturan biner gazelle
, yang dapat Anda jalankan menggunakan perintah di bawah ini:
bazel run //:gazelle
Ini akan menghasilkan file BUILD.bazel
dengan target go_library, go_binary, dan go_test untuk setiap paket dalam proyek Anda. Anda dapat menjalankan perintah yang sama di masa mendatang untuk memperbarui file build yang ada dengan file sumber, dependensi, dan opsi baru.
Jika proyek Anda tidak mengikuti konvensi go build
atau Anda memilih untuk tidak menggunakan gazelle, Anda dapat menulis file build dengan tangan.
Di setiap direktori yang berisi kode Go, buat file bernama BUILD.bazel
Tambahkan pernyataan load
di bagian atas file untuk aturan yang Anda gunakan.
load ( "@io_bazel_rules_go//go:def.bzl" , "go_binary" , "go_library" , "go_test" )
Untuk setiap perpustakaan, tambahkan aturan go_library seperti di bawah ini. File sumber tercantum dalam atribut srcs
. Paket yang diimpor di luar perpustakaan standar dicantumkan dalam atribut deps
menggunakan label Bazel yang mengacu pada aturan go_library yang sesuai. Jalur impor perpustakaan harus ditentukan dengan atribut 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" ],
)
Untuk pengujian, tambahkan aturan go_test seperti di bawah ini. Pustaka yang diuji harus dicantumkan dalam atribut embed
.
go_test (
name = "foo_test" ,
srcs = [
"a_test.go" ,
"b_test.go" ,
],
embed = [ ":foo_lib" ],
deps = [
"//testtools" ,
"@org_golang_x_utils//morestuff" ,
],
)
Untuk biner, tambahkan aturan go_binary seperti di bawah ini.
go_binary (
name = "foo" ,
srcs = [ "main.go" ],
)
Untuk setiap repositori Go, tambahkan aturan go_repository ke WORKSPACE
seperti di bawah ini. Aturan ini berasal dari repositori Gazelle, jadi Anda harus memuatnya. gazelle update-repo dapat membuat atau memperbarui aturan ini secara otomatis dari file go.mod atau 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 ()
Untuk menghasilkan kode dari buffering protokol, Anda harus menambahkan ketergantungan pada com_google_protobuf
ke WORKSPACE
Anda.
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 ()
Anda memerlukan rantai alat C/C++ yang terdaftar untuk platform eksekusi (platform tempat Bazel menjalankan tindakan) untuk membangun protoc.
Aturan proto_library disediakan oleh repositori rules_proto
. protoc-gen-go
, plugin kompiler proto Go, disediakan oleh repositori com_github_golang_protobuf
. Keduanya dideklarasikan oleh go_rules_dependencies. Anda tidak perlu mendeklarasikan ketergantungan eksplisit kecuali Anda secara khusus ingin menggunakan versi lain. Lihat Mengganti dependensi untuk petunjuk penggunaan versi yang berbeda.
Dependensi gRPC tidak dideklarasikan secara default (terlalu banyak). Anda dapat mendeklarasikannya di WORKSPACE menggunakan go_repository. Anda mungkin ingin menggunakan gazelle update-repo untuk mengimpornya dari go.mod
.
Lihat Dependensi proto, dependensi gRPC untuk informasi selengkapnya. Lihat juga Menghindari konflik.
Setelah semua dependensi didaftarkan, Anda dapat mendeklarasikan aturan proto_library dan go_proto_library untuk menghasilkan dan mengkompilasi kode Go dari file .proto.
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" ],
)
Target go_proto_library
dapat diimpor dan diandalkan seperti go_library
pada umumnya.
Perhatikan bahwa versi terbaru dari Rules_go mendukung APIv1 ( github.com/golang/protobuf
) dan APIv2 ( google.golang.org/protobuf
). Secara default, kode dibuat dengan github.com/golang/protobuf/cmd/protoc-gen-gen
untuk kompatibilitas dengan kedua antarmuka. Kode klien dapat diimpor menggunakan perpustakaan runtime atau keduanya.
Pergi
Buffer protokol
Ketergantungan dan pengujian
Ya, tapi tidak secara langsung.
Rules_go memanggil compiler dan linker Go secara langsung, berdasarkan target yang dijelaskan dengan go_binary dan aturan lainnya. Bazel dan rule_go bersama-sama mengisi peran yang sama dengan perintah go
, jadi perintah go
tidak perlu digunakan di ruang kerja Bazel.
Meskipun demikian, biasanya merupakan ide bagus untuk mengikuti konvensi yang disyaratkan oleh perintah go
(misalnya, satu paket per direktori, jalur paket cocok dengan jalur direktori). Alat yang tidak kompatibel dengan Bazel akan tetap berfungsi, dan proyek Anda dapat diandalkan oleh proyek non-Bazel.
Jika Anda perlu menggunakan perintah go
untuk melakukan tugas yang tidak dicakup oleh Bazel (seperti menambahkan dependensi baru ke go.mod
), Anda dapat menggunakan pemanggilan Bazel berikut untuk menjalankan biner go
dari Go SDK yang dikonfigurasi Bazel:
bazel run @io_bazel_rules_go//go -- < args >
Lebih baik memilih ini daripada menjalankan go
secara langsung karena ini memastikan bahwa versi Go identik dengan yang digunakan oleh rule_go.
Ya, tapi tidak secara langsung. Bazel mengabaikan file go.mod
, dan semua dependensi paket harus dinyatakan melalui atribut deps
dalam target yang dijelaskan dengan go_library dan aturan lainnya.
Anda dapat mengunduh modul Go pada versi tertentu sebagai repositori eksternal menggunakan go_repository, aturan ruang kerja yang disediakan oleh Gazelle. Ini juga akan menghasilkan file build menggunakan Gazelle.
Anda dapat mengimpor aturan go_repository dari file go.mod
menggunakan gazelle update-repo.
Ini digunakan untuk menjaga konsistensi jalur impor di perpustakaan yang dapat dibangun dengan go build
sebelum atribut importpath
tersedia.
Untuk mengkompilasi dan menautkan dengan benar, rule_go harus mengetahui jalur impor Go (string yang dapat digunakan untuk mengimpor paket) untuk setiap perpustakaan. Ini sekarang disetel secara eksplisit dengan atribut importpath
. Sebelum atribut tersebut ada, jalur impor disimpulkan dengan menggabungkan string dari aturan go_prefix
khusus serta nama paket dan label perpustakaan. Misalnya, jika go_prefix
adalah github.com/example/project
, untuk perpustakaan //foo/bar:bar
, Rules_go akan menyimpulkan jalur impor sebagai github.com/example/project/foo/bar/bar
. Gagap di bagian akhir tidak kompatibel dengan go build
, jadi jika nama labelnya adalah go_default_library
, jalur impor tidak akan menyertakannya. Jadi untuk perpustakaan //foo/bar:go_default_library
, jalur impornya adalah github.com/example/project/foo/bar
.
Karena go_prefix
telah dihapus dan atribut importpath
menjadi wajib (lihat #721), nama go_default_library
tidak lagi berguna. Kami mungkin memutuskan untuk berhenti menggunakannya di masa mendatang (lihat #265).
Anda dapat melakukan kompilasi silang dengan menyetel tanda --platforms
pada baris perintah. Misalnya:
$ bazel build --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64 //cmd
Secara default, cgo dinonaktifkan saat kompilasi silang. Untuk melakukan kompilasi silang dengan cgo, tambahkan akhiran _cgo
ke platform target. Anda harus mendaftarkan rantai alat C/C++ kompilasi silang dengan Bazel agar ini berfungsi.
$ bazel build --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64_cgo //cmd
Sumber khusus platform dengan tag build atau akhiran nama file difilter secara otomatis pada waktu kompilasi. Anda dapat secara selektif menyertakan dependensi spesifik platform dengan ekspresi select
(Gazelle melakukannya secara otomatis).
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" : [],
}),
)
Untuk membuat target go_binary spesifik untuk platform target atau menggunakan versi SDK golang tertentu, gunakan aturan go_cross_binary. Ini berguna untuk menghasilkan banyak biner untuk platform berbeda dalam satu build.
Untuk membuat target go_test yang spesifik untuk platform target, tetapkan atribut goos
dan goarch
pada aturan tersebut.
Anda juga dapat bergantung pada aturan go_binary atau go_test melalui transisi konfigurasi Bazel di //command_line_option:platforms
(ada masalah dengan pendekatan ini sebelum Rules_go 0.23.0).
Bazel menjalankan pengujian di kotak pasir, yang berarti pengujian tidak secara otomatis memiliki akses ke file. Anda harus menyertakan file pengujian menggunakan atribut data
. Misalnya, jika Anda ingin memasukkan semuanya ke dalam direktori testdata
:
go_test (
name = "foo_test" ,
srcs = [ "foo_test.go" ],
data = glob ([ "testdata/**" ]),
importpath = "github.com/example/project/foo" ,
)
Secara default, pengujian dijalankan di direktori file build yang mendefinisikannya. Perhatikan bahwa ini mengikuti konvensi pengujian Go, bukan konvensi Bazel yang diikuti oleh bahasa lain, yang dijalankan di root repositori. Ini berarti Anda dapat mengakses file pengujian menggunakan jalur relatif. Anda dapat mengubah direktori pengujian menggunakan atribut rundir
. Lihat go_test.
Gazelle akan secara otomatis menambahkan atribut data
seperti di atas jika Anda memiliki direktori testdata
kecuali direktori tersebut berisi file .go atau file build yang dapat dibangun, dalam hal ini, testdata
diperlakukan sebagai paket normal.
Perhatikan bahwa di Windows, file data tidak langsung tersedia untuk pengujian, karena file data pengujian bergantung pada tautan simbolik, dan secara default, Windows tidak mengizinkan pengguna yang tidak memiliki hak istimewa membuat tautan simbolik. Anda dapat menggunakan perpustakaan github.com/bazelbuild/rules_go/go/tools/bazel untuk mengakses file data.
Lokasi di mana go_binary
menulis file yang dapat dieksekusi tidak stabil di seluruh versi rule_go dan tidak dapat diandalkan. Direktori induk menyertakan beberapa data konfigurasi dalam namanya. Hal ini mencegah cache Bazel diracuni ketika biner yang sama dibuat dalam konfigurasi berbeda. Nama dasar biner mungkin juga bergantung pada platform: pada Windows, kami menambahkan ekstensi .exe.
Untuk bergantung pada executable dalam aturan go_test
, referensikan executable tersebut dalam atribut data
(agar terlihat), lalu perluas lokasinya di args
. Lokasi sebenarnya akan diteruskan ke pengujian pada baris perintah. Misalnya:
go_binary (
name = "cmd" ,
srcs = [ "cmd.go" ],
)
go_test (
name = "cmd_test" ,
srcs = [ "cmd_test.go" ],
args = [ "$(location :cmd)" ],
data = [ ":cmd" ],
)
Lihat //tests/core/cross untuk contoh lengkap pengujian yang mengakses biner.
Alternatifnya, Anda dapat mengatur atribut out
dari go_binary ke nama file tertentu. Perhatikan bahwa ketika out
disetel, biner tidak akan di-cache saat mengubah konfigurasi.
go_binary (
name = "cmd" ,
srcs = [ "cmd.go" ],
out = "cmd" ,
)
go_test (
name = "cmd_test" ,
srcs = [ "cmd_test.go" ],
data = [ ":cmd" ],
)
Lihat Menghindari konflik dalam dokumentasi proto.
Ini tidak didukung. Saat menggunakan go_proto_library dengan kompiler @io_bazel_rules_go//proto:go_grpc
, ketergantungan implisit ditambahkan pada @org_golang_google_grpc//:go_default_library
. Jika Anda menautkan salinan lain dari paket yang sama dari //vendor/google.golang.org/grpc:go_default_library
atau di mana pun, Anda mungkin mengalami konflik pada waktu kompilasi atau waktu proses.
Jika Anda menggunakan Gazelle dengan pembuatan aturan proto diaktifkan, impor google.golang.org/grpc
akan otomatis diselesaikan ke @org_golang_google_grpc//:go_default_library
untuk menghindari konflik. Dalam kasus ini, gRPC yang di-vendorkan harus diabaikan.
Jika Anda secara khusus perlu menggunakan paket gRPC yang disediakan vendor, sebaiknya hindari penggunaan go_proto_library
sama sekali. Anda dapat memeriksa file .pb.go yang telah dibuat sebelumnya dan membuatnya dengan aturan go_library
. Gazelle akan membuat aturan-aturan ini ketika pembuatan aturan proto dinonaktifkan (tambahkan # gazelle:proto disable_global
ke file build root Anda).
Lihat Mengganti dependensi untuk instruksi mengganti repositori yang dideklarasikan di go_rules_dependencies.
Referensi:
Untuk menjalankan pengujian Bazel di Travis CI, Anda harus menginstal Bazel di skrip before_install
. Lihat file konfigurasi kami yang tertaut di atas.
Anda sebaiknya menjalankan Bazel dengan sejumlah tanda untuk mencegahnya menghabiskan banyak memori di lingkungan pengujian.
--host_jvm_args=-Xmx500m --host_jvm_args=-Xms500m
: Tetapkan ukuran heap JVM maksimum dan awal. Tetap sama berarti JVM tidak akan menghabiskan waktu untuk mengembangkan heap. Pilihan ukuran heap agak sewenang-wenang; file konfigurasi lain merekomendasikan batas setinggi 2500m. Nilai yang lebih tinggi berarti pembangunan lebih cepat, tetapi risiko pembunuhan OOM lebih tinggi.--bazelrc=.test-bazelrc
: Gunakan file konfigurasi Bazel khusus untuk Travis CI. Anda dapat meletakkan sebagian besar opsi yang tersisa di sini.build --spawn_strategy=standalone --genrule_strategy=standalone
: Nonaktifkan sandboxing untuk build. Sandboxing mungkin gagal di dalam container Travis karena panggilan sistem mount
tidak diizinkan.test --test_strategy=standalone
: Nonaktifkan juga sandboxing untuk pengujian.--local_resources=1536,1.5,0.5
: Tetapkan batas Bazel pada RAM yang tersedia dalam MB, inti yang tersedia untuk komputasi, dan inti yang tersedia untuk I/O. Nilai yang lebih tinggi berarti pembangunan lebih cepat, namun pertentangan dan risiko kematian OOM lebih tinggi.--noshow_progress
: Menyembunyikan pesan kemajuan dalam output untuk log yang lebih bersih.--verbose_failures
: Dapatkan pesan kegagalan yang lebih detail.--test_output=errors
: Tampilkan test stderr di log Travis. Biasanya, keluaran pengujian berupa file log tertulis yang tidak disimpan atau dilaporkan oleh Travis. Pengunduhan di Travis relatif lambat (jaringan sangat bersaing), jadi sebaiknya minimalkan jumlah I/O jaringan di build Anda. Mengunduh Bazel dan Go SDK adalah bagian terbesarnya. Untuk menghindari pengunduhan Go SDK, Anda dapat meminta container dengan versi Go yang sudah terinstal di file .travis.yml
Anda, lalu memanggil go_register_toolchains(go_version = "host")
di file WORKSPACE
khusus Travis.
Anda mungkin tergoda untuk memasukkan cache Bazel ke dalam cache Travis Anda. Meskipun hal ini dapat mempercepat pembangunan Anda secara signifikan, Travis menyimpan cache-nya di Amazon, dan memerlukan waktu yang sangat lama untuk mentransfernya. Pembangunan yang bersih tampak lebih cepat dalam praktiknya.
Rules_go hanya mendukung rilis resmi Go SDK. Namun, Anda masih dapat menguji versi beta dan RC dengan meneruskan version
seperti "1.16beta1"
ke go_register_toolchains. Lihat juga 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" )