Bu sayfada, projenizin oluşturma şeklini özelleştirmek için Bazel'ın API'si olan Starlark yapılandırmalarının avantajları ve temel kullanımları ele alınmaktadır. Derleme ayarlarının nasıl tanımlanacağını içerir ve örnekler sağlar.
Bu sayede:
- Projeniz için özel işaretler tanımlayabilirsiniz. Böylece
--define
- Bağımlılıkları, üst öğelerinden farklı yapılandırmalarda (
--compilation_mode=opt
veya--cpu=arm
gibi) yapılandırmak için geçişler yazma - Kurallara daha iyi varsayılan değerler ekleme (ör. belirli bir SDK ile
//my:android_app
otomatik olarak derleme)
ve daha fazlasını tamamen .bzl dosyalarından (Bazel sürümü gerekmez) oluşturabilirsiniz. Örnekler için bazelbuild/examples
deposuna bakın.
Kullanıcı tanımlı derleme ayarları
Derleme ayarı, tek bir yapılandırma bilgisidir. Yapılandırmayı bir anahtar/değer eşlemesi olarak düşünün. --cpu=ppc
ve --copt="-DFoo"
ayarlandığında {cpu: ppc, copt: "-DFoo"}
gibi görünen bir yapılandırma oluşturulur. Her giriş bir derleme ayarıdır.
cpu
ve copt
gibi geleneksel işaretler yerel ayarlardır. Anahtarları tanımlanır ve değerleri yerel bazel java kodu içinde ayarlanır.
Bazı kullanıcılar bu dosyaları yalnızca komut satırı ve yerel olarak yönetilen diğer API'ler aracılığıyla okuyabilir ve yazabilir. Yerel işaretleri ve bunları gösteren API'leri değiştirmek için bazel sürümü gerekir. Kullanıcı tanımlı derleme ayarları .bzl
dosyalarında tanımlanır (bu nedenle, değişiklikleri kaydetmek için bazel sürümüne gerek yoktur). Bu değerler komut satırı üzerinden de ayarlanabilir (flags
olarak belirlenmişse daha fazla bilgi için aşağıya bakın). Ayrıca kullanıcı tanımlı geçişler aracılığıyla da ayarlanabilir.
Derleme ayarlarını tanımlama
build_setting
rule()
parametresi
Derleme ayarları, diğer kurallar gibi kurallardır ve Starlark rule()
işlevinin build_setting
özelliği kullanılarak ayırt edilir.
# example/buildsettings/build_settings.bzl
string_flag = rule(
implementation = _impl,
build_setting = config.string(flag = True)
)
build_setting
özelliği, derleme ayarının türünü belirten bir işlev alır. Tür, bool
ve string
gibi temel Starlark türleriyle sınırlıdır. Ayrıntılar için config
modülü dokümanlarına bakın. Kuralın uygulama işlevinde daha karmaşık yazma işlemleri yapılabilir. Bu konu hakkında daha fazla bilgiyi aşağıda bulabilirsiniz.
config
modülünün işlevleri, varsayılan olarak yanlış olarak ayarlanmış isteğe bağlı bir boole parametresi olan flag
parametresini alır. flag
doğru olarak ayarlanırsa derleme ayarı, varsayılan değerler ve geçişler aracılığıyla hem kullanıcılar tarafından komut satırında hem de kural yazarları tarafından dahili olarak ayarlanabilir.
Tüm ayarlar kullanıcılar tarafından değiştirilemez. Örneğin, kural yazarı olarak test kurallarında etkinleştirmek istediğiniz bir hata ayıklama modunuz varsa kullanıcılara bu özelliği test dışı diğer kurallarda da etkinleştirme olanağı vermek istemezsiniz.
ctx.build_setting_value değerini kullanma
Tüm kurallar gibi derleme ayarı kuralları da uygulama işlevlerine sahiptir.
Derleme ayarlarının temel Starlark türündeki değerine ctx.build_setting_value
yöntemi aracılığıyla erişilebilir. Bu yöntem yalnızca derleme ayarı kurallarının ctx
nesneleri tarafından kullanılabilir. Bu uygulama yöntemleri, derleme ayarları değerini doğrudan yönlendirebilir veya tür denetimi ya da daha karmaşık struct oluşturma gibi işlemler üzerinde ek işler yapabilir. enum
türündeki bir derleme ayarını nasıl uygulayacağınız aşağıda açıklanmıştır:
# 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)
)
Çok kümeli dize işaretlerini tanımlama
Dize ayarlarında, işaretin komut satırında veya bazelrcs'de birden çok kez ayarlanmasına olanak tanıyan ek bir allow_multiple
parametresi bulunur. Bunların varsayılan değeri hâlâ dize türünde bir özellikle ayarlanır:
# example/buildsettings/build_settings.bzl
allow_multiple_flag = rule(
implementation = _impl,
build_setting = config.string(flag = True, allow_multiple = True)
)
# example/buildsettings/BUILD
load("//example/buildsettings:build_settings.bzl", "allow_multiple_flag")
allow_multiple_flag(
name = "roasts",
build_setting_default = "medium"
)
İşaretin her ayarı tek bir değer olarak ele alınır:
$ bazel build //my/target --//example:roasts=blonde \
--//example:roasts=medium,dark
Yukarıdaki değer {"//example:roasts": ["blonde", "medium,dark"]}
olarak ayrıştırılır ve ctx.build_setting_value
, ["blonde", "medium,dark"]
listesini döndürür.
Derleme ayarlarını örneklendirme
build_setting
parametresiyle tanımlanan kurallarda, zorunlu build_setting_default
özelliği varsayılan olarak bulunur. Bu özellik, build_setting
parametresi tarafından belirtilenle aynı türdedir.
# 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/buildsettings/BUILD
load("//example/buildsettings:build_settings.bzl", "flavor")
flavor(
name = "favorite_flavor",
build_setting_default = "APPLE"
)
Önceden tanımlanmış ayarlar
Skylib kitaplığı, özel Starlark yazmak zorunda kalmadan örneklendirebileceğiniz önceden tanımlanmış bir dizi ayar içerir.
Örneğin, sınırlı sayıda dize değeri kabul eden bir ayar tanımlamak için:
# example/BUILD
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
string_flag(
name = "myflag",
values = ["a", "b", "c"],
build_setting_default = "a",
)
Tam liste için Ortak derleme ayarı kuralları başlıklı makaleyi inceleyin.
Derleme ayarlarını kullanma
Derleme ayarlarına bağlı olarak
Bir hedef, yapılandırma bilgilerini okumak istiyorsa normal bir özellik bağımlılığı aracılığıyla doğrudan derleme ayarına bağlı olabilir.
# 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",
)
Diller, tüm kuralların bağlı olduğu standart bir derleme ayarları grubu oluşturmak isteyebilir. fragments
doğal kavramı artık Starlark yapılandırma dünyasında kodlanmış bir nesne olarak mevcut olmasa da bu kavramı çevirmenin bir yolu, ortak gizli özellik kümeleri kullanmaktır. Örneğin:
# 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)
Komut satırında derleme ayarlarını kullanma
Çoğu yerel işarete benzer şekilde, bayrak olarak işaretlenen derleme ayarlarını belirlemek için komut satırını kullanabilirsiniz. Derleme ayarının adı, name=value
söz dizimini kullanan tam hedef yoludur:
$ bazel build //my/target --//example:string_flag=some-value # allowed
$ bazel build //my/target --//example:string_flag some-value # not allowed
Özel boole söz dizimi desteklenir:
$ bazel build //my/target --//example:boolean_flag
$ bazel build //my/target --no//example:boolean_flag
Derleme ayarı takma adlarını kullanma
Derleme ayarı hedef yolunuz için bir takma ad belirleyerek komut satırında okumayı kolaylaştırabilirsiniz. Takma adlar, yerel işaretlere benzer şekilde çalışır ve çift kısa çizgi seçeneği söz diziminden de yararlanır.
.bazelrc
alanına --flag_alias=ALIAS_NAME=TARGET_PATH
ekleyerek bir takma ad belirleyin . Örneğin, coffee
için bir takma ad ayarlamak istiyorsanız:
# .bazelrc
build --flag_alias=coffee=//experimental/user/starlark_configurations/basic_build_setting:coffee-temp
En İyi Uygulama: Bir takma adın birden fazla kez ayarlanması, en yeni takma ada öncelik verilmesini sağlar. İstenmeyen ayrıştırma sonuçlarını önlemek için benzersiz takma adlar kullanın.
Takma adı kullanmak için derleme ayarı hedef yolu yerine bu adı yazın.
Kullanıcının .bazelrc
ayarlarında yukarıdaki coffee
örneğini kullanarak:
$ bazel build //my/target --coffee=ICED
yerine
$ bazel build //my/target --//experimental/user/starlark_configurations/basic_build_setting:coffee-temp=ICED
En iyi uygulama: Komut satırında takma ad ayarlamak mümkün olsa da bunları .bazelrc
içinde bırakmak komut satırındaki dağınıklığı azaltır.
Etiket türünde derleme ayarları
Diğer derleme ayarlarının aksine, etiket türündeki ayarlar build_setting
kural parametresi kullanılarak tanımlanamaz. Bunun yerine bazel'de iki yerleşik kural vardır:
label_flag
ve label_setting
. Bu kurallar, derleme ayarının ayarlandığı gerçek hedefin sağlayıcılarını yönlendirir. label_flag
ve label_setting
, geçişler tarafından okunabilir/yazılabilir ve label_flag
, diğer build_setting
kuralları gibi kullanıcı tarafından ayarlanabilir. Tek farkları, özel olarak
tanımlanamayacaklarıdır.
Etiket türündeki ayarlar, geç bağlanmış varsayılanların işlevini zaman içinde değiştirecektir. Geç bağlanan varsayılan özellikler, nihai değerleri yapılandırmadan etkilenebilen etiket türündeki özelliklerdir. Starlark'ta bu, configuration_field
API'nin yerini alır.
# 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"
)
Build settings ve select()
Kullanıcılar, select()
kullanarak derleme ayarlarındaki özellikleri yapılandırabilir. Derleme ayarı hedefleri, config_setting
öğesinin flag_values
özelliğine iletilebilir. Yapılandırmayla eşleştirilecek değer bir String
olarak iletilir ve ardından eşleştirme için derleme ayarının türüne göre ayrıştırılır.
config_setting(
name = "my_config",
flag_values = {
"//example:favorite_flavor": "MANGO"
}
)
Kullanıcı tanımlı geçişler
Yapılandırma geçişi, derleme grafiğinde bir yapılandırılmış hedeften diğerine yapılan dönüşümü eşler.
Bu kuralları belirleyen kurallar özel bir özellik içermelidir:
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist"
)
Geçişler ekleyerek derleme grafiğinizin boyutunu kolayca büyütebilirsiniz. Bu işlem, bu kuralın hedeflerini oluşturabileceğiniz paketlerde izin verilenler listesi oluşturur. Yukarıdaki kod bloğunda bulunan varsayılan değer her şeyi izin verilenler listesine ekler. Ancak kuralınızı kimlerin kullanabileceğini kısıtlamak istiyorsanız bu özelliği kendi özel izin verilenler listenizi işaret edecek şekilde ayarlayabilirsiniz. Geçişlerin derleme performansınızı nasıl etkileyebileceğini anlamak için bazel-caption@googlegroups.com adresinden destek veya tavsiye alabilirsiniz.
Tanımlama
Geçişler, kurallar arasındaki yapılandırma değişikliklerini tanımlar. Örneğin, "Bağımlılıklarımı üst öğesinden farklı bir CPU için derle" gibi bir istek, bir geçiş tarafından ele alınır.
Geçiş, resmi olarak bir giriş yapılandırmasından bir veya daha fazla çıkış yapılandırmasına giden bir işlevdir. Çoğu geçiş 1:1'dir (ör. "--cpu=ppc
ile giriş yapılandırmasını geçersiz kıl"). 1:2 veya daha fazla geçiş de olabilir ancak bunlar özel kısıtlamalara tabidir.
Starlark'ta geçişler, tanımlayan bir transition()
işlevi
ve uygulama işlevi ile kurallara benzer şekilde tanımlanır.
# 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"]
)
transition()
işlevi bir uygulama işlevi, okunacak bir yapı ayarları grubu(inputs
) ve yazılacak bir yapı ayarları grubu (outputs
) alır. Uygulama işlevi settings
ve attr
olmak üzere iki parametreye sahiptir. settings
, inputs
parametresinde transition()
için tanımlanan tüm ayarların {String
:Object
} bir sözlüğüdür.
attr
, geçişin eklendiği kuralın özelliklerini ve değerlerini içeren bir sözlüktür. Giden uç geçişi olarak eklendiğinde bu özelliklerin değerlerinin tamamı, "select() sonrası" çözünürlükle yapılandırılmıştır. Gelen kenar geçişi olarak eklendiğinde attr
, değerini çözmek için seçici kullanan özellikleri içermez. --foo
özelliğinde gelen bir uç geçişi, bar
özelliğini okur ve bar
özelliğini ayarlamak için --foo
alanında da seçim yaparsa gelen kenar geçişinin geçişte yanlış bar
değerini okuma ihtimali vardır.
Uygulama işlevi, uygulanacak yeni derleme ayarları değerlerinin bir sözlüğünü (veya birden fazla çıkış yapılandırması içeren geçişler söz konusu olduğunda sözlük listesi) döndürmelidir. Döndürülen sözlük anahtar kümeleri, tam olarak geçiş işlevinin outputs
parametresine iletilen derleme ayarları grubunu içermelidir. Bu durum, bir derleme ayarı geçiş sırasında gerçekten değiştirilmemiş olsa bile geçerlidir. Orijinal değeri, döndürülen sözlüğe açıkça iletilmelidir.
1:2+ geçişleri tanımlama
Giden uç geçişi, tek bir giriş yapılandırmasını iki veya daha fazla çıkış yapılandırmasıyla eşleyebilir. Bu, çoklu mimari kodları içeren kuralları tanımlamak için yararlıdır.
1:2+ geçişleri, geçiş uygulama işlevinde bir sözlük listesi döndürülerek tanımlanır.
# 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"]
)
Ayrıca, kural uygulama işlevinin bağımsız bağımlılıkları okumak için kullanabileceği özel anahtarlar ayarlayabilirler:
# 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"]
)
Geçiş ekleme
Geçişler iki yere eklenebilir: gelen kenarlar ve giden kenarlar. Bu, kuralların kendi yapılandırmalarını (gelen kenar geçişi) ve bağımlılıklarının yapılandırmalarını (giden kenar geçişi) geçirebileceği anlamına gelir.
NOT: Starlark geçişlerini yerel kurallara eklemenin şu anda bir yolu yoktur. Bunu yapmanız gerekiyorsa geçici çözümler bulmak üzere yardım almak için bazel-tartışma@googlegroups.com adresine e-posta gönderin.
Gelen kenar geçişleri
Gelen kenar geçişleri, rule()
cfg
parametresine bir transition
nesnesi (transition()
tarafından oluşturulmuş) eklenerek etkinleştirilir:
# example/rules.bzl
load("example/transitions:transitions.bzl", "hot_chocolate_transition")
drink_rule = rule(
implementation = _impl,
cfg = hot_chocolate_transition,
...
Gelen kenar geçişleri 1:1 geçişler olmalıdır.
Giden kenar geçişleri
Giden kenar geçişleri, bir özelliğin cfg
parametresine transition
nesnesi (transition()
tarafından oluşturulur) eklenerek etkinleştirilir:
# example/rules.bzl
load("example/transitions:transitions.bzl", "coffee_transition")
drink_rule = rule(
implementation = _impl,
attrs = { "dep": attr.label(cfg = coffee_transition)}
...
Giden kenar geçişleri 1:1 veya 1:2+ olabilir.
Bu anahtarları nasıl okuyacağınızı öğrenmek için Geçişlerle özelliklere erişme başlıklı makaleyi inceleyin.
Yerel seçeneklerde geçişler
Starlark geçişleri, seçenek adına eklenen özel bir ön ek ile yerel derleme yapılandırma seçeneklerinde okuma ve yazma işlemlerini de bildirebilir.
# 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"]
Desteklenmeyen yerel seçenekler
Bazel, --define
'te "//command_line_option:define"
ile geçişi desteklemez. Bunun yerine özel bir derleme ayarı kullanın. Genel olarak, --define
'ün yeni kullanımlarının derleme ayarları lehine bırakılması önerilir.
Bazel, --config
'te geçişi desteklemez. Bunun nedeni, --config
'ün diğer işaretlere genişleyen bir "genişleme" işareti olmasıdır.
Önemli bir nokta, --config
'ün, derleme yapılandırmasını etkilemeyen işaretler (ör. --spawn_strategy
) içerebilmesidir. Bazel, tasarım gereği bu tür işaretleri tek tek hedeflere bağlayamaz. Bu, bunların geçişlerde uygulanmasının tutarlı bir yolu olmadığı anlamına gelir.
Geçişinizde yapılandırma kapsamında bulunan işaretleri açıkça listeleyebilirsiniz. Bunun için --config
'nin genişletmesini iki yerde korumanız gerekir. Bu, bilinen bir kullanıcı arayüzü kusurudur.
Birden fazla derleme ayarına izin veren geçişler
Birden fazla değere izin veren derleme ayarları belirlenirken ayarın değeri bir listeyle ayarlanmalıdır.
# 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"]
)
İşlemsiz geçişler
Bir geçiş {}
, []
veya None
döndürürse bu, tüm ayarların orijinal değerlerinde tutulması için kısayoldur. Bu, her çıkışı açıkça kendi kendisine ayarlamaktan daha uygun olabilir.
# 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",
]
)
Geçişlerle özelliklere erişme
Giden bir kenara geçiş eklenirken (geçişin 1:1 veya 1:2+ geçiş olması fark etmez) ctx.attr
, hâlihazırda bir liste değilse liste olmaya zorlanır. Bu listedeki öğelerin sırası belirtilmemiş.
# 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)
})
Geçiş 1:2+
ise ve özel anahtarlar ayarlıyorsa ctx.split_attr
, her anahtar için ayrı ayrı bağımlılıklarını okumak üzere kullanılabilir:
# 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)
})
Tam örneği burada bulabilirsiniz.
Platformlar ve araç zincirleriyle entegrasyon
--cpu
ve --crosstool_top
gibi birçok yerel işaret, günümüzde araç zinciri çözümüyle ilgilidir. Gelecekte bu tür işaretlerdeki açık geçişlerin yerini muhtemelen hedef platformda geçiş yapacaktır.
Bellek ve performansla ilgili dikkat edilmesi gereken noktalar
Yapınıza geçişler ve dolayısıyla yeni yapılandırmalar eklemenin bir maliyeti vardır: daha büyük yapı grafikleri, daha az anlaşılır yapı grafikleri ve daha yavaş derlemeler. Derleme kurallarınızda geçişleri kullanmayı düşünürken bu maliyetleri göz önünde bulundurmanız gerekir. Aşağıda, bir geçişin yapı grafiğinizde nasıl katlanarak büyüme sağlayabileceğine dair bir örnek verilmiştir.
Kötü davranışlı derlemeler: bir örnek olay
Şekil 1. Üst düzey bir hedefi ve bağımlılıklarını gösteren ölçeklenebilirlik grafiği.
Bu grafikte, //pkg:1_0 ve //pkg:1_1 adlı iki hedefe bağlı olan üst düzey bir hedef (//pkg:app) gösterilmektedir. Bu hedeflerin ikisi de //pkg:2_0 ve //pkg:2_1 adlı iki hedefe bağlıdır. Bu hedeflerin her ikisi de iki hedefe bağlıdır: //pkg:3_0 ve //pkg:3_1. Bu işlem, her ikisi de tek bir hedefe (//pkg:dep) bağlı olan //pkg:n_0 ve //pkg:n_1'e kadar devam eder.
//pkg:app
oluşturmak için \(2n+2\) hedefler gereklidir:
//pkg:app
//pkg:dep
- \(i\) adlı kuruluş biriminde \([1..n]\)için
//pkg:i_0
ve//pkg:i_1
--//foo:owner=<STRING>
işaretini uyguladığınızı ve //pkg:i_b
'ın geçerli olduğunu düşünün
depConfig = myConfig + depConfig.owner="$(myConfig.owner)$(b)"
Diğer bir deyişle, //pkg:i_b
tüm bağımlılıkları için b
değerini --owner
değerinin eski değerine ekler.
Bu işlem, aşağıdaki yapılandırılmış hedefleri oluşturur:
//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
, \(2^n\) yapılandırılmış hedefler oluşturur: config.owner=
\(\{0,1\}\)içindeki tüm \(b_i\) için "\(b_0b_1...b_n\)".
Bu durum, derleme grafiğini hedef grafikten katlanarak daha büyük hale getirir ve buna karşılık gelen bellek ve performans sonuçları ortaya çıkar.
TODO: Bu sorunların ölçümü ve azaltılması için stratejiler ekleyin.
Daha fazla bilgi
Derleme yapılandırmalarını değiştirme hakkında daha fazla bilgi için aşağıdaki makaleleri inceleyin:
- Starlark Derleme Yapılandırması
- Bazel Yapılandırılabilirlik Yol Haritası
- Uçtan uca örneklerin tam seti