Konfigurasi

Laporkan masalah Lihat sumber Nightly · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

Halaman ini membahas manfaat dan penggunaan dasar konfigurasi Starlark, API Bazel untuk menyesuaikan cara project Anda dibangun. Bagian ini mencakup cara menentukan setelan build dan memberikan contoh.

Hal ini memungkinkan Anda untuk:

  • menentukan flag kustom untuk project Anda, sehingga tidak perlu menggunakan --define
  • menulis transisi untuk mengonfigurasi dependensi dalam konfigurasi yang berbeda dari induknya (seperti --compilation_mode=opt atau --cpu=arm)
  • membuat default yang lebih baik ke dalam aturan (seperti membuat //my:android_app secara otomatis dengan SDK tertentu)

dan lainnya, semuanya sepenuhnya dari file .bzl (tidak memerlukan rilis Bazel). Lihat repo bazelbuild/examples untuk contoh.

Setelan build yang ditentukan pengguna

Setelan build adalah satu bagian informasi konfigurasi. Anggap konfigurasi sebagai peta kunci/nilai. Menetapkan --cpu=ppc dan --copt="-DFoo" menghasilkan konfigurasi yang terlihat seperti {cpu: ppc, copt: "-DFoo"}. Setiap entri adalah 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 menulisnya 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 (dan dengan demikian, tidak memerlukan rilis bazel untuk mendaftarkan perubahan). Setelan 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

Contoh end-to-end

Parameter build_setting rule()

Setelan build adalah aturan seperti aturan lainnya dan dibedakan menggunakan atribut build_setting fungsi Starlark rule().

# example/buildsettings/build_settings.bzl
string_flag = rule(
    implementation = _impl,
    build_setting = config.string(flag = True)
)

Atribut build_setting mengambil fungsi yang menentukan jenis setelan build. Jenisnya terbatas pada serangkaian jenis Starlark dasar seperti bool dan string. Lihat configmodul dokumentasi untuk mengetahui detailnya. Pengetikan yang lebih rumit dapat dilakukan dalam fungsi penerapan aturan. Informasi selengkapnya dapat dibaca di bawah.

Fungsi modul config menggunakan parameter boolean opsional, flag, yang disetel ke false secara default. Jika flag disetel ke true, setelan build dapat ditetapkan di command line oleh pengguna serta secara internal oleh penulis aturan melalui nilai default dan transisi. Tidak semua setelan harus dapat ditetapkan oleh pengguna. Misalnya, jika Anda sebagai penulis aturan memiliki beberapa mode debug yang ingin diaktifkan dalam aturan pengujian, Anda tidak ingin memberi pengguna kemampuan untuk mengaktifkan fitur tersebut secara sembarangan dalam aturan non-pengujian lainnya.

Menggunakan ctx.build_setting_value

Seperti semua aturan, aturan setelan build memiliki fungsi penerapan. Nilai jenis Starlark dasar setelan build dapat diakses melalui metode ctx.build_setting_value. Metode ini hanya tersedia untuk objek ctx dari aturan setelan build. Metode penerapan ini dapat meneruskan nilai setelan build secara langsung atau melakukan pekerjaan tambahan, seperti pemeriksaan jenis atau pembuatan struktur yang lebih kompleks. Berikut cara menerapkan 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 di command line atau di bazelrc. 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 tanda diperlakukan sebagai satu nilai:

$ bazel build //my/target --//example:roasts=blonde \
    --//example:roasts=medium,dark

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 diisi secara implisit. Atribut ini memiliki 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 yang telah ditentukan sebelumnya

Contoh end-to-end

Library Skylib menyertakan serangkaian setelan yang telah ditentukan sebelumnya yang dapat Anda buat 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 daftar lengkap, lihat Aturan setelan build umum.

Menggunakan setelan build

Bergantung pada setelan build

Jika target ingin membaca informasi konfigurasi, target dapat bergantung langsung 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 setelan build kanonis yang menjadi dasar semua aturan untuk bahasa tersebut. Meskipun konsep fragments native tidak lagi ada sebagai objek yang dikodekan secara permanen di dunia konfigurasi Starlark, salah satu cara untuk menerjemahkan konsep ini adalah dengan menggunakan set 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

Mirip 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

Sintaks 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 tanda bawaan dan juga menggunakan sintaksis opsi tanda hubung ganda.

Tetapkan alias dengan menambahkan --flag_alias=ALIAS_NAME=TARGET_PATH ke .bazelrc Anda . 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 membuat alias yang terakhir ditetapkan menjadi yang diprioritaskan. Gunakan nama alias unik untuk menghindari hasil parsing yang tidak diinginkan.

Untuk menggunakan alias, ketik alias tersebut di tempat 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 alias dapat ditetapkan di command line, membiarkannya dalam .bazelrc akan mengurangi kekacauan command line.

Setelan build berjenis label

Contoh end-to-end

Tidak seperti setelan build lainnya, setelan berjenis label tidak dapat ditentukan menggunakan parameter aturan build_setting. Sebagai gantinya, bazel memiliki dua aturan bawaan: label_flag dan label_setting. Aturan ini meneruskan penyedia target sebenarnya yang ditetapkan setelan build-nya. label_flag dan label_setting dapat dibaca/ditulis oleh transisi dan label_flag dapat ditetapkan oleh pengguna seperti aturan build_setting lainnya. Satu-satunya perbedaan adalah keduanya tidak dapat ditentukan secara kustom.

Setelan berjenis label pada akhirnya akan menggantikan fungsi default yang terikat terlambat (late-bound). Atribut default yang terikat terlambat adalah atribut berjenis Label yang nilai akhirnya dapat dipengaruhi oleh konfigurasi. Di Starlark, hal ini akan menggantikan API configuration_field.

# 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()

Contoh end-to-end

Pengguna dapat mengonfigurasi atribut pada setelan build menggunakan select(). Target setelan build dapat diteruskan ke atribut flag_values dari config_setting. Nilai yang cocok 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 lain dalam grafik build.

Aturan yang menyetelnya harus menyertakan atribut khusus:

  "_allowlist_function_transition": attr.label(
      default = "@bazel_tools//tools/allowlists/function_transition_allowlist"
  )

Dengan menambahkan transisi, Anda dapat dengan mudah memperbesar ukuran grafik build. Setelan ini menetapkan daftar yang diizinkan pada paket tempat Anda dapat membuat target aturan ini. Nilai default dalam blok kode di atas mengizinkan semuanya. Namun, jika Anda ingin membatasi siapa yang menggunakan aturan Anda, Anda dapat menetapkan atribut tersebut untuk mengarah ke daftar yang diizinkan kustom Anda sendiri. Hubungi bazel-discuss@googlegroups.com jika Anda ingin mendapatkan saran atau bantuan untuk memahami pengaruh transisi terhadap performa build Anda.

Mendefinisikan

Transisi menentukan perubahan konfigurasi antar-aturan. Misalnya, permintaan seperti "kompilasi 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 adalah 1:1 seperti "mengganti konfigurasi input dengan --cpu=ppc". Transisi 1:2+ juga dapat terjadi, tetapi disertai batasan khusus.

Di Starlark, transisi ditentukan seperti aturan, dengan transition() fungsi yang menentukan dan fungsi penerapan.

# 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() mengambil fungsi penerapan, serangkaian setelan build untuk dibaca(inputs), dan serangkaian setelan build untuk ditulis (outputs). Fungsi penerapan memiliki dua parameter, settings dan attr. settings adalah kamus {String:Object} dari semua setelan yang dideklarasikan dalam parameter inputs ke transition().

attr adalah kamus atribut dan nilai aturan yang terlampir pada transisi. Saat dilampirkan sebagai transisi tepi keluar, nilai atribut ini semuanya dikonfigurasi setelah resolusi select(). Saat dilampirkan sebagai transisi tepi masuk, attr tidak mencakup atribut apa pun yang menggunakan pemilih untuk menyelesaikan nilainya. Jika transisi tepi masuk pada --foo membaca atribut bar, lalu juga memilih --foo untuk menetapkan atribut bar, ada kemungkinan transisi tepi masuk membaca nilai bar yang salah dalam transisi.

Fungsi penerapan harus menampilkan kamus (atau daftar kamus, dalam kasus transisi dengan beberapa konfigurasi output) nilai setelan build baru yang akan diterapkan. Kumpulan kunci kamus yang ditampilkan harus berisi persis kumpulan setelan build yang diteruskan ke parameter outputs dari 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+

Contoh end-to-end

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 penerapan 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 kustom yang dapat digunakan oleh fungsi penerapan aturan untuk membaca setiap dependensi:

# 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

Contoh end-to-end

Transisi dapat dilampirkan di dua tempat: tepi masuk dan tepi keluar. Artinya, aturan dapat melakukan transisi konfigurasi mereka sendiri (transisi edge masuk) dan melakukan transisi 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 alternatif.

Transisi tepi masuk

Transisi tepi masuk diaktifkan dengan melampirkan 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 tepi masuk harus berupa transisi 1:1.

Transisi tepi keluar

Transisi tepi keluar diaktifkan dengan melampirkan 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 tepi keluar dapat berupa 1:1 atau 1:2+.

Lihat Mengakses atribut dengan transisi untuk mengetahui cara membaca kunci ini.

Transisi pada opsi native

Contoh end-to-end

Transisi Starlark juga dapat mendeklarasikan pembacaan dan penulisan pada opsi konfigurasi build native melalui awalan khusus untuk 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 kustom. Secara umum, penggunaan --define baru tidak dianjurkan dan lebih baik menggunakan setelan build.

Bazel tidak mendukung transisi di --config. Hal ini karena --config adalah tanda "perluasan" yang diperluas ke tanda lain.

Yang penting, --config dapat menyertakan tanda yang tidak memengaruhi konfigurasi build, seperti --spawn_strategy . Secara desain, Bazel tidak dapat mengikat flag tersebut ke target individual. Artinya, tidak ada cara yang koheren untuk menerapkannya dalam transisi.

Sebagai solusi sementara, Anda dapat mencantumkan secara eksplisit flag yang merupakan bagian dari konfigurasi dalam transisi Anda. Hal ini mengharuskan mempertahankan perluasan --config di dua tempat, yang merupakan masalah UI yang diketahui.

Transisi pada memungkinkan 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 singkatan untuk mempertahankan semua setelan pada nilai aslinya. Hal 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

Contoh end-to-end

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 setiap deps 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 bawaan saat ini, seperti --cpu dan --crosstool_top, terkait dengan penyelesaian toolchain. Pada masa mendatang, transisi eksplisit pada jenis tanda ini kemungkinan akan digantikan dengan transisi pada platform target.

Pertimbangan memori dan performa

Menambahkan transisi, dan oleh karena itu konfigurasi baru, ke build Anda akan menimbulkan 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 menciptakan pertumbuhan eksponensial pada grafik build Anda.

Build yang berperilaku buruk: studi kasus

Grafik skalabilitas

Gambar 1. Grafik skalabilitas yang menampilkan target tingkat teratas 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. Proses ini berlanjut hingga //pkg:n_0 dan //pkg:n_1, yang keduanya bergantung pada satu target, //pkg:dep.

Membangun //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 target yang \(2^n\) dikonfigurasi: config.owner= "\(b_0b_1...b_n\)" untuk semua \(b_i\) di \(\{0,1\}\).

Hal ini membuat grafik build jauh lebih besar daripada grafik target, dengan konsekuensi memori dan performa yang sesuai.

TODO: Tambahkan strategi untuk pengukuran dan mitigasi masalah ini.

Bacaan lebih lanjut

Untuk mengetahui detail selengkapnya tentang cara mengubah konfigurasi build, lihat: