Bu sayfada, makro kullanmanın temel bilgileri ele alınmakta ve tipik kullanım alanları, hata ayıklama ve kurallar açıklanmaktadır.
Makro, BUILD
dosyasından çağrılan ve kuralları başlatabilen bir işlevdir.
Makrolar, temel olarak mevcut kuralların ve diğer makroların kapsüllenmesi ve kodun 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 oluşturulan kuralların somut kümesini görür.
Kullanım
Makroların tipik kullanım alanı, bir kuralı yeniden kullanmak istediğiniz durumlardır.
Örneğin, bir BUILD
dosyasındaki genrule, komuta sabit kodlanmış bir some_arg
bağımsız değişkeniyle //: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şkenlere sahip daha fazla dosya oluşturmak istiyorsanız bu kodu bir makro işlevine ayıklayabilirsiniz. file_generator
ve arg
parametrelerine sahip olan makroya file_generator
adını verelim.name
genrule'u aşağıdakiyle 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şlevi tanımlarını ayrı bir .bzl
dosyasına yerleştirerek BUILD
dosyalarınızı temiz ve bildirimsel tutarsınız. .bzl
dosyası, çalışma alanındaki herhangi bir paketten yüklenebilir.
Son olarak, path/generator.bzl
bölümünde, orijinal genrule tanımını kapsayacak ve parametrelendirecek şekilde makronun 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'un önceki bir genrule'un çıkışlarını giriş olarak kullandığı zincirlenmiş genrule'lar 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 nesil kurala görünürlük değeri atanır. Bu, makro yazarların ara kuralların çıkışlarını, çalışma alanındaki diğer hedefler tarafından kullanılmaktan gizlemesine olanak tanır.
Genişletme makroları
Bir makronun ne yaptığını araştırmak istediğinizde genişletilmiş biçimi 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ı başlatma
Yerel kurallar (load()
ifadesi gerektirmeyen kurallar) native modülünden başlatılabilir:
def my_macro(name, visibility=None):
native.cc_library(
name = name,
srcs = ["main.cc"],
visibility = visibility,
)
Paket adını (ör. hangi BUILD
dosyası makroyu çağırıyor) bilmeniz gerekiyorsa native.package_name() işlevini kullanın.
native
yalnızca .bzl
dosyalarında kullanılabilir, WORKSPACE
veya BUILD
dosyalarında kullanılamaz.
Makrolarda etiket çözümü
Makrolar yükleme aşamasında değerlendirildiğinden,
bir makroda yer alan "//foo:bar"
gibi etiket dizeleri, tanımlandığı .bzl
dosyasına göre değil, makronun kullanıldığı BUILD
dosyasına göre yorumlanır. Bu davranış, yayınlanmış bir Starlark kural kümesinin parçası olmaları gibi nedenlerle diğer depolarda kullanılmak üzere tasarlanan makrolar için genellikle istenmeyen bir durumdur.
Starlark kurallarında olduğu gibi aynı davranışı elde etmek için etiket dizelerini Label
oluşturucuyla 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 workspace, 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 sonra nasıl göründüğünü gösterir. Tüm makrolar, globlar ve döngüler genişletilir. Bilinen sınırlama:select
ifadeleri şu anda çıkışta gösterilmemektedir.Çıkışı
generator_function
(kuralları hangi işlevin oluşturduğu) veyagenerator_name
(makronun ad özelliği) temelinde filtreleyebilirsiniz:bash $ bazel query --output=build 'attr(generator_function, my_macro, //my/path:all)'
foo
kuralınınBUILD
dosyasında tam olarak nerede oluşturulduğunu öğrenmek için aşağıdaki yöntemi deneyebilirsiniz. Bu 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. Kuralfoo
oluşturulduğunda (ad çakışması nedeniyle) tam yığın izini gösteren bir istisna alırsınız.Hata ayıklama için print işlevini de kullanabilirsiniz. Yükleme aşamasında mesajı
DEBUG
günlük satırı olarak gösterir. Nadiren görülen durumlar dışında, kodu depoya göndermeden önceprint
çağrılarını kaldırın veyaFalse
varsayılan değerine sahip birdebugging
parametresi altında koşullu hale getirin.
Hatalar
Hata oluşturmak istiyorsanız fail işlevini kullanın.
Kullanıcıya neyin yanlış gittiğini ve BUILD
dosyasını nasıl düzelteceğ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
Kuralları oluşturan tüm genel işlevler (alt çizgiyle başlamayan işlevler) bir
name
bağımsız değişkenine sahip 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 (konum bağımsız değişkeni değil) olmalıdır.Makro tarafından oluşturulan kuralların
name
özelliği, ad bağımsız değişkenini önek olarak içermelidir. Örneğin,macro(name = "foo")
,cc_library
foo
ve genrulefoo_gen
oluşturabilir.Çoğu durumda, isteğe bağlı parametrelerin varsayılan değeri
None
olmalıdır.None
, herhangi bir bağımsız değişken iletmemişsiniz gibi davranan yerel kurallara doğrudan iletilebilir. Bu nedenle, bu amaçla0
,False
veya[]
ile değiştirmenize gerek yoktur. Bunun yerine, varsayılan değerleri karmaşık olabileceğinden veya zaman içinde değişebileceğinden makro, oluşturduğu kurallara uymalıdır. Ayrıca, varsayılan değerine açıkça ayarlanmış bir parametre, sorgu dili veya derleme sistemi iç kısımları üzerinden erişildiğinde hiç ayarlanmamış (veyaNone
olarak ayarlanmış) bir parametreden farklı görünür.Makrolarda isteğe bağlı bir
visibility
bağımsız değişkeni olmalıdır.