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

समस्या की शिकायत करें सोर्स देखें ठीक

शुरुआती जानकारी

क्या Babel के लिए नए हैं? आप सही जगह पर हैं. Basel का इस्तेमाल करना आसान बनाने के लिए, First Build के इस ट्यूटोरियल को देखें. इस ट्यूटोरियल में मुख्य शब्दों के बारे में बताया गया है, क्योंकि इनका इस्तेमाल Baze के कॉन्टेक्स्ट में किया गया है. साथ ही, इसमें आपको Basel के वर्कफ़्लो की बुनियादी बातें भी बताई गई हैं. सबसे पहले, आपको अपनी ज़रूरत के हिसाब से टूल बनाने होंगे और उनमें बढ़ती जटिलता के साथ, तीन प्रोजेक्ट बनाने होंगे. साथ ही, आपको यह जानकारी भी मिलेगी कि प्रोजेक्ट जटिल कैसे और क्यों होता है.

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

पूरा होने का अनुमानित समय: 30 मिनट.

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

अगर आपने पहले से ऐसा नहीं किया है, तो Basel का ऐप्लिकेशन इंस्टॉल करें और उसे इंस्टॉल करके शुरू करें. यह ट्यूटोरियल सोर्स कंट्रोल के लिए 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

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

सारांश: परिचय

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

प्रारंभ करना

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

अब अपनी हाल ही में बनाई गई बाइनरी की जांच करें. इससे:

bazel-bin/main/hello-world

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

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

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

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

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

दूसरा चरण: कई बिल्ड टारगेट

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

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

    ├──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 फ़ाइल की मदद से, Basel ने सबसे पहले hello-greet लाइब्रेरी (Baze के बिल्ट-इन 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 में बदलाव किया जाता है और प्रोजेक्ट को फिर से बनाया जाता है, तो Basel, उस फ़ाइल को सिर्फ़ रीकंपाइल करता है.

डिपेंडेंसी ग्राफ़ को देखने पर, आपको पता चलता है कि hello-world एक अतिरिक्त इनपुट पर निर्भर है, जिसका नाम hello-greet है:

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

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

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

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

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

अब प्रोजेक्ट का यह फ़ाइनल वर्शन बनाएं. चलाकर 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

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

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

अगले चरण

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

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