Konfigurasi

Laporkan masalah Lihat sumber Per Malam · 7,3 · 7,2 · 7,1 · 7,0 · 6,5

Halaman ini membahas manfaat dan penggunaan dasar konfigurasi Starlark, API Bazel untuk menyesuaikan cara build project Anda. Panduan ini juga berisi cara menentukan setelan build dan memberikan contoh.

Hal ini memungkinkan Anda untuk:

  • menentukan penanda khusus untuk proyek Anda, sehingga penggunaan --define
  • tulis transitions 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 mem-build //my:android_app secara otomatis dengan SDK yang ditentukan)

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.

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 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

Contoh menyeluruh

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 dokumentasi modul config untuk mengetahui detailnya. Mengetik lebih rumit dapat dilakukan dalam fungsi implementasi aturan. Selengkapnya dapat dibaca di bawah.

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

Menggunakan ctx.build_setting_value

Seperti semua aturan, aturan setelan build memiliki fungsi implementasi. Nilai jenis Starlark dasar dari 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 langsung meneruskan nilai setelan build atau melakukan pekerjaan tambahan padanya, 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 tanda ditetapkan beberapa kali di command line atau di bazelrcs. 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 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 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

Contoh menyeluruh

Library Skylib menyertakan kumpulan setelan standar yang dapat Anda buat instance-nya tanpa harus menulis Starlark kustom.

Misalnya, untuk menentukan setelan yang menerima kumpulan 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 bagian informasi konfigurasi, target tersebut 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 menjadi dasar 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 pada baris perintah. Alias berfungsi mirip dengan tanda native dan juga dapat digunakan dari sintaks opsi garis putus-putus.

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 Anda dapat menetapkan alias di command line, membiarkannya di .bazelrc akan mengurangi kekacauan command line.

Setelan build berjenis label

Contoh menyeluruh

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

Contoh menyeluruh

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 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 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 ditentukan seperti aturan, dengan menentukan fungsi transition() 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. Saat dilampirkan sebagai transisi tepi keluar, nilai atribut ini semuanya dikonfigurasi resolusi pasca-select(). Saat dilampirkan sebagai transisi tepi 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 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 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+

Contoh menyeluruh

Transisi tepi keluar dapat memetakan satu input konfigurasinya ke dua atau lebih konfigurasi {i>output<i}. Hal ini berguna untuk menentukan aturan yang memaketkan 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

Contoh menyeluruh

Transisi dapat dilampirkan 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 melakukannya, 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 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 menyeluruh

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 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 flag "ekspansi" yang diperluas ke flag lain.

Yang terpenting, --config dapat menyertakan flag yang tidak memengaruhi konfigurasi build, seperti --spawn_strategy kami. Bazel, secara desain, tidak dapat mengikat flag tersebut ke setiap target. Artinya tidak ada cara yang koheren untuk menerapkannya dalam transisi.

Sebagai solusi, Anda dapat mencantumkan flag yang merupakan bagian dari konfigurasi dalam transisi secara eksplisit. 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 mempertahankan semua setelan pada 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

Contoh menyeluruh

Saat melampirkan transisi ke tepi keluar (terlepas dari apakah transisi tersebut 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 dependensi 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

Saat ini, banyak flag native, seperti --cpu dan --crosstool_top, terkait 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. 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

Grafik skalabilitas

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. 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\) 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 dep-nya.

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\) di \(\{0,1\}\).

Hal ini membuat grafik build secara eksponensial 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 detail selengkapnya tentang memodifikasi konfigurasi build, lihat: