Baज़ल, बिल्ड टूल के कई अलग-अलग वर्शन, जैसे कि लिंकर और कंपाइलर का इस्तेमाल करके, कई तरह के हार्डवेयर, ऑपरेटिंग सिस्टम, और सिस्टम कॉन्फ़िगरेशन पर कोड बना सकता है और उनकी जांच कर सकता है. इस जटिलता को मैनेज करने में मदद करने के लिए, Bazel में सीमाओं और प्लैटफ़ॉर्म का कॉन्सेप्ट है. शर्त एक ऐसा डाइमेंशन है जिसमें बिल्ड या प्रोडक्शन एनवायरमेंट अलग-अलग हो सकते हैं. जैसे, सीपीयू आर्किटेक्चर, जीपीयू की मौजूदगी या अनुपस्थिति या सिस्टम में इंस्टॉल किए गए कंपाइलर का वर्शन. प्लैटफ़ॉर्म, इन कंस्ट्रेंट के लिए विकल्पों का एक नाम है, जो कुछ एनवायरमेंट में उपलब्ध खास रिसॉर्स को दिखाता है.
एनवायरमेंट को प्लैटफ़ॉर्म के तौर पर मॉडलिंग करने से, Bazel को बिल्ड ऐक्शन के लिए सही टूलचेन अपने-आप चुनने में मदद मिलती है. कॉन्फ़िगर किए जा सकने वाले एट्रिब्यूट लिखने के लिए, प्लैटफ़ॉर्म का इस्तेमाल config_setting नियम के साथ भी किया जा सकता है.
Bazel, तीन तरह की भूमिकाओं को पहचानता है जो किसी प्लैटफ़ॉर्म की हो सकती हैं:
- होस्ट - वह प्लैटफ़ॉर्म जिस पर 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 आर्किटेक्चर पर, 2.25 वर्शन के glibc के साथ Linux ऑपरेटिंग सिस्टम चलाता है. (Bazel में पहले से मौजूद पाबंदियों के बारे में ज़्यादा जानने के लिए, नीचे देखें.)
platform(
name = "linux_x86",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
":glibc_2_25",
],
)
आम तौर पर काम की शर्तें और प्लैटफ़ॉर्म
नेटवर्क को एक जैसा बनाए रखने के लिए, Bazel टीम सबसे लोकप्रिय सीपीयू आर्किटेक्चर और ऑपरेटिंग सिस्टम के लिए, पाबंदी की परिभाषाओं के साथ एक रिपॉज़िटरी बनाए रखती है. ये सभी यूआरएल https://github.com/bazelbuild/platforms में मौजूद हैं.
Bazel, प्लैटफ़ॉर्म की इस खास परिभाषा के साथ शिप होता है:
@platforms//host
(@bazel_tools//tools:host_platform
के तौर पर जाना जाता है). यह अपने-आप पता चलने वाले होस्ट प्लैटफ़ॉर्म की वैल्यू है - यह उस सिस्टम के लिए अपने-आप पता चलने वाले प्लैटफ़ॉर्म को दिखाता है जिस पर Bazel चल रहा है.
बिल्ड के लिए प्लैटफ़ॉर्म तय करना
किसी बिल्ड के लिए होस्ट और टारगेट प्लैटफ़ॉर्म तय करने के लिए, यहां दिए गए कमांड-लाइन फ़्लैग का इस्तेमाल किया जा सकता है:
--host_platform
- डिफ़ॉल्ट रूप से@bazel_tools//tools:host_platform
पर सेट होता है- इस टारगेट का दूसरा नाम
@platforms//host
है. यह टारगेट, एक रिपॉज़िट्री नियम के आधार पर काम करता है. यह नियम, होस्ट ओएस और सीपीयू का पता लगाता है और प्लैटफ़ॉर्म टारगेट को लिखता है. @platforms//host:constraints.bzl
भी है, जोHOST_CONSTRAINTS
नाम का एक कलेक्शन दिखाता है. इसका इस्तेमाल, अन्य BUILD और Starlark फ़ाइलों में किया जा सकता है.
- इस टारगेट का दूसरा नाम
--platforms
- होस्ट प्लैटफ़ॉर्म को डिफ़ॉल्ट रूप से सेट करता है- इसका मतलब है कि जब कोई और फ़्लैग सेट नहीं किया जाता है,
तो
@platforms//host
टारगेट प्लैटफ़ॉर्म होता है. - अगर
--host_platform
को सेट किया गया है और--platforms
नहीं, तो--host_platform
की वैल्यू, होस्ट और टारगेट प्लैटफ़ॉर्म, दोनों होगी.
- इसका मतलब है कि जब कोई और फ़्लैग सेट नहीं किया जाता है,
तो
काम न करने वाले टारगेट को स्किप करना
किसी खास टारगेट प्लैटफ़ॉर्म के लिए बिल्ड करते समय, अक्सर उन टारगेट को स्किप करना बेहतर होता है जो उस प्लैटफ़ॉर्म पर कभी काम नहीं करेंगे. उदाहरण के लिए, //...
के साथ Linux मशीन पर बिल्ड करते समय, आपके Windows डिवाइस ड्राइवर से कई कंपाइलर गड़बड़ियां जनरेट हो सकती हैं. Bazel को यह बताने के लिए कि आपके कोड में टारगेट प्लैटफ़ॉर्म से जुड़ी कौनसी पाबंदियां हैं, target_compatible_with
एट्रिब्यूट का इस्तेमाल करें.
इस एट्रिब्यूट का सबसे आसान इस्तेमाल, किसी टारगेट को सिर्फ़ एक प्लैटफ़ॉर्म पर सीमित करता है.
टारगेट, किसी भी ऐसे प्लैटफ़ॉर्म के लिए नहीं बनाया जाएगा जो सभी सीमाओं को पूरा नहीं करता. इस उदाहरण में, 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 के साथ सिर्फ़ काम करता है. यह किसी और के साथ काम नहीं करता. एक-दूसरे के साथ काम न करने की समस्या, एक से ज़्यादा डिवाइसों पर हो सकती है. ऐसे सभी टारगेट जिन्हें काम न करने वाले टारगेट पर ट्रांज़िटिव तरीके से निर्भर किया गया है उन्हें भी काम न करने वाला माना जाता है.
टारगेट कब स्किप किए जाते हैं?
जब टारगेट काम नहीं करते, तो उन्हें स्किप कर दिया जाता है. साथ ही, टारगेट पैटर्न के एक्सपैंशन के हिस्से के तौर पर, उन्हें बिल्ड में शामिल किया जाता है. उदाहरण के लिए, नीचे दिए गए दो invocatio, टारगेट पैटर्न के एक्सपैंशन में मिले ऐसे सभी टारगेट को स्किप कर देते हैं जो काम नहीं करते.
$ 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
अगर --skip_incompatible_explicit_targets
चालू है, तो काम न करने वाले साफ़ तौर पर बताए गए टारगेट को चुपचाप छोड़ दिया जाता है.
ज़्यादा जानकारी देने वाली पाबंदियां
पाबंदियों को ज़्यादा आसानी से बताने के लिए, ऐसे @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
आम समस्याएं
काम न करने वाले टारगेट, प्रॉडक्ट दिखने से जुड़ी पाबंदियों को अनदेखा करते हैं.