बेज़ेल ट्यूटोरियल: C++ प्रोजेक्ट बनाएं

संग्रह की मदद से व्यवस्थित रहें अपनी प्राथमिकताओं के आधार पर, कॉन्टेंट को सेव करें और कैटगरी में बांटें.
किसी समस्या की शिकायत करें स्रोत देखें

सुविधा के बारे में जानकारी

Bazel का इस्तेमाल पहली बार कर रहे हैं? आप सही जगह पर हैं. Bazel का इस्तेमाल करने के बारे में सामान्य जानकारी देने के लिए, इस फ़र्स्ट बिल्ड ट्यूटोरियल का पालन करें. इस ट्यूटोरियल में, बेज़ेल के संदर्भ में इस्तेमाल किए गए अहम शब्दों के बारे में बताया गया है. इन शर्तों की मदद से, आप Bazel के काम करने के तरीके की बुनियादी बातों के बारे में जानेंगे. आपको जिन टूल की ज़रूरत है उनसे शुरू करते हुए, आप तीन प्रोजेक्ट बनाएं और चलाएंगे. साथ ही, यह भी जानें कि वे ज़्यादा जटिल कैसे होते हैं और उनके ज़्यादा कॉम्प्लेक्स क्यों होते हैं.

Bazel एक बिल्ड सिस्टम है, जिसमें कई भाषाओं में बिल्ड काम करता है. हालांकि, यह ट्यूटोरियल, उदाहरण के तौर पर C++ प्रोजेक्ट का इस्तेमाल करता है. इसमें, सामान्य दिशा-निर्देश और फ़्लो शामिल हैं, जो ज़्यादातर भाषाओं पर लागू होते हैं.

परफ़ॉर्मेंस की जांच पूरी होने का अनुमानित समय: 30 मिनट.

ज़रूरी शर्तें

अगर आपने अभी तक ऐसा नहीं किया है, तो Bzel इंस्टॉल करके शुरू करें. यह ट्यूटोरियल, सोर्स कंट्रोल के लिए Git का इस्तेमाल करता है. इसलिए, सबसे अच्छे नतीजों के लिए GitHub इंस्टॉल करें.

इसके बाद, अपनी पसंद के कमांड-लाइन टूल में आगे चलकर, Bazel की GitHub डेटा स्टोर करने की जगह से सैंपल प्रोजेक्ट पाएं:

git clone https://github.com/bazelbuild/examples

इस ट्यूटोरियल का सैंपल प्रोजेक्ट, examples/cpp-tutorial डायरेक्ट्री में है.

स्ट्रक्चर्ड डेटा देखने का तरीका नीचे देखें:

examples
└── cpp-tutorial
    ├──stage1
    │  ├── main
    │  │   ├── BUILD
    │  │   └── hello-world.cc
    │  └── WORKSPACE
    ├──stage2
    │  ├── main
    │  │   ├── BUILD
    │  │   ├── hello-world.cc
    │  │   ├── hello-greet.cc
    │  │   └── hello-greet.h
    │  └── WORKSPACE
    └──stage3
       ├── main
       │   ├── BUILD
       │   ├── hello-world.cc
       │   ├── hello-greet.cc
       │   └── hello-greet.h
       ├── lib
       │   ├── BUILD
       │   ├── hello-time.cc
       │   └── hello-time.h
       └── WORKSPACE

फ़ाइलों के तीन सेट हैं, जिनमें से हर एक सेट इस ट्यूटोरियल में मौजूद स्टेज को दिखाता है. पहले चरण में, आप एक ही टारगेट एक पैकेज में रहते हैं. दूसरे चरण में, आप एक पैकेज से बाइनरी और लाइब्रेरी, दोनों बनाएंगे. तीसरे और आखिरी चरण में, आपको कई पैकेज के साथ एक प्रोजेक्ट बनाना होगा और उसे कई टारगेट के साथ बनाना होगा.

खास जानकारी: परिचय

Bazel (और Git) इंस्टॉल करके और इस ट्यूटोरियल के लिए डेटा स्टोर करने की जगह बनाकर, आपने Bzel के पहले बिल्ड का आधार बनाया है. कुछ शब्द तय करने और अपने फ़ाइल फ़ोल्डर को सेट अप करने के लिए अगले सेक्शन पर जाएं.

शुरुआत करना

फ़ाइल फ़ोल्डर सेट करें

कोई प्रोजेक्ट बनाने से पहले, आपको उसका फ़ाइल फ़ोल्डर सेट अप करना होगा. फ़ाइल फ़ोल्डर एक ऐसी डायरेक्ट्री है जिसमें आपके प्रोजेक्ट की सोर्स फ़ाइलें होती हैं और Bazel के बिल्ड आउटपुट शामिल होते हैं. इसमें ये अहम फ़ाइलें भी शामिल हैं:

  • WORKSPACE file , जो डायरेक्ट्री और उसके कॉन्टेंट की पहचान बेज़ल फ़ाइल फ़ोल्डर के तौर पर करता है. यह प्रोजेक्ट की डायरेक्ट्री के रूट के रूट पर होता है.
  • एक या एक से ज़्यादा BUILD files , जो Bazel को बताते हैं कि प्रोजेक्ट के अलग-अलग हिस्सों को कैसे बनाया जाए. फ़ाइल फ़ोल्डर में BUILD फ़ाइल वाला एक डायरेक्ट्री एक पैकेज होता है. (इस ट्यूटोरियल में बाद में पैकेज पर ज़्यादा जानकारी.)

आने वाले समय के प्रोजेक्ट में, किसी डायरेक्ट्री को बेज़ल फ़ाइल फ़ोल्डर के तौर पर बताने के लिए, उस डायरेक्ट्री में WORKSPACE नाम की एक खाली फ़ाइल बनाएं. इस ट्यूटोरियल के उद्देश्यों के लिए, हर चरण में एक WORKSPACE फ़ाइल पहले से मौजूद होती है.

ध्यान दें: जब बेज़ल प्रोजेक्ट बनाता है, तो सभी इनपुट एक ही फ़ाइल फ़ोल्डर में होने चाहिए. अलग-अलग फ़ाइल फ़ोल्डर में रहने वाली फ़ाइलें एक-दूसरे से अलग होती हैं, जब तक कि उन्हें एक-दूसरे से लिंक न किया गया हो. फ़ाइल फ़ोल्डर के नियमों के बारे में ज़्यादा जानकारी के लिए, यह गाइड देखें.

BUILD फ़ाइल को समझें

BUILD फ़ाइल में Bazel के लिए, कई अलग-अलग तरह के निर्देश दिए गए हैं. हर BUILD फ़ाइल के लिए, निर्देशों के सेट के तौर पर कम से कम एक नियम की ज़रूरत होती है. इस नियम से, बेज़ल को मनचाहे आउटपुट बनाने का तरीका पता चलता है, जैसे कि एक्ज़ीक्यूटेबल बाइनरी या लाइब्रेरी. BUILD फ़ाइल में बिल्ड नियम के हर इंस्टेंस को टारगेट कहा जाता है. यह सोर्स फ़ाइलों के खास सेट और डिपेंडेंसी पर ले जाता है. टारगेट, किसी दूसरे टारगेट पर भी ले जा सकता है.

cpp-tutorial/stage1/main डायरेक्ट्री में, BUILD फ़ाइल पर एक नज़र डालें:

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
)

हमारे उदाहरण में, hello-world टारगेट, बेज़ल के बिल्ट-इन cc_binary rule को इंस्टैंशिएट करता है. इस नियम से, बेज़ैल को hello-world.cc सोर्स फ़ाइल से, एक्ज़ीक्यूटेबल बाइनरी बनाने में मदद मिलती है. यह बाइनरी एक डिपेंडेंसी नहीं है.

खास जानकारी: शुरू करना

अब आप कुछ मुख्य शब्दों के बारे में जानते हैं. साथ ही, आप जानते हैं कि आम तौर पर इस प्रोजेक्ट और बेज़ेल के संदर्भ में इनका क्या मतलब है. अगले सेक्शन में, आप प्रोजेक्ट का पहला चरण बनाएंगे और उसकी जांच करेंगे.

पहला चरण: एक टारगेट, एक पैकेज

अब प्रोजेक्ट का पहला हिस्सा बनाने का समय हो गया है. विज़ुअल का रेफ़रंस देने के लिए, प्रोजेक्ट के स्टेज 1 सेक्शन का स्ट्रक्चर इस तरह है:

examples
└── cpp-tutorial
    └──stage1
       ├── main
       │   ├── BUILD
       │   └── hello-world.cc
       └── WORKSPACE

cpp-tutorial/stage1 निर्देशिका में ले जाने के लिए इन्हें चलाएं:

cd cpp-tutorial/stage1

इसके बाद, चलाएं:

bazel build //main:hello-world

टारगेट लेबल में, फ़ाइल फ़ोल्डर के रूट के हिसाब से //main: फ़ाइल, BUILD फ़ाइल की जगह होती है. साथ ही, BUILD फ़ाइल में टारगेट किया गया नाम hello-world होता है.

बेज़ल कुछ ऐसा पेश करता है, जो कुछ ऐसा दिखता है:

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-bin डायरेक्ट्री में आउटपुट बनाता है.

अब आपकी नई बनी बाइनरी की जांच करें:

bazel-bin/main/hello-world

इस वजह से, आपको प्रिंट किया गया “Hello world” मैसेज मिल जाता है.

यहां स्टेज 1 का डिपेंडेंसी ग्राफ़ दिया गया है:

हैलो-वर्ल्डी के लिए डिपेंडेंसी ग्राफ़, एक सोर्स फ़ाइल के साथ एक टारगेट दिखाता है.

खास जानकारी: पहला चरण

आपने अपना पहला बिल्ड पूरा कर लिया है, इसलिए आपको इस बारे में एक बेसिक आइडिया मिलता है कि बिल्ड को कैसे व्यवस्थित किया जाता है. अगले चरण में, आप एक और टारगेट जोड़कर मुश्किल जोड़ देंगे.

चरण 2: एक से ज़्यादा बिल्ड टारगेट

हालांकि, छोटे प्रोजेक्ट के लिए एक ही टारगेट काफ़ी होता है, लेकिन हो सकता है कि आप बड़े प्रोजेक्ट को कई टारगेट और पैकेज में बांटना चाहें. इससे, तेज़ी से बढ़ने वाले बिल्ड को अनुमति मिलती है – यानी, बेज़ल सिर्फ़ उन चीज़ों को फिर से बनाता है जिनमें बदलाव हुआ है – और एक साथ कई प्रोजेक्ट बनाकर आपके बिल्ड तेज़ी से लोड होते हैं. ट्यूटोरियल के इस स्टेज में, एक टारगेट जोड़ा जाता है और अगले चरण में एक पैकेज जोड़ा जाता है.

यह वह डायरेक्ट्री है जिसमें आप दूसरे चरण के लिए काम कर रहे हैं:

    ├──stage2
    │  ├── main
    │  │   ├── BUILD
    │  │   ├── hello-world.cc
    │  │   ├── hello-greet.cc
    │  │   └── hello-greet.h
    │  └── WORKSPACE

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 rule का इस्तेमाल किया गया. इसके बाद, hello-world बाइनरी का इस्तेमाल किया गया. hello-world टारगेट में मौजूद deps एट्रिब्यूट से, बेज़ल को यह पता चलता है कि hello-greet लाइब्रेरी को hello-world बाइनरी बनाने की ज़रूरत है.

इस प्रोजेक्ट का नया वर्शन बनाने से पहले, आपको नीचे दी गई डायरेक्ट्री को बदलकर, cpp-tutorial/stage2 डायरेक्ट्री में बदलना होगा:

cd ../stage2

अब आप नीचे दिए गए जाने-पहचाने निर्देश का इस्तेमाल करके नई बाइनरी बना सकते हैं:

bazel build //main:hello-world

एक बार फिर, बेज़ल कुछ ऐसा पेश करती हैं:

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-world` के लिए डिपेंडेंसी ग्राफ़, फ़ाइल में बदलाव के बाद स्ट्रक्चर में हुए बदलावों को दिखाता है.

खास जानकारी: दूसरा चरण

अब आपने दो टारगेट के साथ प्रोजेक्ट बनाया है. hello-world टारगेट एक सोर्स फ़ाइल बनाता है और एक अन्य टारगेट (//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
   └── WORKSPACE

अब आप दो सब-डायरेक्ट्री देख सकते हैं और हर एक में BUILD फ़ाइल होती है. इसलिए, बेज़ल में, अब फ़ाइल फ़ोल्डर में दो पैकेज हैं: 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) पर निर्भर करता है - बेज़ल को यह deps एट्रिब्यूट के ज़रिए पता है. आपको यह डिपेंडेंसी ग्राफ़ में दिखेगा:

`hello-world` के लिए डिपेंडेंसी ग्राफ़, दिखाता है कि मुख्य पैकेज में दिया गया टारगेट, `lib` पैकेज में मौजूद टारगेट पर कैसे निर्भर करता है.

बिल्ड हो जाने के लिए, आपको lib/BUILD में मौजूद //lib:hello-time का टारगेट, विज़िबिलिटी एट्रिब्यूट का इस्तेमाल करके, main/BUILD में मौजूद टारगेट करने के लिए साफ़ तौर पर दिखाना होगा. ऐसा इसलिए है, क्योंकि डिफ़ॉल्ट रूप से ये टारगेट सिर्फ़ उसी BUILD फ़ाइल में मौजूद दूसरे टारगेट को दिखते हैं. Bazel, लाइब्रेरी को लागू करने से जुड़ी समस्याओं जैसी समस्याओं से बचने के लिए, टारगेट विज़िबिलिटी का इस्तेमाल करता है. इसमें, सार्वजनिक एपीआई में डेटा लीक होने के बारे में जानकारी शामिल होती है.

अब प्रोजेक्ट का यह फ़ाइनल वर्शन बनाएं. यह चलाकर cpp-tutorial/stage3 डायरेक्ट्री पर स्विच करें:

cd  ../stage3

एक बार फिर, यह निर्देश चलाएं:

bazel build //main:hello-world

बेज़ल कुछ ऐसा पेश करता है, जो कुछ ऐसा दिखता है:

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 की मदद से सीखना जारी रखने के लिए, यहां कुछ और संसाधन दिए गए हैं:

बिल्डिंग की शुभकामनाएं!