प्लैटफ़ॉर्म

समस्या की शिकायत करें स्रोत देखें

Bazel कई तरह के हार्डवेयर, ऑपरेटिंग सिस्टम और सिस्टम कॉन्फ़िगरेशन पर कोड बना सकता है और उसकी जांच कर सकता है. इसके लिए, वह लिंकर और कंपाइलर जैसे बिल्ड टूल के कई अलग-अलग वर्शन का इस्तेमाल करता है. इस जटिलता को मैनेज करने में मदद करने के लिए, Bazel ने सीमाएं और प्लैटफ़ॉर्म का सिद्धांत दिया है. कंस्ट्रेंट एक ऐसा डाइमेंशन है जिसमें बिल्ड या प्रोडक्शन एनवायरमेंट में अंतर हो सकता है. जैसे, सीपीयू आर्किटेक्चर, जीपीयू की मौजूदगी या न होना या सिस्टम पर इंस्टॉल किए गए कंपाइलर का वर्शन. प्लैटफ़ॉर्म, इन पाबंदियों के लिए विकल्पों का नाम का एक कलेक्शन होता है. यह ऐसे खास संसाधनों को दिखाता है जो कुछ एनवायरमेंट में उपलब्ध होते हैं.

एनवायरमेंट को एक प्लैटफ़ॉर्म के तौर पर मॉडल करने से, Bazel को बिल्ड ऐक्शन के लिए अपने-आप टूलचेन चुनने में मदद मिलती है. कॉन्फ़िगर किए जा सकने वाले एट्रिब्यूट लिखने के लिए, प्लैटफ़ॉर्म को config_setting नियम के साथ भी इस्तेमाल किया जा सकता है.

Bazel तीन भूमिकाओं की पहचान करता है, जो कि एक प्लैटफ़ॉर्म पर मिल सकता है:

  • होस्ट - वह प्लैटफ़ॉर्म जिस पर Bazel खुद चलता है.
  • एक्ज़ीक्यूशन - एक ऐसा प्लैटफ़ॉर्म जिस पर बिल्ड टूल इंटरमीडिएट और फ़ाइनल आउटपुट बनाने के लिए बिल्ड ऐक्शन लागू करता है.
  • टारगेट - वह प्लैटफ़ॉर्म जिस पर आखिरी आउटपुट मौजूद होता है और लागू होता है.

Bazel, प्लैटफ़ॉर्म से जुड़े इन बिल्ड मामलों में काम करता है:

  • सिंगल-प्लैटफ़ॉर्म बिल्ड (डिफ़ॉल्ट) - होस्ट, एक्ज़ीक्यूशन, और टारगेट प्लैटफ़ॉर्म एक जैसे होते हैं. उदाहरण के लिए, Intel x64 CPU पर चलने वाले 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",
    ],
)

आम तौर पर, काम की पाबंदियां और प्लैटफ़ॉर्म

नेटवर्क को एक जैसा बनाए रखने के लिए, 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 डिवाइस का ड्राइवर, कंपाइलर की बहुत सारी गड़बड़ियां जनरेट कर सकता है. target_compatible_with एट्रिब्यूट का इस्तेमाल करके, Bazel को बताएं कि आपके कोड में मौजूद टारगेट प्लैटफ़ॉर्म क्या हैं.

इस एट्रिब्यूट का आसानी से इस्तेमाल करने पर, टारगेट एक ही प्लैटफ़ॉर्म पर सीमित हो जाता है. टारगेट को ऐसे किसी भी प्लैटफ़ॉर्म के लिए नहीं बनाया जाएगा जो सभी शर्तें पूरी नहीं करता. इस उदाहरण में 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"],
    }),
)

ऊपर इस तरह समझा जा सकता है:

  1. macOS को टारगेट करते समय, टारगेट में कोई पाबंदी नहीं होती.
  2. Linux को टारगेट करते समय, टारगेट में कोई सीमा नहीं होती.
  3. ऐसा न होने पर, टारगेट में @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

समस्याएं जिनके बारे में जानकारी है

काम न करने वाले टारगेट, किसको दिखे से जुड़ी पाबंदियों को अनदेखा करें.