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