Baज़ल, बिल्ड टूल के कई अलग-अलग वर्शन, जैसे कि लिंकर और कंपाइलर का इस्तेमाल करके, कई तरह के हार्डवेयर, ऑपरेटिंग सिस्टम, और सिस्टम कॉन्फ़िगरेशन पर कोड बना सकता है और उनकी जांच कर सकता है. इस जटिलता को मैनेज करने में मदद करने के लिए, Bazel में सीमाओं और प्लैटफ़ॉर्म का कॉन्सेप्ट है. शर्त एक ऐसा डाइमेंशन है जिसमें बिल्ड या प्रोडक्शन एनवायरमेंट अलग-अलग हो सकते हैं. जैसे, सीपीयू आर्किटेक्चर, जीपीयू की मौजूदगी या अनुपस्थिति या सिस्टम में इंस्टॉल किए गए कंपाइलर का वर्शन. प्लैटफ़ॉर्म, इन पाबंदियों के लिए विकल्पों का एक नाम दिया गया कलेक्शन होता है. यह किसी एनवायरमेंट में उपलब्ध खास संसाधनों को दिखाता है.
एनवायरमेंट को एक प्लैटफ़ॉर्म के तौर पर मॉडल करने से, Baze को अपने-आप सही टूलचेन चुनने में मदद मिलती है. कॉन्फ़िगर किए जा सकने वाले एट्रिब्यूट लिखने के लिए, प्लैटफ़ॉर्म का इस्तेमाल config_setting नियम के साथ भी किया जा सकता है.
बेज़ल इन तीन भूमिकाओं को समझते हैं जो एक प्लैटफ़ॉर्म पूरा कर सकता है:
- होस्ट - वह प्लैटफ़ॉर्म जिस पर Bazel खुद चलता है.
- निष्पादित करना - वह प्लैटफ़ॉर्म जिस पर टूल बिल्ड ऐक्शन बनाते हैं, ताकि इंटरमीडिएट और फ़ाइनल आउटपुट जनरेट किए जा सकें.
- टारगेट - वह प्लैटफ़ॉर्म जिस पर फ़ाइनल आउटपुट सेव होता है और लागू होता है.
Bazel, प्लैटफ़ॉर्म के लिए इन बिल्ड स्थितियों के साथ काम करता है:
सिंगल-प्लैटफ़ॉर्म बिल्ड (डिफ़ॉल्ट) - होस्ट, एक्ज़ीक्यूशन, और टारगेट प्लैटफ़ॉर्म एक जैसे होते हैं. उदाहरण के लिए, Intel x64 सीपीयू पर चलने वाले Ubuntu पर, Linux के लिए बने किसी प्रोग्राम को बनाना.
क्रॉस-कंपाइलेशन बिल्ड - होस्ट और एक्सीक्यूशन प्लैटफ़ॉर्म एक ही होते हैं, लेकिन टारगेट प्लैटफ़ॉर्म अलग होता है. उदाहरण के लिए, MacBook Pro पर macOS पर चलने वाला iOS ऐप्लिकेशन बनाना.
मल्टी-प्लैटफ़ॉर्म बिल्ड - होस्ट, एक्ज़ीक्यूशन, और टारगेट प्लैटफ़ॉर्म सभी अलग-अलग होते हैं.
सीमाओं और प्लैटफ़ॉर्म तय करना
BUILD
फ़ाइलों में constraint_setting
और
constraint_value
नियमों का इस्तेमाल करके, प्लैटफ़ॉर्म के लिए संभावित विकल्पों की जगह तय की जाती है. constraint_setting
एक नया डाइमेंशन बनाता है, जबकि
constraint_value
किसी दिए गए डाइमेंशन के लिए एक नई वैल्यू बनाता है. साथ में, ये एक 'एनम' और उसकी संभावित वैल्यू को असरदार तरीके से तय करते हैं. उदाहरण के लिए, BUILD
फ़ाइल का नीचे दिया गया स्निपेट, दो संभावित वैल्यू के साथ सिस्टम के glibc वर्शन के लिए एक कंस्ट्रेंट पेश करता है.
constraint_setting(name = "glibc_version")
constraint_value(
name = "glibc_2_25",
constraint_setting = ":glibc_version",
)
constraint_value(
name = "glibc_2_26",
constraint_setting = ":glibc_version",
)
वर्कस्पेस में, अलग-अलग पैकेज में सीमाएं और उनकी वैल्यू तय की जा सकती हैं. इनका रेफ़रंस लेबल से दिया जाता है और इन्हें दिखने के लिए, आम तौर पर लागू होने वाले कंट्रोल का इस्तेमाल किया जाता है. अगर विज़िबिलिटी की अनुमति हो, तो किसी मौजूदा कंस्ट्रेंट सेटिंग के लिए, अपनी वैल्यू तय करके उसे बढ़ाया जा सकता है.
platform
नियम से, एक नया प्लैटफ़ॉर्म शुरू होता है. इसमें, पाबंदी की वैल्यू के कुछ विकल्प होते हैं. नीचे दिए गए नतीजे, linux_x86
नाम का एक प्लैटफ़ॉर्म बनाते हैं. इसमें बताया गया है कि यह ऐसे किसी भी एनवायरमेंट के बारे में बताता है जो x86_64 आर्किटेक्चर पर Linux ऑपरेटिंग सिस्टम चलाता है और इसका glibc वर्शन 2.25 है. (Bazel में पहले से मौजूद पाबंदियों के बारे में ज़्यादा जानने के लिए, नीचे देखें.)
platform(
name = "linux_x86",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
":glibc_2_25",
],
)
आम तौर पर काम की शर्तें और प्लैटफ़ॉर्म
नेटवर्क को एक जैसा रखने के लिए, Basel टीम ने सबसे लोकप्रिय सीपीयू आर्किटेक्चर और ऑपरेटिंग सिस्टम के लिए कंस्ट्रेंट डेफ़िनिशन वाली एक रिपॉज़िटरी (डेटा स्टोर करने की जगह) बनाए रखी है. ये सभी https://github.com/bazelbuild/platforms पर मौजूद हैं.
Bazel में, प्लैटफ़ॉर्म की खास परिभाषा के तौर पर यह जानकारी शामिल होती है:
@local_config_platform//:host
. यह अपने-आप पता चलने वाले होस्ट प्लैटफ़ॉर्म की वैल्यू है -
यह उस सिस्टम के लिए अपने-आप पता चलने वाले प्लैटफ़ॉर्म को दिखाता है जिस पर Bazel चल रहा है.
बिल्ड के लिए प्लैटफ़ॉर्म तय करना
किसी बिल्ड के लिए होस्ट और टारगेट प्लैटफ़ॉर्म तय करने के लिए, यहां दिए गए कमांड-लाइन फ़्लैग का इस्तेमाल किया जा सकता है:
--host_platform
- डिफ़ॉल्ट रूप से@bazel_tools//platforms:host_platform
--platforms
- डिफ़ॉल्ट रूप से@bazel_tools//platforms:target_platform
काम न करने वाले टारगेट को स्किप करना
किसी खास टारगेट प्लैटफ़ॉर्म के लिए काम करते समय, अक्सर ज़रूरी होता है कि आप उन टारगेट को छोड़ दें जो उस प्लैटफ़ॉर्म पर कभी काम नहीं करेंगे. उदाहरण के लिए, //...
के साथ Linux मशीन पर बिल्ड करते समय, आपके Windows डिवाइस ड्राइवर से कई कंपाइलर गड़बड़ियां जनरेट हो सकती हैं. target_compatible_with
एट्रिब्यूट का इस्तेमाल करके, Basel को बताएं कि आपके कोड में टारगेट प्लैटफ़ॉर्म की कौनसी सीमाएं हैं.
इस एट्रिब्यूट का सबसे आसान इस्तेमाल, किसी टारगेट को सिर्फ़ एक प्लैटफ़ॉर्म पर सीमित करता है.
टारगेट, किसी भी ऐसे प्लैटफ़ॉर्म के लिए नहीं बनाया जाएगा जो सभी सीमाओं को पूरा नहीं करता. इस उदाहरण में, win_driver_lib.cc
को 64-बिट Windows पर सीमित किया गया है.
cc_library(
name = "win_driver_lib",
srcs = ["win_driver_lib.cc"],
target_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:windows",
],
)
:win_driver_lib
, 64-बिट वाले Windows के साथ सिर्फ़ काम करता है. यह किसी और के साथ काम नहीं करता. एक-दूसरे के साथ काम न करने की समस्या, एक से ज़्यादा डिवाइसों पर हो सकती है. ऐसे सभी टारगेट जिन्हें काम न करने वाले टारगेट पर ट्रांज़िटिव तरीके से निर्भर किया गया है उन्हें भी काम न करने वाला माना जाता है.
टारगेट कब स्किप किए जाते हैं?
जब टारगेट काम नहीं करते, तो उन्हें स्किप कर दिया जाता है. साथ ही, टारगेट पैटर्न के एक्सपैंशन के हिस्से के तौर पर, उन्हें बिल्ड में शामिल किया जाता है. उदाहरण के लिए, नीचे दिए गए दो शुरू होने की वजह से टारगेट पैटर्न एक्सपैंशन में मौजूद, काम न करने वाले टारगेट को छोड़ दिया जाता है.
$ bazel build --platforms=//:myplatform //...
$ bazel build --platforms=//:myplatform //:all
अगर --expand_test_suites
के साथ कमांड लाइन पर test_suite
तय किया गया है, तो test_suite
में काम न करने वाले टेस्ट को भी इसी तरह स्किप कर दिया जाता है.
दूसरे शब्दों में, कमांड लाइन पर test_suite
टारगेट, :all
और
...
की तरह काम करते हैं. --noexpand_test_suites
का इस्तेमाल करने से, टारगेटिंग का दायरा नहीं बढ़ता. साथ ही, जिन टारगेट के लिए काम न करने वाले टेस्ट इस्तेमाल किए गए हैं वे भी काम नहीं करते.
कमांड-लाइन पर काम न करने वाले टारगेट को साफ़ तौर पर बताने पर, गड़बड़ी का मैसेज दिखता है और बिल्ड नहीं होता.
$ bazel build --platforms=//:myplatform //:target_incompatible_with_myplatform
...
ERROR: Target //:target_incompatible_with_myplatform is incompatible and cannot be built, but was explicitly requested.
...
FAILED: Build did NOT complete successfully
ज़्यादा जानकारी देने वाली पाबंदियां
पाबंदियों को ज़्यादा आसानी से बताने के लिए, ऐसे @platforms//:incompatible
constraint_value
का इस्तेमाल करें जो किसी भी प्लैटफ़ॉर्म पर काम न करता हो.
ज़्यादा जटिल पाबंदियां बताने के लिए, select()
के साथ
@platforms//:incompatible
का इस्तेमाल करें. जैसे, बेसिक OR लॉजिक को लागू करने के लिए इसका इस्तेमाल करें. यहां दी गई लाइब्रेरी, macOS और Linux के साथ काम करती है, लेकिन किसी दूसरे प्लैटफ़ॉर्म के साथ नहीं.
cc_library(
name = "unixish_lib",
srcs = ["unixish_lib.cc"],
target_compatible_with = select({
"@platforms//os:osx": [],
"@platforms//os:linux": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
)
ऊपर दी गई जानकारी को इस तरह समझा जा सकता है:
- macOS को टारगेट करते समय, टारगेट पर कोई पाबंदी नहीं होती.
- Linux को टारगेट करते समय, टारगेट पर कोई पाबंदी नहीं होती.
- ऐसा न होने पर, टारगेट में
@platforms//:incompatible
शर्त होती है.@platforms//:incompatible
किसी भी प्लैटफ़ॉर्म का हिस्सा नहीं है. इसलिए, इसे टारगेट के साथ काम नहीं करता है.
अपनी सीमाओं को पढ़ने में आसान बनाने के लिए, skylib के selects.with_or()
का इस्तेमाल करें.
इसी तरह, अलग-अलग डिवाइसों के साथ काम करने की सुविधा के बारे में भी बताया जा सकता है. यहां दिए गए उदाहरण में, एक ऐसी लाइब्रेरी के बारे में बताया गया है जो ARM के अलावा सभी प्लैटफ़ॉर्म के साथ काम करती है.
cc_library(
name = "non_arm_lib",
srcs = ["non_arm_lib.cc"],
target_compatible_with = select({
"@platforms//cpu:arm": ["@platforms//:incompatible"],
"//conditions:default": [],
],
)
bazel cquery
का इस्तेमाल करके, काम न करने वाले टारगेट का पता लगाना
bazel cquery
के Starlark आउटपुट फ़ॉर्मैट में, IncompatiblePlatformProvider
का इस्तेमाल करके, काम न करने वाले टारगेट को काम करने वाले टारगेट से अलग किया जा सकता है.
इसका इस्तेमाल, काम न करने वाले टारगेट को फ़िल्टर करने के लिए किया जा सकता है. नीचे दिए गए उदाहरण में, सिर्फ़ उन टारगेट के लेबल प्रिंट होंगे जो साथ काम करते हैं. काम न करने वाले टारगेट को प्रिंट नहीं किया जाता.
$ cat example.cquery
def format(target):
if "IncompatiblePlatformProvider" not in providers(target):
return target.label
return ""
$ bazel cquery //... --output=starlark --starlark:file=example.cquery
आम समस्याएं
काम न करने वाले टारगेट किसको दिखे, इससे जुड़ी पाबंदियों को अनदेखा करें.