Modül uzantıları

Sorun bildirin Kaynağı göster

Modül uzantıları, kullanıcıların bağımlılık grafiğindeki modüllerden giriş verilerini okuyarak, bağımlılıkları çözmek için gerekli mantığı uygulayarak ve son olarak kod deposu kurallarını çağırarak depolar oluşturarak modül sistemini genişletmesine olanak tanır. Bu uzantılar, dosya G/Ç işlemi gerçekleştirme, ağ istekleri gönderme ve benzeri işlemler gerçekleştirmelerini sağlayan depo kurallarına benzer özelliklere sahiptir. Ayrıca, Bazel'in diğer paket yönetimi sistemleriyle etkileşim kurmasına ve Bazel modüllerinden oluşturulan bağımlılık grafiğine uymasına olanak tanır.

.bzl dosyalarında modül uzantılarını, depo kurallarında olduğu gibi tanımlayabilirsiniz. Bunlar doğrudan çağrılmaz. Bunun yerine her modül, uzantıların okunması için etiketler adı verilen veri parçalarını belirtir. Bazel, uzantıları değerlendirmeden önce modül çözünürlüğünü çalıştırır. Uzantı, bağımlılık grafiğinin tamamında kendisine ait tüm etiketleri okur.

Uzantı kullanımı

Uzantılar Bazel modüllerinde barındırılır. Bir modülde uzantı kullanmak için önce uzantıyı barındıran modüle bir bazel_dep ekleyin ve ardından uzantıyı kapsama dahil etmek için use_extension yerleşik işlevini çağırın. Şu örneği inceleyelim: rules_jvm_external modülünde tanımlanan "maven" uzantısını kullanmak için MODULE.bazel dosyasından bir snippet:

bazel_dep(name = "rules_jvm_external", version = "4.5")
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")

Bu, use_extension işlevinin döndürülen değerini bir değişkene bağlar. Böylece kullanıcı, uzantıya ilişkin etiketleri belirtmek için nokta söz dizimini kullanabilir. Etiketler, uzantı tanımında belirtilen ilgili etiket sınıflarının tanımladığı şemaya uymalıdır. Bazı maven.install ve maven.artifact etiketlerini belirtme örneği için:

maven.install(artifacts = ["org.junit:junit:4.13.2"])
maven.artifact(group = "com.google.guava",
               artifact = "guava",
               version = "27.0-jre",
               exclusions = ["com.google.j2objc:j2objc-annotations"])

Uzantının oluşturduğu depoları mevcut modülün kapsamına almak için use_repo yönergesini kullanın.

use_repo(maven, "maven")

Bir uzantı tarafından oluşturulan depolar, bu uzantının API'sinin parçasıdır. Bu örnekte, "maven" modülü uzantısı maven adlı bir depo oluşturmayı taahhüt ediyor. Yukarıdaki beyanla birlikte uzantı, @maven//:org_junit_junit gibi etiketleri "maven" uzantısı tarafından oluşturulan depoya işaret edecek şekilde doğru şekilde çözümler.

Uzantı tanımı

module_extension işlevini kullanarak modül uzantılarını depo kurallarına benzer şekilde tanımlayabilirsiniz. Bununla birlikte, depo kuralları birkaç özelliğe sahipken modül uzantılarında her birinin bir dizi özelliği olan tag_class özellikleri bulunur. Etiket sınıfları, bu uzantı tarafından kullanılan etiketler için şemaları tanımlar. Örneğin, yukarıdaki "maven" uzantısı şöyle tanımlanabilir:

# @rules_jvm_external//:extensions.bzl

_install = tag_class(attrs = {"artifacts": attr.string_list(), ...})
_artifact = tag_class(attrs = {"group": attr.string(), "artifact": attr.string(), ...})
maven = module_extension(
  implementation = _maven_impl,
  tag_classes = {"install": _install, "artifact": _artifact},
)

Bu bildirimler, maven.install ve maven.artifact etiketlerinin belirtilen özellik şeması kullanılarak belirtilebileceğini gösterir.

Modül uzantılarının uygulama işlevi, kod deposu kurallarına benzer. Tek fark, modül uzantılarının module_ctx nesnesini almalarıdır. Bu nesne, uzantıyı ve ilgili tüm etiketleri kullanan tüm modüllere erişim izni verir. Ardından uygulama işlevi, depo oluşturmak için depo kurallarını çağırır.

# @rules_jvm_external//:extensions.bzl

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")  # a repo rule
def _maven_impl(ctx):
  # This is a fake implementation for demonstration purposes only

  # collect artifacts from across the dependency graph
  artifacts = []
  for mod in ctx.modules:
    for install in mod.tags.install:
      artifacts += install.artifacts
    artifacts += [_to_artifact(artifact) for artifact in mod.tags.artifact]

  # call out to the coursier CLI tool to resolve dependencies
  output = ctx.execute(["coursier", "resolve", artifacts])
  repo_attrs = _process_coursier_output(output)

  # call repo rules to generate repos
  for attrs in repo_attrs:
    http_file(**attrs)
  _generate_hub_repo(name = "maven", repo_attrs)

Uzantı kimliği

Modül uzantıları, use_extension çağrısında görünen .bzl dosyası ve adla tanımlanır. Aşağıdaki örnekte maven uzantısı, .bzl dosyası @rules_jvm_external//:extension.bzl ve maven adıyla tanımlanmıştır:

maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")

Bir uzantı farklı bir .bzl dosyasından yeniden dışa aktarıldığında ona yeni bir kimlik verilir. Geçişli modül grafiğinde uzantının her iki sürümü de kullanılıyorsa bunlar ayrı olarak değerlendirilir ve yalnızca söz konusu kimlikle ilişkilendirilen etiketleri görür.

Uzantı yazarı olarak, kullanıcıların modül uzantınızı yalnızca tek bir .bzl dosyasından kullanacağından emin olmalısınız.

Kod deposu adları ve görünürlüğü

Uzantılar tarafından oluşturulan kod depoları module_repo_canonical_name~extension_name~repo_name biçiminde standart adlara sahiptir. Kök modülde barındırılan uzantılar için module_repo_canonical_name bölümü, _main dizesiyle değiştirilir. Standart ad biçiminin kullanmanız gereken bir API olmadığını unutmayın. Bu biçim herhangi bir zamanda değiştirilebilir.

Bu adlandırma politikası, her uzantının kendi "depo ad alanına" sahip olduğu anlamına gelir. İki farklı uzantı, çakışma riski olmadan aynı ada sahip bir depo tanımlayabilir. Ayrıca, repository_ctx.name komutu deponun standart adını bildirir. Bu ad, depo kuralı çağrısında belirtilen adla aynı değildir.

Modül uzantıları tarafından oluşturulan depoları dikkate alan birkaç depo görünürlük kuralı vardır:

  • Bazel modül deposu, bazel_dep ve use_repo aracılığıyla MODULE.bazel dosyasında sunulan tüm depoları görebilir.
  • Modül uzantısı tarafından oluşturulan bir depo, uzantıyı barındıran modül tarafından görülebilen tüm depoları ve aynı modül uzantısı tarafından oluşturulan diğer tüm depoları görebilir (depo kuralı çağrılarında belirtilen adların görünen adlar olarak kullanılması).
    • Bu durum bir çakışmaya yol açabilir. Modül deposu, foo görünen bir depo görebiliyorsa ve uzantı, foo belirtilen ada sahip bir depo oluşturuyorsa bu uzantı tarafından oluşturulan tüm depolar için foo kod deposunu ifade eder.

En iyi uygulamalar

Bu bölümde; kolayca kullanılabilmesi, korunabilmesi ve zaman içindeki değişikliklere uyum sağlaması için uzantı yazmayla ilgili en iyi uygulamalar açıklanmaktadır.

Her uzantıyı ayrı bir dosyaya yerleştirin

Uzantılar farklı bir dosyada yer aldığında, bir uzantının başka bir uzantı tarafından oluşturulan depoları yüklemesine olanak tanır. Bu işlevi kullanmıyor olsanız bile, daha sonra ihtiyaç duymanız ihtimaline karşı bunları ayrı dosyalara yerleştirmek en iyi seçenektir. Bunun nedeni, uzantının kimliğinin kendi dosyasına dayanmasıdır. Dolayısıyla, uzantıyı daha sonra başka bir dosyaya taşımak, herkese açık API'nizi değiştirir ve kullanıcılarınız için geriye dönük olarak uyumsuz bir değişikliktir.