Bu sayfada, makro kullanmayla ilgili temel bilgiler, tipik kullanım alanları, hata ayıklama ve kurallar ele alınmaktadır.
Makro, BUILD
dosyasından çağrılan ve kuralları örnekleyebilen bir işlevdir.
Makrolar, çoğunlukla mevcut kurallar ile diğer makroların kapsüllenmesi ve yeniden kullanılması için kullanılır. Yükleme aşamasının sonunda makrolar artık mevcut değildir ve Bazel yalnızca somut olarak oluşturulmuş kurallar grubunu görür.
Kullanım
Makroların tipik kullanım alanı, bir kuralı yeniden kullanmak istediğinizdedir.
Örneğin, BUILD
dosyasındaki genrule, komuta kodlanmış bir some_arg
bağımsız değişkeni ile //:generator
kullanarak bir dosya oluşturur:
genrule(
name = "file",
outs = ["file.txt"],
cmd = "$(location //:generator) some_arg > $@",
tools = ["//:generator"],
)
Farklı bağımsız değişkenlerle daha fazla dosya oluşturmak istiyorsanız bu kodu bir makro işlevine ayıklamak isteyebilirsiniz. Makroyu file_generator
olarak adlandıralım. Bu makroda name
ve arg
parametreleri vardır. Genrule'ı şununla değiştirin:
load("//path:generator.bzl", "file_generator")
file_generator(
name = "file",
arg = "some_arg",
)
file_generator(
name = "file-two",
arg = "some_arg_two",
)
file_generator(
name = "file-three",
arg = "some_arg_three",
)
Burada, //path
paketinde bulunan bir .bzl
dosyasından file_generator
simgesini yüklersiniz. Makro işlev tanımlarını ayrı bir .bzl
dosyasına yerleştirerek BUILD
dosyalarınızı temiz ve açıklayıcı tutarsınız. .bzl
dosyası, çalışma alanındaki herhangi bir paketten yüklenebilir.
Son olarak, path/generator.bzl
içinde orijinal genrule tanımını kapsayacak ve parametrelendirecek makro tanımını yazın:
def file_generator(name, arg, visibility=None):
native.genrule(
name = name,
outs = [name + ".txt"],
cmd = "$(location //:generator) %s > $@" % arg,
tools = ["//:generator"],
visibility = visibility,
)
Kuralları birbirine bağlamak için makroları da kullanabilirsiniz. Bu örnekte, bir genrule üyesinin önceki bir genrulenin çıkışlarını giriş olarak kullandığı zincirlenmiş genel kurallar gösterilmektedir:
def chained_genrules(name, visibility=None):
native.genrule(
name = name + "-one",
outs = [name + ".one"],
cmd = "$(location :tool-one) $@",
tools = [":tool-one"],
visibility = ["//visibility:private"],
)
native.genrule(
name = name + "-two",
srcs = [name + ".one"],
outs = [name + ".two"],
cmd = "$(location :tool-two) $< $@",
tools = [":tool-two"],
visibility = visibility,
)
Örnekte yalnızca ikinci genrule için bir visibility değeri atanır. Bu, makro yazarlarının ara kuralların çıkışlarının çalışma alanındaki diğer hedefler tarafından bağımlı kalmasının engellenmesini sağlar.
Genişletilmiş makrolar
Bir makronun ne yaptığını incelemek istediğinizde genişletilmiş biçimini görmek için query
komutunu --output=build
ile birlikte kullanın:
$ bazel query --output=build :file
# /absolute/path/test/ext.bzl:42:3
genrule(
name = "file",
tools = ["//:generator"],
outs = ["//test:file.txt"],
cmd = "$(location //:generator) some_arg > $@",
)
Yerel kuralları örneklendirme
Yerel kurallar (load()
beyanı gerektirmeyen kurallar), native modülünden oluşturulabilir:
def my_macro(name, visibility=None):
native.cc_library(
name = name,
srcs = ["main.cc"],
visibility = visibility,
)
Paket adını (örneğin, makroyu hangi BUILD
dosyasının çağırdığını) bilmeniz gerekiyorsa native.package_name() işlevini kullanın. native
'ın yalnızca .bzl
dosyalarında kullanılabileceğini, BUILD
dosyalarında kullanılamayacağını unutmayın.
Makrolarda etiket çözünürlüğü
Makrolar yükleme aşamasında değerlendirildiğinden, bir makroda oluşan "//foo:bar"
gibi etiket dizeleri, makronun tanımlandığı .bzl
dosyasına göre değil, makronun içinde kullanıldığı BUILD
dosyasına göre yorumlanır. Bu davranış genellikle diğer depolarda kullanılması amaçlanan makrolar için (örneğin, yayınlanan bir Starlark kural grubunun parçası olmaları gibi) istenmeyen bir davranıştır.
Starlark kurallarıyla aynı davranışı elde etmek için etiket dizelerini Label
kurucusuyla sarmalayın:
# @my_ruleset//rules:defs.bzl
def my_cc_wrapper(name, deps = [], **kwargs):
native.cc_library(
name = name,
deps = deps + select({
# Due to the use of Label, this label is resolved within @my_ruleset,
# regardless of its site of use.
Label("//config:needs_foo"): [
# Due to the use of Label, this label will resolve to the correct target
# even if the canonical name of @dep_of_my_ruleset should be different
# in the main repo, such as due to repo mappings.
Label("@dep_of_my_ruleset//tools:foo"),
],
"//conditions:default": [],
}),
**kwargs,
)
Hata ayıklama
bazel query --output=build //my/path:all
,BUILD
dosyasının değerlendirmeden sonraki durumunu gösterir. Tüm makrolar, glob'lar ve döngüler genişletilir. Bilinen sınırlama: Şu andaselect
ifadeleri çıkışta gösterilmemektedir.Çıktıyı
generator_function
(kuralları hangi işlevin oluşturduğu) veyagenerator_name
'a (makronun ad özelliği) göre filtreleyebilirsiniz:bash $ bazel query --output=build 'attr(generator_function, my_macro, //my/path:all)'
foo
kuralının birBUILD
dosyasında tam olarak nerede oluşturulduğunu öğrenmek için aşağıdaki numarayı deneyebilirsiniz. Aşağıdaki satırıBUILD
dosyasının üst kısmına yakın bir yere ekleyin:cc_library(name = "foo")
. Bazel'i çalıştırın.foo
kuralı oluşturulduğunda (ad çakışması nedeniyle) tam yığın izleme bilgisini gösteren bir istisna alırsınız.Hata ayıklama için print komutunu da kullanabilirsiniz. Yükleme aşamasında mesajı
DEBUG
günlük satırı olarak gösterir. Nadir durumlar hariç, kodu depoya göndermeden önceprint
çağrılarını kaldırın veya varsayılan olarakFalse
olan birdebugging
parametresi altında koşullu hale getirin.
Hatalar
Hata oluşturmak istiyorsanız fail işlevini kullanın.
Kullanıcıya sorunun ne olduğunu ve BUILD
dosyasının nasıl düzeltileceğini net bir şekilde açıklayın.
Hata yakalamak mümkün değildir.
def my_macro(name, deps, visibility=None):
if len(deps) < 2:
fail("Expected at least two values in deps")
# ...
Kongreler
Kural başlatan tüm herkese açık işlevler (alt çizgi ile başlamayan işlevler) için
name
bağımsız değişkeni olmalıdır. Bu bağımsız değişken isteğe bağlı olmamalıdır (varsayılan değer vermeyin).Herkese açık işlevler, Python kurallarına uygun bir docstring kullanmalıdır.
BUILD
dosyalarında, makrolarınname
bağımsız değişkeni bir anahtar kelime bağımsız değişkeni (konumsal bağımsız değişken değil) olmalıdır.Bir makro tarafından oluşturulan kuralların
name
özelliği, ad bağımsız değişkenini ön ek olarak içermelidir. Örneğin,macro(name = "foo")
bircc_library
foo
ve bir genrulefoo_gen
oluşturabilir.Çoğu durumda, isteğe bağlı parametrelerin varsayılan değeri
None
olmalıdır.None
doğrudan yerel kurallara iletilebilir. Bu durumda, herhangi bir bağımsız değişken iletmemişsiniz gibi değerlendirilir. Bu nedenle, bu amaç için0
,False
veya[]
ile değiştirmeniz gerekmez. Bunun yerine, varsayılan değerleri karmaşık olabileceği veya zaman içinde değişebileceği için makro, oluşturduğu kurallara göre işlem yapmalıdır. Ayrıca, varsayılan değerine açıkça ayarlanmış bir parametre, sorgu dili veya derleme sistemi dahili aracılığıyla erişildiğinde hiç ayarlanmamış (veyaNone
olarak ayarlanmış) bir parametreden farklı görünür.Makroların isteğe bağlı bir
visibility
bağımsız değişkeni olmalıdır.