Bazel, दूसरे प्रोजेक्ट के टारगेट पर निर्भर हो सकता है. इन दूसरे प्रोजेक्ट की डिपेंडेंसी को एक्सटर्नल डिपेंडेंसी कहा जाता है.
वर्कस्पेस डायरेक्ट्री में मौजूद WORKSPACE फ़ाइल (या WORKSPACE.bazel फ़ाइल),
Bazel को यह बताती है कि दूसरे प्रोजेक्ट के सोर्स कैसे हासिल किए जाएं.
इन दूसरे प्रोजेक्ट में, अपने टारगेट के साथ एक या उससे ज़्यादा BUILD फ़ाइलें हो सकती हैं. मुख्य प्रोजेक्ट में मौजूद BUILD फ़ाइलें, WORKSPACE फ़ाइल से उनके नाम का इस्तेमाल करके, इन एक्सटर्नल टारगेट पर निर्भर हो सकती हैं.
उदाहरण के लिए, मान लें कि किसी सिस्टम पर दो प्रोजेक्ट मौजूद हैं:
/
home/
user/
project1/
WORKSPACE
BUILD
srcs/
...
project2/
WORKSPACE
BUILD
my-libs/
अगर project1 को
/home/user/project2/BUILD में तय किए गए टारगेट :foo पर निर्भर होना है, तो वह यह तय कर सकता है कि
project2 नाम का डेटाबेस, /home/user/project2 पर मौजूद है. इसके बाद, /home/user/project1/BUILD में मौजूद टारगेट, @project2//:foo पर निर्भर हो सकते हैं.
WORKSPACE फ़ाइल की मदद से, उपयोगकर्ता फ़ाइल सिस्टम के दूसरे हिस्सों से टारगेट पर निर्भर हो सकते हैं. साथ ही, इंटरनेट से डाउनलोड किए गए टारगेट पर भी निर्भर हो सकते हैं. यह BUILD फ़ाइलों के जैसी ही सिंटैक्स का इस्तेमाल करती है. हालांकि, इसमें डेटाबेस के नियम (इन्हें कभी-कभी वर्कस्पेस के नियम भी कहा जाता है) नाम के नियमों का एक अलग सेट इस्तेमाल किया जाता है. Bazel में, डेटाबेस के कुछ
बिल्ट-इन नियम और
Starlark के एम्बेड किए गए डेटाबेस के नियमों का एक सेट शामिल है.
उपयोगकर्ता, ज़्यादा जटिल व्यवहार पाने के लिए, डेटाबेस के कस्टम नियम
भी लिख सकते हैं.
एक्सटर्नल डिपेंडेंसी के इस्तेमाल किए जा सकने वाले टाइप
एक्सटर्नल डिपेंडेंसी के कुछ बुनियादी टाइप इस्तेमाल किए जा सकते हैं:
- Bazel के दूसरे प्रोजेक्ट पर डिपेंडेंसी
- Bazel के अलावा दूसरे प्रोजेक्ट पर डिपेंडेंसी
- एक्सटर्नल पैकेज पर डिपेंडेंसी
Bazel के दूसरे प्रोजेक्ट पर डिपेंडेंसी
अगर आपको Bazel के दूसरे प्रोजेक्ट के टारगेट इस्तेमाल करने हैं, तो आप
इस्तेमाल कर सकते हैं
local_repository,
git_repository
या http_archive
का इस्तेमाल करके, उन्हें लोकल फ़ाइल सिस्टम से सिमलंक किया जा सकता है. साथ ही, गिट डेटाबेस को रेफ़र किया जा सकता है या उन्हें डाउनलोड
किया जा सकता है.
उदाहरण के लिए, मान लें कि आप 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 के तौर पर रेफ़र कर सकता है. एक्सटर्नल प्रोजेक्ट के नाम,
वर्कस्पेस के मान्य नाम होने चाहिए.
Bazel के अलावा दूसरे प्रोजेक्ट पर डिपेंडेंसी
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"],
)
इसके बाद, अपने प्रोजेक्ट की BUILD फ़ाइलों से, @coworkers_project//:some-lib पर निर्भर हुआ जा सकता है.
एक्सटर्नल पैकेज पर डिपेंडेंसी
Maven के आर्टफ़ैक्ट और डेटाबेस
Maven के डेटाबेस से आर्टफ़ैक्ट डाउनलोड करने और उन्हें Java
की डिपेंडेंसी के तौर पर उपलब्ध कराने के लिए, rules_jvm_external
के नियमसेट का इस्तेमाल करें.
डिपेंडेंसी फ़ेच करना
डिफ़ॉल्ट रूप से, एक्सटर्नल डिपेंडेंसी को bazel build के दौरान, ज़रूरत के हिसाब से फ़ेच किया जाता है. अगर
आपको टारगेट के किसी खास सेट के लिए ज़रूरी डिपेंडेंसी को पहले से फ़ेच करना है, तो
bazel fetch का इस्तेमाल करें.
सभी एक्सटर्नल डिपेंडेंसी को बिना किसी शर्त के फ़ेच करने के लिए, इस्तेमाल करें
bazel sync.
फ़ेच किए गए डेटाबेस, आउटपुट बेस में सेव किए जाते हैं. इसलिए, हर वर्कस्पेस के लिए फ़ेचिंग
की जाती है.
डिपेंडेंसी को शैडो करना
हमारा सुझाव है कि जहां तक हो सके, अपने प्रोजेक्ट में एक ही वर्शन की नीति अपनाएं. यह उन डिपेंडेंसी के लिए ज़रूरी है जिन्हें कंपाइल किया जाता है और जो आपकी फ़ाइनल बाइनरी में शामिल होती हैं. हालांकि, ऐसे मामलों में जहां यह ज़रूरी नहीं है, डिपेंडेंसी को शैडो किया जा सकता है. यह उदाहरण देखें:
myproject/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 में, इन टेस्ट रनर के साथ-साथ काम न करने की कोई वजह नहीं है. हालांकि, ये एक-दूसरे से टकराएंगे, क्योंकि इनके नाम एक जैसे हैं. दोनों डिपेंडेंसी का एलान करने के लिए, 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 की डिपेंडेंसी एक ही है, लेकिन उन्हें अलग-अलग नामों से कॉल किया जाता है, तो उन डिपेंडेंसी को myproject/WORKSPACE में जोड़ा जा सकता है.
कमांड लाइन से डेटाबेस को ओवरराइड करना
कमांड लाइन से, एलान किए गए डेटाबेस को लोकल डेटाबेस से ओवरराइड करने के लिए,
use the
--override_repository
फ़्लैग का इस्तेमाल करें. इस फ़्लैग का इस्तेमाल करने से, सोर्स कोड में बदलाव किए बिना, एक्सटर्नल डेटाबेस का कॉन्टेंट बदल जाता है.
उदाहरण के लिए, लोकल डायरेक्ट्री /path/to/local/foo पर @foo को ओवरराइड करने के लिए,
--override_repository=foo=/path/to/local/foo फ़्लैग पास करें.
इसके कुछ इस्तेमाल के उदाहरण यहां दिए गए हैं:
- गड़बड़ियाँ ठीक करने के लिए. उदाहरण के लिए,
http_archiveडेटाबेस को किसी लोकल डायरेक्ट्री पर ओवरराइड किया जा सकता है, जहां बदलाव ज़्यादा आसानी से किए जा सकते हैं. - वेंडरिंग. अगर आप ऐसे एनवायरमेंट में हैं जहां नेटवर्क कॉल नहीं किए जा सकते, तो नेटवर्क पर आधारित डेटाबेस के नियमों को ओवरराइड करके, उन्हें लोकल डायरेक्ट्री पर पॉइंट करें.
प्रॉक्सी का इस्तेमाल करना
Bazel, HTTPS_PROXY और HTTP_PROXY एनवायरमेंट वैरिएबल से प्रॉक्सी पते लेगा. साथ ही, इनका इस्तेमाल करके, एचटीटीपी/एचटीटीपीएस फ़ाइलें डाउनलोड करेगा (अगर तय किया गया हो).
IPv6 के लिए सहायता
सिर्फ़ IPv6 वाले कंप्यूटरों पर, Bazel बिना किसी बदलाव के डिपेंडेंसी डाउनलोड कर पाएगा. हालांकि, डुअल-स्टैक IPv4/IPv6 वाले कंप्यूटरों पर, Bazel Java के जैसा ही तरीका अपनाता है: अगर IPv4 चालू है, तो IPv4 को प्राथमिकता दी जाती है. कुछ स्थितियों में, जैसे कि जब IPv4 नेटवर्क, एक्सटर्नल पतों को हल/उन तक नहीं पहुंच पाता, तो इससे Network unreachable अपवाद और बिल्ड में गड़बड़ियां हो सकती हैं.
इन मामलों में, Bazel के व्यवहार को ओवरराइड किया जा सकता है, ताकि वह IPv6
को प्राथमिकता दे. इसके लिए, java.net.preferIPv6Addresses=true सिस्टम प्रॉपर्टी का इस्तेमाल करें.
खास तौर पर, इस बारे में जानकारी मिलती है:
स्टार्टअप विकल्प
--host_jvm_args=-Djava.net.preferIPv6Addresses=trueका इस्तेमाल करें, उदाहरण के लिए, अपनी.bazelrcफ़ाइल में यह लाइन जोड़ें:startup --host_jvm_args=-Djava.net.preferIPv6Addresses=trueअगर Java के बिल्ड टारगेट चलाए जा रहे हैं जिन्हें इंटरनेट से भी कनेक्ट करना है (कभी-कभी इंटिग्रेशन टेस्ट के लिए इसकी ज़रूरत होती है), तो
--jvmopt=-Djava.net.preferIPv6Addresses=trueटूल फ़्लैग का भी इस्तेमाल करें. उदाहरण के लिए, अपनी.bazelrcफ़ाइल में यह लाइन जोड़ें:build --jvmopt=-Djava.net.preferIPv6Addressesअगर rules_jvm_external का इस्तेमाल किया जा रहा है, तो डिपेंडेंसी वर्शन रिज़ॉल्यूशन के लिए,
-Djava.net.preferIPv6Addresses=trueकोCOURSIER_OPTSएनवायरमेंट वैरिएबल में जोड़ें, ताकि Coursier के लिए JVM विकल्प उपलब्ध कराए जा सकें
ट्रांज़िटिव डिपेंडेंसी
Bazel सिर्फ़ आपकी WORKSPACE फ़ाइल में शामिल डिपेंडेंसी को पढ़ता है. अगर आपका प्रोजेक्ट
(A), किसी दूसरे प्रोजेक्ट (B) पर निर्भर है और उसकी WORKSPACE फ़ाइल में, तीसरे
प्रोजेक्ट (C) पर डिपेंडेंसी शामिल है, तो आपको अपने प्रोजेक्ट की WORKSPACE फ़ाइल में B
और C, दोनों को जोड़ना होगा. इस ज़रूरी शर्त की वजह से,
WORKSPACE फ़ाइल का साइज़ बढ़ सकता है. हालांकि, इससे इस बात की संभावना कम हो जाती है कि एक लाइब्रेरी
में C का वर्शन 1.0 और दूसरी लाइब्रेरी में C का वर्शन 2.0 शामिल हो.
एक्सटर्नल डिपेंडेंसी की कैश मेमोरी
डिफ़ॉल्ट रूप से, Bazel एक्सटर्नल डिपेंडेंसी को सिर्फ़ तब फिर से डाउनलोड करेगा, जब उनकी परिभाषा में बदलाव होगा. Bazel, परिभाषा में रेफ़र की गई फ़ाइलों (जैसे कि पैच या BUILD फ़ाइलें) में किए गए बदलावों को भी ध्यान में रखता है.
फिर से डाउनलोड करने के लिए, bazel sync का इस्तेमाल करें.
लेआउट
एक्सटर्नल डिपेंडेंसी, आउटपुट बेस में मौजूद सबडायरेक्ट्री
external के तहत किसी डायरेक्ट्री में डाउनलोड की जाती हैं. लोकल डेटाबेस के मामले में, नई डायरेक्ट्री बनाने के बजाय, वहां एक सिमलंक बनाया जाता है.
external डायरेक्ट्री देखने के लिए, यह कमांड चलाएं:
ls $(bazel info output_base)/externalध्यान दें कि bazel clean चलाने से, एक्सटर्नल डायरेक्ट्री असल में नहीं मिटेगी. सभी एक्सटर्नल आर्टफ़ैक्ट हटाने के लिए, bazel clean --expunge का इस्तेमाल करें.
ऑफ़लाइन बिल्ड
कभी-कभी ऑफ़लाइन तरीके से बिल्ड चलाना ज़रूरी होता है. सामान्य इस्तेमाल के उदाहरणों के लिए, जैसे कि हवाई जहाज़ में यात्रा करते समय,
prefetching डेटाबेस को
bazel fetch या bazel sync की मदद से, पहले से फ़ेच करना काफ़ी हो सकता है. इसके अलावा,
--nofetch विकल्प का इस्तेमाल करके, बिल्ड के दौरान अन्य डेटाबेस को फ़ेच करने की सुविधा बंद की जा सकती है.
पूरी तरह ऑफ़लाइन बिल्ड के लिए, जहां ज़रूरी फ़ाइलें Bazel के अलावा किसी दूसरी इकाई से उपलब्ध कराई जानी हैं, Bazel, --distdir विकल्प के साथ काम करता है. जब भी कोई डेटाबेस का नियम, Bazel से
ctx.download या
ctx.download_and_extract
के ज़रिए कोई फ़ाइल फ़ेच करने के लिए कहता है और ज़रूरी फ़ाइल का हैश सम उपलब्ध कराता है, तो Bazel सबसे पहले उस विकल्प से तय की गई डायरेक्ट्री में, उपलब्ध कराए गए पहले यूआरएल के बेसनेम से मेल खाने वाली फ़ाइल को देखेगा. अगर हैश मैच होता है, तो वह लोकल कॉपी का इस्तेमाल करेगा.
Bazel, डिस्ट्रिब्यूशन
आर्टफ़ैक्ट से ऑफ़लाइन बूटस्ट्रैप करने के लिए, इसी तकनीक का इस्तेमाल करता है.
यह, ज़रूरी सभी एक्सटर्नल
डिपेंडेंसी को, इंटरनल
distdir_tar में इकट्ठा करके ऐसा करता है.
हालांकि, Bazel, डेटाबेस के नियमों में किसी भी कमांड को चलाने की अनुमति देता है. भले ही, उन्हें नेटवर्क पर कॉल किया गया हो या नहीं. इसलिए, Bazel के पास ऐसे बिल्ड को पूरी तरह ऑफ़लाइन करने का कोई विकल्प नहीं है. इसलिए, यह जांचने के लिए कि कोई बिल्ड ऑफ़लाइन सही तरीके से काम करता है या नहीं, नेटवर्क को एक्सटर्नल तरीके से ब्लॉक करना ज़रूरी है. जैसे, Bazel अपने बूटस्ट्रैप टेस्ट में करता है.
सबसे सही तरीके
डेटाबेस के नियम
डेटाबेस के नियम की ज़िम्मेदारी आम तौर पर यह होनी चाहिए:
- सिस्टम सेटिंग का पता लगाना और उन्हें फ़ाइलों में लिखना.
- सिस्टम में कहीं और मौजूद संसाधन ढूंढना.
- यूआरएल से संसाधन डाउनलोड करना.
- एक्सटर्नल डेटाबेस डायरेक्ट्री में BUILD फ़ाइलें जनरेट करना या उन्हें सिमलंक करना.
जहां तक हो सके, repository_ctx.execute का इस्तेमाल न करें. उदाहरण के लिए, Make का इस्तेमाल करके बिल्ड करने वाली, Bazel के अलावा C++
लाइब्रेरी का इस्तेमाल करते समय, ctx.execute(["make"]) चलाने के बजाय, repository_ctx.download() का इस्तेमाल करना बेहतर है. इसके बाद,
एक BUILD फ़ाइल लिखें जो इसे बिल्ड करे.
git_repository और
new_git_repository के बजाय, http_archive का इस्तेमाल करें. इसकी वजहें यहां दी गई हैं:
- गिट डेटाबेस के नियम, सिस्टम
git(1)पर निर्भर करते हैं. वहीं, एचटीटीपी डाउनलोडर, Bazel में बिल्ट-इन होता है और इसकी कोई सिस्टम डिपेंडेंसी नहीं होती. http_archive, मिरर के तौर परurlsकी सूची के साथ काम करता है. वहीं,git_repositoryसिर्फ़ एकremoteके साथ काम करता है.http_archiveडेटाबेस की कैश मेमोरी के साथ काम करता है. हालांकि,git_repositoryऐसा नहीं करता. ज़्यादा जानकारी के लिए, #5116 देखें.
bind() का इस्तेमाल न करें. इसकी समस्याओं और विकल्पों के बारे में ज़्यादा जानकारी के लिए, "bind को हटाने के बारे में जानकारी" देखें.