Bazel modülü, her biri bağlı olduğu diğer modüllerle ilgili meta verileri yayınlayan birden fazla sürümü olabilen bir Bazel projesidir. Bu, diğer bağımlılık yönetimi sistemlerindeki bilinen kavramlara benzer. Örneğin, Maven artifact, npm package, Go �module veya Cargo �crate.
Bir modülün, depo kökünde (WORKSPACE
dosyasının yanında) MODULE.bazel
dosyası bulunmalıdır. Bu dosya, modülün manifest dosyasıdır. Modülün adını, sürümünü, doğrudan bağımlılıklarının listesini ve diğer bilgilerini içerir. Temel bir örnek için:
module(name = "my-module", version = "1.0")
bazel_dep(name = "rules_cc", version = "0.0.1")
bazel_dep(name = "protobuf", version = "3.19.0")
MODULE.bazel
dosyalarında kullanılabilen yönergelerin tam listesini inceleyin.
Bazel, modül çözümlemesi yapmak için önce kök modülün MODULE.bazel
dosyasını okur, ardından tüm bağımlılıkların MODULE.bazel
dosyasını Bazel kayıt defterinden tekrar tekrar ister. Bu işlem, bağımlılık grafiğinin tamamı keşfedilene kadar devam eder.
Varsayılan olarak Bazel, kullanılacak her modülün bir sürümünü seçer. Bazel, her modülü bir depo ile temsil eder ve her bir deponun nasıl tanımlanacağını öğrenmek için kayıt defterine tekrar danışır.
Sürüm biçimi
Bazel'in çeşitli bir ekosistemi vardır ve projelerde çeşitli sürüm oluşturma şemaları kullanılır. En popüler olanı SemVer olsa da Abseil gibi farklı şemalar kullanan önemli projeler de vardır (ör. 20210324.2
). Abseil'in sürümleri tarih tabanlıdır.
Bu nedenle Bzlmod, SemVer spesifikasyonunun daha esnek bir sürümünü kullanır. Farklılıklar şunlardır:
- SemVer, sürümün "yayın" bölümünün 3 segmentten oluşması gerektiğini belirtir:
MAJOR.MINOR.PATCH
. Bazel'de bu şart gevşetilir ve herhangi bir sayıda segmente izin verilir. - SemVer'de "yayın" bölümündeki segmentlerin her biri yalnızca rakamlardan oluşmalıdır. Bazel'de bu kısıtlama, harflere de izin verecek şekilde gevşetilir ve karşılaştırma semantiği, "ön sürüm" bölümündeki "tanımlayıcılarla" eşleşir.
- Ayrıca, ana, alt ve yama sürümü artışlarının semantiği zorunlu kılınmaz. Ancak geriye dönük uyumluluğu nasıl gösterdiğimizle ilgili ayrıntılar için uyumluluk düzeyine bakın.
Geçerli herhangi bir SemVer sürümü, geçerli bir Bazel modül sürümüdür. Ayrıca, iki SemVer sürümü a
ve b
, yalnızca Bazel modül sürümleri olarak karşılaştırıldıklarında aynı durum geçerliyse a < b
karşılaştırılır.
Sürüm seçimi
Sürüm oluşturulmuş bağımlılık yönetimi alanında temel bir sorun olan elmas bağımlılığı sorununu ele alalım. Bağımlılık grafiğinizin aşağıdaki gibi olduğunu varsayalım:
A 1.0
/ \
B 1.0 C 1.1
| |
D 1.0 D 1.1
Hangi D
sürümü kullanılmalıdır? Bzlmod, bu sorunu çözmek için Go modül sisteminde kullanılan Minimal Version Selection (MVS) algoritmasını kullanır. MVS, bir modülün tüm yeni sürümlerinin geriye dönük olarak uyumlu olduğunu varsayar ve bu nedenle herhangi bir bağımlı tarafından belirtilen en yüksek sürümü (örneğimizde D 1.1
) seçer. Bu sürüm, gereksinimlerimizi karşılayabilecek en eski sürüm olduğu için "minimal" olarak adlandırılır. D 1.2
veya daha yeni sürümler olsa bile bunları seçmeyiz.D 1.1
MVS kullanıldığında yüksek kaliteli ve yeniden üretilebilir bir sürüm seçme süreci oluşturulur.
Kaldırılan sürümler
Kayıt, belirli sürümlerin (ör. güvenlik açıkları nedeniyle) kullanılmaması gerektiğini belirtmek için bu sürümleri yanked (kullanımdan kaldırıldı) olarak bildirebilir. Bazel, bir modülün geri çekilmiş sürümü seçildiğinde hata veriyor. Bu hatayı düzeltmek için daha yeni ve geri çekilmemiş bir sürüme yükseltin veya geri çekilmiş sürüme açıkça izin vermek için --allow_yanked_versions
işaretini kullanın.
Uyumluluk düzeyi
Go'da, MVS'nin geriye dönük uyumlulukla ilgili varsayımı, bir modülün geriye dönük uyumlu olmayan sürümlerini ayrı bir modül olarak ele aldığından işe yarar. SemVer açısından bu, A 1.x
ve A 2.x
öğelerinin ayrı modüller olarak kabul edildiği ve çözümlenen bağımlılık grafiğinde birlikte bulunabileceği anlamına gelir. Bu da Go'daki paket yolunda ana sürümün kodlanmasıyla mümkün olur. Böylece derleme veya bağlantı zamanı çakışmaları olmaz.
Ancak Bazel bu tür garantiler veremez. Bu nedenle, geriye dönük olarak uyumsuz sürümleri algılamak için "ana sürüm" numarasına ihtiyaç duyar. Bu sayıya uyumluluk düzeyi adı verilir ve her modül sürümü tarafından module()
yönergesinde belirtilir. Bu bilgiler sayesinde Bazel, çözümlenen bağımlılık grafiğinde farklı uyumluluk düzeylerine sahip aynı modülün sürümlerinin bulunduğunu algıladığında hata verebilir.
Geçersiz kılar:
Bazel modülü çözümlemesinin davranışını değiştirmek için MODULE.bazel
dosyasında geçersiz kılmaları belirtin. Yalnızca kök modülün geçersiz kılmaları geçerli olur. Bir modül bağımlılık olarak kullanılıyorsa geçersiz kılmaları yoksayılır.
Her geçersiz kılma işlemi belirli bir modül adı için belirtilir ve bağımlılık grafiğindeki tüm sürümlerini etkiler. Yalnızca kök modülün geçersiz kılmaları geçerli olsa da bunlar, kök modülün doğrudan bağlı olmadığı geçişli bağımlılıklar için olabilir.
Tek sürümü geçersiz kılma
single_version_override
birkaç amaca hizmet eder:
version
özelliğiyle, bağımlılık grafiğinde hangi bağımlılık sürümlerinin istendiğinden bağımsız olarak bir bağımlılığı belirli bir sürüme sabitleyebilirsiniz.registry
özniteliğiyle, normal kayıt defteri seçimi sürecini izlemek yerine bu bağımlılığın belirli bir kayıt defterinden gelmesini zorlayabilirsiniz.patch*
özellikleri ile indirilen modüle uygulanacak bir yama grubu belirtebilirsiniz.
Bu özelliklerin tümü isteğe bağlıdır ve birbirleriyle karıştırılıp eşleştirilebilir.
Birden fazla sürümü geçersiz kılma
Aynı modülün birden fazla sürümünün çözümlenen bağımlılık grafiğinde birlikte bulunmasına izin vermek için multiple_version_override
belirtilebilir.
Modül için izin verilen sürümlerin açık bir listesini belirtebilirsiniz. Bu sürümlerin, çözümlemeden önce bağımlılık grafiğinde bulunması gerekir. İzin verilen her sürüme bağlı olarak bazı geçişli bağımlılıklar olmalıdır. Çözümden sonra yalnızca modülün izin verilen sürümleri kalır. Bazel ise modülün diğer sürümlerini aynı uyumluluk düzeyinde izin verilen en yakın yüksek sürüme yükseltir. Aynı uyumluluk düzeyinde daha yüksek bir izin verilen sürüm yoksa Bazel hata verir.
Örneğin, çözümlemeden önce bağımlılık grafiğinde 1.1
, 1.3
, 1.5
, 1.7
ve 2.0
sürümleri varsa ve ana sürüm uyumluluk düzeyi ise:
1.3
,1.7
ve2.0
sonuçlarına izin veren çok sürümlü bir geçersiz kılma işlemi,1.1
sürümünün1.3
sürümüne,1.5
sürümünün1.7
sürümüne yükseltilmesine ve diğer sürümlerin aynı kalmasına neden olur.1.5
ve2.0
'ye izin veren çok sürümlü bir geçersiz kılma işlemi,1.7
'nin aynı uyumluluk düzeyinde yükseltilebileceği daha yüksek bir sürümü olmadığı için hataya neden olur.1.9
ve2.0
sonuçlarına izin veren çok sürümlü bir geçersiz kılma işlemi,1.9
çözümlenmeden önce bağımlılık grafiğinde bulunmadığı için hataya neden olur.
Ayrıca kullanıcılar, tek sürümlü geçersiz kılmalara benzer şekilde registry
özelliğini kullanarak kayıt defterini geçersiz kılabilir.
Kayıt dışı geçersiz kılma işlemleri
Kayıt dışı geçersiz kılmalar, bir modülü sürüm çözümlemeden tamamen kaldırır. Bazel, bu MODULE.bazel
dosyaları bir kayıt defterinden değil, doğrudan depodan ister.
Bazel aşağıdaki kayıt dışı geçersiz kılmaları destekler:
Bazel modüllerini temsil etmeyen depoları tanımlama
bazel_dep
ile diğer Bazel modüllerini temsil eden depolar tanımlayabilirsiniz.
Bazen Bazel modülünü temsil etmeyen bir depo tanımlamak gerekir. Örneğin, veri olarak okunacak düz bir JSON dosyası içeren bir depo.
Bu durumda, bir depo kuralı çağırarak doğrudan bir depo tanımlamak için use_repo_rule
yönergesini kullanabilirsiniz. Bu depo yalnızca tanımlandığı modül tarafından görülebilir.
Bu özellik, arka planda module extensions ile aynı mekanizma kullanılarak uygulanır. Bu sayede, depoları daha esnek bir şekilde tanımlayabilirsiniz.
Depo adları ve katı bağımlılıklar
Bir modülü doğrudan bağımlılarına destekleyen bir deponun görünen adı, bazel_dep
yönergesinin repo_name
özelliği aksi yönde bir ifade içermediği sürece varsayılan olarak modül adı olur. Bu durumda bir modülün yalnızca doğrudan bağımlılıklarını bulabileceğini unutmayın. Bu, geçişli bağımlılıklardaki değişiklikler nedeniyle yanlışlıkla oluşan bozulmaları önlemeye yardımcı olur.
Bir modülü destekleyen deponun standart adı, bağımlılık grafiğinin tamamında modülün birden fazla sürümü olup olmadığına bağlı olarak module_name~version
(örneğin, bazel_skylib~1.0.3
) veya module_name~
(örneğin, bazel_features~
) olur (bkz. multiple_version_override
).
Standart ad biçiminin, bağımlı olmanız gereken bir API olmadığını ve herhangi bir zamanda değişebileceğini unutmayın. Kanonik adı sabit kodlamak yerine, doğrudan Bazel'den almak için desteklenen bir yöntem kullanın:
* BUILD ve .bzl
dosyalarında, Label
örneğinde Label.repo_name
kullanın.Bu örnek, depo adının görünen adıyla verilen bir etiket dizesinden oluşturulur. Örneğin:
Label("@bazel_skylib").repo_name
.
* Çalıştırma dosyalarını ararken $(rlocationpath ...)
veya @bazel_tools//tools/{bash,cpp,java}/runfiles
içindeki çalıştırma dosyası kitaplıklarından birini ya da bir kural grubu rules_foo
için @rules_foo//foo/runfiles
içindeki çalıştırma dosyası kitaplıklarından birini kullanın.
* Bazel ile IDE veya dil sunucusu gibi harici bir araçtan etkileşimde bulunurken, belirli bir dizi depo için görünen adlardan standart adlara eşlemeyi almak üzere bazel mod dump_repo_mapping
komutunu kullanın.
Modül uzantıları, bir modülün görünür kapsamına ek depolar da ekleyebilir.