Sık sorulan sorular

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ı, dikkatli bir şekilde yönetilmediği takdirde MODULE.bazel ç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 ortadan kaldırmak daha basit ve güvenlidir.

  • Tutarsızlık: Bir modülü kayıt dışı geçersiz kılma kullanarak belirli bir işlemeyle 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 işlemeler yapılmışsa bu işlemelerden biriyle geçersiz kılma işlemi yapan kullanıcılar yine 0.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ğerlerin kullanılması, kullanıcılar bir modülü kayıt dışı geçersiz kılma ile 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 istediği davranış olan en yüksek sürüm olarak sıralanmaz.

Bu nedenle, sürümü kaynak arşivde ayarlamaktan kaçınmak en iyisidir MODULE.bazel. Bunun yerine, kayıt defterinde depolanan MODULE.bazel içinde ayarlayın (ör.Bazel Central Registry). Bu, Bazel'in harici bağımlılık çözümlemesi sırasında modül sürümünün gerçek bilgi kaynağıdır (Bazel kayıtları bölümüne bakın).

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 yama oluştururMODULE.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 sayede, kayıt defterindeki yayınlarda sürüm doğru şekilde yayınlanan sürüm olarak ayarlanır ve böylece bazel_dep, single_version_override ve multiple_version_override beklendiği gibi çalışır. 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).

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ı commit işleminde 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ün farklı uyumluluk düzeylerine sahip üçüncü bir modülün sürümlerine bağlı olması bu duruma neden olabilir.

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 dosyaysa Bazel'in tüm kaynak arşivini getirmeden bu dosyayı getirmesi mümkün değildir.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 (ör. .bzl dosyasında) depolanan derleme meta verileriyle tutarlı olmasını sağlama: Bu, bir BUILD dosyasından yüklenen .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. Aynı nedenle MODULE.bazel dosyalarında load kullanılmasına izin verilmez. 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 ettiklerini 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 Sürüm Seçimi'ni 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 en son sürümü otomatik olarak alabilir 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.

Burada önerilen çözüm, bu işi otomasyona bırakmaktı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'den alınan 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 ihtiyaç duyması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 durum yalnızca tanımladığı bir depo istenirse modül uzantısı çalıştıracağı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ı, çalıştırılana 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 bazel mod tidy komutunu çalıştırarak use_repo yönergelerini güncelleyebilir.

Bzlmod 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 edebilirsiniz. Kısa yanıt, MODULE.bazel (Bzlmod) dosyasının önce değerlendirildiğidir.

Uzun yanıt ise "hangisi önce değerlendirilir?" sorusunun doğru soru olmadığıdır. Bunun yerine, standart adı @@foo olan depo bağlamında görünen depo adı @bar neye karşılık gelir? sorusu sorulmalıdır. Alternatif olarak, @@base için depo eşlemesi nedir?

Açıkça depo adları içeren etiketler (tek bir baştaki @), çö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, taşıma kılavuzundaki "repository visibility" tablosu, görünen bir adın hangi depoya çözümlendiğini bulmak için kullanılabilir.

  • Bağlam deposu ana depo ise (@@):
    1. 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, söz konusu MODULE.bazel dosyasının iddia ettiği şekilde çözümlenir.
    2. Aksi takdirde, bar WORKSPACE'te tanımlanmış bir depo ise (yani kanonik adı @@bar ise) @bar, @@bar olarak çözümlenir.
    3. 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üldeki use_repo_rule örneklemelerinde tanıtılan tüm depoları içerir.
  • Bağlam deposu WORKSPACE'te tanımlanmışsa:
    1. Ö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ımlanmış bir depo için aşağıdaki @baz'ye bakacağız).
    2. bar, kök modülün MODULE.bazel dosyası tarafından tanıtılan 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.)
    3. Aksi takdirde @bar, @@bar olarak çözümlenir. Bu büyük olasılıkla WORKSPACE'te tanımlanan bir depoya bar işaret eder. Böyle bir depo tanımlanmamışsa Bazel hata verir.

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 --repo deposunu getirmek için bazel fetch --repo @foo gibi bir işaret kullanabilir (ana depo bağlamında çözülür, yukarıdaki soruya bakın) veya @foo//:bar öğesinin tüm geçişli bağımlılıklarını getirmek için bazel fetch @foo//:bar gibi bir hedef kalıbı kullanabilirsiniz (bu, bazel build --nobuild @foo//:bar ile eşdeğerdir).@foo

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.

Derlemelerimi internetten nasıl yalıtabilirim?

Tipik bir Bazel derlemesinin bağlı olduğu, herkese açık internetteki bazı web siteleri ve özellikle kurumsal bir Bazel kullanıcısı olarak kendinizi olası kesintilerden korumak için yapabilecekleriniz aşağıda açıklanmıştır.

  • releases.bazel.build: Bazelisk, Bazel sürüm ikililerini bu web sitesinden indirir. Bunun yerine şirketinizin dahili yansıtma sunucusundan indirmesi için Bazelisk'i yapılandırabilirsiniz.
  • bcr.bazel.build: Bazel, modül çözümleme sırasında modül meta verileri için BCR'ye danışır. BCR'nin kendisini yansıtabilir ve --registry işaretini ayarlayarak BCR yayınlama altyapısına olan bağımlılığınızı kaldırabilirsiniz (daha fazla bilgi için sorumluluk reddi beyanına bakın). Alternatif olarak, MODULE.bazel.lock dosyanızın güncel olduğundan emin olabilir ve CI veya geliştirici makinelerinizi önceden doldurulmuş bir indirme önbelleğiyle (--repository_cache) ayarlayabilirsiniz. Doğru şekilde ayarlanırsa indirme önbelleği, derleme için gereken tüm kayıt dosyalarını içerir ve kilit dosyası, bu dosyaların sağlama toplamlarını içerir. Ardından Bazel, önbelleğe alınmış sonuçları kullanır ve modül çözümü sırasında internet erişimini tamamen önler.
  • mirror.bazel.build ve github.com: Birçok modülün kaynak arşivleri bu iki web sitesinde barındırılır. Kaynak arşivleri için şirket içinde bir yansıtma oluşturmayı ve Bazel'i bu arşivlere yönlendirmek için --downloader_config veya --module_mirrors kullanmayı düşünebilirsiniz. Alternatif olarak, önceki madde işaretinde belirtildiği gibi önceden doldurulmuş bir indirme önbelleği de Bazel'in kaynak arşivleri için internete erişmekten tamamen kaçınmasına yardımcı olur.

HTTP proxy'leri nasıl kullanırım?

Bazel, diğer programlar (ör. curl) tarafından yaygın olarak kabul edilen http_proxy ve HTTPS_PROXY ortam değişkenlerine uyar.

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:

  • Örneğin, .bazelrc dosyanıza aşağıdaki satırı ekleyerek --host_jvm_args=-Djava.net.preferIPv6Addresses=true başlangıç seçeneğini kullanın:

    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ız COURSIER_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, 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 yerel olarak çalıştırılmaya devam ettiğini 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, uzak yürütme hizmetine giriş dosyası olarak 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.

Diğer bir neden ise Bazel'in, yükleme ve analiz işlemlerini gerçekleştirmek için genellikle indirilen ve ayıklanan arşivlerdeki BUILD dosyalarına ihtiyacı olması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 (örneğin, query komutlarının işlemleri çalıştırması gerekebilir ve bu da tasarımlarını karmaşıklaştırır).

Bu konuyla ilgili önceki tartışmalar için A way to support repositories that need Bazel for being fetched başlıklı makaleyi inceleyin.