प्लैटफ़ॉर्म

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

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

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

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

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

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

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

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

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 डिवाइस ड्राइवर कई कंपाइलर गड़बड़ियां जनरेट कर सकता है. 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 वाले Windows में किया जा सकता है. यह 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 का इस्तेमाल करें, जो किसी भी प्लैटफ़ॉर्म पर काम नहीं करता.

ज़्यादा मुश्किल पाबंदियों के बारे में बताने के लिए, 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"],
    }),
)

ऊपर दिए गए मतलब को इस तरह समझा जा सकता है:

  1. macOS को टारगेट करते समय, टारगेट में कोई सीमा नहीं होती.
  2. Linux को टारगेट करते समय, टारगेट में कोई सीमा नहीं होती.
  3. ऐसा न होने पर, टारगेट में @platforms//:incompatible कंस्ट्रेंट है. @platforms//:incompatible किसी भी प्लैटफ़ॉर्म का हिस्सा नहीं है, इसलिए यह टारगेट काम नहीं करता है.

पाबंदियों को ज़्यादा आसानी से पढ़ने लायक बनाने के लिए, skylib की selects.with_or() सुविधा का इस्तेमाल करें.

आप व्युत्क्रम संगत को इसी तरह से व्यक्त कर सकते हैं. नीचे दिए गए उदाहरण में ऐसी लाइब्रेरी के बारे में बताया गया है जो एआरएम के अलावा, बाकी सभी चीज़ों के साथ काम करती है.

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

आम समस्याएं

काम न करने वाले टारगेट, किसको दिखे ऐसी पाबंदियों को अनदेखा करते हैं.