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şletmelerini sağlar. Bu uzantılar, depo kurallarına benzer özellikler içerir. Bu özellikler dosya G/Ç'sini gerçekleştirmelerini, ağ istekleri göndermelerini ve benzeri işlemleri gerçekleştirmelerini sağlar. Diğer olanaklarının yanı sıra Bazel'ın diğer paket yönetimi sistemleriyle etkileşimde bulunmasına olanak tanırken Bazel modüllerinden oluşturulan bağımlılık grafiğine de riayet eder.
Kod deposu kurallarında olduğu gibi, .bzl
dosyalarında modül uzantılarını tanımlayabilirsiniz. Bunlar doğrudan çağrılmaz. Her modül, uzantıların okunması için etiket adı verilen veri parçalarını belirtir. Bazel, uzantıları değerlendirmeden önce modül
çözünürlüğü ç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ül içinde uzantı kullanmak için öncelikle uzantıyı barındıran modüle bir bazel_dep
ekleyin. Daha sonra, uzantıyı kapsama almak için use_extension
yerleşik işlevini çağırın. Şu örneği inceleyin: rules_jvm_external
modülünde tanımlanan "maven" uzantısını kullanmak için MODULE.bazel
dosyasından alınan bir snippet:
bazel_dep(name = "rules_jvm_external", version = "4.5")
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
Bu işlem, use_extension
döndürülen değerini bir değişkene bağlar. Böylece kullanıcı, uzantı etiketlerini belirtmek için nokta söz dizimini kullanabilir. Etiketler, uzantı tanımında belirtilen karşılık gelen etiket sınıfları tarafından tanımlanan şemaya uygun olmalıdır. Bazı maven.install
ve maven.artifact
etiketlerini belirten bir örnek:
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ı 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, ilgili API'nin bir parçasıdır. Bu örnekte "maven" modülü uzantısı, maven
adlı bir depo oluşturmayı taahhüt eder. Yukarıdaki beyanla uzantı, "maven" uzantısı tarafından oluşturulan depoya işaret etmek için @maven//:org_junit_junit
gibi etiketleri doğru şekilde çözer.
Uzantı tanımı
module_extension
işlevini kullanarak modül uzantılarını depo kurallarına benzer şekilde tanımlayabilirsiniz. Bununla birlikte, depo kurallarının birkaç özelliği vardır. Modül uzantılarında ise her biri belirli özelliklere sahip tag_class
öğeleri 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, depoların kurallarına benzerdir. Tek fark, uzantıyı ve ilgili tüm etiketleri kullanan tüm modüllere 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 .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ımlanır:
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
Bir uzantıyı farklı bir .bzl
dosyasından yeniden dışa aktarmak, uzantıya yeni bir kimlik verir ve 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 bu kimlikle ilişkilendirilen etiketleri görür.
Uzantı yazarı olarak, kullanıcıların modül uzantınızı sadece tek bir .bzl
dosyasından kullanacaklarından emin olmalısınız.
Kod deposu adları ve görünürlük
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
bölümü, _main
dizesiyle değiştirilir. Standart ad biçiminin güvenmeniz gereken bir API olmadığını ve her an değişebileceğini unutmayın.
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. Bu aynı zamanda repository_ctx.name
hizmetinin, deponun standart adını bildirdiği anlamına gelir. Bu ad, depo kuralı çağrısında belirtilen adla aynı değildir.
Modül uzantıları tarafından oluşturulan depolar dikkate alındığında, birkaç depo görünürlüğü kuralı vardır:
- Bazel modülü deposu,
bazel_dep
veuse_repo
aracılığıylaMODULE.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üle görünür olan 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, görünen adları olarak kullanılır).
- Bu durum, çakışmaya neden olabilir. Modül deposu görünen adı
foo
olan bir depo görebiliyorsa ve uzantı, belirtilen adıfoo
olan bir depo oluşturuyorsa bu uzantı tarafından oluşturulan tüm kod depoları içinfoo
, eski kod deposunu ifade eder.
- Bu durum, çakışmaya neden olabilir. Modül deposu görünen adı
En iyi uygulamalar
Bu bölümde, uzantıların kullanılması, bakımı kolay ve zaman içindeki değişikliklere iyi 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ı dosyalarda olduğunda, 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 ihtiyacınız olması ihtimaline karşı bunları ayrı dosyalara yerleştirmek en iyisidir. Bunun nedeni, uzantının kimliğinin dosyaya 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şiklik olur.
İşletim sistemini ve mimariyi belirleme
Uzantınız işletim sistemini veya mimari türünü temel alıyorsa bunu uzantı tanımında os_dependent
ve arch_dependent
boole özelliklerini kullanarak belirttiğinizden emin olun. Bu sayede, ikisinden birinde değişiklik olduğunda Bazel'in yeniden değerlendirme ihtiyacını anlamasını sağlar.
Kod deposu adlarını doğrudan yalnızca kök modül etkilemelidir
Bir uzantı depo oluşturduğunda bunların, uzantının ad alanı içinde oluşturulduğunu unutmayın. Bu durum, farklı modüllerin aynı uzantıyı kullanması ve sonuçta aynı ada sahip bir depo oluşturulması durumunda çakışmaların meydana gelebileceği anlamına gelir. Bu durum genellikle modül uzantısının tag_class
öğesinin, depo kuralının name
değeri olarak aktarılan bir name
bağımsız değişkenine sahip olması olarak görünür.
Örneğin, A
kök modülünü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")
çağrısı yaparsa her ikisi de mylang
modülü içinde foo
adlı bir depo oluşturmayı dener ve bir hata oluşur.
Bunu önlemek için doğrudan kod deposu adını ayarlama özelliğini kaldırın veya yalnızca kök modülün yapmasına izin verin. Kök modüle hiçbir şey bağımlı olmayacağından izin verebilirsiniz. Böylece çakışan bir ad oluşturacak başka bir modülün endişelenmesi gerekmez.