Bağımlılıklar

A hedefi, derleme veya yürütme zamanında A için B gerekiyorsa bir hedefe bağlıdır.B Bu ilişki bağımlı ilişkisiyle, hedefler üzerinde Yönlendirilmiş Döngüsel Grafik'in (DAG) ortaya çıkmasına neden olur ve bağımlılık grafiği olarak adlandırılır.

Bir hedefin doğrudan bağımlılıkları, bağımlılık grafiğinde 1 uzunluğunda bir yol ile erişilebilen diğer hedeflerdir. Bir hedefin geçişli bağımlılıkları, grafikteki herhangi bir uzunluktaki bir yol aracılığıyla 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 iki grafik çok benzer olduğundan bu ayrımı yapmama gerek yoktur, ancak aşağıdaki tartışma için faydalıdır.

Gerçek ve bildirilen bağımlılıklar

X hedefinin doğru şekilde derlenebilmesi için Y mevcut, oluşturulmuş ve güncel olması gerekiyorsa X hedefi gerçekten Y hedefine bağlıdır. Derleme; oluşturulan, işlenen, derlenen, derlenen, arşivlenen, sıkıştırılan, yürütülen veya bir derleme sırasında düzenli olarak gerçekleşen diğer görev türleri anlamına gelebilir.

Bir hedef X, X paketinde X ile Y arasında bir bağımlılık sınırı varsa Y hedefi için bildirilen bir bağımlılığa sahip olur.

Doğru derlemeler için gerçek bağımlılıkların grafiği A, bildirilen bağımlılıkların D grafiğinin alt grafiği olmalıdır. Yani A bölgesindeki her x --> y doğrudan bağlı düğüm çifti aynı zamanda D bölgesinde de doğrudan bağlı olmalıdır. D'nin, A'nın aşırı tahmini olduğu söylenebilir.

BUILD dosya yazarları, her kural için gerçek doğrudan bağımlılıkların tümünü derleme sistemine açıkça bildirmelidir ve bundan fazlasını belirtmemelidir.

Bu ilkeye uyulmaması, tanımlanmamış davranışa neden olur: Derleme başarısız olabilir, ancak daha da kötüsü, derleme önceki bazı işlemlere veya hedefin sahip olduğu geçişli bildirilmiş 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 listelemeniz gerekmez (ve listelemeniz gerekmez).

X hedefinin oluşturulması sırasında derleme aracı, X bağımlılıklarının geçişli olarak kapanmasını tümüyle inceleyerek bu hedeflerdeki değişikliklerin nihai sonuca yansıtılmasını sağlar ve gerektiğinde ara ürünler yeniden oluşturulur.

Bağımlılıkların geçişli yapısı sık karşılaşılan bir hataya yol açar. Bazen bir dosyadaki kod, dolaylı bir bağımlılık (bildirilen bağımlılık grafiğinde geçişli ancak doğrudan olmayan bir uç) tarafından sağlanan kodu kullanabilir. Dolaylı bağımlılıklar 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şiklikler izlenemez:

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

Başlangıçta her şey yolundadır. a paketindeki kod, b paketindeki kodu kullanıyor. b paketindeki kod, c paketindeki kodu kullandığından a, geçişli olarak c paketine 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 bağlayan okların olduğu beyan edilmiş bağımlılık grafiği
Beyan edilen bağımlılık grafiği
a, b ve c'yi bağlayan oklarla bildirilen bağımlılık grafiğiyle eşleşen gerçek bağımlılık grafiği
Gerçek bağımlılık grafiği

Bildirilen bağımlılıklar, gerçek bağımlılıklara yakın. Hiç sorun değil.

2. Bildirilmemiş bir bağımlılık ekleme

Bir kullanıcı a için c öğesine doğrudan gerçek bağımlılık oluşturan bir kod ekler ancak derleme dosyasında bunu belirtmeyi unutursa a/BUILD gizli bir tehlike ortaya çıkar.

a / a.in  
        import b;
        import c;
        b.foo();
        c.garply();
      
 
a, b ve c'yi bağlayan okların olduğu beyan edilmiş bağımlılık grafiği
Beyan edilen bağımlılık grafiği
a, b ve c'yi bağlayan okların olduğu gerçek bağımlılık grafiği. Bir ok, A'yı C'ye de bağlar. Bu, beyan edilen bağımlılık grafiğiyle eşleşmiyor
Gerçek bağımlılık grafiği

Beyan edilen bağımlılıklar, artık gerçek bağımlılıklara yaklaşmıyor. Bu, iki grafiğin geçişli kapanışları eşit olduğu ancak maske bir sorunu olduğu için sorun teşkil edebilir: a, c üzerinde gerçek ancak bildirilmemiş bir bağımlılığa sahiptir.

3. Beyan edilen ve gerçekleşen bağımlılık grafikleri arasındaki fark

Birisi b ürününü artık c ürününe bağlı olmayacak şekilde yeniden düzenlediğinde ve istemeden a ürününü kendi hatası olmayan bir şekilde kırdığında tehlike ortaya çıkar.

  b/BUILD
 
rule(
    name = "b",
    srcs = "b.in",
    deps = "//d:d",
)
      
  b / b.in
 
      import d;
      function foo() {
        d.baz();
      }
      
a ve b'yi birleştiren okların bulunduğu beyan edilmiş bağımlılık grafiği.
                  b artık c'ye bağlanmaz ve bu da a'nın c ile bağlantısını keser
Beyan edilen bağımlılık grafiği
Bir b ve c'ye bağlanmayı gösteren ancak b'nin artık c'ye bağlanmadığını gösteren gerçek bağımlılık grafiği
Gerçek bağımlılık grafiği

Beyan edilen bağımlılık grafiği, geçişli olarak kapalı olsa bile artık gerçek bağımlılıkların yaklaşık tahminidir. Derleme büyük olasılıkla başarısız olur.

2. Adımda tanıtılan a ile c arasındaki gerçek bağımlılığın BUILD dosyasında doğru bir şekilde beyan edilmesi sağlanarak sorun önlenebilir.

Bağımlılık türleri

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

Birçok kural, compiler veya resources gibi kurala özgü bağımlılık türleri için ek özelliklere de sahiptir. Bu yöntemler, Ansiklopedi Oluştur bölümünde ayrıntılı olarak açıklanmıştır.

srcs bağımlılık

Doğrudan kural veya kaynak dosyaları oluşturan kurallar tarafından tüketilen dosyalar.

deps bağımlılık

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

data bağımlılık

Derleme hedefinin doğru şekilde çalışması için bazı veri dosyalarına ihtiyacı olabilir. Bu veri dosyaları kaynak kod değildir: Hedefin oluşturulma şeklini etkilemezler. Örneğin, birim testi, bir işlevin çıkışını bir 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 olacaktı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 mevcut olduğu izole bir dizinde çalıştırır. Dolayısıyla, bir ikili program/kitaplık/test için bazı dosyaların çalışması gerekiyorsa bunları data içinde belirtin (veya bunları içeren bir derleme kuralı oluşturun). Ö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, path/to/data/file göreli yolu kullanılarak kullanılabilir. Testlerde, testin kaynak dizininin ve çalışma alanına bağlı yolun (örneğin, ${TEST_SRCDIR}/workspace/path/to/data/file) yollarını birleştirerek bu dosyalara başvurabilirsiniz.

Dizinlere referans vermek için etiketleri kullanma

BUILD dosyalarımıza göz atarken, bazı data etiketlerinin dizinlere atıfta bulunduğunu fark edebilirsiniz. Bu etiketler, aşağıdaki örneklerde olduğu gibi /. veya / ile biter. Bu örnekleri kullanmamanız gerekir:

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

Önerilmeyendata = ["testdata/."]

Önerilmeyendata = ["testdata/"]

Bu, bir testin dizindeki tüm veri dosyalarını kullanmasına olanak tanıdığından özellikle testler açısından kullanışlı görünür.

Ama bunu yapmamaya çalışın. Bir değişiklikten sonra artımlı yeniden derlemelerin doğru şekilde yapılmasını (ve testlerin yeniden yürütülmesini) sağlamak için derleme sistemi, derleme (veya test) girdileri olan eksiksiz dosya grubunun farkında olmalıdır. 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 ilişkili dizini etkilemediği için bağımsız dosyalarda yapılan düzenlemeleri algılayamaz. Dizinleri derleme sistemi için girişler olarak belirtmek yerine, bunların içindeki dosya grubunu açıkça veya glob() işlevini kullanarak numaralandırmanız gerekir. (glob() öğesini yinelemeli olmaya zorlamak için ** kullanın.)

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

Maalesef dizin etiketlerinin kullanılması gereken bazı senaryolar vardır. Örneğin, testdata dizini, adları etiket söz dizimine uygun olmayan dosyalar içeriyorsa dosyaların açık bir şekilde numaralandırılması veya glob() işlevinin kullanılması geçersiz etiket hatasına neden olur. Bu durumda dizin etiketlerini kullanmanız gerekir ancak yukarıda açıklanan hatalı yeniden oluşturma riskine karşı dikkatli olun.

Dizin etiketlerini kullanmanız gerekirse üst pakete göreli bir ../ yoluyla referans veremeyeceğinizi unutmayın. Bunun yerine //data/regression:unittest/. gibi mutlak bir yol kullanın.

Birden fazla dosya kullanması gereken bir harici kural (ör. test) bu dosyaların tümüne bağımlı olduğunu açıkça beyan etmelidir. BUILD dosyasındaki dosyaları gruplandırmak için filegroup() öğesini kullanabilirsiniz:

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

Daha sonra, testinizdeki veri bağımlılığı olarak my_data etiketine başvurabilirsiniz.

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