Halaman ini membahas manfaat dan penggunaan dasar konfigurasi Starlark, API Bazel untuk menyesuaikan cara project Anda dibangun. Panduan ini juga berisi cara menentukan setelan build dan memberikan contoh.
Hal ini memungkinkan untuk:
- menentukan penanda khusus untuk proyek Anda, sehingga penggunaan
--define
- tulis
transisi untuk mengonfigurasi dependensi di
konfigurasi yang berbeda dari induknya
(seperti
--compilation_mode=opt
atau--cpu=arm
) - memasukkan default yang lebih baik ke dalam aturan (seperti membangun
//my:android_app
secara otomatis dengan SDK tertentu)
dan banyak lagi, semuanya berasal dari file .bzl (tidak perlu rilis Bazel). Lihat
bazelbuild/examples
repo untuk
contoh.
Setelan build yang ditentukan pengguna
Setelan build adalah satu bagian dari
konfigurasi
tidak akurat atau tidak sesuai. Bayangkan konfigurasi sebagai peta kunci/nilai. Menyetel --cpu=ppc
dan --copt="-DFoo"
menghasilkan konfigurasi yang terlihat seperti
{cpu: ppc, copt: "-DFoo"}
. Setiap entri adalah setelan build.
Tanda tradisional seperti cpu
dan copt
adalah setelan native —
kunci mereka ditentukan dan nilainya
diatur dalam kode java bazel asli.
Pengguna Bazel hanya dapat membaca dan menulisnya melalui baris perintah
dan API lainnya dipelihara secara native. Mengubah tanda native dan API
yang mengeksposnya, diperlukan pelepasan bazel. Build yang ditentukan pengguna
setelan ditentukan dalam file .bzl
(sehingga, tidak memerlukan rilis bazel untuk
mendaftarkan perubahan). Mereka juga dapat diatur melalui baris perintah
(jika ditetapkan sebagai flags
, lihat selengkapnya di bawah), tetapi juga dapat berupa
disetel melalui transisi yang ditentukan pengguna.
Menentukan setelan build
Parameter build_setting
rule()
Setelan pembangunan adalah aturan seperti aturan lainnya dan dibedakan menggunakan
build_setting
fungsi rule()
Starlark
atribut.
# 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. Tipe ini terbatas pada serangkaian
tipe Starlark dasar seperti
bool
dan string
. Lihat modul config
dokumentasi untuk mengetahui detailnya. Mengetik lebih rumit dapat
dilakukan dalam fungsi implementasi aturan. Informasi selengkapnya dapat dibaca di bawah.
Fungsi modul config
mengambil parameter boolean opsional, flag
,
yang diatur ke false secara {i>default<i}. jika flag
disetel ke benar (true), setelan build
dapat diatur di command line oleh pengguna serta secara internal oleh penulis aturan
melalui nilai default dan transisi.
Tidak semua setelan dapat disetel oleh pengguna. Misalnya, jika Anda seorang aturan
{i>writer<i} memiliki beberapa mode {i>debug<i} yang
ingin Anda aktifkan di dalam aturan pengujian,
Anda tidak ingin memberikan pengguna
kemampuan untuk mengaktifkan
fitur di dalam aturan non-pengujian lainnya.
Menggunakan ctx.build_setting_value
Seperti semua aturan, aturan setelan build memiliki fungsi implementasi.
Nilai dasar tipe Starlark dari pengaturan build bisa diakses melalui
Metode ctx.build_setting_value
. Metode ini hanya tersedia untuk
Objek ctx
dari aturan setelan build. Implementasi ini
dapat langsung meneruskan nilai setelan build atau melakukan pekerjaan tambahan pada
itu, seperti pemeriksaan jenis atau
pembuatan struct yang lebih kompleks. Berikut adalah cara Anda
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 multiset
Setelan string memiliki parameter allow_multiple
tambahan yang memungkinkan
penanda diatur beberapa kali pada
baris perintah atau di {i>bazelrc<i}. Defaultnya
nilai masih ditetapkan dengan atribut bertipe 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 tanda 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 aturan wajib implisit
Atribut build_setting_default
. Atribut ini menggunakan
tipe 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
Tujuan Skylib mencakup serangkaian setelan yang telah ditentukan yang dapat Anda buat instance-nya tanpa harus untuk 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 daftar lengkapnya, lihat Aturan setelan build umum.
Menggunakan setelan build
Bergantung pada setelan build
Jika target ingin membaca informasi konfigurasi, ia bisa secara 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 semua aturan
yang bergantung pada 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 pada command line
Mirip dengan sebagian besar flag native, Anda dapat menggunakan command line untuk menetapkan setelan build
yang ditandai sebagai tanda. Build
nama setelan adalah jalur target lengkap yang 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 pada baris perintah. Alias berfungsi mirip dengan tanda native dan juga dapat digunakan sintaks opsi {i>double-dash<i}.
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 versi terbaru salah satunya akan diprioritaskan. Gunakan nama alias yang unik untuk menghindari hasil penguraian yang tidak diinginkan.
Untuk menggunakan alias, ketik alias di tempat jalur target setelan build.
Dengan contoh coffee
di atas yang ditetapkan dalam .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 memungkinkan untuk menetapkan alias pada command line, membiarkannya
di .bazelrc
akan mengurangi kekacauan command line.
Setelan build berjenis label
Tidak seperti pengaturan build lainnya, pengaturan bertipe label tidak bisa ditentukan menggunakan
Parameter aturan build_setting
. Sebagai gantinya, bazel memiliki dua aturan bawaan:
label_flag
dan label_setting
. Aturan ini akan meneruskan penyedia
target aktual tempat setelan build ditetapkan. label_flag
dan
label_setting
dapat dibaca/ditulis oleh transisi dan label_flag
dapat disetel
oleh pengguna seperti yang bisa dilakukan oleh aturan build_setting
lainnya. Satu-satunya perbedaan adalah
tidak dapat ditentukan
secara khusus.
Setelan berjenis label pada akhirnya akan menggantikan fungsi batas akhir
secara default. Atribut default yang terlambat adalah atribut berjenis Label yang
nilai akhir dapat
terpengaruh oleh konfigurasi. Di Starlark, ini akan menggantikan
configuration_field
Compute Engine 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"
)
Membuat setelan 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 dicocokkan dengan konfigurasi akan diteruskan sebagai
String
kemudian diuraikan ke jenis setelan build untuk pencocokan.
config_setting(
name = "my_config",
flag_values = {
"//example:favorite_flavor": "MANGO"
}
)
Transisi yang ditentukan pengguna
Konfigurasi transisi memetakan transformasi dari satu target yang dikonfigurasi ke target lainnya dalam membuat 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 bisa dengan mudah meledakkan ukuran grafik build Anda. Ini akan menetapkan daftar yang diizinkan pada paket yang dapat Anda membuat target dari aturan ini. Nilai default dalam blok kode di atas mengizinkan semuanya. Namun, jika ingin membatasi siapa yang menggunakan aturan Anda, Anda dapat menetapkan atribut tersebut agar mengarah ke daftar yang diizinkan kustom Anda sendiri. Hubungi bazel-discuss@googlegroups.com jika butuh saran atau bantuan memahami bagaimana transisi bisa memengaruhi performa build Anda.
Mendefinisikan
Transisi menentukan perubahan konfigurasi di antara aturan. Misalnya, sebuah permintaan seperti "mengompilasi dependensi saya untuk CPU yang berbeda dari induknya" ditangani oleh transisi.
Secara formal, transisi adalah fungsi dari konfigurasi input ke satu atau lebih
konfigurasi output. Sebagian besar transisi bersifat 1:1, seperti "mengganti input
konfigurasi dengan --cpu=ppc
". Transisi 1:2+ juga bisa ada, tetapi
dengan batasan khusus.
Di Starlark, transisi didefinisikan mirip
seperti aturan, dengan memberi
transition()
fungsi
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, yaitu kumpulan
setelan build untuk membaca(inputs
), dan serangkaian 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
menjadi transition()
.
attr
adalah kamus atribut dan nilai dari aturan yang
transisi dilampirkan. Jika dilampirkan sebagai
transisi edge keluar, nilai parameter ini
semua atribut adalah resolusi
post-select() yang dikonfigurasi. Saat dilampirkan sebagai
transisi edge masuk, attr
tidak
menyertakan atribut apa pun yang menggunakan pemilih untuk me-resolve nilainya. Jika
transisi edge yang masuk di --foo
membaca atribut bar
dan juga
memilih pada --foo
untuk menetapkan atribut bar
, maka ada kemungkinan
transisi edge yang masuk untuk membaca nilai bar
yang salah dalam transisi.
Fungsi implementasi harus mengembalikan kamus (atau daftar
kamus, dalam kasus
transisi dengan beberapa konfigurasi output)
nilai setelan build baru untuk diterapkan. Keyset kamus yang ditampilkan harus
berisi set setelan build yang diteruskan ke outputs
fungsi transisi. Hal ini tetap berlaku meskipun setelan build adalah
tidak benar-benar berubah selama transisi - nilai aslinya harus
secara eksplisit diteruskan melalui kamus yang ditampilkan.
Menentukan transisi 1:2+
Transisi tepi keluar dapat memetakan satu input konfigurasinya ke dua atau lebih konfigurasi {i>output<i}. Cara ini berguna untuk mendefinisikan aturan yang menggabungkan kode multi-arsitektur.
Transisi 1:2+ didefinisikan dengan mengembalikan daftar kamus di 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"]
)
Mereka juga dapat menetapkan kunci khusus yang dapat digunakan fungsi penerapan aturan untuk membaca dependensi individual:
# 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 dipasang di dua tempat: tepi masuk dan tepi keluar. Secara efektif, ini berarti aturan dapat mentransisikan konfigurasinya sendiri (masuk transisi edge) dan mentransisikan dependensi mereka konfigurasi (keluar transisi edge).
CATATAN: Saat ini tidak ada cara untuk melampirkan transisi Starlark ke aturan native. Jika Anda perlu melakukan ini, hubungi bazel-discuss@googlegroups.com untuk mendapatkan bantuan dalam mencari solusi.
Transisi edge masuk
Transisi edge yang masuk diaktifkan dengan menambahkan objek transition
(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 edge yang masuk harus berupa transisi 1:1.
Transisi edge keluar
Transisi edge keluar diaktifkan dengan menambahkan objek transition
(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 edge keluar dapat berupa 1:1 atau 1:2+.
Lihat Mengakses atribut dengan transisi untuk mengetahui cara membaca kunci-kunci ini.
Transisi pada opsi native
Transisi Starlark juga bisa mendeklarasikan pembacaan dan penulisan pada build native opsi konfigurasi melalui awalan khusus ke 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 yang tidak didukung
Bazel tidak mendukung transisi di --define
dengan
"//command_line_option:define"
. Sebagai gantinya, gunakan
setelan build. Secara umum, penggunaan baru
--define
tidak disarankan dan akan digantikan dengan setelan build.
Bazel tidak mendukung transisi di --config
. Hal ini karena --config
adalah
sebuah "perluasan" penanda yang diperluas ke penanda lain.
Yang terpenting, --config
dapat menyertakan flag yang tidak memengaruhi konfigurasi build,
seperti
--spawn_strategy
kami. Bazel, berdasarkan desainnya, tidak dapat mengikat tanda seperti itu dengan setiap target. Artinya
tidak ada cara yang koheren untuk
menerapkannya dalam transisi.
Sebagai solusinya, Anda dapat secara eksplisit memerinci tanda yang merupakan bagian dari
konfigurasi dalam transisi Anda. Hal ini mengharuskan Anda mempertahankan--config
perluasan di dua tempat, yang merupakan noda UI.
Transisi pada mengizinkan beberapa setelan build
Saat mengatur pengaturan build yang allow multiple values, yaitu nilai 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 singkatan untuk menyimpan semua
{i>setting<i} ke nilai aslinya. Ini bisa lebih mudah
daripada secara eksplisit
mengatur setiap {i>output<i} ke dirinya sendiri.
# 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 edge keluar
(terlepas dari apakah transisinya merupakan transisi 1:1 atau 1:2+), ctx.attr
terpaksa 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 transisinya 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 tanda native saat ini, seperti --cpu
dan --crosstool_top
dikaitkan dengan
resolusi toolchain. Di masa mendatang, transisi eksplisit pada jenis
penanda kemungkinan akan diganti dengan transisi pada
platform target.
Pertimbangan memori dan performa
Menambahkan transisi, dan juga konfigurasi baru, ke build Anda dilakukan dengan biaya: grafik build lebih besar, grafik build yang kurang mudah dipahami, dan lebih lambat build yang berbeda. Ada baiknya Anda mempertimbangkan biaya-biaya ini saat menggunakan transisi dalam aturan build. Di bawah ini adalah contoh bagaimana transisi dapat menghasilkan pertumbuhan eksponensial grafik build.
Build yang berperilaku buruk: studi kasus
Gambar 1. Grafik skalabilitas yang menunjukkan target tingkat atas dan dependensinya.
Grafik ini menunjukkan target tingkat 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
.
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\) dalam \([1..n]\)
Bayangkan Anda menerapkan sebuah 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 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 terkait.
TODO: Tambahkan strategi untuk pengukuran dan mitigasi masalah ini.
Bacaan lebih lanjut
Untuk detail selengkapnya tentang memodifikasi konfigurasi build, lihat:
- Konfigurasi Build Starlark
- Roadmap Konfigurasi Bazel
- Kumpulan lengkap contoh menyeluruh