Bu sayfada, Bazel'deki harici bağımlılıklar hakkında sık sorulan bazı soruların yanıtları verilmektedir.
MODULE.bazel
Bazel modüllerini nasıl sürümlemeliyim?
Kaynak arşivdeki module
yönergesiyle version
ayarlanması
MODULE.bazel
dikkatli bir şekilde yönetilmezse çeşitli dezavantajlara ve istenmeyen yan etkilere yol açabilir:
Çoğaltma: Bir modülün yeni sürümünü yayınlamak genellikle hem
MODULE.bazel
içindeki sürümü artırmayı hem de yayını etiketlemeyi içerir. Bu iki ayrı adım senkronize olmayabilir. Otomasyon bu riski azaltabilir ancak riski tamamen önlemek daha basit ve güvenlidir.Tutarsızlık: Bir modülü kayıt dışı geçersiz kılma kullanarak belirli bir commit ile geçersiz kılan kullanıcılar yanlış bir sürüm görür. Örneğin, kaynak arşivdeki
MODULE.bazel
,version = "0.3.0"
olarak ayarlanmışsa ancak bu sürümden sonra ek commit'ler yapılmışsa bu commit'lerden biriyle geçersiz kılma işlemi yapan kullanıcı yine de0.3.0
görür. Gerçekte sürüm, yayınlanmadan önce olduğunu yansıtmalıdır. Örneğin,0.3.1-rc1
.Kayıt dışı geçersiz kılma sorunları: Yer tutucu değerler kullanmak, kullanıcılar bir modülü kayıt dışı geçersiz kılmayla geçersiz kıldığında sorunlara neden olabilir. Örneğin,
0.0.0
, genellikle kullanıcıların kayıt dışı geçersiz kılma işlemi yaparken beklediği davranış olan en yüksek sürüm olarak sıralanmaz.
Bu nedenle, kaynak arşivde sürüm ayarlamaktan kaçınmak en iyisidir
MODULE.bazel
. Bunun yerine, Bazel'in harici bağımlılık çözümlemesi sırasında modül sürümü için gerçek bilgi kaynağı olan kayıt defterinde (ör.Bazel Central Registry) depolanan MODULE.bazel
içinde ayarlayın (bkz. Bazel kayıtları).
Bu işlem genellikle otomatiktir. Örneğin, rules-template
örnek kural deposu, sürümü BCR'ye yayınlamak için bazel-contrib/publish-to-bcr publish.yaml GitHub Action'ı kullanır. Bu işlem, yayın sürümüyle birlikte kaynak arşivi için bir yama oluşturur MODULE.bazel
. Bu yama, kayıt defterinde depolanır ve Bazel'in harici bağımlılık çözümlemesi sırasında modül getirildiğinde uygulanır.
Bu şekilde, kayıt defterindeki yayınlarda sürüm doğru şekilde yayınlanan sürüm olarak ayarlanır. Böylece, kaynak arşivdeki sürüm varsayılan değer (''
) olacağından kayıt defteri dışı geçersiz kılma işlemi yapılırken olası sorunlar önlenir. Bu değer her zaman doğru şekilde işlenir (sonuçta varsayılan sürüm değeridir) ve sıralama sırasında beklendiği gibi davranır (boş dize en yüksek sürüm olarak kabul edilir). Bu sayede bazel_dep
, single_version_override
ve multiple_version_override
beklendiği gibi çalışır.
Uyumluluk düzeyini ne zaman artırmalıyım?
Bir Bazel modülünün compatibility_level
, geriye dönük uyumsuz ("bozucu") bir değişikliğin yapıldığı aynı taahhütte artırılmalıdır.
Ancak Bazel, çözümlenen bağımlılık grafiğinde aynı modülün farklı uyumluluk düzeylerine sahip sürümlerinin bulunduğunu algılarsa hata verebilir. Örneğin, iki modül farklı uyumluluk düzeylerine sahip üçüncü bir modülün sürümlerine bağlı olduğunda bu durum oluşabilir.
Bu nedenle, compatibility_level
değerini çok sık artırmak oldukça rahatsız edici olabilir ve önerilmez. Bu durumu önlemek için compatibility_level
, yalnızca uyumsuzluk yaratan değişiklik çoğu kullanım alanını etkilediğinde ve kolayca taşınamadığında ve/veya geçici çözüm bulunamadığında artırılmalıdır.
MODULE.bazel neden load
'ları desteklemiyor?
Bağımlılık çözümleme sırasında, referans verilen tüm harici bağımlılıkların MODULE.bazel dosyası kayıt defterlerinden alınır. Bu aşamada, bağımlılıkların kaynak arşivleri henüz getirilmemiştir. Bu nedenle, MODULE.bazel dosyası başka bir dosya ise Bazel'in tüm kaynak arşivi getirmeden bu dosyayı getirmesinin bir yolu yoktur.load
MODULE.bazel dosyasının doğrudan kayıt defterinde barındırıldığı için özel olduğunu unutmayın.
MODULE.bazel dosyasında load
isteyen kullanıcıların genellikle ilgilendiği ve load
olmadan çözülebilecek birkaç kullanım alanı vardır:
- MODULE.bazel'de listelenen sürümün başka bir yerde depolanan derleme meta verileriyle (ör. .bzl dosyasında) tutarlı olmasını sağlama: Bu, BUILD dosyasından yüklenen bir .bzl dosyasında
native.module_version
yöntemi kullanılarak yapılabilir. - Çok büyük bir MODULE.bazel dosyasını yönetilebilir bölümlere ayırma,
özellikle tek depolu sistemler için: Kök modül, MODULE.bazel dosyasını birden fazla segmente ayırmak için
include
yönergesini kullanabilir. MODULE.bazel dosyalarındaload
s'ye izin vermememizin nedeni de aynıdır.include
, kök olmayan modüllerde kullanılamaz. - Eski WORKSPACE sisteminin kullanıcıları, bir depo bildirdiklerini ve ardından karmaşık mantık yürütmek için hemen o depodan
load
işlemi yaptıklarını hatırlayabilir. Bu özellik, modül uzantıları ile değiştirildi.
bazel_dep
için SemVer aralığı belirtebilir miyim?
Hayır. npm ve Cargo gibi diğer bazı paket yöneticileri, sürüm aralıklarını (örtülü veya açıkça) destekler. Bu da genellikle bir kısıtlama çözücü gerektirir (çıktının kullanıcılar için tahmin edilmesini zorlaştırır) ve sürüm çözümlemesini kilit dosyası olmadan yeniden üretilemez hale getirir.
Bunun yerine Bazel, Go gibi Minimal Version Selection (Minimum Sürüm Seçimi) kullanır. Bu da çıktının tahmin edilmesini kolaylaştırır ve yeniden üretilebilirliği garanti eder. Bu, Bazel'in tasarım hedefleriyle eşleşen bir denge noktasıdır.
Ayrıca, Bazel modül sürümleri SemVer'in üst kümesidir. Bu nedenle, katı bir SemVer ortamında mantıklı olan her şey Bazel modül sürümlerine aktarılmaz.
bazel_dep
için otomatik olarak en son sürümü edinebilir miyim?
Bazı kullanıcılar, bir bağımlılığın en son sürümünü otomatik olarak almak için zaman zaman bazel_dep(name = "foo",
version = "latest")
belirtme olanağı ister. Bu, SemVer aralıklarıyla ilgili soruya benzer ve yanıtı da hayır.
Bu durumda önerilen çözüm, otomasyonun bu işi yapmasını sağlamaktır. Örneğin, Renovate, Bazel modüllerini destekler.
Bazen bu soruyu soran kullanıcılar, yerel geliştirme sırasında hızlı bir şekilde yineleme yapmanın bir yolunu arıyor olabilir. Bu, local_path_override
kullanılarak yapılabilir.
Neden bu kadar çok use_repo
var?
MODULE.bazel dosyalarındaki modül uzantısı kullanımları bazen büyük bir use_repo
yönergesiyle birlikte gelir. Örneğin, gazelle
tarafından sunulan go_deps
uzantısının tipik bir kullanımı şu şekilde olabilir:
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//:go.mod")
use_repo(
go_deps,
"com_github_gogo_protobuf",
"com_github_golang_mock",
"com_github_golang_protobuf",
"org_golang_x_net",
... # potentially dozens of lines...
)
Bilgiler, referans verilen go.mod
dosyasında zaten bulunduğu için uzun use_repo
yönergesi gereksiz görünebilir.
Bazel'in bu use_repo
yönergesine ihtiyacı olmasının nedeni, modül uzantılarını geç yüklemesidir. Yani, bir modül uzantısı yalnızca sonucu gözlemlenirse çalıştırılır. Modül uzantısının "çıkışı" depo tanımları olduğundan, bu, yalnızca tanımladığı bir depo istendiğinde modül uzantısı çalıştırdığımız anlamına gelir (örneğin, yukarıdaki örnekte hedef @org_golang_x_net//:foo
oluşturulursa). Ancak, bir modül uzantısının hangi depoları tanımlayacağını, uzantıyı çalıştırana kadar bilemeyiz. Bu noktada use_repo
yönergesi devreye girer. Kullanıcı, uzantının hangi depoları oluşturmasını beklediğini Bazel'e söyleyebilir. Bazel de uzantıyı yalnızca bu depolar kullanıldığında çalıştırır.
Bu use_repo
yönergesinin korunmasına yardımcı olmak için bir modül uzantısı, uygulama işlevinden bir extension_metadata
nesnesi döndürebilir. Kullanıcı, bu modül uzantıları için use_repo
yönergelerini güncellemek üzere bazel mod tidy
komutunu çalıştırabilir.
Bzlmod'a taşıma
MODULE.bazel mi yoksa WORKSPACE mi önce değerlendirilir?
Hem --enable_bzlmod
hem de --enable_workspace
ayarlandığında hangi sisteme önce danışıldığını merak etmeniz normaldir. Kısaca, MODULE.bazel
(Bzlmod) önce değerlendirilir.
Uzun yanıt şu: "Hangisi önce değerlendirilir?" sorusu doğru soru değil. Doğru soru şu: @@foo
kanonik adı olan depo bağlamında, görünen depo adı @bar
neye dönüşür? Alternatif olarak, @@base
için depo eşlemesi nedir?
Açıkça depo adları içeren etiketler (tek bir önde gelen @
), çözümlendikleri bağlama bağlı olarak farklı şeyleri ifade edebilir. Bir etiket @bar//:baz
gördüğünüzde ve bunun aslında neye işaret ettiğini merak ettiğinizde öncelikle bağlam deposunun ne olduğunu bulmanız gerekir. Örneğin, etiket @@foo
deposunda bulunan bir BUILD dosyasındaysa bağlam deposu @@foo
olur.
Ardından, bağlam deposunun ne olduğuna bağlı olarak, görünen bir adın hangi depoya çözümlendiğini öğrenmek için taşıma kılavuzundaki "repository visibility" tablosu kullanılabilir.
- Bağlam deposu ana depo ise (
@@
):bar
, kök modülün MODULE.bazel dosyası tarafından (bazel_dep
,use_repo
,module
,use_repo_rule
aracılığıyla) tanıtılan belirgin bir depo adıysa@bar
, MODULE.bazel dosyasının iddia ettiği şekilde çözümlenir.- Aksi takdirde,
bar
WORKSPACE'te tanımlanmış bir depo ise (yani kanonik adı@@bar
ise)@bar
,@@bar
olarak çözümlenir. - Aksi takdirde,
@bar
@@[unknown repo 'bar' requested from @@]
gibi bir değere çözümlenir ve bu durum sonuç olarak hataya neden olur.
- Bağlam deposu bir Bzlmod-world deposuysa (yani kök olmayan bir Bazel modülüne karşılık geliyorsa veya bir modül uzantısı tarafından oluşturulmuşsa) yalnızca diğer Bzlmod-world depolarını görür ve WORKSPACE-world depolarını görmez.
- Bu, özellikle kök modüldeki
non_module_deps
benzeri bir modül uzantısında veya kök modüldekiuse_repo_rule
örneklemelerinde sunulan tüm depoları içerir.
- Bu, özellikle kök modüldeki
- Bağlam deposu WORKSPACE'te tanımlanmışsa:
- Öncelikle, bağlam deposu tanımında sihirli
repo_mapping
özelliğinin olup olmadığını kontrol edin. Bu durumda, önce eşlemeyi inceleyin (ör.repo_mapping = {"@bar": "@baz"}
ile tanımlanan bir depo için aşağıdaki@baz
'ye bakacağız). bar
, kök modülün MODULE.bazel dosyası tarafından sunulan belirgin bir depo adıysa@bar
, bu MODULE.bazel dosyasının iddia ettiği şekilde çözümlenir. (Bu, ana depo örneğindeki 1. öğeyle aynıdır.)- Aksi takdirde
@bar
,@@bar
olarak çözümlenir. Bu büyük olasılıkla WORKSPACE'te tanımlanan birbar
deposunu işaret eder. Böyle bir depo tanımlanmamışsa Bazel hata verir.
- Öncelikle, bağlam deposu tanımında sihirli
Daha kısa bir versiyon için:
- Bzlmod-world depoları (ana depo hariç) yalnızca Bzlmod-world depolarını görür.
- WORKSPACE-world depoları (ana depo dahil) önce Bzlmod dünyasındaki kök modülün ne tanımladığını görür, ardından WORKSPACE-world depolarını görmeye geri döner.
Bazel komut satırındaki etiketlerin (Starlark işaretleri, etiket türünde işaret değerleri ve derleme/test hedefi kalıpları dahil) bağlam deposu olarak ana depoya sahip olduğu kabul edilir.
Diğer
Çevrimdışı derlemeyi nasıl hazırlar ve çalıştırırım?
Depoları önceden getirmek için bazel fetch
komutunu kullanın. Yalnızca depoyu getirmek için --repo
işaretini (ör. bazel fetch --repo @foo
) kullanabilirsiniz @foo
(ana depo bağlamında çözülür, yukarıdaki soruya bakın) veya @foo//:bar
'nin tüm geçişli bağımlılıklarını getirmek için hedef kalıbı (ör. bazel fetch @foo//:bar
) kullanabilirsiniz (bu, bazel build --nobuild @foo//:bar
ile eşdeğerdir).
Derleme sırasında getirme işlemi yapılmadığından emin olmak için --nofetch
kullanın. Daha net bir ifadeyle, bu durum yerel olmayan bir depo kuralını çalıştırma girişimlerinin başarısız olmasına neden olur.
Depoları getirip ve yerel olarak test etmek için değiştirmek istiyorsanız bazel vendor
komutunu kullanabilirsiniz.
HTTP proxy'leri nasıl kullanırım?
Bazel, http_proxy
ve HTTPS_PROXY
ortam değişkenlerini diğer programlar gibi yaygın olarak kabul eder (ör. curl).
How do I make Bazel prefer IPv6 in dual-stack IPv4/IPv6 setups?
Yalnızca IPv6 kullanan makinelerde Bazel, bağımlılıkları herhangi bir değişiklik yapmadan indirebilir. Ancak, çift yığınlı IPv4/IPv6 makinelerde Bazel, Java ile aynı kuralı izler ve etkinse IPv4'ü tercih eder. Bazı durumlarda (ör. IPv4 ağı harici adresleri çözemediğinde/bu adreslere ulaşamadığında) bu durum Network
unreachable
istisnalarına ve derleme hatalarına neden olabilir. Bu durumlarda, java.net.preferIPv6Addresses=true
system
property özelliğini kullanarak Bazel'ın davranışını geçersiz kılabilir ve IPv6'yı tercih edebilirsiniz.
Özellikle:
--host_jvm_args=-Djava.net.preferIPv6Addresses=true
startup option'ı kullanın. Örneğin,.bazelrc
dosyanıza aşağıdaki satırı ekleyin:startup --host_jvm_args=-Djava.net.preferIPv6Addresses=true
İnternete bağlanması gereken Java derleme hedefleri (ör. entegrasyon testleri için) çalıştırırken
--jvmopt=-Djava.net.preferIPv6Addresses=true
tool flag'i kullanın. Örneğin,.bazelrc
dosyanıza aşağıdakileri ekleyin:build --jvmopt=-Djava.net.preferIPv6Addresses
Bağımlılık sürümü çözümü için
rules_jvm_external
kullanıyorsanızCOURSIER_OPTS
ortam değişkenine-Djava.net.preferIPv6Addresses=true
de ekleyerek Coursier için JVM seçenekleri sağlayın.
Depo kuralları, uzaktan yürütme ile uzaktan çalıştırılabilir mi?
Hayır veya en azından henüz değil. Derlemelerini hızlandırmak için uzaktan yürütme hizmetlerini kullanan kullanıcılar, depo kurallarının hâlâ yerel olarak çalıştırıldığını fark edebilir. Örneğin, bir http_archive
önce yerel makineye indirilir (varsa yerel indirme önbelleği kullanılarak), çıkarılır ve ardından her kaynak dosya, giriş dosyası olarak uzak yürütme hizmetine yüklenir. Uzaktan yürütme hizmetinin neden bu arşivi indirip ayıklamadığı ve böylece gereksiz bir gidiş dönüşü önlemediği sorusu akla gelebilir.
Bunun bir nedeni, depo kurallarının (ve modül uzantılarının) Bazel'in kendisi tarafından çalıştırılan "komut dosyalarına" benzemesidir. Uzak yürütücüde Bazel'in yüklü olması bile gerekmez.
Başka bir neden de Bazel'in yükleme ve analiz işlemlerini gerçekleştirmek için genellikle indirilen ve çıkarılan arşivlerdeki BUILD dosyalarına ihtiyaç duymasıdır. Bu işlemler yerel olarak gerçekleştirilir.
Depo kurallarını derleme kuralları olarak yeniden tasarlayarak bu sorunu çözmeye yönelik ön fikirler var. Bu fikirler, kuralların doğal olarak uzaktan çalıştırılmasına olanak tanıyacak ancak bunun karşılığında yeni mimari endişelere yol açacak (ör. query
komutlarının işlemleri çalıştırması gerekebilir ve bu da tasarımlarını karmaşıklaştırır).
Bu konuyla ilgili daha önceki tartışmalar için A way to support repositories that need Bazel for being fetched başlıklı makaleyi inceleyin.