परिचय
क्या आपने पहले कभी Bazel का इस्तेमाल नहीं किया है? आप सही जगह पर हैं. Bazel का इस्तेमाल करने के बारे में आसान जानकारी पाने के लिए, इस 'पहली बार बिल्ड करना' ट्यूटोरियल को देखें. इस ट्यूटोरियल में, Bazel के संदर्भ में इस्तेमाल किए गए मुख्य शब्दों की परिभाषाएं दी गई हैं. साथ ही, इसमें Bazel के वर्कफ़्लो की बुनियादी जानकारी दी गई है. आपको अपनी ज़रूरत के हिसाब से टूल इस्तेमाल करने का मौका मिलेगा. साथ ही, आपको तीन प्रोजेक्ट बनाने और उन्हें चलाने का मौका मिलेगा. इन प्रोजेक्ट में, मुश्किलों का लेवल बढ़ता जाएगा. आपको यह भी पता चलेगा कि इन प्रोजेक्ट में मुश्किलों का लेवल कैसे और क्यों बढ़ता है.
Bazel एक बिल्ड सिस्टम है, जो कई भाषाओं में बिल्ड करने की सुविधा देता है. हालांकि, इस ट्यूटोरियल में C++ प्रोजेक्ट का इस्तेमाल किया गया है. साथ ही, इसमें सामान्य दिशा-निर्देश और फ़्लो दिए गए हैं, जो ज़्यादातर भाषाओं पर लागू होते हैं.
पूरा होने में लगने वाला अनुमानित समय: 30 मिनट.
ज़रूरी शर्तें
अगर आपने पहले से Bazel इंस्टॉल नहीं किया है, तो सबसे पहले इसे इंस्टॉल करें. इस ट्यूटोरियल में, सोर्स कंट्रोल के लिए Git का इस्तेमाल किया गया है. इसलिए, बेहतर नतीजों के लिए Git इंस्टॉल करें.
इसके बाद, Bazel की GitHub रिपॉज़िटरी से सैंपल प्रोजेक्ट पाएं. इसके लिए, अपनी पसंद की कमांड-लाइन टूल में यह कमांड चलाएं:
git clone https://github.com/bazelbuild/examples
इस ट्यूटोरियल के लिए सैंपल प्रोजेक्ट, examples/cpp-tutorial
डायरेक्ट्री में है.
देखें कि यह कैसे काम करता है:
examples
└── cpp-tutorial
├──stage1
│ ├── main
│ │ ├── BUILD
│ │ └── hello-world.cc
│ └── MODULE.bazel
├──stage2
│ ├── main
│ │ ├── BUILD
│ │ ├── hello-world.cc
│ │ ├── hello-greet.cc
│ │ └── hello-greet.h
│ └── MODULE.bazel
└──stage3
├── main
│ ├── BUILD
│ ├── hello-world.cc
│ ├── hello-greet.cc
│ └── hello-greet.h
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
└── MODULE.bazel
फ़ाइलों के तीन सेट हैं. हर सेट, इस ट्यूटोरियल के एक चरण को दिखाता है. पहले चरण में, आपको एक पैकेज में मौजूद एक टारगेट बनाना होगा. दूसरे चरण में, आपको एक ही पैकेज से बाइनरी और लाइब्रेरी, दोनों बनानी होंगी. तीसरे और आखिरी चरण में, आपको कई पैकेज वाला प्रोजेक्ट बनाना होगा. साथ ही, उसे कई टारगेट के साथ बनाना होगा.
खास जानकारी: शुरुआती जानकारी
Bazel और Git को इंस्टॉल करके और इस ट्यूटोरियल के लिए रिपॉज़िटरी को क्लोन करके, आपने Bazel के साथ अपनी पहली बिल्ड के लिए बुनियादी ढांचा तैयार कर लिया है. कुछ शर्तों को तय करने और अपना वर्कस्पेस सेट अप करने के लिए, अगले सेक्शन पर जाएं.
शुरू करना
कोई प्रोजेक्ट बनाने से पहले, आपको उसका वर्कस्पेस सेट अप करना होगा. वर्कस्पेस एक डायरेक्ट्री होती है. इसमें आपके प्रोजेक्ट की सोर्स फ़ाइलें और Bazel के बिल्ड आउटपुट होते हैं. इसमें ये अहम फ़ाइलें भी शामिल हैं:
MODULE.bazel
फ़ाइल, डायरेक्ट्री और उसके कॉन्टेंट की पहचान Bazel वर्कस्पेस के तौर पर करती है. यह प्रोजेक्ट की डायरेक्ट्री स्ट्रक्चर के रूट में मौजूद होती है. इसी फ़ाइल में, बाहरी डिपेंडेंसी के बारे में भी बताया जाता है.- एक या उससे ज़्यादा
BUILD
फ़ाइलें. इनसे Bazel को यह पता चलता है कि प्रोजेक्ट के अलग-अलग हिस्सों को कैसे बनाया जाए. वर्कस्पेस में मौजूद ऐसी डायरेक्ट्री जिसमेंBUILD
फ़ाइल होती है उसे पैकेज कहा जाता है. (इस ट्यूटोरियल में पैकेज के बारे में बाद में ज़्यादा जानकारी दी गई है.)
आने वाले समय में, किसी डायरेक्ट्री को Bazel वर्कस्पेस के तौर पर सेट करने के लिए, उस डायरेक्ट्री में MODULE.bazel
नाम की एक खाली फ़ाइल बनाएं. इस ट्यूटोरियल के लिए, हर स्टेज में MODULE.bazel
फ़ाइल पहले से मौजूद है.
BUILD फ़ाइल के बारे में जानकारी
BUILD
फ़ाइल में, Bazel के लिए कई तरह के निर्देश होते हैं. हर BUILD
फ़ाइल में कम से कम एक नियम होना चाहिए. यह निर्देशों का एक सेट होता है. इससे Bazel को यह पता चलता है कि आपको कौनसे आउटपुट बनाने हैं. जैसे, एक्ज़ीक्यूटेबल बाइनरी या लाइब्रेरी. BUILD
फ़ाइल में मौजूद बिल्ड रूल के हर इंस्टेंस को टारगेट कहा जाता है. यह सोर्स फ़ाइलों और डिपेंडेंसी के किसी खास सेट की ओर इशारा करता है. कोई टारगेट, दूसरे टारगेट की ओर भी पॉइंट कर सकता है.
cpp-tutorial/stage1/main
डायरेक्ट्री में मौजूद BUILD
फ़ाइल देखें:
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
)
हमारे उदाहरण में, hello-world
टारगेट, Bazel के बिल्ट-इन cc_binary
नियम को इंस्टैंशिएट करता है. इस नियम से Bazel को यह निर्देश मिलता है कि वह hello-world.cc
> सोर्स फ़ाइल से, बिना किसी डिपेंडेंसी के एक निष्पादन-योग्य बाइनरी बनाए.
खास जानकारी: शुरू करना
अब आपको कुछ मुख्य शब्दों के बारे में पता चल गया है. साथ ही, आपको यह भी पता चल गया है कि इस प्रोजेक्ट और Bazel के संदर्भ में उनका क्या मतलब है. अगले सेक्शन में, प्रोजेक्ट के पहले चरण को बनाया और टेस्ट किया जाएगा.
पहला चरण: एक टारगेट, एक पैकेज
अब प्रोजेक्ट का पहला हिस्सा बनाने का समय है. विज़ुअल रेफ़रंस के लिए, प्रोजेक्ट के पहले चरण के सेक्शन का स्ट्रक्चर यह है:
examples
└── cpp-tutorial
└──stage1
├── main
│ ├── BUILD
│ └── hello-world.cc
└── MODULE.bazel
cpp-tutorial/stage1
डायरेक्ट्री पर जाने के लिए, यह कमांड चलाएं:
cd cpp-tutorial/stage1
इसके बाद, यह कमांड चलाएं:
bazel build //main:hello-world
टारगेट लेबल में, //main:
हिस्सा, Workspace के रूट के हिसाब से BUILD
फ़ाइल की जगह की जानकारी देता है. वहीं, hello-world
, BUILD
फ़ाइल में टारगेट का नाम होता है.
Bazel, इस तरह का कुछ आउटपुट जनरेट करता है:
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 2.267s, Critical Path: 0.25s
आपने अभी-अभी अपना पहला Bazel टारगेट बनाया है. Bazel, बिल्ड आउटपुट को वर्कस्पेस के रूट में मौजूद bazel-bin
डायरेक्ट्री में रखता है.
अब अपने नए बाइनरी की जांच करें. यह बाइनरी:
bazel-bin/main/hello-world
इस वजह से, "Hello world
" मैसेज प्रिंट हो जाता है.
यहां स्टेज 1 का डिपेंडेंसी ग्राफ़ दिया गया है:
खास जानकारी: पहला चरण
अब आपने पहला बिल्ड पूरा कर लिया है. इससे आपको बिल्ड के स्ट्रक्चर के बारे में बुनियादी जानकारी मिल गई है. अगले चरण में, एक और टारगेट जोड़कर इसे और मुश्किल बनाया जाएगा.
दूसरा चरण: एक से ज़्यादा बिल्ड टारगेट
छोटे प्रोजेक्ट के लिए एक टारगेट काफ़ी होता है. हालांकि, बड़े प्रोजेक्ट को कई टारगेट और पैकेज में बांटा जा सकता है. इससे तेज़ी से इंक्रीमेंटल बिल्ड तैयार किए जा सकते हैं. इसका मतलब है कि Bazel सिर्फ़ उन हिस्सों को फिर से बनाता है जिनमें बदलाव किया गया है. साथ ही, यह एक साथ किसी प्रोजेक्ट के कई हिस्सों को बनाकर, आपके बिल्ड को तेज़ करता है. ट्यूटोरियल के इस चरण में एक टारगेट जोड़ा जाता है. इसके बाद, अगले चरण में एक पैकेज जोड़ा जाता है.
यह वह डायरेक्ट्री है जिसका इस्तेमाल आपको दूसरे चरण के लिए करना है:
├──stage2
│ ├── main
│ │ ├── BUILD
│ │ ├── hello-world.cc
│ │ ├── hello-greet.cc
│ │ └── hello-greet.h
│ └── MODULE.bazel
cpp-tutorial/stage2/main
डायरेक्ट्री में मौजूद BUILD
फ़ाइल देखें:
cc_library(
name = "hello-greet",
srcs = ["hello-greet.cc"],
hdrs = ["hello-greet.h"],
)
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
deps = [
":hello-greet",
],
)
इस BUILD
फ़ाइल की मदद से, Bazel पहले hello-greet
लाइब्रेरी बनाता है. इसके लिए, Bazel के बिल्ट-इन cc_library
नियम का इस्तेमाल किया जाता है. इसके बाद, hello-world
बाइनरी बनाई जाती है. hello-world
टारगेट में मौजूद deps
एट्रिब्यूट, Bazel को बताता है कि hello-world
बाइनरी बनाने के लिए hello-greet
लाइब्रेरी की ज़रूरत है.
प्रोजेक्ट का नया वर्शन बनाने से पहले, आपको डायरेक्ट्री बदलनी होगी. इसके लिए, यह कमांड चलाकर cpp-tutorial/stage2
डायरेक्ट्री पर स्विच करें:
cd ../stage2
अब इस जानी-पहचानी कमांड का इस्तेमाल करके, नया बाइनरी बनाया जा सकता है:
bazel build //main:hello-world
Bazel, एक बार फिर इस तरह का कुछ आउटपुट जनरेट करता है:
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 2.399s, Critical Path: 0.30s
अब आपके पास, हाल ही में बनाए गए बाइनरी को टेस्ट करने का विकल्प है. इससे एक और "Hello
world
" मिलता है:
bazel-bin/main/hello-world
अगर अब hello-greet.cc
में बदलाव किया जाता है और प्रोजेक्ट को फिर से बनाया जाता है, तो Bazel सिर्फ़ उस फ़ाइल को फिर से कंपाइल करेगा.
डिपेंडेंसी ग्राफ़ में, यह देखा जा सकता है कि hello-world
, hello-greet
नाम के एक अतिरिक्त इनपुट पर निर्भर करता है:
खास जानकारी: दूसरा चरण
अब आपने दो टारगेट वाला प्रोजेक्ट बना लिया है. hello-world
टारगेट, एक सोर्स फ़ाइल बनाता है. साथ ही, यह एक अन्य टारगेट (//main:hello-greet
) पर निर्भर करता है. //main:hello-greet
टारगेट, दो अतिरिक्त सोर्स फ़ाइलें बनाता है. अगले सेक्शन में, एक और पैकेज जोड़ें.
तीसरा चरण: एक से ज़्यादा पैकेज
इस अगले चरण में, एक और लेयर जोड़ी जाती है. साथ ही, कई पैकेज वाला प्रोजेक्ट बनाया जाता है. cpp-tutorial/stage3
डायरेक्ट्री का स्ट्रक्चर और कॉन्टेंट देखें:
└──stage3
├── main
│ ├── BUILD
│ ├── hello-world.cc
│ ├── hello-greet.cc
│ └── hello-greet.h
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
└── MODULE.bazel
अब आपको दिखेगा कि दो सब-डायरेक्ट्री हैं और हर एक में BUILD
फ़ाइल है. इसलिए, Bazel के लिए अब वर्कस्पेस में दो पैकेज हैं: lib
और main
.
lib/BUILD
फ़ाइल देखें:
cc_library(
name = "hello-time",
srcs = ["hello-time.cc"],
hdrs = ["hello-time.h"],
visibility = ["//main:__pkg__"],
)
साथ ही, main/BUILD
फ़ाइल में:
cc_library(
name = "hello-greet",
srcs = ["hello-greet.cc"],
hdrs = ["hello-greet.h"],
)
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
deps = [
":hello-greet",
"//lib:hello-time",
],
)
मुख्य पैकेज में मौजूद hello-world
टारगेट, lib
पैकेज में मौजूद hello-time
टारगेट पर निर्भर करता है. इसलिए, टारगेट का लेबल //lib:hello-time
है. Bazel को इस बारे में deps
एट्रिब्यूट से पता चलता है. इसे डिपेंडेंसी ग्राफ़ में देखा जा सकता है:
बिल्ड को पूरा करने के लिए, विज़िबिलिटी एट्रिब्यूट का इस्तेमाल करके, lib/BUILD
में मौजूद //lib:hello-time
टारगेट को main/BUILD
में मौजूद टारगेट के लिए साफ़ तौर पर दिखाया जाता है.
ऐसा इसलिए है, क्योंकि डिफ़ॉल्ट रूप से टारगेट सिर्फ़ उसी BUILD
फ़ाइल में मौजूद अन्य टारगेट को दिखते हैं. Bazel, टारगेट विज़िबिलिटी का इस्तेमाल करता है. इससे, सार्वजनिक एपीआई में लागू करने से जुड़ी जानकारी वाली लाइब्रेरी जैसी समस्याओं को रोकने में मदद मिलती है.
अब प्रोजेक्ट का यह फ़ाइनल वर्शन बनाएं. cpp-tutorial/stage3
डायरेक्ट्री पर स्विच करने के लिए, यह कमांड चलाएं:
cd ../stage3
यहां दिया गया कमांड फिर से चलाएं:
bazel build //main:hello-world
Bazel, इस तरह का कुछ आउटपुट जनरेट करता है:
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 0.167s, Critical Path: 0.00s
अब इस ट्यूटोरियल के आखिरी बाइनरी को फ़ाइनल Hello world
मैसेज के लिए टेस्ट करें:
bazel-bin/main/hello-world
खास जानकारी: तीसरा चरण
अब आपने प्रोजेक्ट को दो पैकेज के तौर पर बनाया है. इनमें तीन टारगेट हैं. साथ ही, आपने इनके बीच की डिपेंडेंसी को समझ लिया है. इससे आपको Bazel का इस्तेमाल करके, आने वाले समय में प्रोजेक्ट बनाने में मदद मिलेगी. अगले सेक्शन में, Bazel का इस्तेमाल जारी रखने का तरीका जानें.
अगले चरण
आपने Bazel की मदद से, पहला बुनियादी बिल्ड तैयार कर लिया है. हालांकि, यह सिर्फ़ शुरुआत है. Bazel के बारे में ज़्यादा जानने के लिए, यहां कुछ और संसाधन दिए गए हैं:
- C++ पर फ़ोकस बनाए रखने के लिए, C++ बिल्ड के इस्तेमाल के सामान्य उदाहरणों के बारे में पढ़ें.
- Bazel का इस्तेमाल करके अन्य ऐप्लिकेशन बनाने के लिए, Java, Android ऐप्लिकेशन या iOS ऐप्लिकेशन के ट्यूटोरियल देखें.
- लोकल और रिमोट रिपॉज़िटरी के साथ काम करने के बारे में ज़्यादा जानने के लिए, बाहरी डिपेंडेंसी के बारे में पढ़ें.
- Bazel के अन्य नियमों के बारे में ज़्यादा जानने के लिए, यह रेफ़रंस गाइड देखें.
ऐप बनाने का आनंद लें!