Bazel modülü, birden fazla sürümü olabilecek bir Bazel projesidir. Her sürüm, bağlı olduğu diğer modüller hakkında meta veriler yayınlar. Bu, Maven öğesi, npm paketi, Go modülü veya Cargo kutusu gibi diğer bağımlılık yönetimi sistemlerindeki bilinen kavramlara benzer.
Bir modülün, depo kökünde (WORKSPACE
dosyasının yanında) bir MODULE.bazel
dosyası olmalıdır. Bu dosya, modülün adını, sürümünü, doğrudan bağımlılıklarının listesini ve diğer bilgileri açıklayan manifest dosyasıdır. Temel bir örnek verecek olursak:
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ümlemeyi gerçekleştirmek için kök modülün MODULE.bazel
dosyasını okuyarak başlar ve ardından bağımlılık grafiğinin tamamını keşfedene kadar Bazel kayıt otoritesinden tüm bağımlılıkların MODULE.bazel
dosyasını tekrar tekrar ister.
Daha sonra Bazel varsayılan olarak kullanılacak her modülün bir sürümünü seçer. Bazel, her modülü bir depoyla temsil eder ve depoların her birinin nasıl tanımlanacağını öğrenmek için kayıt defterine tekrar başvurur.
Sürüm biçimi
Bazel'in çeşitli bir ekosistemi vardır ve projelerde çeşitli sürümlendirme şemaları kullanılır. Şu ana kadar en popüler olan SemVer olsa da farklı şemaların kullanıldığı önemli projeler de vardır. Örneğin 20210324.2
gibi versiyonları tarih tabanlı olan Abseil).
Bu nedenle Bzlmod, SemVer spesifikasyonunun daha esnek bir sürümünü kullanır. Farklılıklar şunlardır:
- SemVer, sürümün "sürüm" kısmının 3 segmentten oluşması gerektiğini belirtir:
MAJOR.MINOR.PATCH
. Bazel'de bu şart, herhangi bir sayıda segmente izin verecek şekilde gevşetilmiştir. - SemVer'de "sürüm" bölümündeki her segment yalnızca rakam içermelidir. Bazel'de bu, harflere de izin verecek şekilde gevşetilir ve karşılaştırma semantikleri, "ön sürüm" bölümündeki "tanımlayıcılar" ile eşleşir.
- Ayrıca, ana, alt ve yama sürümü artışlarının semantikleri zorunlu kılınmaz. Bununla birlikte, geriye dönük uyumluluğu nasıl ifade ettiğimizle ilgili ayrıntılar için uyumluluk düzeyine bakın.
Geçerli tüm SemVer sürümleri geçerli Bazel modülü sürümüdür. Ayrıca, iki SemVer sürümü a
ve b
, Bazel modülü sürümleri olarak karşılaştırıldığında aynı sonucu verirse ve yalnızca bu durumda a < b
ile karşılaştırılır.
Sürüm seçimi
Sürümlü bağımlılık yönetimi alanında temel bir unsur olan elmas bağımlılık sorununu düşünün. Aşağıdaki bağımlılığı grafiğiniz olduğunu varsayalım:
A 1.0
/ \
B 1.0 C 1.1
| |
D 1.0 D 1.1
D
'nin hangi sürümü kullanılmalıdır? Bzlmod, bu soruyu yanıtlamak için Go modül sisteminde sunulan Minimal Sürüm Seçimi (MVS) algoritmasını kullanıyor. MVS, bir modülün tüm yeni sürümlerinin geriye dönük 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 "minimal" olarak adlandırılmıştır, çünkü D 1.1
, gereksinimlerimizi karşılayabilecek ilk sürümdür. D 1.2
veya daha yeni bir sürüm mevcut olsa bile, bunları seçmeyiz. MVS kullanılması, yüksek kaliteli ve tekrarlanabilir bir sürüm seçme süreci oluşturur.
Geri çekilen sürümler
Kayıt defteri, belirli sürümlerin kullanılmasından kaçınılması gerekiyorsa (ör. güvenlik açıkları nedeniyle) bu sürümleri geri çekilmiş olarak tanımlayabilir. Bazel, bir modülün geri çekilmiş sürümünü seçerken hata veriyor. Bu hatayı düzeltmek için yayından kaldırılmamış, daha yeni bir sürüme geçin veya yayından kaldırılmış sürüme açıkça izin vermek için --allow_yanked_versions
işaretini kullanın.
Uyumluluk seviyesi
Go'da MVS'nin geriye dönük uyumluluk varsayımı, bir modülün geriye dönük uyumsuz sürümlerini ayrı bir modül olarak ele aldığı için işe yarar. SemVer açısından bu, A 1.x
ve A 2.x
'nin ayrı modüller olarak kabul edildiği ve çözümlenen bağımlılık grafiğinde bir arada bulunabileceği anlamına gelir. Bu da Go'da paket yolunda büyük sürümü kodlayarak mümkün kılınmıştır. Böylece derleme veya bağlantı sırasında herhangi bir çakışma olmaz.
Ancak Bazel bu tür garantiler sağlayamaz. Bu nedenle, geriye dönük uyumlu olmayan sürümleri algılamak için "büyük sürüm" numarasına ihtiyacı vardır. Bu sayıya uyumluluk düzeyi denir ve her modül sürümü tarafından module()
yönergesinde belirtilir. Bazel, bu bilgilerle, çözülmüş bağımlılık grafiğinde aynı modülün farklı uyumluluk düzeylerine sahip sürümlerinin bulunduğunu tespit ettiğinde 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ılma işlemlerini belirtin. Yalnızca kök modülün geçersiz kılma işlemleri geçerli olur. Bir modül bağımlılık olarak kullanılırsa geçersiz kılma işlemleri dikkate alınmaz.
Her geçersiz kılma, bağımlılık grafiğindeki tüm sürümlerini etkileyen belirli bir modül adı için belirtilir. Yalnızca kök modülün geçersiz kılma işlemleri geçerli olsa da bu geçersiz kılma işlemleri, kök modülün doğrudan bağlı olmadığı geçişli bağımlılar için olabilir.
Tek sürüm geçersiz kılma
single_version_override
birden fazla amaca hizmet eder:
version
özelliğiyle, bağımlılığın hangi sürümlerinin bağımlılığı grafiğinde istendiğine bakılmaksızın bir bağımlılığı belirli bir sürüme sabitleyebilirsiniz.registry
özelliğiyle, normal kayıt defteri seçim sürecini izlemek yerine bu bağımlılığın belirli bir kayıt defteri tarafından sağlanmasını zorunlu kılabilirsiniz.patch*
özellikleriyle, indirilen modüle uygulanacak bir dizi yamayı 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ün geçersiz kılınması
Çözüme ulaştırılan bağımlılık grafiğinde aynı modülün birden fazla sürümünün birlikte var olmasına izin vermek için bir multiple_version_override
belirtilebilir.
Modül için izin verilen sürümlerin açık bir listesini belirtebilirsiniz. Bu liste, çözümden önce bağımlılık grafiğinde bulunmalıdır. İzin verilen her sürüme bağlı olarak, geçişli bir bağımlılık olması gerekir. Çözümleme işleminden sonra, modülün yalnızca 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 sürüme yükseltir. Aynı uyumluluk düzeyinde izin verilen daha yüksek bir sürüm yoksa Bazel hata verir.
Örneğin, çözümleme öncesi bağımlılık grafiğinde 1.1
, 1.3
, 1.5
, 1.7
ve 2.0
sürümleri varsa ve büyük sürüm uyumluluk düzeyiyse:
1.3
,1.7
ve2.0
'ye izin veren birden fazla sürümün geçersiz kılınması,1.1
'in1.3
,1.5
'in1.7
sürümüne yükseltilmesine ve diğer sürümlerin aynı kalmasına neden olur.1.5
ve2.0
'e izin veren birden fazla sürüm geçersiz kılma işlemi,1.7
'nin aynı uyumluluk düzeyinde yükseltilebilecek daha yüksek bir sürümü olmadığı için hatayla sonuçlanır.- Çözümden önce bağımlılık grafiğinde
1.9
bulunmadığı için1.9
ve2.0
'e izin veren birden fazla sürüm geçersiz kılma işlemi hata verir.
Ayrıca kullanıcılar, tek sürüm geçersiz kılma işlemlerine benzer şekilde registry
özelliğini kullanarak kayıt defterini geçersiz kılabilir.
Kayıt otoritesi dışındaki geçersiz kılmalar
Kayıt dışı geçersiz kılma işlemleri, bir modülü sürüm çözünürlüğünden tamamen kaldırır. Bazel, bu MODULE.bazel
dosyalarını bir kayıt defterinden değil, deponun kendisinden ister.
Bazel, kayıt otoritesi dışındaki aşağıdaki geçersiz kılma işlemlerini 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ü olmayan bir depo tanımlamanız gerekir. Örneğin, veri olarak okunacak düz bir JSON dosyası içeren bir depo.
Bu durumda, bir depo kuralını ç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, modül uzantılarıyla aynı mekanizma kullanılarak uygulanır. Bu sayede, depoları daha fazla esneklikle tanımlayabilirsiniz.
Depo adları ve katı bağımlılar
Bir modülü doğrudan bağımlılarına destekleyen bir deponun görünür adı, bazel_dep
yönergesinin repo_name
özelliği aksini belirtmediği sürece varsayılan olarak modül adıdır. Bu, bir modülün yalnızca doğrudan bağımlılarını bulabileceği anlamına gelir. Bu, geçişli bağımlılıklardaki değişiklikler nedeniyle yanlışlıkla oluşabilecek kesintileri önlemeye yardımcı olur.
Bir modülü destekleyen deposunun kanonik adı, bağımlılık grafiğinin tamamında modülün birden fazla sürümünün olup olmadığına bağlı olarak module_name~version
(ör. bazel_skylib~1.0.3
) veya module_name~
(ör. bazel_features~
) olur (multiple_version_override
bölümüne bakın). Kanonik ad biçiminin, güvenebileceğiniz 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.repo_name
değerini, deponun görünen adı tarafından verilen bir etiket dizesinden oluşturulan bir Label
örneğinde kullanın. Örneğin:
Label("@bazel_skylib").repo_name
.
* Çalışma dosyalarını ararken $(rlocationpath ...)
veya @bazel_tools//tools/{bash,cpp,java}/runfiles
'daki çalışma dosyası kitaplıklarından birini ya da rules_foo
kural kümesi için @rules_foo//foo/runfiles
'i kullanın.
* Bazel ile IDE veya dil sunucusu gibi harici bir araçtan etkileşime geçtiğinizde, belirli bir depo grubu 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.