Harici bağımlılıkları Bzlmod ile yönetin

. Sorun bildirin Kaynağı göster Gece · 7,3 · 7,2 · 7,1 · 7,0 · 6,5

Bzlmod, yeni harici bağımlılık sisteminin kod adıdır. kullanıma sunduk. Pazarlama sürecinin birtakım sorunları aşamalı olarak düzeltilemeyecek eski bir sistem bkz. Orijinal tasarım dokümanının Sorun Beyanı bölümü inceleyebilirsiniz.

Bazel 5.0'da Bzlmod varsayılan olarak etkin değildir. bayrak Aşağıdakilerin geçerli olması için --experimental_enable_bzlmod belirtilmelidir etkisi. İşaret adından da anlaşılacağı gibi, bu özellik şu anda deneme aşamasındadır; Özellik resmi olarak kullanıma sunulana kadar API'ler ve davranışlar değişebilir.

Projenizi Bzlmod'a taşımak için Bzlmod Taşıma Rehberi'ndeki talimatları uygulayın. examples deposunda örnek Bzlmod kullanımlarını da bulabilirsiniz.

Bazel Modülleri

Eski WORKSPACE tabanlı harici bağımlılık sisteminin merkezinde Depo kuralları (veya depo kuralları) aracılığıyla oluşturulan depolar (veya depolar). Depolar yeni sistemde hâlâ önemli bir kavram olsa da modüller, temel bağımlılık birimleridir.

Modül, temelde her biri birden çok sürümü olabilen bir Bazel projesidir. Bu modül, bağımlı olduğu diğer modüllerle ilgili meta verileri yayınlar. Bu diğer bağımlılık yönetimi sistemlerindeki bilinen kavramlara benzer: Maven artifact, bir npm paketi, kargo kabı, Go modülü vb.

Bir modül name ve version çiftlerini kullanarak bağımlılıklarını belirtir. yerine WORKSPACE içindeki belirli URL'ler yerine kullanabilirsiniz. Daha sonra bu bağımlılıklar Bazel sicil dairesi; varsayılan olarak Bazel Central Registry. Çalışma alanınızda modülü de bir depoya dönüştürülür.

MODULE.bazel

Her modülün her sürümünde, aşağıdakileri beyan eden bir MODULE.bazel dosyası bulunur: ve diğer meta verileri içerir. Aşağıda temel bir örnek verilmiştir:

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 dosyası, Workspace dizininin kök dizininde bulunmalıdır. (WORKSPACE dosyasının yanında). WORKSPACE dosyasından farklı olarak geçişli bağımlılıklarınızı belirtmek için; Bunun yerine yalnızca doğrudan bağımlılıklar ve bağımlılıklarınızın MODULE.bazel dosyaları ve geçişli bağımlılıkları otomatik olarak keşfetmek için kullanılır.

MODULE.bazel dosyası desteklenmeyen BUILD dosyalarına benziyor Kontrol akışı biçimi; ayrıca load ifadelerine de izin verilmez. Yönergeler MODULE.bazel dosyaları desteklenir:

Sürüm biçimi

Bazel çeşitlilik içeren bir ekosisteme sahiptir ve projelerde çeşitli sürüm oluşturma şemaları kullanılmaktadır. İlgili içeriği oluşturmak için kullanılan en popüler olanı SemVer, ancak çeşitli şemaların kullanıldığı önemli projeler, örneğin Abseil sürümler tarihe dayalıdır (örneğin, 20210324.2).

Bu nedenle, Bzlmod SemVer spesifikasyonunun daha rahat bir sürümünü kullanır. İlgili içeriği oluşturmak için kullanılan farklılıklar şunları içerir:

  • SemVer, “yayınlanan” sürüm bölümü 3'ten oluşmalıdır segmentler: MAJOR.MINOR.PATCH. Bazel'de bu şart gevşetilmiştir. izin verilen belirli bir sayıda segmente izin verilir.
  • SemVer'de, "sürüm"deki segmentlerin her biri kısmı yalnızca rakamlardan oluşmalıdır. Bazel'de bu değer gevşetilerek harflere de izin verilir ve karşılaştırma anlamsal olarak "tanımlayıcılar" ile eşleşir "yayın öncesi"nde bölümü.
  • Ayrıca ana, alt ve yama sürümü artışlarının anlamları da zorunlu kılınmaz. (Ancak sonuçlar için uyumluluk düzeyine ilişkin ayrıntıları inceleyin.)

Geçerli herhangi bir SemVer sürümü, geçerli bir Bazel modülü sürümüdür. Buna ek olarak, Aynı muhafazalar etkinken a ve b SemVer sürümleri, a < b Bazel modül sürümleriyle karşılaştırıldı.

Sürüm çözünürlüğü

Elmas bağımlılık problemi, sürümlü bağımlılıkların en önemli unsurlarından biridir. yönetim alanında Aşağıdaki bağımlılık grafiğine sahip olduğunuzu 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 çözmek için Minimum Sürüm Seçimi (MVS) algoritması kullanıma sunuldu. MVS, tüm yeni içeriklerin sürümlerin geriye dönük uyumluluğa sahip olduğunu ve bu nedenle, herhangi bir bağımlı tarafından belirtilen sürüm (örneğimizde D 1.1). Adı "minimal" Çünkü D 1.1 gereksinimlerimizi karşılayabilecek en küçük sürümdür; D 1.2 veya daha yeni bir sürüm mevcut olsa bile, bunları seçmeyiz. Bunun ek bir faydası var. sürüm seçiminin yüksek doğrulukta ve yeniden oluşturulabilir olduğundan emin olun.

Sürüm çözümlemesi, kayıt defteri tarafından değil, makinenizde yerel olarak gerçekleştirilir.

Uyumluluk düzeyi

MVS'nin geriye dönük uyumlulukla ilgili varsayımı, bir modülün geriye dönük uyumsuz sürümlerini ayrı bir modül olarak ele alır. SemVer açısından bu, A 1.x ve A 2.x'in ayrı modüller olarak kabul edildiği anlamına gelir. ve çözülmüş bağımlılık grafiğinde bir arada bulunabilir. Bu da aynı zamanda ana sürümün paket yolunda kodlanması sayesinde mümkün Böylece hiçbir derleme zamanı veya bağlantı zamanı çakışması olmaz.

Bazel'de böyle bir garantimiz yoktur. Dolayısıyla, en önemli husustan bahsederken sürüm" sayısını kontrol etmek için kullanır. Bu numara uyumluluk düzeyi olarak adlandırılır ve module() yönergesi. Bu bilgiler elimize ulaştığında hata yapabiliriz aynı modülün sürümlerinin farklı uyumluluğa sahip olduğunu tespit ettiğimizde düzeyleri çözülmüş bağımlılık grafiğinde bulunur.

Kod deposu adları

Bazel'de her harici bağımlılığın bir depo adı vardır. Bazen aynı bağımlılık farklı depo adlarıyla kullanılabilir (örneğin, @io_bazel_skylib ve @bazel_skylib ortalama Bazel skylib) veya aynı depo adı, farklı projelerdeki farklı bağımlılıklar için kullanılabilir.

Bzlmod'da, depolar Bazel modülleri ve modül uzantılarını inceleyin. Depo adı çakışmalarını çözmek için depo eşlemeyi benimsiyoruz. mekanizmaya geçmeleri gerekir. İki önemli kavram aşağıda açıklanmıştır:

  • Standart depo adı: Her biri için global olarak benzersiz depo adı depodur. Bu, deponun bulunduğu dizin adı olacaktır.
    Aşağıdaki gibi oluşturulmuştur (Uyarı: Standart ad biçimi (bu API, kullanılması gereken bir API değildir; her zaman değişebilir):

    • Bazel modül depoları için: module_name~version
      (Örnek. @bazel_skylib~1.0.3)
    • Modül uzantısı depoları için: module_name~version~extension_name~repo_name
      (Örnek. @rules_cc~0.0.1~cc_configure~local_config_cc)
  • Görünür kod deposu adı: BUILD ve Bir kod deposunda .bzl dosya. Aynı bağımlılık farklı bir görünüme sahip olabilir farklı repolarda yer alır.
    Şu şekilde belirlenir:

    • Bazel modül havuzları için: module_name tarafından veya repo_name özelliği tarafından belirtilen ad bazel_dep.
    • Modül uzantı depoları için: depo adı use_repo.

Her deponun doğrudan bağımlılıklarını içeren bir depo eşleme sözlüğü vardır. Bu, görünen kod deposu adından standart depo adına yönlendiren bir haritadır. Kod deposu eşlemesini, bir etiket. Standart depo adları arasında herhangi bir çakışma olmadığını ve görünen depo adlarının kullanımları, MODULE.bazel ayrıştırılarak keşfedilebilir. Böylece, çakışmalar etkilenmeden kolayca yakalanıp çözülebilir. ve diğer bağımlılıkları belirlemenize yardımcı olur.

Katı kısıtlamalar

Yeni bağımlılık spesifikasyonu biçimi, daha katı denetimler gerçekleştirmemize olanak tanıyor. İçinde bir modülün yalnızca kendi API'leri ile oluşturulan ve doğrudan bağımlılıkları ifade eder. Bu sayede, yanlışlıkla ve hata ayıklaması zor olan kesintilerin önüne geçilir geçişli bağımlılık grafiğindeki bir şey değiştiğinde ortaya çıkar.

Katı yetkilendirmeler şuna göre uygulanır: depo eşleme ile ilgili daha fazla bilgi edinin. Özetlemek gerekirse Her depo için depo eşleme tüm doğrudan bağımlılıklarını, diğer depo görünür değil. Her depo için görünür bağımlılıklar şu şekilde belirlenir:

  • Bazel modül deposu, MODULE.bazel dosyasında sunulan tüm depoları görebilir bazel_dep ve use_repo.
  • Modül uzantı deposu, modülün mevcut bağımlılıklarını , uzantıyı ve aynı modül tarafından oluşturulan diğer tüm depoları sağlar uzantısına sahip olur.

Kayıtlar

Bzlmod, Bazel'dan bilgilerini isteyerek bağımlılıkları tespit ediyor kayıtları. Bazel kaydı, basit bir şekilde Bazel modüllerinin yer aldığı bir veritabanıdır. Tek Desteklenen bir kayıt otoritesi, dizin kaydı şeklindedir. yerel bir dizin veya belirli bir biçimi izleyen statik HTTP sunucusudur. tek modüllü kayıt defterleri için destek sunmayı planlıyoruz. projenin kaynağını ve geçmişini içeren git depolarıdır.

Dizin kaydı

Dizin kayıt defteri, aşağıdakileri içeren bir yerel dizin veya statik HTTP sunucusudur: ana sayfaları, bakımını yapan kişiler, modüller ve Her sürümün MODULE.bazel dosyası ve her sürümün kaynağının nasıl getirileceği sürümünü değil. Özellikle kaynak arşivlerin kendisini sunması gerekmez.

Dizin kaydı aşağıdaki biçimde olmalıdır:

  • /bazel_registry.json: Kayıt defteriyle ilgili aşağıdaki gibi meta verileri içeren bir JSON dosyası:
    • mirrors, kaynak arşivler için kullanılacak yansıtmaların listesini belirtiyor.
    • module_base_path, aşağıdakileri içeren modüller için temel yolu belirtir: source.json dosyasına local_repository türü ekleyin.
  • /modules: Bu dizindeki her modülün alt dizinini içeren kayıt otoritesi.
  • /modules/$MODULE: Her sürüm için bir alt dizin içeren dizin şu dosyanın yanı sıra inceleyin:
    • metadata.json: Modül hakkında bilgi içeren bir JSON dosyası, şu alanları kullanın:
      • homepage: Proje ana sayfasının URL'si.
      • maintainers: Her biri kayıt defterindeki modülün koruyucu bilgilerini içerir. Bunun yazarlarla aynı olması gerekmediğini unutmayın belirler.
      • versions: Bu modülün şurada bulunacak tüm sürümlerinin listesi: kayıt defterinden dışa aktarma işlemi yapılır.
      • yanked_versions: Bu modülün yanked sürümlerinin listesi. Bu şu an için işlemsizdir ancak gelecekte, yanked sürümleri atladığı veya hata verdiği anlamına geliyor.
  • /modules/$MODULE/$VERSION: Şu dosyaları içeren bir dizin:
    • MODULE.bazel: Bu modül sürümünün MODULE.bazel dosyası.
    • source.json: bu modül sürümünün kaynağını kontrol edin.
      • Varsayılan tür: "arşiv" şu alanları kullanın:
        • url: Kaynak arşivin URL'si.
        • integrity: Alt Kaynak Bütünlüğü sağlama toplamıdır.
        • strip_prefix: Ayıklanırken çıkarılacak dizin öneki. kaynak arşivi.
        • patches: Her biri bir yama dosyasını uygulanır. Yama dosyaları şunun altında bulunur: /modules/$MODULE/$VERSION/patches dizini.
        • patch_strip: Unix yamasının --strip bağımsız değişkeniyle aynıdır.
      • Tür, şu alanlarla yerel bir yol kullanacak şekilde değiştirilebilir:
        • type: local_path
        • path: Deponun yerel yolu. Şu şekilde hesaplanır:
          • Yol mutlak bir yolsa olduğu gibi kullanılır.
          • Yol göreli bir yol ve module_base_path mutlak bir yolsa yol <module_base_path>/<path> olarak çözümlendi
          • Hem yol hem de module_base_path göreli yollarsa yol <registry_path>/<module_base_path>/<path> olarak çözüldü. Kayıt defteri, yerel olarak barındırılmalı ve --registry=file://<registry_path> tarafından kullanılmalıdır. Aksi takdirde, Bazel hata verir.
    • patches/: Yama dosyalarını içeren isteğe bağlı bir dizin (yalnızca source.json "arşiv" içerdiğinde kullanılır) türü.

Bazel Merkezi Kayıt Otoritesi

Bazel Central Registry (BCR), aşağıdaki konumda bulunan bir dizin kaydı kuruluşudur: bcr.bazel.build. İçeriği GitHub deposuyla destekleniyor bazelbuild/bazel-central-registry.

BCR, Bazel topluluğu tarafından yönetilir; katkıda bulunanlar gönderebilir pull istekleri. Görüntüleyin Bazel Merkezi Kayıt Politikaları ve Prosedürleri.

BCR, normal bir dizin kaydı biçimine ek olarak, her modül sürümü için bir presubmit.yml dosyası (/modules/$MODULE/$VERSION/presubmit.yml). Bu dosyada proje yönetiminde bu testin geçerliliğini kontrol etmek için kullanılabilecek geliştirme ve test hedefleri modül sürümü vardır ve birlikte çalışabilirlik sağlamak için BCR'nin CI ardışık düzenleri tarafından kullanılır BCR'deki modüllerin arasında.

Kayıt otoritelerini seçme

Tekrarlanabilir Bazel işareti --registry, kayıt defterleri ekleyebilirsiniz. Böylece projenizi, gerekli değişiklikleri yapmaya bağımlılığınızı kontrol altında tutabilirsiniz. Daha önceki kayıtlarda önceliklendirme. Kolaylık sağlaması açısından --registry işaretlerini Projenizin .bazelrc dosyası.

Modül Uzantıları

Modül uzantıları, giriş verilerini okuyarak modül sistemini genişletmenize olanak tanır bağımlılık grafiğindeki modüllerden yararlanarak, sorunları çözmek için gerekli mantığı ve son olarak kod deposu kurallarını çağırarak depolar oluşturmayı öğreneceksiniz. Benzer bugünün WORKSPACE makrolarına göre işlev görür ancak dünyasına daha uygundur bağımlılıkları ve geçişli bağımlılıkları inceledik.

Modül uzantıları, depo kuralları gibi .bzl dosyalarında veya WORKSPACE makro. Doğrudan başlatılmazlar; her modülün uzantıların okuyacağı etiketler adı verilen veri parçalarını belirtme Modülden sonra sürüm çözümlemesi tamamlandığında modül uzantıları çalıştırılır. Her uzantı çalıştırılır Modül çözümlemesinden sonra (hâlâ herhangi bir derleme gerçekleşmeden önce) ve tüm bağımlılık grafiğinde kendisine ait tüm etiketleri okuması gerekir.

          [ A 1.1                ]
          [   * maven.dep(X 2.1) ]
          [   * maven.pom(...)   ]
              /              \
   bazel_dep /                \ bazel_dep
            /                  \
[ B 1.2                ]     [ C 1.0                ]
[   * maven.dep(X 1.2) ]     [   * maven.dep(X 2.1) ]
[   * maven.dep(Y 1.3) ]     [   * cargo.dep(P 1.1) ]
            \                  /
   bazel_dep \                / bazel_dep
              \              /
          [ D 1.4                ]
          [   * maven.dep(Z 1.4) ]
          [   * cargo.dep(Q 1.1) ]

Yukarıdaki örnek bağımlılık grafiğinde A 1.1, B 1.2 vb. Bazel modülleridir; her birini bir MODULE.bazel dosyası gibi düşünebilirsiniz. Her modülde modül uzantıları için etiketler; burada bazıları "maven" uzantısı için belirtilmiştir. bazıları da "kargo" için belirtilir. Bu bağımlılık grafiği tamamlandığı zaman ( belki B 1.2 adlı kullanıcının D 1.3 aboneliğinde bazel_dep aboneliği var ancak C nedeniyle D 1.4), "maven" uzantıları ve çalıştırıldıktan sonra tüm maven.* etiketleri, buradaki bilgileri kullanarak hangi depoların oluşturulacağına karar verir. Benzer şekilde "kargo" için uzantısına sahip olur.

Uzantı kullanımı

Uzantılar Bazel modüllerinde barındırılır. Bu nedenle, için, ilk olarak bu modüle bir bazel_dep eklemeniz ve ardından yerleşik use_extension işlevinden bahsedeceğiz. Aşağıdaki örneğe dönelim: varsayımsal bir "maven" kullanmak için MODULE.bazel dosyası , rules_jvm_external modülü:

bazel_dep(name = "rules_jvm_external", version = "1.0")
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")

Uzantıyı kapsama sunduktan sonra, aşağıdakileri yapmak için nokta söz dizimini kullanabilirsiniz: bunun için etiketleri belirtin. Etiketlerin karşılık gelen etiket sınıfları (uzantı tanımına bakın bölümüne bakın). Bazı maven.dep ve maven.pom etiketlerinin belirtildiği bir örneği burada bulabilirsiniz.

maven.dep(coord="org.junit:junit:3.0")
maven.dep(coord="com.google.guava:guava:1.2")
maven.pom(pom_xml="//:pom.xml")

Uzantı, modülünüzde kullanmak istediğiniz kod depoları oluşturuyorsa Bildirilecek use_repo yönergesi gerekir. Bu, katı deps koşulunu karşılamak ve yerel depo adından kaçınmak içindir çatışmaya neden olabilir.

use_repo(
    maven,
    "org_junit_junit",
    guava="com_google_guava_guava",
)

Bir uzantı tarafından oluşturulan kod depoları, API'sinin bir parçasıdır. Bu nedenle, "maven"in bu özellik için uzantısı, yeni bir ve "com_google_guava_guava" adlı bir depo bulunur. Entegre use_repo, isteğe bağlı olarak bunları modülünüz kapsamında yeniden adlandırabilirsiniz. Örneğin: "guava" burayı tıklayın.

Uzantı tanımı

Modül uzantıları kod deposu kurallarına benzer şekilde, module_extension işlevini kullanın. Her ikisinin de uygulama işlevi vardır; depo kurallarında ise özelliklerine sahip olduğundan, modül uzantılarının Her biri bir tag_classes özellik sayısı. Etiket sınıfları, bu uzantısına sahip olur. Varsayımsal "maven" örneğimizden devam edelim. yukarıdaki uzantıyı:

# @rules_jvm_external//:extensions.bzl
maven_dep = tag_class(attrs = {"coord": attr.string()})
maven_pom = tag_class(attrs = {"pom_xml": attr.label()})
maven = module_extension(
    implementation=_maven_impl,
    tag_classes={"dep": maven_dep, "pom": maven_pom},
)

Bu bildirimler, maven.dep ve maven.pom etiketlerinin belirtilen özellik şeması kullanılır.

Uygulama işlevi, WORKSPACE makrosuna benzer, ancak bir module_ctx nesnesi alır ve bu nesne bağımlılık grafiğine ve tüm ilgili etiketlere erişebilir. Uygulama fonksiyonunun depo kurallarını çağırması gerekir:

# @rules_jvm_external//:extensions.bzl
load("//:repo_rules.bzl", "maven_single_jar")
def _maven_impl(ctx):
  coords = []
  for mod in ctx.modules:
    coords += [dep.coord for dep in mod.tags.dep]
  output = ctx.execute(["coursier", "resolve", coords])  # hypothetical call
  repo_attrs = process_coursier(output)
  [maven_single_jar(**attrs) for attrs in repo_attrs]

Yukarıdaki örnekte, bağımlılık grafiğindeki tüm modüllerin üzerinden geçelim. (ctx.modules) olmak üzere, her biri bir tags alanı olan bazel_module nesne modüldeki tüm maven.* etiketlerini gösterir. Ardından CLI yardımcı programını çağırırız. Maven ile iletişime geçmek ve çözüm işlemini gerçekleştirmek için eğitim. Son olarak, sonuçta elde edilen sonuca göre maven_single_jar, bir dizi depo kuralı.