Bazel, अलग-अलग हार्डवेयर, ऑपरेटिंग सिस्टम, और सिस्टम कॉन्फ़िगरेशन पर कोड को बिल्ड और टेस्ट कर सकता है. इसके लिए, वह लिंक करने वाले टूल और कंपाइलर जैसे बिल्ड टूल के कई अलग-अलग वर्शन का इस्तेमाल करता है. इस जटिलता को मैनेज करने के लिए, Bazel में शर्तों और प्लैटफ़ॉर्म का कॉन्सेप्ट है. शर्त एक ऐसा डाइमेंशन है जिसमें बिल्ड या प्रोडक्शन एनवायरमेंट अलग-अलग हो सकते हैं. जैसे, सीपीयू आर्किटेक्चर, जीपीयू का होना या न होना या सिस्टम में इंस्टॉल किए गए कंपाइलर का वर्शन. प्लैटफ़ॉर्म, इन शर्तों के लिए चुने गए विकल्पों का एक नाम वाला कलेक्शन होता है. यह किसी एनवायरमेंट में उपलब्ध खास संसाधनों के बारे में बताता है.
एनवायरमेंट को प्लैटफ़ॉर्म के तौर पर मॉडल करने से, Bazel बिल्ड ऐक्शन के लिए सही टूलचेन को अपने-आप चुन लेता है. प्लैटफ़ॉर्म का इस्तेमाल, config_setting नियम के साथ मिलाकर, कॉन्फ़िगर किए जा सकने वाले ए/ट्रिब्यूट लिखने के लिए भी किया जा सकता है.
Bazel, प्लैटफ़ॉर्म की तीन भूमिकाओं को पहचानता है:
- होस्ट - वह प्लैटफ़ॉर्म जिस पर Bazel खुद चलता है.
- एक्ज़ीक्यूशन - वह प्लैटफ़ॉर्म जिस पर बिल्ड टूल, इंटरमीडिएट और फ़ाइनल आउटपुट जनरेट करने के लिए बिल्ड ऐक्शन को एक्ज़ीक्यूट करते हैं.
- टारगेट - वह प्लैटफ़ॉर्म जिस पर फ़ाइनल आउटपुट मौजूद होता है और एक्ज़ीक्यूट होता है.
प्लैटफ़ॉर्म के बारे में, Bazel इन बिल्ड स्थितियों के साथ काम करता है:
सिंगल-प्लैटफ़ॉर्म बिल्ड (डिफ़ॉल्ट) - होस्ट, एक्ज़ीक्यूशन, और टारगेट प्लैटफ़ॉर्म एक ही होते हैं. उदाहरण के लिए, Intel x64 सीपीयू पर चलने वाले Ubuntu पर, Linux एक्ज़ीक्यूटेबल को बिल्ड करना.
क्रॉस-कंपाइलेशन बिल्ड - होस्ट और एक्ज़ीक्यूशन प्लैटफ़ॉर्म एक ही होते हैं, लेकिन टारगेट प्लैटफ़ॉर्म अलग होता है. उदाहरण के लिए, MacBook Pro पर चलने वाले macOS पर, iOS ऐप्लिकेशन को बिल्ड करना.
मल्टी-प्लैटफ़ॉर्म बिल्ड - होस्ट, एक्ज़ीक्यूशन, और टारगेट प्लैटफ़ॉर्म अलग-अलग होते हैं.
शर्तों और प्लैटफ़ॉर्म तय करना
प्लैटफ़ॉर्म के लिए चुने जा सकने वाले विकल्पों का दायरा,
constraint_setting और
constraint_value नियमों का इस्तेमाल करके BUILD फ़ाइलों में तय किया जाता है.
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",
],
)
आम तौर पर काम आने वाली शर्तें और प्लैटफ़ॉर्म
इकोसिस्टम को एक जैसा बनाए रखने के लिए, Bazel की टीम, सबसे लोकप्रिय सीपीयू आर्किटेक्चर और ऑपरेटिंग सिस्टम के लिए, शर्तों की परिभाषाओं वाला एक रिपॉज़िटरी बनाए रखती है. ये सभी https://github.com/bazelbuild/platforms में मौजूद हैं.
Bazel के साथ, प्लैटफ़ॉर्म की यह खास परिभाषा मिलती है: @local_config_platform//:host. यह, होस्ट प्लैटफ़ॉर्म की अपने-आप पता लगाई गई वैल्यू है. यह उस सिस्टम के लिए अपने-आप पता लगाए गए प्लैटफ़ॉर्म को दिखाती है जिस पर Bazel चल रहा है.
किसी बिल्ड के लिए प्लैटफ़ॉर्म तय करना
कमांड-लाइन फ़्लैग का इस्तेमाल करके, किसी बिल्ड के लिए होस्ट और टारगेट प्लैटफ़ॉर्म तय किए जा सकते हैं:
--host_platform- डिफ़ॉल्ट रूप से@local_config_platform//:host- पर सेट होता है
@local_config_platformएक रिपॉज़िटरी नियम है. यह होस्ट ओएस और सीपीयू का पता लगाता है और प्लैटफ़ॉर्म टारगेट लिखता है.- यह
@local_config_platform//:constraintz.bzlभी बनाता है. इससेHOST_CONSTRAINTSनाम का एक कलेक्शन दिखता है. इसका इस्तेमाल, अन्य BUILD और Starlark फ़ाइलों में किया जा सकता है.
--platforms- डिफ़ॉल्ट रूप से होस्ट प्लैटफ़ॉर्म पर सेट होता है- इसका मतलब है कि जब कोई अन्य फ़्लैग सेट नहीं किया जाता है, तो
@local_config_platform//: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 के साथ बिल्ड करने के लिए काम करता है. यह किसी अन्य प्लैटफ़ॉर्म के साथ काम नहीं करता. काम न करने की स्थिति, एक से दूसरी जगह ट्रांसफ़र हो सकती है. ऐसे सभी टारगेट जो काम न करने वाले टारगेट पर ट्रांज़िटिव तरीके से निर्भर होते हैं उन्हें भी काम न करने वाला माना जाता है.
टारगेट कब छोड़े जाते हैं?
टारगेट तब छोड़े जाते हैं, जब उन्हें काम न करने वाला माना जाता है और टारगेट पैटर्न के एक्सपैंशन के हिस्से के तौर पर, उन्हें बिल्ड में शामिल किया जाता है. उदाहरण के लिए, इन दोनों तरीकों से, टारगेट पैटर्न के एक्सपैंशन में मिले, काम न करने वाले सभी टारगेट छोड़ दिए जाते हैं.
$ bazel build --platforms=//:myplatform //...
$ bazel build --platforms=//:myplatform //:all
test_suite में मौजूद, काम न करने वाले टेस्ट भी इसी तरह छोड़ दिए जाते हैं. ऐसा तब होता है, जब कमांड लाइन पर test_suite को
--expand_test_suites के साथ तय किया जाता है.
दूसरे शब्दों में, कमांड लाइन पर test_suite टारगेट, :all और ... की तरह काम करते हैं. --noexpand_test_suites का इस्तेमाल करने पर, एक्सपैंशन नहीं होता. साथ ही, काम न करने वाले टेस्ट वाले
test_suite टारगेट भी काम नहीं करते.
कमांड लाइन पर, काम न करने वाले टारगेट को साफ़ तौर पर तय करने पर, गड़बड़ी का मैसेज दिखता है और बिल्ड पूरा नहीं हो पाता.
$ 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
का इस्तेमाल करें. यह किसी भी प्लैटफ़ॉर्म के साथ काम नहीं करता.
ज़्यादा जटिल पाबंदियां तय करने के लिए,
@platforms//:incompatible के साथ select() का इस्तेमाल करें. उदाहरण के लिए, इसका इस्तेमाल बुनियादी 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's
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's Starlark output
format में
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
आम तौर पर होने वाली समस्याएं
काम न करने वाले टारगेट, दिखने से जुड़ी पाबंदियों को अनदेखा करते हैं.