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. 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 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
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ı 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ı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, 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 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ı ş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 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ının uygulama işlevine benzer. Ancak bu işlev, module_ctx
nesnesini alı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 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 olmanız gerekir.
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ılarda module_repo_canonical_name
kısmı _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 "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
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
veuse_repo
aracılığıylaMODULE.bazel
dosyasında tanıtılan 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çinfoo
, önceki depoyu ifade eder.
- Bu durum, çakışmaya neden olabilir. Modül deposu
En iyi uygulamalar
Bu bölümde, uzantıların kullanımı kolay, bakımı yapılabilir ve zaman içindeki değişikliklere iyi uyum sağlayacak şekilde yazılmasıyla ilgili en iyi uygulamalar açıklanmaktadır.
Her uzantıyı ayrı bir dosyaya yerleştirin
Uzantılar farklı dosyalarda olduğunda, bir uzantının başka bir uzantı tarafından oluşturulan depoları yüklemesine izin verilir. 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 dayalı olmasıdır. Dolayısıyla, uzantıyı daha sonra başka bir dosyaya taşımak genel API'nizi değiştirir ve kullanıcılarınız için geriye dönük olarak uyumsuz bir değişikliktir.