अगर बिल्ड के लिए A
तक B
की ज़रूरत हो, तो टारगेट A
पर निर्भर B
निष्पादन समय. संबंध पर निर्भर करता है और
निर्देशित एकसाइक्लिक ग्राफ़
(DAG) को टारगेट के ऊपर रखा जाता है. इसे डिपेंडेंसी ग्राफ़ कहा जाता है.
टारगेट की डायरेक्ट डिपेंडेंसी वे दूसरे टारगेट होते हैं जिन तक पाथ से पहुंचा जा सकता है डिपेंडेंसी ग्राफ़ में लंबाई 1 का. टारगेट की ट्रांज़िव डिपेंडेंसी वे लक्ष्य जिन पर यह ग्राफ़ के माध्यम से किसी भी लंबाई के पथ के माध्यम से निर्भर करता है.
बिल्ड के मामले में, दो डिपेंडेंसी ग्राफ़ होते हैं, ग्राफ़ असल डिपेंडेंसी और एलान की गई डिपेंडेंसी का ग्राफ़. ज़्यादातर समय, दोनों ग्राफ़ इतने समान हैं कि यह भेद करने की आवश्यकता नहीं है, लेकिन यह नीचे दी गई चर्चा के लिए उपयोगी है.
असल और तय की गई डिपेंडेंसी
अगर Y
मौजूद होना ज़रूरी है, तो टारगेट X
असल में टारगेट Y
पर निर्भर होता है,
बनाई गई है और अप-टू-डेट है, ताकि X
सही तरीके से बनाई जा सके. पहले से मौजूद ये काम कर सके
मध्यमान जनरेट किया गया, संसाधित किया गया, कंपाइल किया गया, लिंक किया गया, संग्रहित, कंप्रेस किया गया, निष्पादित किया गया, या
बिल्ड के दौरान नियमित तौर पर होने वाले अन्य टास्क.
अगर कोई डिपेंडेंसी है, तो टारगेट X
के लिए टारगेट Y
पर डिपेंडेंसी का एलान किया गया है
X
के पैकेज में, X
से Y
किनारे पर.
सही बिल्ड के लिए, असल डिपेंडेंसी A का ग्राफ़
तय की गई डिपेंडेंसी D का ग्राफ़. इसका मतलब है कि
A में सीधे तौर पर जुड़े नोड x --> y
भी सीधे तौर पर जुड़े होने चाहिए
D. ऐसा कहा जा सकता है कि D, A के अंदाज़ है.
BUILD
फ़ाइल राइटर को डायरेक्ट डायरेक्ट विज्ञापनों से जुड़ी सभी समस्याओं के बारे में साफ़ तौर पर जानकारी देनी होगी
बिल्ड सिस्टम पर हर नियम के लिए डिपेंडेंसी. इसके अलावा, कोई और नियम तय करने की ज़रूरत नहीं है.
इस सिद्धांत को न समझ पाने की वजह से, व्यवहार के बारे में जानकारी नहीं मिलती: बिल्ड फ़ेल हो सकता है, लेकिन इससे भी बुरा, बिल्ड कुछ पहले के ऑपरेशन या ट्रांज़िट पर निर्भर कर सकता है तय की गई ऐसी डिपेंडेंसी जो टारगेट में होती हैं. बेज़ल गुमराह करने वाले का पता लगाता है डिपेंडेंसी और रिपोर्ट से जुड़ी गड़बड़ियां हैं. हालांकि, मुमकिन नहीं है कि सभी मामलों में पूरा होता है.
इंपोर्ट की गई सभी चीज़ों को सीधे तौर पर इंपोर्ट करने की ज़रूरत नहीं है (और न करनी चाहिए),
भले ही, एक्ज़ीक्यूशन के समय A
को इसकी ज़रूरी हो.
टारगेट X
के बिल्ड के दौरान, बिल्ड टूल पूरे ट्रांज़िटिव की जांच करता है
यह पक्का करने के लिए कि उन टारगेट में होने वाले किसी भी बदलाव को X
की डिपेंडेंसी के तौर पर बंद किया गया हो
को ध्यान में रखते हुए, इंटरमीडिएट को ज़रूरत के हिसाब से फिर से बनाया जा सकता है.
डिपेंडेंसी की ट्रांज़िटिव प्रकृति से एक आम गलती होती है. कभी-कभी,
एक फ़ाइल में मौजूद कोड, किसी इनडायरेक्ट डिपेंडेंसी से मिले कोड का इस्तेमाल कर सकता है — a
तय डिपेंडेंसी ग्राफ़ में ट्रांज़िटिव, लेकिन डायरेक्ट एज नहीं. इनडायरेक्ट
BUILD
फ़ाइल में डिपेंडेंसी नहीं दिखती हैं. क्योंकि नियम यह
सेवा देने वाली कंपनी पर सीधे निर्भर करता है. बदलावों को ट्रैक करने का कोई तरीका नहीं है, जैसा कि
टाइमलाइन का यह उदाहरण देखें:
1. तय की गई डिपेंडेंसी, असल डिपेंडेंसी से मेल खाती हैं
पहली बार में सब कुछ ठीक से काम करता है. पैकेज a
का कोड, पैकेज b
में मौजूद कोड का इस्तेमाल करता है.
b
पैकेज में मौजूद कोड, c
पैकेज में मौजूद कोड का इस्तेमाल करता है. इसलिए, a
ट्रांज़िट स्थिति में होता है
c
पर निर्भर करता है.
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(); } |
|
|
तय की गई डिपेंडेंसी, असल डिपेंडेंसी से ज़्यादा अनुमानित होती हैं. सब ठीक है.
2. ऐसी डिपेंडेंसी जोड़ना जिसका एलान नहीं किया गया है
जब कोई व्यक्ति a
में कोड जोड़ता है, जो
c
पर सीधे तौर पर असल डिपेंडेंसी होती है, लेकिन बिल्ड फ़ाइल में इस बारे में एलान नहीं किया जाता
a/BUILD
.
a / a.in |
|
---|---|
import b; import c; b.foo(); c.garply(); |
|
|
|
तय की गई डिपेंडेंसी अब असल डिपेंडेंसी से ज़्यादा अनुमानित नहीं होती हैं.
यह सही हो सकता है, क्योंकि दो ग्राफ़ के ट्रांज़िटिव क्लोज़र बराबर हैं,
लेकिन किसी समस्या को मास्क कर देता है: a
में c
पर, असल में, लेकिन तय नहीं किया गया डिपेंडेंसी है.
3. एलान किए गए और असल डिपेंडेंसी ग्राफ़ के बीच फ़र्क़
खतरे का पता तब चलता है, जब कोई व्यक्ति b
को इस तरह से रीफ़ैक्ट करता है कि यह प्रॉडक्ट पर निर्भर न रहे
c
, अनजाने में a
को तोड़ रहा है
खुद में ज़्यादा कमी है.
b/BUILD |
|
---|---|
rule( name = "b", srcs = "b.in", deps = "//d:d", ) |
|
b / b.in |
|
import d; function foo() { d.baz(); } |
|
|
|
घोषित डिपेंडेंसी ग्राफ़ अब असल डिपेंडेंसी, भले ही ये अस्थायी तौर पर बंद हों; बिल्ड के असफल होने की संभावना है.
यह पक्का करके समस्या टल सकती थी कि असल में
दूसरे चरण में पेश किए गए a
से c
के बारे में, BUILD
फ़ाइल में सही तरीके से बताया गया था.
डिपेंडेंसी के टाइप
ज़्यादातर बिल्ड नियमों में, अलग-अलग तरह के एट्रिब्यूट तय करने के लिए तीन एट्रिब्यूट होते हैं
जेनरिक डिपेंडेंसी: srcs
, deps
, और data
. इनके बारे में नीचे बताया गया है. इसके लिए
ज़्यादा जानकारी के लिए, देखें
सभी नियमों के लिए आम तौर पर इस्तेमाल होने वाले एट्रिब्यूट.
कई नियमों में नियम-विशिष्ट प्रकार के लिए अतिरिक्त विशेषताएं भी होती हैं
डिपेंडेंसी, उदाहरण के लिए, compiler
या resources
. यहां दी गई जानकारी
एनसाइक्लोपीडिया बनाना.
srcs
डिपेंडेंसी
ऐसी फ़ाइलें जो सीधे तौर पर इस्तेमाल की जाने वाली फ़ाइलें हैं.
deps
डिपेंडेंसी
हेडर फ़ाइलें उपलब्ध कराने वाले अलग से कंपाइल किए गए मॉड्यूल की ओर इशारा करने वाला नियम, सिंबल, लाइब्रेरी, डेटा वगैरह.
data
डिपेंडेंसी
बिल्ड टारगेट को ठीक से चलाने के लिए, कुछ डेटा फ़ाइलों की ज़रूरत पड़ सकती है. ये डेटा फ़ाइलें सोर्स कोड नहीं होते: इनसे टारगेट को बनाने के तरीके पर कोई असर नहीं पड़ता. उदाहरण के लिए, यूनिट टेस्ट, फ़ंक्शन के आउटपुट की तुलना, फ़ाइल के कॉन्टेंट से कर सकता है. आसानी से अपने कैलेंडर में जोड़ें. ऐसा यूनिट टेस्ट बनाएं जिसकी आपको फ़ाइल की ज़रूरत नहीं है. हालांकि, फ़ाइल को रन करते समय का पता लगाना है. यही बात उन टूल पर भी लागू होती है जो प्रोग्राम चलाने के दौरान लॉन्च किए जाते हैं.
बिल्ड सिस्टम जांच को एक ऐसी अलग डायरेक्ट्री में करता है जिसमें सिर्फ़ इस फ़ॉर्मैट वाली फ़ाइलें
data
उपलब्ध हैं. इस तरह, अगर किसी बाइनरी/लाइब्रेरी/टेस्ट को चलाने के लिए कुछ फ़ाइलों की ज़रूरत है,
data
में उन्हें (या उनमें शामिल एक बिल्ड नियम) तय करें. उदाहरण के लिए:
# 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",
...
],
)
ये फ़ाइलें मिलते-जुलते पाथ path/to/data/file
का इस्तेमाल करके उपलब्ध हैं. जांचों में,
टेस्ट के सोर्स के पाथ में शामिल होकर, इन फ़ाइलों को देखा जा सकता है
डायरेक्ट्री और फ़ाइल फ़ोल्डर-रिलेटिव पाथ, जैसे कि
${TEST_SRCDIR}/workspace/path/to/data/file
.
डायरेक्ट्री के लिए लेबल इस्तेमाल करना
हमारी BUILD
फ़ाइलों को देखते समय, शायद आपको पता चले कि कुछ data
लेबल
डायरेक्ट्री देखें. इन लेबल के अंत में /.
या /
दिए गए हैं. जैसे, नीचे दिए गए उदाहरण
इनका इस्तेमाल नहीं करना चाहिए:
इसका सुझाव नहीं दिया जाता —
data = ["//data/regression:unittest/."]
इसका सुझाव नहीं दिया जाता —
data = ["testdata/."]
इसका सुझाव नहीं दिया जाता —
data = ["testdata/"]
यह सुविधाजनक लगता है, खास तौर पर टेस्ट के लिए, क्योंकि इससे टेस्ट डायरेक्ट्री की सभी डेटा फ़ाइलों का इस्तेमाल करना होगा.
हालांकि, ऐसा न करने की कोशिश करें. यह पक्का करने के लिए कि कैंपेन सही तरीके से रीबिल्ड (और
टेस्ट को दोबारा लागू करने के लिए) है, तो बिल्ड सिस्टम को
उन फ़ाइलों का सेट पूरा करें जो बिल्ड (या टेस्ट) के इनपुट हों. जब आप तय करें
डायरेक्ट्री होती है, तो बिल्ड सिस्टम खुद ही डायरेक्ट्री को फिर से बनाता है
बदलाव (फ़ाइलों को जोड़ने या मिटाने की वजह से), लेकिन उनका पता नहीं लगाया जा सकता
अलग-अलग फ़ाइलों में बदलाव करता है, क्योंकि ये बदलाव आस-पास की डायरेक्ट्री पर कोई असर नहीं डालते.
बिल्ड सिस्टम के लिए इनपुट के तौर पर डायरेक्ट्री तय करने के बजाय, आपको यह करना चाहिए
उसमें मौजूद फ़ाइलों के सेट की गणना करें
glob()
फ़ंक्शन का इस्तेमाल करें. (ज़बरदस्ती लागू करने के लिए, **
का इस्तेमाल करें
glob()
बार-बार होने वाली होनी चाहिए.)
सुझाव —
data = glob(["testdata/**"])
माफ़ करें, कुछ मामलों में डायरेक्ट्री लेबल का इस्तेमाल करना ज़रूरी होता है.
उदाहरण के लिए, अगर testdata
डायरेक्ट्री में ऐसी फ़ाइलें हैं जिनके नाम में
लेबल सिंटैक्स के मुताबिक हो,
फ़ाइलों की साफ़ तौर पर गिनती, या
glob()
फ़ंक्शन एक अमान्य लेबल बनाता है
गड़बड़ी. इस मामले में आपको डायरेक्ट्री लेबल इस्तेमाल करना चाहिए, लेकिन इन बातों का ध्यान रखें:
से जुड़ा जोखिम है, जिसके बारे में ऊपर बताया गया है.
अगर आपको डायरेक्ट्री लेबल का इस्तेमाल करना ज़रूरी है, तो ध्यान रखें कि आप
मिलते-जुलते ../
पाथ वाला पैरंट पैकेज; इसके बजाय, ऐब्सलूट पाथ का इस्तेमाल करें, जैसे कि
//data/regression:unittest/.
.
कोई भी बाहरी नियम, जैसे कि टेस्ट, जिसके लिए कई फ़ाइलों का इस्तेमाल करने की ज़रूरत हो
एलान किया जा सकता है कि यह उन सभी पर निर्भर है. filegroup()
का इस्तेमाल इन कामों के लिए किया जा सकता है
BUILD
फ़ाइल में एक साथ फ़ाइलों का ग्रुप बनाएं:
filegroup(
name = 'my_data',
srcs = glob(['my_unittest_data/*'])
)
इसके बाद, टेस्ट में डेटा डिपेंडेंसी के तौर पर my_data
लेबल का रेफ़रंस दिया जा सकता है.
बिल्ड फ़ाइलें | किसको दिखे |