Makrolar

. Sorun bildirin Kaynağı göster Gece · 7,3 · 7,2 · 7,1 · 7,0 · 6,5

Bu sayfada, makroların kullanımıyla ilgili temel bilgiler ve tipik kullanım örnekleri, öğreneceğiz.

Makro, BUILD dosyasından çağrılan ve kuralları örneklendirebilen bir işlevdir. Makrolar genellikle mevcut kuralları kapsüllemek ve kodu yeniden kullanmak için kullanılır ve diğer makrolar için geçerlidir. yükleme aşamasında, makrolar artık mevcut değilse ve Bazel yalnızca örneklendirilmiş kuralların somut kümesini görür.

Kullanım

Bir makronun tipik kullanım alanı, kuralı yeniden kullanmak istediğiniz durumlardır.

Örneğin, bir BUILD dosyasındaki genrule, Komuta sabit kodlu bir some_arg bağımsız değişkeniyle //:generator:

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 çıkarın. file_generator makrosuna name ve arg parametrelerine sahip. 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, aynı konumda bulunan bir .bzl dosyasından file_generator simgesini yüklersiniz (//path paketinde) Makro işlev tanımlarını ayrı bir .bzl dosyası, BUILD dosyanızı temiz ve bildirim amaçlı tutarsınız, .bzl dosyası, çalışma alanındaki herhangi bir paketten yüklenebilir.

Son olarak, path/generator.bzl dilinde, makronun tanımını orijinal genrule tanımını kapsülleyin ve parametreleştirin:

def file_generator(name, arg, visibility=None):
  native.genrule(
    name = name,
    outs = [name + ".txt"],
    cmd = "$(location //:generator) %s > $@" % arg,
    tools = ["//:generator"],
    visibility = visibility,
  )

Makroları, kuralları birbirine bağlamak için de kullanabilirsiniz. Bu örnekte zincir mağaza genrules, bu örnekte bir genrule önceki bir genrule'ın çıkışlarını giriş olarak kullanır:

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

Örnek yalnızca ikinci nesile bir görünürlük değeri atar. Bu da makro yazarlarının, ara kuralların çıktılarını bu çıktılara bağımlı kalmalarını önler diğer hedefler tarafından kontrol edilir.

Genişletme makroları

Bir makronun ne yaptığını incelemek istediğinizde query komutunu Genişletilmiş formu görmek için --output=build:

$ 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() ifadesi gerektirmeyen kurallar) native modülünden örnekler:

def my_macro(name, visibility=None):
  native.cc_library(
    name = name,
    srcs = ["main.cc"],
    visibility = visibility,
  )

Paket adını bilmeniz gerekiyorsa (örneğin, BUILD makrosuyla birlikte) native.package_name() işlevini kullanın. native öğesinin yalnızca .bzl dosyalarında kullanılabildiğini, WORKSPACE veya BUILD dosya.

Makrolarda etiket çözünürlüğü

Makrolar yükleme aşamasında değerlendirildiğinden bir makroda yer alan "//foo:bar" gibi etiket dizeleri yorumlanır ile göreli olarak değil, makronun kullanıldığı BUILD dosyasına göre içinde tanımlandığı .bzl dosyası. Bu, genellikle istenmeyen bir davranış diğer depolarda kullanılması amaçlanan makrolara yönelik (ör. yayınlanmış bir Starlark kural setinin parçasıdır.

Starlark kurallarıyla aynı davranışı elde etmek için etiket dizelerini Label oluşturucu:

# @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 nasıl yapılacağını gösterecek. değerlendirmeden geçer. Tüm makrolar, glob'lar, döngüler genişletilir. Bilinen sınırlama: select ifadeleri şu anda çıkışta gösterilmiyor.

  • Çıkışı, generator_function işlevine göre filtreleyebilirsiniz. tarafından oluşturulmuşsa) veya generator_name (makronun ad özelliği): bash $ bazel query --output=build 'attr(generator_function, my_macro, //my/path:all)'

  • foo kuralının BUILD dosyasında tam olarak nerede oluşturulduğunu öğrenmek için aşağıdaki numarayı deneyebilirsiniz. Bu satırı BUILD öğesinin üst kısmına yakın bir yere ekleyin dosya: cc_library(name = "foo"). Bazel'i çalıştırın. Aşağıdaki durumlarda istisna yapılır: foo kuralı oluşturulur (ad çakışması nedeniyle). Bu kural, size tam yığın izleme (stack trace) hakkında bilgi edinin.

  • Hata ayıklama için yazdırma yöntemini de kullanabilirsiniz. Gösterilen bu mesajı, yükleme aşamasında DEBUG günlük satırı olarak kaydedebilirsiniz. Nadir olanlar hariç ya print çağrıları kaldırın ya da bir debugging parametresi için kodu göndermeden önce varsayılan olarak False sağlar.

Hatalar

Hata vermek 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 yakalanamaz.

def my_macro(name, deps, visibility=None):
  if len(deps) < 2:
    fail("Expected at least two values in deps")
  # ...

Kongreler

  • Tüm herkese açık işlevler (alt çizgiyle başlamayan işlevler) örneklendirme kurallarının bir name bağımsız değişkeni olmalıdır. Bu bağımsız değişken isteğe bağlı (varsayılan değer vermeyin).

  • Herkese açık işlevler, Python'dan sonra bir docstring kullanmalıdır inceleyin.

  • BUILD dosyalarında, makroların name bağımsız değişkeni bir anahtar kelime olmalıdır bağımsız değişkenine (konumsal bağımsız değişken değil) girin.

  • Bir makro tarafından oluşturulan kuralların name özelliği, bağımsız değişkenini önek olarak ayarlar. Örneğin, macro(name = "foo") şunları oluşturabilir: cc_library foo ve bir genel foo_gen.

  • Çoğu durumda, isteğe bağlı parametreler için varsayılan değer None olmalıdır. None doğrudan yerel kurallara iletilebilir. Bu kurallar, yerel kurallara tartışmayı geçemediniz. Dolayısıyla, bu e-posta adresinin Bu amaçla 0, False veya [] ile kullanın. Bunun yerine makro, varsayılanları karmaşık olabileceğinden veya zaman içinde değişebileceğinden, gerekir. Ayrıca, varsayılan değerine açık bir şekilde ayarlanmış bir parametre erişildiğinde hiçbir zaman ayarlanmayan (veya None olarak ayarlanmış) olandan farklı görünüyor test dili veya derleme sistemi dahili ayarlarını kullanabilirsiniz.

  • Makroların isteğe bağlı bir visibility bağımsız değişkeni olmalıdır.