Halaman ini membahas manfaat dan penggunaan dasar konfigurasi Starlark, Bazel's API untuk menyesuaikan cara pembuatan project Anda. Panduan ini mencakup cara menentukan setelan build dan memberikan contoh.
Hal ini memungkinkan untuk:
- menentukan flag kustom untuk project Anda, yang tidak lagi memerlukan
--define
- menulis
transisi untuk mengonfigurasi dependensi dalam
konfigurasi yang berbeda dengan induknya
(seperti
--compilation_mode=opt
atau--cpu=arm
) - sisipkan default yang lebih baik ke dalam aturan (seperti secara otomatis membuat
//my:android_app
dengan SDK yang ditentukan)
dan lainnya, semuanya dari file .bzl (tidak diperlukan rilis Bazel). Lihat
repo bazelbuild/examples
untuk
contoh.
Setelan build yang ditentukan pengguna
Setelan build adalah sebuah
informasi konfigurasi. Anggap konfigurasi sebagai peta kunci/nilai. Menetapkan --cpu=ppc
dan --copt="-DFoo"
akan menghasilkan konfigurasi yang terlihat seperti
{cpu: ppc, copt: "-DFoo"}
. Setiap entri merupakan setelan build.
Flag tradisional seperti cpu
dan copt
adalah setelan native —
kuncinya ditentukan dan nilainya ditetapkan di dalam kode java bazel native.
Pengguna Bazel hanya dapat membaca dan menulis melalui command line
dan API lain yang dikelola secara native. Mengubah flag native, dan API
yang mengeksposnya, memerlukan rilis bazel. Setelan build yang ditentukan pengguna ditentukan dalam file .bzl
(sehingga tidak memerlukan rilis bazel untuk mendaftarkan perubahan). Atribut ini juga dapat ditetapkan melalui command line
(jika ditetapkan sebagai flags
, lihat selengkapnya di bawah), tetapi juga
dapat ditetapkan melalui transisi yang ditentukan pengguna.
Menentukan setelan build
Parameter build_setting
rule()
Setelan build adalah aturan seperti aturan lainnya dan dibedakan menggunakan
atribut
fungsi rule()
Starlark.build_setting
# example/buildsettings/build_settings.bzl
string_flag = rule(
implementation = _impl,
build_setting = config.string(flag = True)
)
Atribut build_setting
menggunakan fungsi yang menentukan jenis
setelan build. Jenis ini terbatas pada sekumpulan jenis Starlark dasar seperti
bool
dan string
. Lihat dokumentasi modul config
untuk mengetahui detailnya. Mengetik yang lebih rumit dapat dilakukan dalam fungsi penerapan aturan. Berikut informasi selengkapnya di sini.
Fungsi modul config
menggunakan parameter boolean opsional, flag
, yang disetel ke salah (false) secara default. jika flag
disetel ke benar (true), setelan build dapat disetel pada command line oleh pengguna serta secara internal oleh penulis aturan melalui nilai dan transisi default.
Tidak semua setelan harus disetel oleh pengguna. Misalnya, jika Anda sebagai penulis aturan memiliki beberapa mode debug yang ingin diaktifkan dalam aturan pengujian, Anda tidak ingin memberikan kemampuan kepada pengguna untuk mengaktifkan fitur tersebut secara acak dalam aturan non-pengujian lainnya.
Menggunakan ctx.build_setting_value
Seperti semua aturan, aturan setelan build memiliki fungsi implementasi.
Nilai dasar jenis Starlark pada setelan build dapat diakses melalui metode ctx.build_setting_value
. Metode ini hanya tersedia untuk objek ctx
dalam aturan setelan build. Metode
implementasi ini dapat langsung meneruskan nilai setelan build atau melakukan pekerjaan tambahan
padanya, seperti pemeriksaan jenis atau pembuatan struct yang lebih kompleks. Berikut adalah cara
mengimplementasikan setelan build berjenis enum
:
# example/buildsettings/build_settings.bzl
TemperatureProvider = provider(fields = ['type'])
temperatures = ["HOT", "LUKEWARM", "ICED"]
def _impl(ctx):
raw_temperature = ctx.build_setting_value
if raw_temperature not in temperatures:
fail(str(ctx.label) + " build setting allowed to take values {"
+ ", ".join(temperatures) + "} but was set to unallowed value "
+ raw_temperature)
return TemperatureProvider(type = raw_temperature)
temperature = rule(
implementation = _impl,
build_setting = config.string(flag = True)
)
Menentukan flag string multi-set
Setelan string memiliki parameter allow_multiple
tambahan yang memungkinkan
flag ditetapkan beberapa kali pada command line atau dalam bazel. Nilai defaultnya
masih ditetapkan dengan atribut berjenis string:
# example/buildsettings/build_settings.bzl
allow_multiple_flag = rule(
implementation = _impl,
build_setting = config.string(flag = True, allow_multiple = True)
)
# example/BUILD
load("//example/buildsettings:build_settings.bzl", "allow_multiple_flag")
allow_multiple_flag(
name = "roasts",
build_setting_default = "medium"
)
Setiap setelan flag diperlakukan sebagai nilai tunggal:
$ bazel build //my/target --//example:roasts=blonde \
--//example:roasts=medium,dark
Hal di atas diuraikan menjadi {"//example:roasts": ["blonde", "medium,dark"]}
dan
ctx.build_setting_value
menampilkan daftar ["blonde", "medium,dark"]
.
Membuat instance setelan build
Aturan yang ditentukan dengan parameter build_setting
memiliki atribut build_setting_default
wajib implisit. Atribut ini menggunakan jenis yang sama dengan
yang dideklarasikan oleh parameter build_setting
.
# example/buildsettings/build_settings.bzl
FlavorProvider = provider(fields = ['type'])
def _impl(ctx):
return FlavorProvider(type = ctx.build_setting_value)
flavor = rule(
implementation = _impl,
build_setting = config.string(flag = True)
)
# example/BUILD
load("//example/buildsettings:build_settings.bzl", "flavor")
flavor(
name = "favorite_flavor",
build_setting_default = "APPLE"
)
Setelan standar
Library Skylib menyertakan serangkaian setelan standar yang dapat Anda buat instance tanpa harus menulis Starlark kustom.
Misalnya, untuk menentukan setelan yang menerima serangkaian nilai string terbatas:
# example/BUILD
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
string_flag(
name = "myflag",
values = ["a", "b", "c"],
build_setting_default = "a",
)
Untuk mengetahui daftar lengkapnya, lihat Aturan setelan build umum.
Menggunakan setelan build
Bergantung pada setelan build
Jika ingin membaca informasi konfigurasi, target dapat langsung bergantung pada setelan build melalui dependensi atribut reguler.
# example/rules.bzl
load("//example/buildsettings:build_settings.bzl", "FlavorProvider")
def _rule_impl(ctx):
if ctx.attr.flavor[FlavorProvider].type == "ORANGE":
...
drink_rule = rule(
implementation = _rule_impl,
attrs = {
"flavor": attr.label()
}
)
# example/BUILD
load("//example:rules.bzl", "drink_rule")
load("//example/buildsettings:build_settings.bzl", "flavor")
flavor(
name = "favorite_flavor",
build_setting_default = "APPLE"
)
drink_rule(
name = "my_drink",
flavor = ":favorite_flavor",
)
Bahasa mungkin ingin membuat kumpulan setelan build kanonis yang bergantung pada semua
aturan untuk bahasa tersebut. Meskipun konsep native fragments
tidak lagi ada sebagai objek hardcode di dunia konfigurasi Starlark, salah satu cara untuk menerjemahkan konsep ini adalah dengan menggunakan kumpulan atribut implisit umum. Contoh:
# kotlin/rules.bzl
_KOTLIN_CONFIG = {
"_compiler": attr.label(default = "//kotlin/config:compiler-flag"),
"_mode": attr.label(default = "//kotlin/config:mode-flag"),
...
}
...
kotlin_library = rule(
implementation = _rule_impl,
attrs = dicts.add({
"library-attr": attr.string()
}, _KOTLIN_CONFIG)
)
kotlin_binary = rule(
implementation = _binary_impl,
attrs = dicts.add({
"binary-attr": attr.label()
}, _KOTLIN_CONFIG)
Menggunakan setelan build di command line
Serupa dengan sebagian besar flag native, Anda dapat menggunakan command line untuk menetapkan setelan build
yang ditandai sebagai flag. Nama setelan build adalah jalur target lengkapnya menggunakan sintaksis name=value
:
$ bazel build //my/target --//example:string_flag=some-value # allowed
$ bazel build //my/target --//example:string_flag some-value # not allowed
Sintaksis boolean khusus didukung:
$ bazel build //my/target --//example:boolean_flag
$ bazel build //my/target --no//example:boolean_flag
Menggunakan alias setelan build
Anda dapat menetapkan alias untuk jalur target setelan build agar lebih mudah dibaca di command line. Alias berfungsi mirip dengan flag native dan juga menggunakan sintaksis opsi tanda hubung ganda.
Tetapkan alias dengan menambahkan --flag_alias=ALIAS_NAME=TARGET_PATH
ke .bazelrc
. Misalnya, untuk menetapkan alias ke coffee
:
# .bazelrc
build --flag_alias=coffee=//experimental/user/starlark_configurations/basic_build_setting:coffee-temp
Praktik Terbaik: Menetapkan alias beberapa kali akan menghasilkan alias terbaru yang lebih diutamakan. Menggunakan nama alias yang unik untuk menghindari hasil penguraian yang tidak diinginkan.
Untuk menggunakan alias, ketik alias sebagai pengganti jalur target setelan build.
Dengan contoh coffee
di atas yang ditetapkan di .bazelrc
pengguna:
$ bazel build //my/target --coffee=ICED
bukan
$ bazel build //my/target --//experimental/user/starlark_configurations/basic_build_setting:coffee-temp=ICED
Praktik Terbaik: Meskipun Anda dapat menetapkan alias di command line, membiarkan alias
dalam .bazelrc
akan mengurangi ketidakrapian command line.
Setelan build berjenis label
Tidak seperti setelan build lainnya, setelan jenis label tidak dapat ditentukan menggunakan parameter aturan build_setting
. Sebaliknya, bazel memiliki dua aturan bawaan:
label_flag
dan label_setting
. Aturan ini meneruskan penyedia
target aktual yang ditetapkan dengan setelan build. label_flag
dan
label_setting
dapat dibaca/ditulis oleh transisi dan label_flag
dapat ditetapkan
oleh pengguna seperti yang dapat dilakukan oleh aturan build_setting
lainnya. Satu-satunya perbedaan adalah keduanya
tidak dapat ditentukan secara khusus.
Setelan jenis label pada akhirnya akan menggantikan fungsi default
batas akhir. Atribut default batas akhir adalah atribut berjenis Label yang
nilai akhirnya dapat dipengaruhi oleh konfigurasi. Di Starlark, ini akan menggantikan
configuration_field
API.
# example/rules.bzl
MyProvider = provider(fields = ["my_field"])
def _dep_impl(ctx):
return MyProvider(my_field = "yeehaw")
dep_rule = rule(
implementation = _dep_impl
)
def _parent_impl(ctx):
if ctx.attr.my_field_provider[MyProvider].my_field == "cowabunga":
...
parent_rule = rule(
implementation = _parent_impl,
attrs = { "my_field_provider": attr.label() }
)
# example/BUILD
load("//example:rules.bzl", "dep_rule", "parent_rule")
dep_rule(name = "dep")
parent_rule(name = "parent", my_field_provider = ":my_field_provider")
label_flag(
name = "my_field_provider",
build_setting_default = ":dep"
)
Setelan build dan select()
Pengguna dapat mengonfigurasi atribut pada setelan build menggunakan
select()
. Target setelan build dapat diteruskan ke atribut flag_values
dari
config_setting
. Nilai yang akan dicocokkan dengan konfigurasi diteruskan sebagai
String
, lalu diuraikan ke jenis setelan build untuk pencocokan.
config_setting(
name = "my_config",
flag_values = {
"//example:favorite_flavor": "MANGO"
}
)
Transisi yang ditentukan pengguna
Transisi konfigurasi memetakan transformasi dari satu target yang dikonfigurasi ke target lainnya dalam grafik build.
Aturan yang menetapkannya harus menyertakan atribut khusus:
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist"
)
Dengan menambahkan transisi, Anda dapat dengan mudah meledakkan ukuran grafik build. Tindakan ini akan menetapkan daftar yang diizinkan pada paket tempat Anda dapat membuat target aturan ini. Nilai default dalam blok kode di atas mengizinkan semua. Namun, jika Anda ingin membatasi siapa yang menggunakan aturan, Anda dapat menetapkan atribut tersebut agar mengarah ke daftar kustom yang diizinkan. Hubungi bazel-discuss@googlegroups.com jika Anda memerlukan saran atau bantuan untuk memahami pengaruh transisi terhadap performa build.
Menentukan
Transisi menentukan perubahan konfigurasi di antara aturan. Misalnya, permintaan seperti "mengompilasi dependensi saya untuk CPU yang berbeda dengan induknya" ditangani oleh transisi.
Secara formal, transisi adalah fungsi dari konfigurasi input ke satu atau beberapa
konfigurasi output. Sebagian besar transisi berdurasi 1:1 seperti "ganti konfigurasi
input dengan --cpu=ppc
". Transisi 1:2+ juga dapat ada, tetapi
memiliki batasan khusus.
Di Starlark, transisi ditentukan seperti aturan, dengan fungsi transition()
yang menentukan dan fungsi implementasi.
# example/transitions/transitions.bzl
def _impl(settings, attr):
_ignore = (settings, attr)
return {"//example:favorite_flavor" : "MINT"}
hot_chocolate_transition = transition(
implementation = _impl,
inputs = [],
outputs = ["//example:favorite_flavor"]
)
Fungsi transition()
menggunakan fungsi implementasi, kumpulan setelan build untuk membaca(inputs
), dan kumpulan setelan build untuk menulis (outputs
). Fungsi implementasi memiliki dua parameter, settings
dan attr
. settings
adalah kamus {String
:Object
} dari semua setelan yang dideklarasikan
dalam parameter inputs
untuk transition()
.
attr
adalah kamus atribut dan nilai aturan tempat transisi dikaitkan. Saat dilampirkan sebagai
transisi edge keluar, nilai atribut
ini semuanya merupakan resolusi pasca-select() yang dikonfigurasi. Saat dilampirkan sebagai
transisi edge yang masuk, attr
tidak
menyertakan atribut apa pun yang menggunakan pemilih untuk me-resolve nilai. Jika
transisi edge yang masuk pada --foo
membaca atribut bar
, lalu juga
memilih pada --foo
untuk menetapkan atribut bar
, akan ada
transisi transisi yang masuk ke nilai yang salah dari bar
dalam transisi.
Fungsi implementasi harus menampilkan kamus (atau daftar
kamus, dalam kasus
transisi dengan beberapa konfigurasi output)
nilai setelan build baru yang akan diterapkan. Keyset kamus yang ditampilkan harus berisi kumpulan setelan build yang persis sama dengan yang diteruskan ke parameter outputs
fungsi transisi. Hal ini berlaku meskipun setelan build
tidak benar-benar berubah selama transisi - nilai aslinya harus
diteruskan secara eksplisit dalam kamus yang ditampilkan.
Menentukan transisi 1:2+
Transisi edge keluar dapat memetakan satu konfigurasi input ke dua atau beberapa konfigurasi output. Hal ini berguna untuk menentukan aturan yang menggabungkan kode multi-arsitektur.
Transisi 1:2+ ditentukan dengan menampilkan daftar kamus dalam fungsi implementasi transisi.
# example/transitions/transitions.bzl
def _impl(settings, attr):
_ignore = (settings, attr)
return [
{"//example:favorite_flavor" : "LATTE"},
{"//example:favorite_flavor" : "MOCHA"},
]
coffee_transition = transition(
implementation = _impl,
inputs = [],
outputs = ["//example:favorite_flavor"]
)
Aturan tersebut juga dapat menetapkan kunci kustom yang dapat digunakan oleh fungsi implementasi aturan untuk membaca dependensi masing-masing:
# example/transitions/transitions.bzl
def _impl(settings, attr):
_ignore = (settings, attr)
return {
"Apple deps": {"//command_line_option:cpu": "ppc"},
"Linux deps": {"//command_line_option:cpu": "x86"},
}
multi_arch_transition = transition(
implementation = _impl,
inputs = [],
outputs = ["//command_line_option:cpu"]
)
Melampirkan transisi
Transisi dapat dilampirkan di dua tempat: tepi masuk dan tepi keluar. Ini secara efektif berarti aturan dapat mentransisi konfigurasinya sendiri (transisi masuk masuk) dan mentransisikan konfigurasi dependensinya (transisi edge keluar).
CATATAN: Saat ini tidak ada cara untuk melampirkan transisi Starlark ke aturan native. Jika Anda perlu melakukannya, hubungi bazel-discuss@googlegroups.com untuk mendapatkan bantuan dalam mencari solusi.
Transisi edge yang masuk
Transisi edge yang masuk diaktifkan dengan melampirkan objek transition
(yang dibuat oleh transition()
) ke parameter cfg
rule()
:
# example/rules.bzl
load("example/transitions:transitions.bzl", "hot_chocolate_transition")
drink_rule = rule(
implementation = _impl,
cfg = hot_chocolate_transition,
...
Transisi tepi yang masuk harus berupa transisi 1:1.
Transisi edge keluar
Transisi edge keluar diaktifkan dengan melampirkan objek transition
(yang dibuat oleh transition()
) ke parameter cfg
atribut:
# example/rules.bzl
load("example/transitions:transitions.bzl", "coffee_transition")
drink_rule = rule(
implementation = _impl,
attrs = { "dep": attr.label(cfg = coffee_transition)}
...
Transisi tepi keluar dapat memiliki rasio 1:1 atau 1:2+.
Lihat Mengakses atribut dengan transisi untuk mengetahui cara membaca kunci ini.
Transisi pada opsi native
Transisi Starlark juga dapat mendeklarasikan operasi baca dan tulis pada opsi konfigurasi build native melalui awalan khusus pada nama opsi.
# example/transitions/transitions.bzl
def _impl(settings, attr):
_ignore = (settings, attr)
return {"//command_line_option:cpu": "k8"}
cpu_transition = transition(
implementation = _impl,
inputs = [],
outputs = ["//command_line_option:cpu"]
Opsi native tidak didukung
Bazel tidak mendukung transisi pada --define
dengan
"//command_line_option:define"
. Sebagai gantinya, gunakan setelan build kustom. Secara umum, penggunaan baru
--define
tidak disarankan demi setelan build.
Bazel tidak mendukung transisi pada --config
. Hal ini karena --config
adalah
flag "perluasan" yang diperluas ke flag lain.
Pada akhirnya, --config
dapat menyertakan tanda yang tidak memengaruhi konfigurasi build,
seperti
--spawn_strategy
. Bazel, pada dasarnya, tidak dapat mengikat flag tersebut ke setiap target. Ini berarti
tidak ada cara koheren untuk menerapkannya dalam transisi.
Sebagai solusinya, Anda dapat secara eksplisit memerinci flag yang adalah bagian dari konfigurasi dalam transisi Anda. Ini memerlukan mempertahankan perluasan
--config
di dua tempat, yang merupakan noda UI yang diketahui.
Transisi mengaktifkan beberapa setelan build
Saat menyetel setelan build yang mengizinkan beberapa nilai, nilai setelan harus ditetapkan dengan daftar.
# example/buildsettings/build_settings.bzl
string_flag = rule(
implementation = _impl,
build_setting = config.string(flag = True, allow_multiple = True)
)
# example/BUILD
load("//example/buildsettings:build_settings.bzl", "string_flag")
string_flag(name = "roasts", build_setting_default = "medium")
# example/transitions/rules.bzl
def _transition_impl(settings, attr):
# Using a value of just "dark" here will throw an error
return {"//example:roasts" : ["dark"]},
coffee_transition = transition(
implementation = _transition_impl,
inputs = [],
outputs = ["//example:roasts"]
)
Transisi tanpa pengoperasian
Jika transisi menampilkan {}
, []
, atau None
, ini adalah cara singkat untuk mempertahankan semua
setelan pada nilai aslinya. Ini bisa lebih mudah daripada menetapkan
setiap output ke dirinya sendiri secara eksplisit.
# example/transitions/transitions.bzl
def _impl(settings, attr):
_ignore = (attr)
if settings["//example:already_chosen"] is True:
return {}
return {
"//example:favorite_flavor": "dark chocolate",
"//example:include_marshmallows": "yes",
"//example:desired_temperature": "38C",
}
hot_chocolate_transition = transition(
implementation = _impl,
inputs = ["//example:already_chosen"],
outputs = [
"//example:favorite_flavor",
"//example:include_marshmallows",
"//example:desired_temperature",
]
)
Mengakses atribut dengan transisi
Saat melampirkan transisi ke tepi keluar
(terlepas dari apakah transisi adalah transisi 1:1 atau 1:2+), ctx.attr
dipaksa menjadi daftar
jika belum. Urutan elemen dalam daftar ini tidak ditentukan.
# example/transitions/rules.bzl
def _transition_impl(settings, attr):
return {"//example:favorite_flavor" : "LATTE"},
coffee_transition = transition(
implementation = _transition_impl,
inputs = [],
outputs = ["//example:favorite_flavor"]
)
def _rule_impl(ctx):
# Note: List access even though "dep" is not declared as list
transitioned_dep = ctx.attr.dep[0]
# Note: Access doesn't change, other_deps was already a list
for other_dep in ctx.attr.other_deps:
# ...
coffee_rule = rule(
implementation = _rule_impl,
attrs = {
"dep": attr.label(cfg = coffee_transition)
"other_deps": attr.label_list(cfg = coffee_transition)
})
Jika transisi adalah 1:2+
dan menetapkan kunci kustom, ctx.split_attr
dapat digunakan
untuk membaca dependensi individual untuk setiap kunci:
# example/transitions/rules.bzl
def _impl(settings, attr):
_ignore = (settings, attr)
return {
"Apple deps": {"//command_line_option:cpu": "ppc"},
"Linux deps": {"//command_line_option:cpu": "x86"},
}
multi_arch_transition = transition(
implementation = _impl,
inputs = [],
outputs = ["//command_line_option:cpu"]
)
def _rule_impl(ctx):
apple_dep = ctx.split_attr.dep["Apple deps"]
linux_dep = ctx.split_attr.dep["Linux deps"]
# ctx.attr has a list of all deps for all keys. Order is not guaranteed.
all_deps = ctx.attr.dep
multi_arch_rule = rule(
implementation = _rule_impl,
attrs = {
"dep": attr.label(cfg = multi_arch_transition)
})
Lihat contoh lengkap di sini.
Integrasi dengan platform dan toolchain
Banyak flag native saat ini, seperti --cpu
dan --crosstool_top
berkaitan dengan
resolusi toolchain. Di masa mendatang, transisi eksplisit pada jenis
flag ini kemungkinan akan diganti dengan melakukan transisi di
platform target.
Pertimbangan memori dan performa
Penambahan transisi, serta konfigurasi baru, ke build Anda dikenai biaya: grafik build yang lebih besar, grafik build yang kurang mudah dipahami, dan build yang lebih lambat. Sebaiknya pertimbangkan biaya ini saat mempertimbangkan penggunaan transisi dalam aturan build Anda. Di bawah ini adalah contoh bagaimana transisi dapat menghasilkan pertumbuhan eksponensial grafik build.
Build yang berperilaku buruk: studi kasus
Gambar 1. Grafik skalabilitas yang menampilkan target tingkat atas dan dependensinya.
Grafik ini menunjukkan target level teratas, //pkg:app
, yang bergantung pada dua target, //pkg:1_0
dan //pkg:1_1
. Kedua target ini bergantung pada dua target, //pkg:2_0
dan
//pkg:2_1
. Kedua target ini bergantung pada dua target, //pkg:3_0
dan //pkg:3_1
.
Hal ini berlanjut hingga //pkg:n_0
dan //pkg:n_1
, yang keduanya bergantung pada satu
target, //pkg:dep
.
Membuat //pkg:app
memerlukan \(2n+2\) target:
//pkg:app
//pkg:dep
//pkg:i_0
dan//pkg:i_1
untuk \(i\) di \([1..n]\)
Bayangkan Anda menerapkan flag
--//foo:owner=<STRING>
dan //pkg:i_b
berlaku
depConfig = myConfig + depConfig.owner="$(myConfig.owner)$(b)"
Dengan kata lain, //pkg:i_b
menambahkan b
ke nilai lama --owner
untuk semua
dependensinya.
Tindakan ini akan menghasilkan target yang dikonfigurasi berikut:
//pkg:app //foo:owner=""
//pkg:1_0 //foo:owner=""
//pkg:1_1 //foo:owner=""
//pkg:2_0 (via //pkg:1_0) //foo:owner="0"
//pkg:2_0 (via //pkg:1_1) //foo:owner="1"
//pkg:2_1 (via //pkg:1_0) //foo:owner="0"
//pkg:2_1 (via //pkg:1_1) //foo:owner="1"
//pkg:3_0 (via //pkg:1_0 → //pkg:2_0) //foo:owner="00"
//pkg:3_0 (via //pkg:1_0 → //pkg:2_1) //foo:owner="01"
//pkg:3_0 (via //pkg:1_1 → //pkg:2_0) //foo:owner="10"
//pkg:3_0 (via //pkg:1_1 → //pkg:2_1) //foo:owner="11"
...
//pkg:dep
menghasilkan \(2^n\) target yang dikonfigurasi: config.owner=
"\(b_0b_1...b_n\)" untuk semua \(b_i\) dalam \(\{0,1\}\).
Hal ini membuat grafik build secara eksponensial lebih besar dari grafik target, dengan konsekuensi memori dan performa yang sesuai.
TODO: Tambahkan strategi untuk pengukuran dan mitigasi masalah ini.
Bacaan lebih lanjut
Untuk detail selengkapnya tentang mengubah konfigurasi build, lihat:
- Konfigurasi Build Starlark
- Roadmap Konfigurasi Bazel
- Kumpulan lengkap contoh menyeluruh