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

किसी समस्या की शिकायत करें सोर्स देखें Nightly · 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

परिचय

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

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

पूरा होने में लगने वाला अनुमानित समय: 30 मिनट.

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

अगर आपने Bazel इंस्टॉल नहीं किया है, तो पहले इसे इंस्टॉल करें. इस ट्यूटोरियल में, सोर्स कंट्रोल के लिए Git का इस्तेमाल किया गया है. इसलिए, बेहतर नतीजे पाने के लिए, Git इंस्टॉल करें.

इसके बाद, अपनी पसंद के कमांड-लाइन टूल में नीचे दिए गए निर्देश को चलाकर, Baze के 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) इंस्टॉल करके और इस ट्यूटोरियल के लिए रिपॉज़िटरी को क्लोन करके, आपने Bazel की मदद से अपने पहले बिल्ड की नींव रख दी है. कुछ शब्दों की परिभाषा देने और अपना वर्कस्पेस सेट अप करने के लिए, अगले सेक्शन पर जाएं.

शुरू करना

फ़ाइल फ़ोल्डर सेट अप करना

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

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

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

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

BUILD फ़ाइल को समझना

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

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

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

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

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

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

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

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

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 है.

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

आपने अभी-अभी अपना पहला Basel टारगेट बनाया है. Bazel, बने हुए आउटपुट को वर्कस्पेस के रूट में मौजूद bazel-bin डायरेक्ट्री में डालता है.

अब अपने नए बाइनरी को टेस्ट करें, जो:

bazel-bin/main/hello-world

इससे, “Hello world” प्रिंट किया हुआ मैसेज दिखेगा.

यहां पहले चरण का डिपेंडेंसी ग्राफ़ दिया गया है:

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

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

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

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

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

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

    ├──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-world बाइनरी बनाने के लिए hello-greet लाइब्रेरी की ज़रूरत है.

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

तीसरा चरण: एक से ज़्यादा पैकेज

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

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

बिल्ड को सफल बनाने के लिए, आपको 'किसको दिखे' एट्रिब्यूट का इस्तेमाल करके, 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

खास जानकारी: तीसरा चरण

अब आपने प्रोजेक्ट को तीन टारगेट के साथ दो पैकेज के तौर पर बना लिया है और दोनों के बीच की निर्भरताओं को समझ लिया है. इससे आपको Basel की मदद से, आने वाले समय में प्रोजेक्ट बनाने में मदद मिलती है. अगले सेक्शन में, Bazel के साथ अपनी यात्रा जारी रखने का तरीका जानें.

अगले चरण

अब आपने Basel के साथ अपना पहला बेसिक बिल्ड पूरा कर लिया है, लेकिन यह तो बस शुरुआत है. Bazel के बारे में ज़्यादा जानने के लिए, यहां कुछ और संसाधन दिए गए हैं:

मज़े से बनाएं!