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

अगर CMake या ndk-build का इस्तेमाल नहीं किया जा रहा है, लेकिन आपको Android Gradle प्लग इन (AGP) 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, और अन्य प्लैटफ़ॉर्म के लिए प्रोजेक्ट जनरेट कर सकता है.

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

  • Premake

  • gn

  • Sharpmake

  • GENie

  • निजी तौर पर बनाए गए कस्टम प्रोजेक्ट जनरेटर

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

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

  • कमांड-लाइन और 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 से तय की गई स्क्रिप्ट में पास किया जाएगा. इस सूची में मौजूद एलिमेंट, मैक्रो के ऐसे सेट का रेफ़रंस दे सकते हैं जिनकी वैल्यू, AGP में मौजूदा कॉन्फ़िगरेशन कॉन्टेक्स्ट पर निर्भर करती है:

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

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

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

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

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

    • ${ndk.minPlatform}, AGP के अनुरोध के मुताबिक टारगेट किया गया कम से कम Android प्लैटफ़ॉर्म है.

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

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

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

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

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

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

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

आम तौर पर, Android C/C++ बिल्ड को सही तरीके से दिखाने वाला ज़्यादातर स्ट्रक्चर काम करेगा. AGP और 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 टारगेट तय करने पर, यह AGP की ओर से बनाई गई लाइब्रेरी का डिफ़ॉल्ट सेट होगा. ऐसा तब होगा, जब 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, भाषा सेवा की सही सुविधाएं दिखा सके. जैसे, अपने-आप पूरा होने की सुविधा और परिभाषा पर जाने की सुविधा. हालांकि, आपको AGP को असल बिल्ड के दौरान, मौजूदा बिल्ड सिस्टम का इस्तेमाल करने के लिए कहना है.

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

उदाहरण के लिए, मान लें कि आपको MSBuild को रैप करना है. आपकी कॉन्फ़िगर स्क्रिप्ट, build.ninja को हमेशा की तरह जनरेट करेगी. हालांकि, इसमें एक पासथ्रू टारगेट भी जोड़ा जाएगा. इससे यह तय होगा कि AGP, 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 खोलें और सहायता > सुझाव/राय दें या शिकायत करें पर क्लिक करें. गड़बड़ी की जानकारी देने के लिए, "कस्टम C/C++ बिल्ड सिस्टम" का रेफ़रंस ज़रूर दें.

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