Android.bp फ़ाइल फ़ॉर्मैट

Android.bp फ़ाइलें, डिज़ाइन के हिसाब से आसान होती हैं. इनमें कंडीशनल या कंट्रोल फ़्लो स्टेटमेंट नहीं होते. इनमें मौजूद सभी जटिलताएं, Go में लिखी गई बिल्ड लॉजिक से मैनेज की जाती हैं.

मॉड्यूल

Android.bp फ़ाइल में मौजूद कोई मॉड्यूल, मॉड्यूल के टाइप से शुरू होता है. इसके बाद, प्रॉपर्टी का सेट name: "value", फ़ॉर्मैट में होता है:

cc_binary {
    name: "gzip",
    srcs: ["src/test/minigzip.c"],
    shared_libs: ["libz"],
    stl: "none",
}

हर मॉड्यूल में name प्रॉपर्टी होनी चाहिए. साथ ही, इसकी वैल्यू सभी Android.bp फ़ाइलों में यूनीक होनी चाहिए. हालांकि, नेमस्पेस और पहले से बने मॉड्यूल में मौजूद name प्रॉपर्टी की वैल्यू दोहराई जा सकती हैं.

srcs प्रॉपर्टी, मॉड्यूल बनाने के लिए इस्तेमाल की गई सोर्स फ़ाइलों के बारे में बताती है. यह प्रॉपर्टी, स्ट्रिंग की सूची के तौर पर काम करती है. सोर्स फ़ाइलें बनाने वाले अन्य मॉड्यूल के आउटपुट का रेफ़रंस दिया जा सकता है. जैसे, genrule या filegroup. इसके लिए, मॉड्यूल रेफ़रंस सिंटैक्स ":<module-name>" का इस्तेमाल करें.

मान्य मॉड्यूल टाइप और उनकी प्रॉपर्टी की सूची देखने के लिए, m soong_docs चलाकर जनरेट किया गया Soong मॉड्यूल रेफ़रंस देखें. इसका आउटपुट, out/soong/docs/soong_build.html में दिखेगा.

टाइप

वैरिएबल और प्रॉपर्टी, मज़बूत टाइप वाली होती हैं. वैरिएबल, पहले असाइनमेंट के आधार पर डाइनैमिक होते हैं. वहीं, प्रॉपर्टी, मॉड्यूल टाइप के हिसाब से स्टैटिक तौर पर सेट की जाती हैं. ये टाइप इस्तेमाल किए जा सकते हैं:

  • बूलियन (true या false)
  • इंटीजर (int)
  • स्ट्रिंग ("string")
  • स्ट्रिंग की सूची (["string1", "string2"])
  • Maps ({key1: "value1", key2: ["value2"]})

Maps में किसी भी टाइप की वैल्यू हो सकती हैं. इनमें नेस्ट किए गए मैप भी शामिल हैं. सूचियों और मैप में, आखिरी वैल्यू के बाद ट्रेलिंग कॉमा हो सकते हैं.

Globs

srcs जैसी प्रॉपर्टी में, फ़ाइलों की सूची के साथ-साथ ग्लोब पैटर्न भी इस्तेमाल किए जा सकते हैं. ग्लोब पैटर्न में, सामान्य UNIX वाइल्डकार्ड * शामिल हो सकता है. उदाहरण के लिए *.java. ग्लोब पैटर्न में, पाथ एलिमेंट के तौर पर एक ** वाइल्डकार्ड भी शामिल हो सकता है. यह वाइल्डकार्ड, शून्य या उससे ज़्यादा पाथ एलिमेंट से मैच करता है. उदाहरण के लिए, java/**/*.java पैटर्न, java/Main.java और java/com/android/Main.java दोनों से मैच करता है.

वैरिएबल

किसी Android.bp फ़ाइल में, टॉप-लेवल वैरिएबल असाइनमेंट शामिल हो सकते हैं:

gzip_srcs = ["src/test/minigzip.c"],
cc_binary {
    name: "gzip",
    srcs: gzip_srcs,
    shared_libs: ["libz"],
    stl: "none",
}

वैरिएबल, उस फ़ाइल के बाकी हिस्से के साथ-साथ, चाइल्ड ब्लूप्रिंट फ़ाइलों के स्कोप में होते हैं जिनमें उन्हें लिखा गया है. वैरिएबल में बदलाव नहीं किया जा सकता. हालांकि, एक अपवाद है: इन्हें += असाइनमेंट के साथ जोड़ा जा सकता है. हालांकि, ऐसा सिर्फ़ तब किया जा सकता है, जब इनका रेफ़रंस न दिया गया हो.

टिप्पणियां

Android.bp फ़ाइलों में, C-स्टाइल मल्टीलाइन /* */ और C++ स्टाइल सिंगल-लाइन // टिप्पणियां शामिल की जा सकती हैं.

ऑपरेटर

स्ट्रिंग, स्ट्रिंग की सूची, और मैप को + ऑपरेटर का इस्तेमाल करके जोड़ा जा सकता है. इंटीजर को + ऑपरेटर का इस्तेमाल करके जोड़ा जा सकता है. मैप को जोड़ने पर, दोनों मैप में मौजूद कुंजियों का यूनियन बनता है. साथ ही, दोनों मैप में मौजूद कुंजियों की वैल्यू जुड़ जाती हैं.

डिफ़ॉल्ट मॉड्यूल

डेवलपर, एक ही प्रॉपर्टी को कई मॉड्यूल में दोहराने के लिए, डिफ़ॉल्ट मॉड्यूल का इस्तेमाल कर सकते हैं. उदाहरण के लिए:

cc_defaults {
    name: "gzip_defaults",
    shared_libs: ["libz"],
    stl: "none",
}

cc_binary {
    name: "gzip",
    defaults: ["gzip_defaults"],
    srcs: ["src/test/minigzip.c"],
}

पहले से बने मॉड्यूल

पहले से बने कुछ मॉड्यूल टाइप की मदद से, किसी मॉड्यूल का नाम उसके सोर्स पर आधारित काउंटरपार्ट के नाम जैसा हो सकता है. उदाहरण के लिए, अगर cc_binary का नाम foo है, तो cc_prebuilt_binary का नाम भी foo हो सकता है. इससे डेवलपर को यह तय करने की सुविधा मिलती है कि उन्हें अपने फ़ाइनल प्रॉडक्ट में कौनसी वर्शन शामिल करनी है. अगर किसी बिल्ड कॉन्फ़िगरेशन में दोनों वर्शन मौजूद हैं, तो पहले से बने मॉड्यूल की परिभाषा में मौजूद prefer फ़्लैग की वैल्यू से यह तय होता है कि किस वर्शन को प्राथमिकता दी जाएगी. ध्यान दें कि पहले से बने कुछ मॉड्यूल के नाम, prebuilt से शुरू नहीं होते. जैसे, android_app_import.

नेमस्पेस मॉड्यूल

जब तक Android, Make से Soong पर पूरी तरह से स्विच नहीं हो जाता, तब तक Make प्रॉडक्ट कॉन्फ़िगरेशन को PRODUCT_SOONG_NAMESPACES की वैल्यू तय करनी होगी. इसकी वैल्यू, स्पेस से अलग किए गए नेमस्पेस की सूची होनी चाहिए. Soong, इन नेमस्पेस को Make में एक्सपोर्ट करता है, ताकि इन्हें m कमांड से बनाया जा सके. Android को Soong में बदलने की प्रोसेस पूरी होने के बाद, नेमस्पेस चालू करने की जानकारी बदल सकती है.

Soong की मदद से, अलग-अलग डायरेक्ट्री में मौजूद मॉड्यूल के लिए एक ही नाम इस्तेमाल किया जा सकता है. हालांकि, इसके लिए ज़रूरी है कि हर मॉड्यूल को अलग नेमस्पेस में लिखा गया हो. डेवलपर, नेमस्पेस का एलान कर सकते हैं:

soong_namespace {
    imports: ["path/to/otherNamespace1", "path/to/otherNamespace2"],
}

ध्यान दें कि किसी नेमस्पेस में name प्रॉपर्टी नहीं होती. उसका पाथ, अपने-आप उसके नाम के तौर पर असाइन हो जाता है.

ट्री में मौजूद जगह के आधार पर, हर Soong मॉड्यूल को नेमस्पेस असाइन किया जाता है. हर Soong मॉड्यूल को नेमस्पेस में मौजूद माना जाता है, जो मौजूदा डायरेक्ट्री या सबसे नज़दीकी पैरंट डायरेक्ट्री में Android.bp फ़ाइल में मिले soong_namespace से तय होता है. अगर कोई ऐसा soong_namespace मॉड्यूल नहीं मिलता है, तो मॉड्यूल को डिफ़ॉल्ट रूट नेमस्पेस में माना जाता है.

यहां एक उदाहरण दिया गया है: Soong, नेमस्पेस N में मौजूद मॉड्यूल M से एलान की गई डिपेंडेंसी D को हल करने की कोशिश करता है. यह नेमस्पेस, I1, I2, I3… नेमस्पेस इंपोर्ट करता है.

  1. अगर D, //namespace:module फ़ॉर्म का पूरी तरह क्वालिफ़ाइड नाम है, तो दिए गए मॉड्यूल के नाम के लिए, सिर्फ़ दिए गए नेमस्पेस को खोजा जाता है.
  2. इसके अलावा, Soong सबसे पहले नेमस्पेस N में एलान किए गए D नाम के मॉड्यूल को खोजता है.
  3. अगर वह मॉड्यूल मौजूद नहीं है, तो Soong, I1, I2, I3… नेमस्पेस में D नाम के मॉड्यूल को खोजता है.
  4. Soong, रूट नेमस्पेस में खोजता है.

कंडीशनल

Soong, Android.bp फ़ाइलों में कंडीशनल के साथ काम नहीं करता. इसके बजाय, बिल्ड नियमों में मौजूद जटिलताओं को Go में मैनेज किया जाता है. इन जटिलताओं के लिए, कंडीशनल की ज़रूरत होती है. Go में, हाई-लेवल लैंग्वेज की सुविधाओं का इस्तेमाल किया जा सकता है. साथ ही, कंडीशनल की वजह से होने वाली डिफ़ॉल्ट डिपेंडेंसी को ट्रैक किया जा सकता है. ज़्यादातर कंडीशनल को मैप प्रॉपर्टी में बदल दिया जाता है. इसमें, मैप में मौजूद किसी एक वैल्यू को चुना जाता है और टॉप-लेवल प्रॉपर्टी में जोड़ दिया जाता है.

उदाहरण के लिए, आर्किटेक्चर के हिसाब से फ़ाइलों के साथ काम करने के लिए:

cc_library {
    ...
    srcs: ["generic.cpp"],
    arch: {
        arm: {
            srcs: ["arm.cpp"],
        },
        x86: {
            srcs: ["x86.cpp"],
        },
    },
}

फ़ॉर्मेटर

Soong में, ब्लूप्रिंट फ़ाइलों के लिए कैननिकल फ़ॉर्मेटर शामिल है. यह gofmt की तरह काम करता है. मौजूदा डायरेक्ट्री में मौजूद सभी Android.bp फ़ाइलों को बार-बार फ़ॉर्मैट करने के लिए, यह कमांड चलाएं:

bpfmt -w .

कैननिकल फ़ॉर्मैट में, चार स्पेस वाले इंडेंट, मल्टीएलिमेंट सूची के हर एलिमेंट के बाद नई लाइन, और सूचियों और मैप में ट्रेलिंग कॉमा शामिल होते हैं.