निंजा (एक्सपेरिमेंट के तौर पर उपलब्ध) का इस्तेमाल करके, कस्टम C/C++ बिल्ड सिस्टम इंटिग्रेट करें

अगर आपको CMake या ndk-build का इस्तेमाल नहीं करना है, लेकिन Android Gradle प्लगिन (एजीपी) C/C++ बिल्ड और Android Studio को पूरी तरह से इंटिग्रेट करना है, तो आपके पास कस्टम C/C++ बिल्ड सिस्टम बनाने का विकल्प है. इसके लिए, आपको एक शेल स्क्रिप्ट बनानी होगी. यह स्क्रिप्ट, Ninja बिल्ड फ़ाइल फ़ॉर्मैट में बिल्ड की जानकारी लिखती है.

Android Studio और AGP में, कस्टम C/C++ बिल्ड सिस्टम के लिए एक्सपेरिमेंट के तौर पर सहायता जोड़ी गई है. यह सुविधा, Android Studio Dolphin | 2021.3.1 Canary 4 और इसके बाद के वर्शन में उपलब्ध है.

खास जानकारी

C/C++ प्रोजेक्ट के लिए एक सामान्य पैटर्न, खास तौर पर कई प्लैटफ़ॉर्म को टारगेट करने वाले प्रोजेक्ट के लिए, कुछ बुनियादी जानकारी से उन सभी प्लैटफ़ॉर्म के लिए प्रोजेक्ट जनरेट करना है. इस पैटर्न का एक अहम उदाहरण CMake है. CMake, CMakeLists.txt फ़ाइल में सेव किए गए एक ही अंडरलाइंग रिप्रज़ेंटेशन से, Android, iOS, और अन्य प्लैटफ़ॉर्म के लिए प्रोजेक्ट जनरेट कर सकता है.

CMake को एजीपी सीधे तौर पर सपोर्ट करता है. हालांकि, प्रोजेक्ट जनरेट करने वाले अन्य टूल भी उपलब्ध हैं जिन्हें एजीपी सीधे तौर पर सपोर्ट नहीं करता:

  • Premake

  • gn

  • Sharpmake

  • GENie

  • प्रोजेक्ट जनरेटर, जिन्हें निजी तौर पर पसंद के मुताबिक बनाया गया है

इस तरह के प्रोजेक्ट जनरेटर, C/C++ बिल्ड के बैकएंड के तौर पर Ninja के साथ काम करते हैं. इसके अलावा, इन्हें Ninja को बैकएंड के तौर पर जनरेट करने के लिए भी अडैप्ट किया जा सकता है.

सही तरीके से कॉन्फ़िगर किए जाने पर, इंटिग्रेट किए गए C/C++ प्रोजेक्ट सिस्टम जनरेटर वाला एजीपी प्रोजेक्ट, उपयोगकर्ताओं को ये काम करने की सुविधा देता है:

  • कमांड-लाइन और Android Studio से बनाएं.

  • Android Studio में, भाषा से जुड़ी पूरी सहायता (उदाहरण के लिए, परिभाषा पर जाएं) के साथ सोर्स में बदलाव करें.

  • नेटिव और मिक्स प्रोसेस को डीबग करने के लिए, Android Studio के डीबगर इस्तेमाल करें.

कस्टम C/C++ बिल्ड कॉन्फ़िगरेशन स्क्रिप्ट का इस्तेमाल करने के लिए, अपने बिल्ड में बदलाव करने का तरीका

इस सेक्शन में, AGP से कस्टम C/C++ बिल्ड कॉन्फ़िगरेशन स्क्रिप्ट इस्तेमाल करने का तरीका बताया गया है.

पहला चरण: कॉन्फ़िगरेशन स्क्रिप्ट का रेफ़रंस देने के लिए, मॉड्यूल-लेवल की build.gradle फ़ाइल में बदलाव करना

AGP में Ninja की सुविधा चालू करने के लिए, मॉड्यूल-लेवल की build.gradle फ़ाइल में experimentalProperties को कॉन्फ़िगर करें:

android {
  defaultConfig {
    externalNativeBuild {
      experimentalProperties["ninja.abiFilters"] = [ "x86", "arm64-v8a" ]
      experimentalProperties["ninja.path"] = "source-file-list.txt"
      experimentalProperties["ninja.configure"] = "configure-ninja"
      experimentalProperties["ninja.arguments"] = [
            "\${ndk.moduleMakeFile}",
            "--variant=\${ndk.variantName}",
            "--abi=Android-\${ndk.abi}",
            "--configuration-dir=\${ndk.configurationDir}",
            "--ndk-version=\${ndk.moduleNdkVersion}",
            "--min-sdk-version=\${ndk.minSdkVersion}"
       ]
     }
   }

AGP, प्रॉपर्टी को इस तरह से समझता है:

  • ninja.abiFilters, उन एबीआई की सूची है जिन्हें बनाना है. मान्य वैल्यू ये हैं: x86, x86-64, armeabi-v7a, और arm64-v8a.

  • ninja.path, C/C++ प्रोजेक्ट फ़ाइल का पाथ है. इस फ़ाइल का फ़ॉर्मैट, आपकी पसंद के मुताबिक कुछ भी हो सकता है. इस फ़ाइल में बदलाव करने पर, Android Studio में Gradle सिंक करने का प्रॉम्प्ट ट्रिगर होगा.

  • ninja.configure, स्क्रिप्ट फ़ाइल का पाथ है. C/C++ प्रोजेक्ट को कॉन्फ़िगर करने की ज़रूरत पड़ने पर, Gradle इस फ़ाइल को चलाएगा. किसी प्रोजेक्ट को पहली बार बिल्ड करने पर, Android Studio में Gradle सिंक के दौरान या स्क्रिप्ट इनपुट में से किसी एक को बदलने पर, उसे कॉन्फ़िगर किया जाता है.

  • ninja.arguments, उन आर्ग्युमेंट की सूची है जिन्हें ninja.configure से तय की गई स्क्रिप्ट में पास किया जाएगा. इस सूची में मौजूद एलिमेंट, मैक्रो के सेट का रेफ़रंस दे सकते हैं. इनकी वैल्यू, एजीपी में मौजूदा कॉन्फ़िगरेशन के हिसाब से तय होती हैं:

    • ${ndk.moduleMakeFile}, ninja.configure फ़ाइल का पूरा पाथ है. इसलिए, उदाहरण के तौर पर, यह C:\path\to\configure-ninja.bat होगा.

    • ${ndk.variantName}, AGP के उस मौजूदा वैरिएंट का नाम है जिसे बनाया जा रहा है. उदाहरण के लिए, डीबग या रिलीज़.

    • ${ndk.abi}, मौजूदा एजीपी एबीआई का नाम है जिसे बनाया जा रहा है. उदाहरण के लिए, x86 या arm64-v8a.

    • ${ndk.buildRoot}, एजीपी से जनरेट किए गए फ़ोल्डर का नाम है. स्क्रिप्ट अपना आउटपुट इसी फ़ोल्डर में सेव करती है. इस बारे में ज़्यादा जानकारी, दूसरा चरण: कॉन्फ़िगर स्क्रिप्ट बनाना में दी जाएगी.

    • ${ndk.ndkVersion}, एनडीके का वह वर्शन है जिसका इस्तेमाल किया जाना है. आम तौर पर, यह build.gradle फ़ाइल में android.ndkVersion को पास की गई वैल्यू होती है. अगर कोई वैल्यू मौजूद नहीं है, तो यह डिफ़ॉल्ट वैल्यू होती है.

    • ${ndk.minPlatform}, एजीपी के लिए ज़रूरी Android प्लैटफ़ॉर्म का कम से कम टारगेट वर्शन है.

  • ninja.targets, Ninja के उन खास टारगेट की सूची है जिन्हें बनाया जाना चाहिए.

दूसरा चरण: कॉन्फ़िगरेशन स्क्रिप्ट बनाना

कॉन्फ़िगर स्क्रिप्ट (पिछले उदाहरण में configure-ninja.bat) की कम से कम ज़िम्मेदारी, build.ninja फ़ाइल जनरेट करना है. Ninja के साथ बनाए जाने पर, यह फ़ाइल प्रोजेक्ट के सभी नेटिव आउटपुट को कंपाइल और लिंक करेगी. आम तौर पर, ये .o (ऑब्जेक्ट), .a (संग्रहित), और .so (शेयर किया गया ऑब्जेक्ट) फ़ाइलें होती हैं.

कॉन्फ़िगर स्क्रिप्ट, आपकी ज़रूरतों के हिसाब से build.ninja फ़ाइल को दो अलग-अलग जगहों पर लिख सकती है.

  • अगर एजीपी को जगह चुनने की अनुमति है, तो कॉन्फ़िगर स्क्रिप्ट ${ndk.buildRoot} मैक्रो में सेट की गई जगह पर build.ninja लिखती है.

  • अगर कॉन्फ़िगरेशन स्क्रिप्ट को build.ninja फ़ाइल की जगह चुननी है, तो वह ${ndk.buildRoot} मैक्रो में सेट की गई जगह पर build.ninja.txt नाम की फ़ाइल भी लिखती है. इस फ़ाइल में, build.ninja फ़ाइल का पूरा पाथ होता है. इस फ़ाइल को कॉन्फ़िगर स्क्रिप्ट ने लिखा है.

build.ninja फ़ाइल का स्ट्रक्चर

आम तौर पर, Android C/C++ बिल्ड को सटीक तरीके से दिखाने वाले ज़्यादातर स्ट्रक्चर काम करेंगे. एजीपी और Android Studio के लिए ज़रूरी मुख्य एलिमेंट ये हैं:

  • C/C++ सोर्स फ़ाइलों की सूची और फ़्लैग, जिनकी ज़रूरत Clang को उन्हें कंपाइल करने के लिए होती है.

  • आउटपुट लाइब्रेरी की सूची. आम तौर पर, ये .so (शेयर किया गया ऑब्जेक्ट) फ़ाइलें होती हैं. हालांकि, ये .a (संग्रहित) या एक्ज़ीक्यूटेबल (कोई एक्सटेंशन नहीं) फ़ाइलें भी हो सकती हैं.

अगर आपको build.ninja फ़ाइल जनरेट करने के उदाहरण चाहिए, तो build.ninja जनरेटर का इस्तेमाल करने पर, CMake का आउटपुट देखें.

यहां build.ninja के बुनियादी टेंप्लेट का एक उदाहरण दिया गया है.

rule COMPILE
   command = /path/to/ndk/clang -c $in -o $out {other flags}
rule LINK
   command = /path/to/ndk/clang $in -o $out {other flags}

build source.o : COMPILE source.cpp
build lib.so : LINK source.o

सुझाव

ज़रूरी शर्तों (सोर्स फ़ाइलों और आउटपुट लाइब्रेरी की सूची) के अलावा, यहां कुछ सुझाव दिए गए हैं.

phony नियमों के साथ नाम वाले आउटपुट का एलान करना

जब भी संभव हो, हमारा सुझाव है कि build.ninja स्ट्रक्चर में phony नियमों का इस्तेमाल करें, ताकि बिल्ड आउटपुट को ऐसे नाम दिए जा सकें जिन्हें कोई व्यक्ति आसानी से पढ़ सके. उदाहरण के लिए, अगर आपके पास c:/path/to/lib.so नाम का कोई आउटपुट है, तो उसे आसानी से पढ़ा जा सकने वाला नाम दिया जा सकता है.

build curl: phony /path/to/lib.so

ऐसा करने का फ़ायदा यह है कि इस नाम को build.gradle फ़ाइल में बिल्ड टारगेट के तौर पर तय किया जा सकता है. उदाहरण के लिए:

android {
  defaultConfig {
    externalNativeBuild {
      ...
      experimentalProperties["ninja.targets"] = [ "curl" ]

'सभी' टारगेट तय करना

all टारगेट तय करने पर, एजीपी डिफ़ॉल्ट रूप से लाइब्रेरी का यह सेट बनाएगा. ऐसा तब होगा, जब build.gradle फ़ाइल में कोई टारगेट साफ़ तौर पर तय न किया गया हो.

rule COMPILE
   command = /path/to/ndk/clang $in -o $out {other flags}
rule LINK
   command = /path/to/ndk/clang $in -o $out {other flags}

build foo.o : COMPILE foo.cpp
build bar.o : COMPILE bar.cpp
build libfoo.so : LINK foo.o
build libbar.so : LINK bar.o
build all: phony libfoo.so libbar.so

बिल्ड करने का कोई दूसरा तरीका बताएं (ज़रूरी नहीं)

इस्तेमाल का एक और बेहतर उदाहरण, किसी ऐसे मौजूदा बिल्ड सिस्टम को रैप करना है जो Ninja पर आधारित नहीं है. इस मामले में, आपको अब भी सभी सोर्स को उनके फ़्लैग के साथ-साथ आउटपुट लाइब्रेरी के साथ दिखाना होगा. इससे Android Studio, ऑटोकंप्लीट और गो-टू डेफ़िनिशन जैसी सही भाषा की सेवा की सुविधाएं दिखा सकता है. हालांकि, आपको एजीपी को असल बिल्ड के दौरान, पहले से मौजूद बिल्ड सिस्टम के हिसाब से काम करने के लिए कहना होगा.

इसके लिए, किसी खास एक्सटेंशन .passthrough के साथ Ninja बिल्ड आउटपुट का इस्तेमाल किया जा सकता है.

एक और उदाहरण के तौर पर, MSBuild को रैप करने के लिए, आपकी कॉन्फ़िगरेशन स्क्रिप्ट हमेशा की तरह build.ninja जनरेट करेगी. हालांकि, यह एक पासथ्रू टारगेट भी जोड़ेगी, जो यह तय करेगा कि एजीपी, MSBuild को कैसे शुरू करेगा.

rule COMPILE
   command = /path/to/ndk/clang $in -o $out {other flags}
rule LINK
   command = /path/to/ndk/clang $in -o $out {other flags}

rule MBSUILD_CURL
  command = /path/to/msbuild {flags to build curl with MSBuild}

build source.o : COMPILE source.cpp
build lib.so : LINK source.o
build curl : phony lib.so
build curl.passthrough : MBSUILD_CURL

सुझाव/राय देना या शिकायत करना

यह सुविधा, एक्सपेरिमेंट के तौर पर उपलब्ध है. इसलिए, हमें आपके सुझाव, शिकायत या राय का इंतज़ार रहेगा. इन तरीकों से सुझाव/राय दी जा सकती है या शिकायत की जा सकती है:

  • सामान्य सुझाव, शिकायत या राय के लिए, इससे जुड़ी गड़बड़ी पर टिप्पणी करें.

  • किसी गड़बड़ी की शिकायत करने के लिए, Android Studio खोलें और Help > Submit Feedback पर क्लिक करें. बग को सही जगह पर भेजने के लिए, "कस्टम C/C++ बिल्ड सिस्टम" का रेफ़रंस ज़रूर दें.

  • अगर आपके पास Android Studio इंस्टॉल नहीं है, तो गड़बड़ी की शिकायत करने के लिए, गड़बड़ी के टेंप्लेट का इस्तेमाल करें.