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