BazelCon 2022, 16 नवंबर से 17 नवंबर तक न्यूयॉर्क में और ऑनलाइन उपलब्ध है.
आज ही रजिस्टर करें!

बाहरी डिपेंडेंसी के साथ काम करना

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

बैज़ेल अन्य प्रोजेक्ट से टारगेट पर निर्भर कर सकता है. इन अन्य प्रोजेक्ट से डिपेंडेंसी को बाहरी डिपेंडेंसी कहा जाता है.

Workspace डायरेक्ट्री में मौजूद WORKSPACE फ़ाइल या WORKSPACE.bazel फ़ाइल से, बेज़ल को पता चलता है कि अन्य प्रोजेक्ट और #39 सोर्स कैसे मिलेंगे. इन अन्य प्रोजेक्ट में अपने टारगेट के साथ एक या ज़्यादा BUILD फ़ाइलें हो सकती हैं. मुख्य प्रोजेक्ट में मौजूद BUILD फ़ाइल, इन WORKSPACE फ़ाइल के नाम का इस्तेमाल करके इन बाहरी टारगेट पर निर्भर कर सकती है.

उदाहरण के लिए, मान लें कि किसी सिस्टम पर दो प्रोजेक्ट हैं:

/
  home/
    user/
      project1/
        WORKSPACE
        BUILD
        srcs/
          ...
      project2/
        WORKSPACE
        BUILD
        my-libs/

अगर project1, टारगेट के हिसाब से :foo पर निर्भर करना चाहता है, तो यह बताया जा सकता है कि /home/user/project2 नाम का रिपॉज़िटरी, /home/user/project2 पर मिल सकता है. इसके बाद, /home/user/project1/BUILD में दिए गए टारगेट, @project2//:foo पर निर्भर कर सकते हैं.

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

बाहरी डिपेंडेंसी के टाइप

बाहरी डिपेंडेंसी के कुछ बुनियादी टाइप इस्तेमाल किए जा सकते हैं:

Bazel के दूसरे प्रोजेक्ट के आधार पर

अगर आपको किसी दूसरे Bazel प्रोजेक्ट का टारगेट इस्तेमाल करना है, तो local_repository, git_repository या http_archive इसका इस्तेमाल करके, स्थानीय फ़ाइल सिस्टम से सिंक किया जा सकता है. इसके अलावा, किसी GIF का डेटा स्टोर करने की जगह का रेफ़रंस देखा जा सकता है या उसे डाउनलोड किया जा सकता है (इसके हिसाब से).

उदाहरण के लिए, मान लें कि आप किसी प्रोजेक्ट my-project/ पर काम कर रहे हैं और आप अपने सहकर्मी, प्रोजेक्ट coworkers-project/ के टारगेट पर निर्भर करना चाहते हैं. दोनों प्रोजेक्ट, Bazel का इस्तेमाल करते हैं. इसलिए, आप अपने साथी के प्रोजेक्ट को बाहरी डिपेंडेंसी के तौर पर जोड़ सकते हैं. इसके बाद, आप अपने साथ काम करने वाले व्यक्ति के बनाए गए किसी भी टारगेट को अपनी BUILD फ़ाइलों से तय कर सकते हैं. आपको my_project/WORKSPACE में यह जोड़ना होगा:

local_repository(
    name = "coworkers_project",
    path = "/path/to/coworkers-project",
)

अगर आपके सहकर्मी का कोई टारगेट //foo:bar है, तो आपका प्रोजेक्ट उसे @coworkers_project//foo:bar के तौर पर बता सकता है. बाहरी प्रोजेक्ट के नाम फ़ाइल फ़ोल्डर के मान्य नाम होने चाहिए.

नॉन-बेज़ल प्रोजेक्ट के आधार पर

new_ से पहले के नियमों, जैसे कि new_local_repository, आपको ऐसे प्रोजेक्ट से टारगेट बनाने की सुविधा मिलती है जो Bazel का इस्तेमाल नहीं करते.

उदाहरण के लिए, मान लें कि आप किसी प्रोजेक्ट my-project/ पर काम कर रहे हैं और आप अपने सहकर्मी, प्रोजेक्ट coworkers-project/ पर निर्भर हैं. आपके सहकर्मी का प्रोजेक्ट make बनाने के लिए इस्तेमाल होता है. हालांकि, आप किसी .so फ़ाइल पर निर्भर होना चाहते हैं. ऐसा करने के लिए, my_project/WORKSPACE में यह जोड़ें:

new_local_repository(
    name = "coworkers_project",
    path = "/path/to/coworkers-project",
    build_file = "coworker.BUILD",
)

build_file, मौजूदा प्रोजेक्ट के ऊपर ओवरले करने के लिए, BUILD फ़ाइल तय करता है, जैसे:

cc_library(
    name = "some-lib",
    srcs = glob(["**"]),
    visibility = ["//visibility:public"],
)

इसके बाद, @coworkers_project//:some-lib अपने प्रोजेक्ट की BUILD फ़ाइलों पर निर्भर किया जा सकता है.

बाहरी पैकेज के आधार पर

Maven आर्टफ़ैक्ट और रिपॉज़िटरी

Maven के डेटा स्टोर करने की जगह से कलाकृतियां डाउनलोड करने और उन्हें Java डिपेंडेंसी के तौर पर उपलब्ध कराने के लिए, नियमrules_jvm_external का इस्तेमाल करें.

डिपेंडेंसी फ़ेच की जा रही हैं

डिफ़ॉल्ट रूप से, बाहरी डिपेंडेंसी bazel build के दौरान फ़ेच की जाती हैं. अगर टारगेट के किसी खास सेट के लिए ज़रूरी डिपेंडेंसी को प्रीफ़ेच करना है, तो bazel fetch का इस्तेमाल करें. सभी बाहरी डिपेंडेंसी को बिना किसी शर्त के फ़ेच करने के लिए, bazel sync का इस्तेमाल करें. फ़ेच किए गए रिपॉज़िटरी (डेटा स्टोर की जगह) आउटपुट बेस में स्टोर होती हैं, इसलिए वे हर फ़ाइल फ़ोल्डर के लिए हैप फ़ेच करती हैं.

शैडोइंग डिपेंडेंसी

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

मेरा प्रोजेक्ट/WORKSPACE

workspace(name = "myproject")

local_repository(
    name = "A",
    path = "../A",
)
local_repository(
    name = "B",
    path = "../B",
)

A/WORKSPACE

workspace(name = "A")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner",
    urls = ["https://github.com/testrunner/v1.zip"],
    sha256 = "...",
)

B/WORKSPACE

workspace(name = "B")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner",
    urls = ["https://github.com/testrunner/v2.zip"],
    sha256 = "..."
)

A और B, दोनों डिपेंडेंसी testrunner पर निर्भर करती हैं. हालांकि, ये testrunner के अलग-अलग वर्शन पर निर्भर करती हैं. इन टेस्ट रनर के लिए यह ऐसा कोई वजह नहीं है कि वे शांत तरीके से myproject में एक साथ काम न कर पाएं. हालांकि, वे एक-दूसरे से मुकाबला कर सकते हैं, क्योंकि दोनों का नाम एक ही है. दोनों डिपेंडेंसी का एलान करने के लिए, मेरा प्रोजेक्ट/WORKSPACE अपडेट करें:

workspace(name = "myproject")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner-v1",
    urls = ["https://github.com/testrunner/v1.zip"],
    sha256 = "..."
)
http_archive(
    name = "testrunner-v2",
    urls = ["https://github.com/testrunner/v2.zip"],
    sha256 = "..."
)
local_repository(
    name = "A",
    path = "../A",
    repo_mapping = {"@testrunner" : "@testrunner-v1"}
)
local_repository(
    name = "B",
    path = "../B",
    repo_mapping = {"@testrunner" : "@testrunner-v2"}
)

इस तरीके का इस्तेमाल हीरों को जोड़ने के लिए भी किया जा सकता है. उदाहरण के लिए, अगर A और B में एक ही डिपेंडेंसी थी, लेकिन उसे अलग-अलग नाम से कॉल किया गया था, तो उन डिपेंडेंसी को मेरे प्रोजेक्ट/WORKSPACE में शामिल किया जा सकता है.

कमांड लाइन से डेटा स्टोर करने की जगह बदलना

कमांड लाइन से किसी लोकल रिपॉज़िटरी (डेटा स्टोर करने की जगह) के साथ, तय किए गए डेटा स्टोर करने की जगह को बदलने के लिए, --override_repository फ़्लैग करें. इस फ़्लैग का इस्तेमाल करने पर, आपके सोर्स कोड में बदलाव किए बिना बाहरी रिपॉज़िटरी का कॉन्टेंट बदल जाता है.

उदाहरण के लिए, @foo को स्थानीय डायरेक्ट्री /path/to/local/foo में बदलने के लिए, --override_repository=foo=/path/to/local/foo फ़्लैग पास करें.

इस्तेमाल के कुछ उदाहरणों में ये शामिल हैं:

  • डीबग करने से जुड़ी समस्याएं. उदाहरण के लिए, आप http_archive रिपॉज़िटरी को किसी स्थानीय डायरेक्ट्री में बदल सकते हैं. यहां आप ज़्यादा आसानी से बदलाव कर सकते हैं.
  • वेंडर. अगर आप किसी ऐसे परिवेश में हैं जहां आप नेटवर्क कॉल नहीं कर सकते, तो इसके बजाय लोकल डायरेक्ट्री पर ले जाने के लिए नेटवर्क-आधारित रिपॉज़िटरी नियमों को बदल दें.

प्रॉक्सी का इस्तेमाल करना

बेज़ल HTTPS_PROXY और HTTP_PROXY एनवायरमेंट वैरिएबल से प्रॉक्सी पते चुनेगा और एचटीटीपी/एचटीटीपीएस फ़ाइलों (अगर बताया गया हो) को डाउनलोड करने के लिए इनका इस्तेमाल करेगा.

IPv6 के लिए सहायता

सिर्फ़ IPv6 मशीन पर, Bazel बिना किसी बदलाव के डिपेंडेंसी डाउनलोड कर पाएगा. ड्यूअल-स्टैक IPv4/IPv6 मशीन पर, हालांकि, Bazel उसी Java की तरह काम करता है: अगर IPv4 चालू है, तो IPv4 को प्राथमिकता दी जाती है. कुछ मामलों में, उदाहरण के लिए, जब IPv4 नेटवर्क बाहरी पतों की समस्या को हल नहीं कर पाता/पाती है, तो इसकी वजह से Network unreachable अपवाद हो सकते हैं और बिल्ड काम नहीं कर सकता. इन मामलों में, आप java.net.preferIPv6Addresses=true सिस्टम प्रॉपर्टी का इस्तेमाल करके Bazel's के व्यवहार को IPv6 के हिसाब से बदल सकते हैं. खास तौर पर:

  • --host_jvm_args=-Djava.net.preferIPv6Addresses=true स्टार्टअप का विकल्प इस्तेमाल करें. उदाहरण के लिए, अपनी .bazelrc फ़ाइल में यह लाइन जोड़कर:

    startup --host_jvm_args=-Djava.net.preferIPv6Addresses=true

  • अगर आप ऐसे Java बिल्ड टारगेट चला रहे हैं जिन्हें इंटरनेट से भी कनेक्ट होने की ज़रूरत है, तो इंटिग्रेशन टूल को भी कभी-कभी इसकी ज़रूरत पड़ सकती है. उदाहरण के लिए, टूल फ़्लैग का इस्तेमाल भी करें. उदाहरण के लिए, अपनी .bazelrc फ़ाइल में, नीचे दी गई लाइन शामिल करें:

    build --jvmopt=-Djava.net.preferIPv6Addresses

  • अगर आप rule_jvm_external का इस्तेमाल कर रहे हैं, उदाहरण के लिए, डिपेंडेंसी के वर्शन का रिज़ॉल्यूशन

ट्रांज़िशनल डिपेंडेंसी

Bazel सिर्फ़ आपकी WORKSPACE फ़ाइल की सूची में शामिल डिपेंडेंसी पढ़ता है. अगर आपका प्रोजेक्ट (A), किसी ऐसे प्रोजेक्ट (B) पर निर्भर है जो अपनी WORKSPACE फ़ाइल में किसी तीसरे प्रोजेक्ट (C) पर निर्भर करता है, तो आपको B और C को प्रोजेक्ट की WORKSPACE फ़ाइल में जोड़ना होगा. इस ज़रूरी शर्त के मुताबिक, WORKSPACE फ़ाइल के साइज़ की जानकारी दी जा सकती है. हालांकि, हो सकता है कि एक लाइब्रेरी के वर्शन 1.0 और C में 2.0 वाला C शामिल हो.

बाहरी डिपेंडेंसी को कैश करना

डिफ़ॉल्ट रूप से, Bazel ने बाहरी डिपेंडेंसी को सिर्फ़ तब दोबारा डाउनलोड किया है, जब उनकी परिभाषा बदल गई हो. परिभाषा में बताई गई फ़ाइलों (जैसे, पैच या BUILD फ़ाइलें) में किए गए बदलावों पर भी बेज़ल का ध्यान रखा जाता है.

फिर से डाउनलोड करने के लिए, bazel sync का इस्तेमाल करें.

लेआउट

एक्सटर्नल डिपेंडेंसी सभी डायरेक्ट्री बेस में सबडायरेक्ट्री external में मौजूद डायरेक्ट्री में डाउनलोड होती हैं. किसी स्थानीय डेटा स्टोर करने की जगह के मामले में, एक नई डायरेक्ट्री बनाने के बजाय वहां एक सिमलिंक बनाया जाता है. आप external डायरेक्ट्री देखकर इसे देख सकते हैं:

ls $(bazel info output_base)/external

ध्यान दें कि bazel clean चलाने से बाहरी डायरेक्ट्री नहीं मिटेगी. सभी बाहरी आर्टफ़ैक्ट हटाने के लिए, bazel clean --expunge का इस्तेमाल करें.

ऑफ़लाइन बिल्ड

कई बार, ऑफ़लाइन होने पर भी बिल्ड चलाना पसंद किया जाता है या ज़रूरी है. इस्तेमाल करने के आसान उदाहरणों के लिए, जैसे कि किसी हवाई जहाज़ से यात्रा करना, bazel fetch या bazel sync के लिए ज़रूरी रिपॉज़िटरी को पॉप अप करना काफ़ी हो सकता है. इसके अलावा, बिल्ड विकल्प के दौरान, --nofetchरिपॉज़िटरी को लाने के विकल्प को बंद किया जा सकता है.

असल ऑफ़लाइन बिल्ड के लिए, जहां ज़रूरी फ़ाइलों को उपलब्ध कराने का काम बेज़ल से अलग किसी इकाई की ओर से किया जाना है, तो बेज़ल में --distdir विकल्प काम करता है. जब भी स्टोर करने के किसी नियम का इस्तेमाल करके, बेज़ल को ctx.download या ctx.download_and_extract के ज़रिए फ़ाइल फ़ेच करने की अनुमति मिलती है और फ़ाइल का हैश करने के लिए ज़रूरी कुल वैल्यू उपलब्ध कराई जाती है, तो बेज़ल पहले उस विकल्प की मदद से बताई गई फ़ाइल में, पहले यूआरएल के बेस नाम से मेल खाता है. साथ ही, हैश करने के लिए उस स्थानीय कॉपी का इस्तेमाल करता है.

Bazel इस तकनीक का इस्तेमाल करके, डिस्ट्रिब्यूशन आर्टफ़ैक्ट से ऑफ़लाइन बूटस्ट्रैप करता है. इसके लिए, संगठन में काम करने वालों के साथ सभी ज़रूरी डिपेंडेंसी इकट्ठा की जाती हैं distdir_tar.

हालांकि, बेज़ल से डेटा स्टोर करने के नियमों में, आर्बिट्रेरी कमांड एक्ज़ीक्यूट करने की अनुमति मिलती है. इसके लिए, उन्हें पता नहीं होता कि वे नेटवर्क से कनेक्ट किए गए हैं या नहीं. इसलिए, bazel में बिल्ड को पूरी तरह से ऑफ़लाइन लागू करने का विकल्प नहीं है. इसलिए, अगर कोई बिल्ड सही तरीके से काम करता है, तो यह टेस्ट करने के लिए नेटवर्क के बाहर नेटवर्क को ब्लॉक करना ज़रूरी होता है, जैसा कि bazel ने अपने बूटस्ट्रैप टेस्ट में किया है.

सबसे सही तरीके

डेटा स्टोर करने के नियम

आम तौर पर, डेटा स्टोर करने के नियम का नियम इनके लिए ज़िम्मेदार होता है:

  • सिस्टम की सेटिंग का पता लगाया जा रहा है और उन्हें फ़ाइलों में लिखा जा रहा है.
  • सिस्टम पर कहीं और संसाधन ढूंढना.
  • यूआरएल से संसाधन डाउनलोड किए जा रहे हैं.
  • बाहरी स्टोरेज डायरेक्ट्री में BUILD फ़ाइलें जनरेट या सिंक की जा रही हैं.

जब भी हो सके, repository_ctx.execute का इस्तेमाल करने से बचें. उदाहरण के लिए, गैर-Bazel C++ लाइब्रेरी का इस्तेमाल करते समय, जिसमें Make का इस्तेमाल करके बिल्ड किया जाता है, तो ctx.execute(["make"]) इस्तेमाल करने के बजाय repository_ctx.download() बनाने के लिए एक बिल्ड फ़ाइल लिखें.

http_archive को git_repository और new_git_repository को प्राथमिकता दें. इसकी वजहें ये हैं:

  • Git repository के नियम सिस्टम पर निर्भर करते हैं git(1) जबकि HTTP डाउनलोडर को Bazel में बनाया गया है और इसमें सिस्टम पर निर्भर नहीं है.
  • http_archive, urls की सूची को मिरर के तौर पर इस्तेमाल करता है और git_repository सिर्फ़ एक remote का इस्तेमाल करता है.
  • http_archive, रिपॉज़िटरी कैश के साथ काम करता है, लेकिन git_repository के साथ नहीं. ज़्यादा जानकारी के लिए, #5116 देखें.

bind() का इस्तेमाल न करें. देखें "बाइंड" को हटाने पर विचार करें; इसकी समस्याओं और विकल्पों के बारे में काफ़ी जानकारी देने के लिए.