Bağımlılıklar

Sorun bildirin Kaynağı göster

A tarafından derleme veya yürütme sırasında B gerekiyorsa hedef A hedefine bağlıdır. Bağımlı olan ilişki, hedefler yerine Yönlendirilmiş Döngüsel Grafik (DAG) oluşturur ve buna bağımlılık grafiği denir.

Hedefin doğrudan bağımlılıkları, bağımlılık grafiğinde 1. uzunluk yolundan erişilebilen diğer hedeflerdir. Bir hedefin geçişli bağımlılığı, grafikte herhangi bir uzunluktaki yol üzerinden bağlı olduğu hedeflerdir.

Aslında, derlemeler bağlamında iki bağımlılık grafiği vardır: gerçek bağımlılıklar grafiği ve bildirilen bağımlılıklar grafiği. Çoğu zaman bu iki grafik birbirine o kadar benzer ki bu ayrımı yapmak gerekmiyor ancak aşağıdaki tartışma için faydalı.

Gerçek ve beyan edilen bağımlılıklar

X öğesinin doğru şekilde derlenmesi için Y özelliğinin mevcut olması, oluşturulması ve güncel olması gerekiyorsa hedef X aslında Y hedefine bağlıdır. Yerleşik, bir derleme sırasında rutin olarak gerçekleşen, oluşturulmuş, işlenmiş, derlenmiş, bağlı, arşivlenmiş, sıkıştırılmış, yürütülmüş veya diğer herhangi bir görev türü anlamına gelebilir.

X paketinde X ile Y arasında bir bağımlılık eşiği varsa X hedefinin bağımlılık beyanı olur.

Doğru derlemeler için A gerçek bağımlılıklarının grafiği, beyan edilen D bağımlılarının grafiğinin bir alt grafiği olmalıdır. Yani A'da doğrudan birbirine bağlanan x --> y düğümlerinin her biri D'de de doğrudan bağlanmalıdır. D'nin, A'ya ilişkin yaklaşık bir tahmin olduğu söylenebilir.

BUILD dosya yazıcıları, her kural için tüm doğrudan doğrudan bağımlılıkları derleme sistemine açıkça belirtmelidir ve artık bunu belirtmemelidir.

Bu ilkeye uyulmaması tanımlanmamış davranışlara yol açar. Derleme başarısız olabilir ancak daha da kötüsü yapı önceki bazı işlemlere veya hedefin sahip olduğu geçişli bildirilen bağımlılıklara bağlı olabilir. Bazel eksik bağımlılıkları kontrol eder ve hataları bildirir ancak bu kontrolün her durumda tamamlanması mümkün değildir.

Yürütme sırasında A tarafından gerekli olsa bile, dolaylı olarak içe aktarılan her şeyi listelemeye çalışmanız gerekmez.

X hedefi oluşturma aşamasında, derleme aracı bu hedeflerdeki değişikliklerin nihai sonuca yansıtıldığından emin olmak için X bağımlılarının tüm geçişli kapanmalarını denetler ve gerektiğinde aracıları yeniden oluşturur.

Bağımlılıkların geçişli yapısı, yaygın bir hataya yol açar. Bazen bir dosyadaki kod, dolaylı bağımlılık tarafından sağlanan kodu kullanabilir. Bu bağımlılık, beyan edilen bağımlılık grafiğinde geçişli ancak doğrudan olmayan bir kenardır. Dolaylı bağımlılar BUILD dosyasında görünmez. Kural doğrudan sağlayıcıya bağlı olmadığından, aşağıdaki örnek zaman çizelgesinde gösterildiği gibi değişiklikleri izlemek mümkün değildir:

1. Bildirilen bağımlılıklar gerçek bağımlılıklarla eşleşir

Başlangıçta her şey çalışır. a paketindeki kod, b paketindeki kodu kullanıyor. b paketindeki kod c paketindeki kodu kullandığı için a kalıcı olarak c koduna bağlıdır.

a/BUILD b/BUILD
rule(
    name = "a",
    srcs = "a.in",
    deps = "//b:b",
)
      
rule(
    name = "b",
    srcs = "b.in",
    deps = "//c:c",
)
      
a / a.in b / b.in
import b;
b.foo();
    
import c;
function foo() {
  c.bar();
}
      
a, b ve c'yi birbirine bağlayan oklarla belirtilen bağımlılık grafiği
Beyan edilen bağımlılık grafiği
A, b ve c arasında bağlantı veren oklarla, beyan edilen bağımlılık grafiğinle eşleşen gerçek bağımlılık grafiği
Gerçek bağımlılık grafiği

Beyan edilen bağımlılıklar, gerçek bağımlılıklara çok yakın. Her şey yolunda.

2. Beyan edilmemiş bağımlılık ekleme

Birisi a uygulamasına doğrudan gerçek bağımlılığı oluşturan ancak c bağımlılığı oluşturan a/BUILD kodunu ekleyen gizli bir tehlike ortaya çıkar.

a / a.in  
        import b;
        import c;
        b.foo();
        c.garply();
      
 
a, b ve c'yi birbirine bağlayan oklarla belirtilen bağımlılık grafiği
Beyan edilen bağımlılık grafiği
a, b ve c arasında bağlantı veren okların yer aldığı gerçek bağımlılık grafiği. Oklar artık A'dan C'ye de bağlanıyor. Bu, beyan edilen bağımlılık grafiğinle eşleşmiyor
Gerçek bağımlılık grafiği

Bildirilen bağımlılıklar artık gerçek bağımlılara fazla yaklaşmıyor. Bu durum, iki grafiğin geçişli sürümlerinin eşit olmasına rağmen bir soruna neden olduğu için sorun oluşturmayabilir: a için c metriğine gerçek ama bildirilmemiş bir bağımlılık var.

3. Bildirilen ve gerçek bağımlılık grafikleri arasındaki fark

Tehlike, b yeniden yapılandırıldığında artık c'a gerek kalmadan ortaya çıkar ve istemeden kendi kusuru üzerinden a bozulur.

  b/BUILD
 
rule(
    name = "b",
    srcs = "b.in",
    deps = "//d:d",
)
      
  b / b.in
 
      import d;
      function foo() {
        d.baz();
      }
      
a ve b'yi bağlayan okların yer aldığı bağımlı bağımlılık grafiği.
                  b artık c'ye bağlanmadığında c bağlantısı kesilir
Beyan edilen bağımlılık grafiği
b ile c'ye bağlanıldığını, ancak b'nin artık c'ye bağlantısının olmadığını gösteren gerçek bağımlılık grafiği
Gerçek bağımlılık grafiği

Beyan edilen bağımlı grafik, geçişli olsa bile artık gerçek bağımlılıkların altında kalan bir tahmindir. Derleme başarısız olabilir.

2. Adımda a ile c arasında verilen gerçek bağımlılığın BUILD dosyasında doğru şekilde belirtildiğinden emin olunması soruna neden olabilir.

Bağımlılık türleri

Çoğu derleme kuralının, farklı genel bağımlı türlerini belirtmek için üç özelliği vardır: srcs, deps ve data. Bunlar aşağıda açıklanmıştır. Ayrıntılı bilgi için Tüm kurallarda ortak olan özellikler bölümüne bakın.

Çoğu kural, kurala bağlı bağımlı türleri (compiler veya resources gibi) için de ek özelliklere sahiptir. Bunlar, Ansiklopedi Oluşturma bölümünde ayrıntılı olarak açıklanmıştır.

srcs bağımlı

Doğrudan kural tarafından veya kaynak dosyaları üreten kurallar tarafından kullanılan dosyalar.

deps bağımlı

Başlık dosyaları, simgeler, kitaplıklar, veriler vb. sağlayan ayrı olarak derlenen modüllere işaret eden kural.

data bağımlı

Bir derleme hedefinin düzgün şekilde çalışması için bazı veri dosyaları gerekebilir. Bu veri dosyaları kaynak kod değildir: Hedefin oluşturulma şeklini etkilemezler. Örneğin, birim testleri bir işlevin çıkışını dosyanın içeriğiyle karşılaştırabilir. Birim testini oluştururken dosyaya ihtiyacınız yoktur ancak testi çalıştırırken dosyaya ihtiyacınız vardır. Aynı durum, yürütme sırasında başlatılan araçlar için de geçerlidir.

Derleme sistemi, testleri yalnızca data olarak listelenen dosyaların bulunduğu izole bir dizinde çalıştırır. Bu nedenle, ikili programın/kitaplık/testin çalıştırılması için bazı dosyalar gerekiyorsa bunları data uygulamasında (veya bunları içeren bir derleme kuralında) belirtin. Örneğin:

# I need a config file from a directory named env:
java_binary(
    name = "setenv",
    ...
    data = [":env/default_env.txt"],
)

# I need test data from another directory
sh_test(
    name = "regtest",
    srcs = ["regtest.sh"],
    data = [
        "//data:file1.txt",
        "//data:file2.txt",
        ...
    ],
)

Bu dosyalar, göreli path/to/data/file yolu kullanılarak kullanılabilir. Testlerde, testin kaynak dizininin ve çalışma alanına bağlı yolun (ör. ${TEST_SRCDIR}/workspace/path/to/data/file) yollarını birleştirerek bu dosyalara başvurabilirsiniz.

Dizinleri referans almak için etiketleri kullanma

BUILD dosyalarımıza baktığınızda bazı data etiketlerinin dizinlerden bahsettiğini görebilirsiniz. Bu etiketler, kullanmamanız gereken /. veya / ile biter. Örneğin:

Önerilmeyendata = ["//data/regression:unittest/."]

Önerilmeyendata = ["testdata/."]

Önerilmeyendata = ["testdata/"]

Bu, özellikle testlerde dizindeki tüm veri dosyalarının kullanılmasına olanak sağladığından testler için kullanışlı görünmektedir.

Ama bunu yapmamaya çalışın. Bir değişiklikten sonra artımlı yeniden derlemelerin (ve testlerin yeniden yürütülmesini) doğru bir şekilde sağlamak için derleme sistemi, derlemeye (veya teste) girdiden oluşan dosya grubunun tamamını bilmelidir. Bir dizin belirttiğinizde, derleme sistemi yalnızca dizinin kendisi değiştiğinde (dosyaların eklenmesi veya silinmesi nedeniyle) yeniden oluşturma işlemi gerçekleştirir. Ancak bu değişiklikler kendilerini çevreleyen dizini etkilemediğinden, dosyalarda yapılan düzenlemeleri algılayamaz. Dizinleri derleme sistemine giriş olarak belirtmek yerine, içerdikleri dosya grubunu açık bir şekilde veya glob() işlevini kullanarak sıralamanız gerekir. (glob() öğesini tekrarlı olmaya zorlamak için ** kullanın.)

Önerilen - data = glob(["testdata/**"])

Maalesef dizin etiketlerinin kullanılması gereken bazı senaryolar vardır. Örneğin, testdata dizininde etiket söz dizimine uymayan dosyalar varsa dosyaların açıkça numaralandırılması veya glob() işlevinin kullanılması geçersiz etiket hatası oluşturur. Bu durumda dizin etiketlerini kullanmanız gerekir, ancak yukarıda açıklanan yanlış yeniden oluşturma riskine karşı dikkatli olun.

Dizin etiketlerini kullanmanız gerekiyorsa göreli ../ yoluna sahip üst pakete başvuramayacağınızı unutmayın. Bunun yerine //data/regression:unittest/. gibi bir mutlak yol kullanın.

Birden fazla dosya kullanması gereken test gibi bir harici kural, bunların tümüne bağımlı olduğunu açık bir şekilde belirtmelidir. Dosyaları BUILD dosyasında birlikte gruplandırmak için filegroup() özelliğini kullanabilirsiniz:

filegroup(
        name = 'my_data',
        srcs = glob(['my_unittest_data/*'])
)

Ardından, testinizde veri bağımlılığı olarak my_data etiketine başvurabilirsiniz.

DERLEME dosyaları Görünürlük