Modül uzantıları

Sorun bildirme Kaynağı görüntüleme Nightly · 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

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 depo kurallarını çağırarak depo oluşturarak modül sistemini genişletmesine olanak tanır. Bu uzantılar, depo kurallarına benzer özelliklere sahiptir. Bu özellikler, dosya G/Ç işlemlerini gerçekleştirmelerine, ağ istekleri göndermelerine vb. olanak tanır. Diğerlerinin yanı sıra, Bazel'in Bazel modüllerinden oluşturulan bağımlılık grafiğine saygı duyarken diğer paket yönetim sistemleriyle etkileşime girmesine olanak tanır.

.bzl dosyalarında modül uzantılarını, depo kurallarında olduğu gibi tanımlayabilirsiniz. Doğrudan çağrılmazlar. Bunun yerine, her modül uzantıların okuması için etiket adı verilen veri parçalarını belirtir. Bazel, uzantıları değerlendirmeden önce modül çözümlemesini ç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 uzantıyı modülde kullanmak için önce uzantıyı barındıran modüle bir bazel_dep ekleyin, ardından kapsama almak için use_extension yerleşik işlevini çağırın. Aşağıdaki örneği inceleyin. Bu örnekte, rules_jvm_external modülünde tanımlanan "maven" uzantısını kullanmak için bir MODULE.bazel dosyasından bir snippet alınmıştır:

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

Bu, use_extension değerini bir değişkene bağlar. Böylece kullanıcı, uzantı için etiketleri belirtmek üzere nokta söz dizimini kullanabilir. Etiketler, uzantı tanımında belirtilen ilgili etiket sınıfları tarafından tanımlanan ş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ı tarafından oluşturulan depoları geçerli 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, uzantının API'sinin bir parçasıdır. Bu örnekte "maven" modülü uzantısı maven adlı bir depo oluşturmayı taahhüt ediyor. Yukarıdaki beyanla uzantı, "maven" uzantısı tarafından oluşturulan deposu işaretlemek için @maven//:org_junit_junit gibi etiketleri doğru şekilde çözer.

Uzantı tanımı

Modül uzantılarını, module_extension işlevini kullanarak 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ı şu şekilde 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 beyanlar, maven.install ve maven.artifact etiketlerinin belirtilen özellik şeması kullanılarak belirtilebileceğini gösterir.

Modül uzantılarının uygulama işlevi, depo kurallarının işlevlerine benzer. Tek fark, uzantıyı kullanan tüm modüllere ve ilgili tüm etiketlere erişim izni veren bir module_ctx nesnesi almalarıdır. 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 ad ve .bzl dosyasıyla tanımlanır. Aşağıdaki örnekte, maven uzantısı .bzl dosyası @rules_jvm_external//:extension.bzl ve ad maven ile tanımlanmaktadır:

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

Bir uzantıyı farklı bir .bzl dosyasından yeniden dışa aktardığınızda uzantıya yeni bir kimlik verilir. Uzantıların her iki sürümü de geçişli modül grafiğinde kullanılırsa ayrı ayrı değerlendirilir ve yalnızca söz konusu kimlikle ilişkili 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.

Depo adları ve görünürlük

Uzantılar tarafından oluşturulan depoların standart adları module_repo_canonical_name~extension_name~repo_name şeklindedir. Kök modülde barındırılan uzantılarda module_repo_canonical_name kısmı _main dizesiyle değiştirilir. Kanonik ad biçiminin, güvenebileceğiniz bir API olmadığını ve herhangi bir zamanda değiştirilebileceğini unutmayın.

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

Modül uzantıları tarafından oluşturulan depolar göz önüne alındığında, birkaç depo görünürlüğü 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.
  • Bir 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, çakışmaya neden olabilir. Modül deposu foo görünen adına sahip bir depo görebiliyorsa ve uzantı, foo adlı bir depo oluşturuyorsa bu uzantı tarafından oluşturulan tüm depolar için foo, önceki depoyu ifade eder.

En iyi uygulamalar

Bu bölümde uzantı yazarken kullanılan en iyi uygulamalar açıklanmaktadır. Bu uygulamalar kolayca kullanılabilir, korunabilir ve zaman içindeki değişikliklere iyi uyum sağlar.

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 kullanmasanız bile, daha sonra ihtiyaç duyabileceğiniz için bunları ayrı dosyalara koymanız önerilir. Bunun nedeni, uzantının kimliğinin dosyasına bağlı olmasıdır. Bu nedenle, 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 uyumlu olmayan bir değişikliktir.

İşletim sistemini ve mimariyi belirtin

Uzantılarınız işletim sistemine veya mimari türüne bağlıysa os_dependent ve arch_dependent Boole özelliklerini kullanarak bunu uzantı tanımında belirtmeyi unutmayın. Bu sayede Bazel, bunlardan birinde değişiklik olması durumunda yeniden değerlendirme yapılması gerektiğini bilir.

Yalnızca kök modül, depo adlarını doğrudan etkilemelidir.

Bir uzantı, depo oluşturduğunda uzantının ad alanında oluşturulduğunu unutmayın. Bu da farklı modüllerin aynı uzantıyı kullanması ve aynı ada sahip bir depo oluşturması durumunda çakışmalar olabileceği anlamına gelir. Bu durum genellikle bir modül uzantısının tag_class, depo kuralı name değeri olarak iletilen bir name bağımsız değişkenine sahip olması şeklinde kendini gösterir.

Örneğin, A adlı kök modülün B modülüne bağlı olduğunu varsayalım. Her iki modül de mylang modülüne bağlıdır. Hem A hem de B, mylang.toolchain(name="foo") işlevini çağırırsa her ikisi de mylang modülü içinde foo adlı bir depo oluşturmaya çalışır ve bir hata meydana gelir.

Bunu önlemek için depo adını doğrudan ayarlama özelliğini kaldırın veya yalnızca kök modülün bunu yapmasına izin verin. Kök modülün bu özelliğe sahip olmasında sakınca yoktur çünkü hiçbir şey ona bağlı değildir. Bu nedenle, başka bir modülün çakışan bir ad oluşturması konusunda endişelenmenize gerek yoktur.