Bir hedef A
, derleme veya yürütme sırasında A
tarafından B
'e ihtiyaç duyuluyorsa B
'e 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ıklar grafiğinde 1 uzunluğunda bir yola ulaşılarak erişilebilen 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 beyan edilen bağımlılar
X
hedefinin doğru şekilde oluşturulabilmesi için Y
hedefinin mevcut, oluşturulmuş ve güncel olması gerekiyorsa X
hedefi Y
hedefine gerçekten bağlıdır. Derlendi ifadesi, oluşturuldu, işlendi, derlendi, bağlandı, arşivlendi, sıkıştırıldı, yürütüldü veya derleme sırasında rutin olarak gerçekleşen diğer görev türlerinden herhangi birini 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'nın aşırı yakınsaması olduğu söylenebilir.
BUILD
dosyası yazarları, her kural için derleme sistemine gerçek doğrudan bağımlılıkların tümünü açıkça belirtmelidir.
Bu ilkeye uyulmaması, tanımlanmamış davranışa neden olur: Derleme başarısız olabilir ancak daha da kötüsü, derleme bazı önceki işlemlere veya hedefin sahip olduğu geçişli olarak tanımlanmış bağımlılıklara bağlı olabilir. Bazel, eksik bağımlılıkları kontrol eder ve hataları raporlar ancak bu kontrolün her durumda eksiksiz olması mümkün değildir.
Yürütme sırasında A
tarafından ihtiyaç duyulsa bile dolaylı olarak içe aktarılan her şeyi listelemeniz gerekmez (ve listelemeniz de gerekmez).
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 yapısı, yaygın bir hataya yol açar. Bazen bir dosyadaki kod, dolaylı bir bağımlılık tarafından sağlanan kodu (tanımlanmış bağımlılık grafiğinde geçişli ancak doğrudan olmayan bir kenar) kullanabilir. 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. Beyan edilen 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
, c
'e dolaylı olarak 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(); } |
Beyan edilen bağımlılıklar, gerçek bağımlılıkları fazla tahmin ediyor. Her şey yolunda.
2. Bildirilmemiş bir bağımlılık ekleme
Bir kullanıcı a
dosyasına c
'a doğrudan gerçek bağımlılık oluşturan kod eklediğinde ancak bunu a/BUILD
derleme dosyasında belirtmeyi unuttuğunuzda gizli bir tehlike ortaya çıkar.
a / a.in |
|
---|---|
import b; import c; b.foo(); c.garply(); |
|
Beyan edilen bağımlılıklar artık gerçek bağımlılıkları aşırı tahmin etmiyor.
İki grafiğin geçişli kapatmaları eşit olduğu için bu derleme işlemi sorunsuz olabilir ancak bir sorunu maskeler: a
, c
'a karşı gerçek ancak bildirilmemiş bir bağımlılığa sahiptir.
3. Beyan edilen ve gerçek bağımlılık grafikleri arasındaki farklılık
Bir kullanıcı b
'ü artık c
'e bağlı olmayacak şekilde yeniden yapılandırdığında ve kendi hatası olmadan a
'yi yanlışlıkla bozduğunda tehlike ortaya çıkar.
b/BUILD |
|
---|---|
rule( name = "b", srcs = "b.in", deps = "//d:d", ) |
|
b / b.in |
|
import d; function foo() { d.baz(); } |
|
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ında, farklı türde genel bağımlılıkları belirtmek için üç özellik bulunur: 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 kuralda, kurala özgü bağımlılık türleri için ek özellikler de bulunur (ör. compiler
veya resources
). Bu bilgiler Build Encyclopedia'da ayrıntılı olarak açıklanmıştır.
srcs
bağımlılıkları
Doğrudan kural tarafından tüketilen veya kaynak dosyaları yayınlayan kurallar.
deps
bağımlılık
Başlık dosyaları, simgeler, kitaplıklar, veriler vb. sağlayan ayrı olarak derlenmiş modülleri işaret eden kural.
data
bağımlılıkları
Bir derleme hedefinin doğru şekilde çalışabilmesi için bazı veri dosyalarına ihtiyacı olabilir. Bu veri dosyaları kaynak kod değildir: Hedefin nasıl oluşturulduğunu etkilemez. Örneğin, bir 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 vardır. Aynı durum, yürütme sırasında başlatılan araçlar için de geçerlidir.
Derleme sistemi, yalnızca data
olarak listelenen dosyaların bulunduğu izole bir dizinde testler ç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 dosyalar, path/to/data/file
göreli yolu kullanılarak kullanılabilir. Testlerde, testin kaynak dizininin yollarını ve Workspace'e göreli yolu (ör. ${TEST_SRCDIR}/workspace/path/to/data/file
) birleştirerek bu dosyalara referans verebilirsiniz.
Dizinlere referans vermek için etiketleri kullanma
BUILD
dosyalarımıza göz atarken bazı data
etiketlerinin dizinlere işaret ettiğini fark edebilirsiniz. Aşağıdaki örneklerde gösterildiği gibi, bu etiketler /.
veya /
ile biter. Bu etiketleri kullanmamanız önerilir:
Önerilmeyen —
data = ["//data/regression:unittest/."]
Önerilmeyen:
data = ["testdata/."]
Önerilmeyen:
data = ["testdata/"]
Bu, özellikle testler için kullanışlıdır çünkü bir testin dizindeki tüm veri dosyalarını kullanmasına olanak tanır.
Ancak bunu yapmamaya çalışın. Bir değişiklikten sonra doğru artımlı yeniden derlemelerin (ve testlerin yeniden yürütülmesinin) yapılması için derleme sisteminin, derlemeye (veya teste) giriş olan tüm dosyalardan haberdar olması gerekir. Bir dizin belirttiğinizde derleme sistemi yalnızca dizinin kendisi değiştiğinde (dosya ekleme veya silme nedeniyle) yeniden derleme yapar ancak bu değişiklikler kapsayıcı dizini etkilemediğinden tek tek dosyalardaki düzenlemeleri algılayamaz.
Derleme sistemine giriş olarak dizinleri belirtmek yerine, bu dizinlerde bulunan dosya grubunu açıkça veya glob()
işlevini kullanarak listelemeniz 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ç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 dikkat edin.
Dizin etiketleri kullanmanız gerekiyorsa üst pakete göreli ../
yolu ile atıfta bulunamayacağınızı 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()
'ü kullanabilirsiniz:
filegroup(
name = 'my_data',
srcs = glob(['my_unittest_data/*'])
)
Daha sonra, testinizde veri bağımlılığı olarak my_data
etiketine referans verebilirsiniz.
BUILD dosyaları | Görünürlük |