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 का इस्तेमाल करें.

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

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

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

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