32-बिट और 64-बिट आर्किटेक्चर के लिए बनाए गए ऐप्लिकेशन

बिल्ड सिस्टम, एक ही बिल्ड में 32-बिट और 64-बिट, दोनों टारगेट सीपीयू आर्किटेक्चर के लिए बाइनरी बनाने की सुविधा देता है. दो टारगेट के लिए बनाए गए इस बिल्ड को मल्टीलिब बिल्ड कहा जाता है.

बिल्ड सिस्टम, इन-बिल्ट स्टैटिक लाइब्रेरी और शेयर की गई लाइब्रेरी के लिए, दोनों आर्किटेक्चर के लिए बाइनरी बनाने के नियम सेट अप करता है. प्रॉडक्ट कॉन्फ़िगरेशन (PRODUCT_PACKAGES) और डिपेंडेंसी ग्राफ़ से यह तय होता है कि सिस्टम इमेज में कौनसी बाइनरी बनाई और इंस्टॉल की जाएंगी.

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

दूसरे सीपीयू आर्किटेक्चर और एबीआई की पहचान करना

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

  • TARGET_2ND_ARCH
  • TARGET_2ND_ARCH_VARIANT
  • TARGET_2ND_CPU_VARIANT
  • TARGET_2ND_CPU_ABI
  • TARGET_2ND_CPU_ABI2

इन वैरिएबल का इस्तेमाल करने वाले मेकफ़ाइल का उदाहरण देखने के लिए, build/make/target/board/generic_arm64/BoardConfig.mk देखें.

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

हालांकि, make कमांड लाइन पर मौजूद मॉड्यूल के नाम, सिर्फ़ 64-बिट वर्शन को कवर करते हैं. उदाहरण के लिए, lunch aosp_arm64-eng चलाने के बाद, make libc सिर्फ़ 64-बिट libc बनाता है. 32-बिट libc बनाने के लिए, आपको make libc_32 चलाना होगा.

Android.mk में मॉड्यूल आर्किटेक्चर तय करना

LOCAL_MULTILIB वैरिएबल का इस्तेमाल करके, अपने बिल्ड को 32-बिट और 64-बिट के लिए कॉन्फ़िगर किया जा सकता है. साथ ही, ग्लोबल TARGET_PREFER_32_BIT वैरिएबल को बदला जा सकता है.

TARGET_PREFER_32_BIT को बदलने के लिए, LOCAL_MULTILIB को इनमें से किसी एक पर सेट करें:

  • both से 32-बिट और 64-बिट, दोनों वर्शन बनते हैं.
  • 32 से सिर्फ़ 32-बिट वर्शन बनता है.
  • 64 से सिर्फ़ 64-बिट वर्शन बनता है.
  • first से सिर्फ़ पहले आर्किटेक्चर (32-बिट डिवाइसों में 32-बिट और 64-बिट डिवाइसों में 64-बिट) के लिए वर्शन बनता है.

डिफ़ॉल्ट रूप से, LOCAL_MULTILIB सेट नहीं होता. साथ ही, बिल्ड सिस्टम यह तय करता है कि मॉड्यूल क्लास और अन्य LOCAL_* वैरिएबल के आधार पर, किस आर्किटेक्चर के लिए वर्शन बनाना है. जैसे, LOCAL_MODULE_TARGET_ARCH और LOCAL_32_BIT_ONLY.

अगर आपको अपने मॉड्यूल को खास आर्किटेक्चर के लिए बनाना है, तो इन वैरिएबल का इस्तेमाल करें:

  • LOCAL_MODULE_TARGET_ARCH - इस वैरिएबल को आर्किटेक्चर की सूची पर सेट करें, जैसे arm x86 arm64. अगर बनाया जा रहा आर्किटेक्चर, उस सूची में शामिल है, तो बिल्ड सिस्टम में मौजूदा मॉड्यूल शामिल किया जाता है.

  • LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH - यह वैरिएबल, LOCAL_MODULE_TARGET_ARCH के उलट है. अगर बनाया जा रहा आर्किटेक्चर, उस सूची में not है, तो बिल्ड सिस्टम में मौजूदा मॉड्यूल शामिल किया जाता है.

इन दोनों वैरिएबल के कुछ मामूली वैरिएंट भी हैं:

  • LOCAL_MODULE_TARGET_ARCH_WARN
  • LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH_WARN

अगर सूची में शामिल आर्किटेक्चर की वजह से, मौजूदा मॉड्यूल को छोड़ दिया जाता है, तो बिल्ड सिस्टम चेतावनी दिखाता है.

किसी खास आर्किटेक्चर के लिए बिल्ड फ़्लैग सेट अप करने के लिए, आर्किटेक्चर के हिसाब से LOCAL_* वैरिएबल का इस्तेमाल करें. यहां * आर्किटेक्चर के हिसाब से सफ़िक्स है. उदाहरण के लिए:

  • LOCAL_SRC_FILES_arm, LOCAL_SRC_FILES_x86,
  • LOCAL_CFLAGS_arm, LOCAL_CFLAGS_arm64,
  • LOCAL_LDFLAGS_arm, LOCAL_LDFLAGS_arm64,

ये वैरिएबल सिर्फ़ तब लागू होते हैं, जब किसी बाइनरी को उस आर्किटेक्चर के लिए बनाया जा रहा हो.

कभी-कभी, बाइनरी को 32-बिट या 64-बिट के लिए बनाया जा रहा है या नहीं, इसके आधार पर फ़्लैग सेट अप करना आसान होता है. LOCAL_* वैरिएबल का इस्तेमाल _32 या _64 सफ़िक्स के साथ करें. उदाहरण के लिए:

  • LOCAL_SRC_FILES_32, LOCAL_SRC_FILES_64,
  • LOCAL_CFLAGS_32, LOCAL_CFLAGS_64,
  • LOCAL_LDFLAGS_32, LOCAL_LDFLAGS_64,

लाइब्रेरी का इंस्टॉलेशन पाथ सेट करना

नॉन-मल्टीलिब बिल्ड के लिए, LOCAL_MODULE_PATH का इस्तेमाल करके, लाइब्रेरी को डिफ़ॉल्ट जगह के अलावा किसी दूसरी जगह पर इंस्टॉल किया जा सकता है. उदाहरण के लिए, LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw.

हालांकि, मल्टीलिब बिल्ड में, इसके बजाय LOCAL_MODULE_RELATIVE_PATH का इस्तेमाल करें:

LOCAL_MODULE_RELATIVE_PATH := hw

इस फ़ॉर्मैट की मदद से, 64-बिट और 32-बिट, दोनों लाइब्रेरी सही जगह पर इंस्टॉल की जाती हैं.

अगर किसी एक्ज़ीक्यूटेबल को 32-बिट और 64-बिट, दोनों के तौर पर बनाया जाता है, तो इंस्टॉलेशन पाथ में अंतर करने के लिए, इनमें से कोई एक वैरिएबल इस्तेमाल करें:

  • LOCAL_MODULE_STEM_32, LOCAL_MODULE_STEM_64 - इंस्टॉल की गई फ़ाइल का नाम तय करता है.
  • LOCAL_MODULE_PATH_32, LOCAL_MODULE_PATH_64 - इंस्टॉलेशन पाथ तय करता है.

सोर्स फ़ाइलों के लिए इंटरमीडिएट डायरेक्ट्री पाना

मल्टीलिब बिल्ड में, अगर सोर्स फ़ाइलें $(local-intermediates-dir) (या साफ़ तौर पर वैरिएबल के साथ $(intermediates-dir-for)) में जनरेट की जाती हैं, तो यह भरोसेमंद तरीके से काम नहीं करता. ऐसा इसलिए होता है, क्योंकि जनरेट किए गए इंटरमीडिएट सोर्स, 32-बिट और 64-बिट, दोनों बिल्ड के लिए ज़रूरी होते हैं. हालांकि, $(local-intermediates-dir) सिर्फ़ दो इंटरमीडिएट डायरेक्ट्री में से किसी एक की ओर इशारा करता है.

बिल्ड सिस्टम, सोर्स जनरेट करने के लिए, मल्टीलिब के साथ काम करने वाली एक खास इंटरमीडिएट डायरेक्ट्री उपलब्ध कराता है. इंटरमीडिएट डायरेक्ट्री का पाथ पाने के लिए, $(local-generated-sources-dir) या $(generated-sources-dir-for) मैक्रो का इस्तेमाल करें. इन मैक्रो का इस्तेमाल, $(local-intermediates-dir) और $(intermediates-dir-for) के जैसा ही होता है.

अगर किसी सोर्स फ़ाइल को इस खास डायरेक्ट्री में जनरेट किया जाता है और LOCAL_GENERATED_SOURCES से चुना जाता है, तो मल्टीलिब बिल्ड में इसे 32-बिट और 64-बिट, दोनों के लिए बनाया जाता है.

पहले से बनाए गए बाइनरी टारगेट के सिस्टम आर्किटेक्चर के बारे में बताना

मल्टीलिब बिल्ड में, पहले से बनाए गए बाइनरी टारगेट के सिस्टम आर्किटेक्चर के बारे में बताने के लिए, TARGET_ARCH या TARGET_ARCH के साथ TARGET_2ND_ARCH का इस्तेमाल नहीं किया जा सकता. इसके बजाय, LOCAL_* वैरिएबल LOCAL_MODULE_TARGET_ARCH या LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH का इस्तेमाल करें.

इन वैरिएबल की मदद से, बिल्ड सिस्टम, 64-बिट मल्टीलिब बिल्ड पर काम करने के दौरान भी, पहले से बनाई गई 32-बिट बाइनरी को चुन सकता है.

अगर आपको पहले से बनाई गई बाइनरी के सोर्स पाथ की गिनती करने के लिए, चुने गए आर्किटेक्चर का इस्तेमाल करना है, तो $(get-prebuilt-src-arch) को कॉल करें.

पक्का करें कि 32-बिट और 64-बिट ODEX फ़ाइलें जनरेट हों

64-बिट डिवाइसों के लिए, Google डिफ़ॉल्ट रूप से बूट इमेज और किसी भी Java लाइब्रेरी के लिए, 32-बिट और 64-बिट, दोनों ODEX फ़ाइलें जनरेट करता है. एपीके के लिए, Google डिफ़ॉल्ट रूप से सिर्फ़ प्राइमरी 64-बिट आर्किटेक्चर के लिए ODEX जनरेट करता है. अगर कोई ऐप्लिकेशन, 32-बिट और 64-बिट, दोनों प्रोसेस में लॉन्च किया जाता है, तो पक्का करें कि 32-बिट और 64-बिट, दोनों ODEX फ़ाइलें जनरेट हों. इसके लिए, LOCAL_MULTILIB := both का इस्तेमाल करें. अगर ऐप्लिकेशन में 32-बिट या 64-बिट JNI लाइब्रेरी मौजूद हैं, तो यह फ़्लैग, बिल्ड सिस्टम को उन्हें शामिल करने के लिए भी कहता है.