Bağımlılıklar

Sorun bildirin Kaynağı göster

Derleme veya yürütme zamanında A için B gerekiyorsa bir A hedefi B hedefine bağlıdır. Bu ilişki, bağımlılık grafiği olarak adlandırılan, hedefler üzerinde Yönlü Döngüsel Grafik (DAG) oluşmasına neden olur ve bu duruma bağımlılık grafiği adı verilir.

Bir hedefin doğrudan bağımlılıkları, bağımlılık grafiğinde 1 uzunluğundaki bir yolla ulaşılabilen diğer hedeflerdir. Bir hedefin geçişli bağımlılıkları, grafik boyunca herhangi bir uzunluktaki bir yoldan bağlı olduğu hedeflerdir.

Aslında derlemeler bağlamında iki bağımlılık grafiği bulunur: gerçek bağımlılıkların grafiği ve bildirilen bağımlılıkların grafiği. İki grafik çoğu zaman birbirine çok benzer olduğundan bu ayrımı yapmanız gerekmez. Yine de, aşağıdaki tartışma için yararlıdır.

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

X hedefinin doğru şekilde oluşturulabilmesi için Y öğesinin mevcut olması, derlenmiş ve güncel olması gerekiyorsa hedef X, Y hedefine bağlıdır. Oluşturulan; oluşturulmuş, işlenmiş, derlenmiş, bağlantılı, arşivlenmiş, sıkıştırılmış, yürütülen veya derleme sırasında rutin olarak gerçekleşen diğer görev türlerini ifade edebilir.

X paketinde X ile Y arasında bir bağımlılık sınırı varsa hedef X için Y hedefinde bildirilen bir bağımlılık vardır.

Doğru derlemeler için gerçek bağımlılıklar grafiği A, bildirilen bağımlılıklar D grafiğinin alt grafiği olmalıdır. Yani A'da doğrudan bağlı x --> y düğümlerinin her bir çifti de D'de doğrudan bağlı olmalıdır. D'nin, A'ya fazla tahmini olduğu söylenebilir.

BUILD dosya yazarları, her kural için derleme sistemine uygulanan doğrudan bağımlılıkların tümünü açıkça beyan etmeli ve bundan sonrasını yapmamalıdır.

Bu ilkeye uyulmaması tanımlanmamış davranışa neden olur: Derleme başarısız olabilir ama daha da kötüsü, derleme önceki bazı işlemlere veya hedefin sahip olduğu geçişli olarak 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 anında A tarihine kadar ihtiyaç duyulsa bile, dolaylı olarak içe aktarılan her şeyi listelemeye çalışmanız gerekmez (ve listelememeniz gerekir).

X hedefi oluşturma işlemi sırasında derleme aracı, X bağımlılıklarının geçişli olarak kapatılmasını inceleyerek bu hedeflerdeki değişikliklerin nihai sonuca yansıtıldığından emin olarak ara öğeleri gerektiği şekilde yeniden oluşturur.

Bağımlılıkların geçişli doğası yaygın bir hataya yol açar. Bazen bir dosyadaki kod, dolaylı bir bağımlılık tarafından sağlanan kodu kullanabilir. Bu dolaylı, bildirilen bağımlılık grafiğinde geçişli ama doğrudan olmayan bir bağımlılıktır. 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şiklikleri izlemek mümkün değildir:

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

Başlangıçta her şey çalışır. a paketindeki kod, b paketindeki kodu kullanıyor. b paketindeki kod, c paketindeki kodu kullandığından a geçişli olarak c öğesine 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 birleştiren oklarla bildirilmiş bağımlılık grafiği
Beyan edilen bağımlılık grafiği
a, b ve c'yi bağlayan oklarla belirtilen 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

Beyan edilen bağımlılıklar, gerçek bağımlılıklara fazla yakındır. Her şey yolunda.

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

Birisi a koda doğrudan gerçek bağımlılık oluşturan c ancak derleme dosyasında bunu bildirmeyi unuttuğunda bir kod eklerse a/BUILD gizli tehlike ortaya çıkar.

a / a.in  
        import b;
        import c;
        b.foo();
        c.garply();
      
 
a, b ve c'yi birleştiren oklarla bildirilmiş bağımlılık grafiği
Beyan edilen bağımlılık grafiği
a, b ve c'yi bağlayan okların yer aldığı gerçek bağımlılık grafiği. Artık bir ok A'dan C'ye de bağlanıyor. Bu, bildirilen 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 fazla değer vermiyor. Bu bir sorun yaratmayabilir, çünkü iki grafiğin geçişli kapanışları eşittir, ancak bir sorunu maskeler: a, c öğesine gerçek ancak bildirilmemiş bir bağımlılığa sahiptir.

3. Beyan edilen bağımlılık grafikleri ile gerçek bağımlılık grafikleri arasındaki farklılık

Birisi, b artık c bağımlılığı kalmayacak şekilde yeniden düzenleme yaptığında tehlike ortaya çıkar. Böylece a, kendi hatasından bağımsız olarak yanlışlıkla ihlal edilmiş olur.

  b/BUILD
 
rule(
    name = "b",
    srcs = "b.in",
    deps = "//d:d",
)
      
  b / b.in
 
      import d;
      function foo() {
        d.baz();
      }
      
a ile b'yi birleştiren okların olduğu bildirilen bağımlılık grafiği.
                  b artık c'ye bağlanmaz, bu da a'nın c ile bağlantısını koparır
Beyan edilen bağımlılık grafiği
b ve c'ye bağlantıyı 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

Bildirilen bağımlılık grafiği, artık geçişli olarak kapatılsa bile gerçek bağımlılıkların düşük bir tahmini olarak sunulmaktadır. Derleme büyük olasılıkla başarısız olacaktır.

2. Adımda belirtilen a ile c arasındaki gerçek bağımlılığın BUILD dosyasında doğru şekilde bildirilmesi sağlanarak sorun önlenebilirdi.

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 için Tüm kurallarda ortak olan özellikler bölümüne bakın.

Birçok kuralın, kurala özgü bağımlılık türleri için compiler veya resources gibi ek özellikleri de vardır. Bunlar Ansiklopedi Oluşturma bölümünde ayrıntılı olarak açıklanmaktadır.

srcs bağımlılık

Doğrudan kaynak dosyaları oluşturan kural veya kurallar tarafından kullanılan 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

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

Derleme sistemi, testleri sadece data olarak listelenen dosyaların kullanılabileceği yalıtılmış bir dizinde çalıştırır. Bu nedenle, bir ikili programın/kitaplık/testin çalışması için bazı dosyalar gerekiyorsa bunları (veya bunları içeren bir derleme kuralını) data içinde 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 dosyalara path/to/data/file göreli yolu kullanılarak erişilebilir. Testlerde, testin kaynak dizininin ve çalışma alanına bağlı yolunun (örneğin, ${TEST_SRCDIR}/workspace/path/to/data/file) yollarını birleştirerek bu dosyalara başvurabilirsiniz.

Dizinlere başvurmak için etiketleri kullanma

BUILD dosyalarımıza göz atarken, bazı data etiketlerinin dizinleri ifade ettiğini fark edebilirsiniz. Bu etiketler, kullanmamanız gereken aşağıdaki örneklerde olduğu gibi /. veya / ile biter:

Ö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 sisteminin, derlemeye (veya teste) giriş olan tüm dosya grubundan haberdar olması gerekir. Bir dizin belirttiğinizde, derleme sistemi yalnızca dizinin kendisi değiştiğinde (dosya ekleme veya silme nedeniyle) yeniden oluşturma işlemi gerçekleştirir, ancak bu değişiklikler ilgili dizini etkilemediğinden, tek tek dosyalarda yapılan düzenlemeleri algılayamaz. Dizinleri, derleme sistemine girişler olarak belirtmek yerine, açıkça veya glob() işlevini kullanarak, içerdikleri dosya grubunu numaralandırmanız gerekir. (glob() öğesini yinelemeli olmaya zorlamak için ** öğesini 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 numaralandırması 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 etiketleri kullanmanız gerekiyorsa üst pakete göreli bir ../ yoluyla referans veremeyeceğinizi unutmayın. Bunun yerine //data/regression:unittest/. gibi mutlak bir yol kullanın.

Test gibi birden fazla dosya kullanması gereken herhangi bir harici kuralın, bu dosyaların tümüne bağımlılığını açıkça belirtmesi gerekir. Dosyaları BUILD dosyasında gruplandırmak için filegroup() öğesini kullanabilirsiniz:

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

Daha sonra, testinizde veri bağımlılığı olarak my_data etiketine referans verebilirsiniz.

dosya derleyin Görünürlük