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

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

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

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

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

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

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

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

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

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

Google कुछ शब्द तय करने के लिए, अगले सेक्शन पर जाएं और फ़ाइल फ़ोल्डर सेट अप करें.

YouTube पर शुरुआत करना

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

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

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

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

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

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 सोर्स फ़ाइल से सेल्फ़-कंटेन्ड एक्ज़ीक्यूटेबल बाइनरी बनाने के लिए, जिसमें कोई डिपेंडेंसी नहीं होती.

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

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

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

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

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 टारगेट बनाया है. बेज़ल, Workspace के रूट में 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 लाइब्रेरी बनाता है (Bzel के बिल्ट-इन 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-greet के नाम वाले अतिरिक्त इनपुट पर निर्भर करता है:

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

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

अब आपने दो टारगेट के साथ प्रोजेक्ट बनाया है. hello-world टारगेट एक सोर्स फ़ाइल बनाता है और एक अन्य टारगेट (//main:hello-greet) पर निर्भर करता है, जो दो अतिरिक्त सोर्स फ़ाइलें बनाता है. अगले सेक्शन में, एक कदम और आगे बढ़ें और दूसरा पैकेज जोड़ें.

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

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

बिल्डिंग बनाने का आनंद लें!