2013-06-27 9 views
12

के साथ मौजूदा मेक फ़ाइल को कैसे शामिल करें, इसलिए मेरे पास एक बड़ी मौजूदा सी प्रोजेक्ट है जिसे मैंने $PROJECT/jni निर्देशिका में रखा है। यह प्रोजेक्ट आमतौर पर कॉन्फ़िगर स्क्रिप्ट चलाकर बनाया जाता है जो मेकफ़ाइल बनाता है जो तब परियोजना को make के माध्यम से संकलित करने की अनुमति देता है।एंड्रॉइड एनडीके

यह प्रोजेक्ट अपेक्षाकृत बड़ा है और इसमें कई निर्देशिकाएं हैं जिनमें स्रोत फ़ाइलें और शीर्षलेख फ़ाइलें हैं।

मुझे लगता है कि मुझे Android.mk काम करने के लिए यहां एक मौलिक समझ याद आ रही है। क्या यह कॉन्फ़िगरेशन और मेकफ़ाइल को प्रतिस्थापित करना है जिसे वर्तमान में प्रोजेक्ट को संकलित करने के लिए उपयोग किया जाता है? या क्या मैं अपनी कॉन्फ़िगर स्क्रिप्ट से जेनरेट मेकफ़ाइल को Android.mk में शामिल करूँगा? वे जो उदाहरण प्रदान करते हैं वे केवल कुछ स्रोत फ़ाइलों के साथ तुच्छ हैं।

jni/ 
    folder1/subfolder1 
    folder1/subfolder2 
    folder1/source 
    folder2/source 
    ..... 
    foldern/source 
    configure/ 
    configure/configure.sh 
    Makefile 
    Android.mk 

उत्पन्न makefiles बहुत व्यापक हैं (विन्यास की अच्छी रकम और हर निर्देशिका में से एक है) तो मैं थोड़ा यह कैसे दृष्टिकोण करने के लिए के रूप में खो रहा हूँ: मेरे jni निर्देशिका अधिक की तरह दिखता है।

संपादित करें:

प्रमुख मुद्दा है कि उदाहरण है कि NDK के साथ जहाज तुच्छ उदाहरण हैं है। शीर्ष स्तर jni निर्देशिका में उनके पास 3-5 स्रोत फ़ाइलें हैं। मेरी समस्या यह है कि यह कई उपनिर्देशिकाओं के साथ प्रत्येक 4 शीर्ष स्तर फ़ोल्डरों के साथ जटिल विन्यास के साथ एक विशाल परियोजना है। मैं बस स्रोत को jni फ़ोल्डर में नहीं ले जा सकता और ndk कंपाइलर चला सकता हूं।

उत्तर

12

अपने प्रश्न का उत्तर देने के लिए, हाँ Android.mk एंड्रॉइड बिल्ड सिस्टम है। Google मुश्किल से उल्लेख करता है कि इस फ़ाइल की "भाषा" जीएनयू मैक्रोज़ बनाने के रूप में लागू की गई है। दस्तावेज़ चाहते हैं कि आप उन मैक्रोज़ के संदर्भ में अपनी परियोजना का वर्णन करें। वे सभी grungy पार संकलन विवरण संभालते हैं। मुझे पूरा यकीन है कि Android.mk फ़ाइलों की अग्रेषित पोर्टेबिलिटी में सुधार के लिए Google ने इस दृष्टिकोण को विकसित किया है क्योंकि विकास उपकरण विकसित होते हैं।

अपशॉट यह है कि (और मुझे पता है कि आप इसे सुनना नहीं चाहते हैं) सबसे अच्छा जवाब शायद आपकी बड़ी परियोजना के लिए स्क्रैच से उचित एनडीके Android.mk लिखना है।

This article उसी 800 अवलोकनों और 300k एसएलओसी की लाइब्रेरी को पोर्ट करने के लिए उसी अवलोकन को प्रस्तुत करता है। दुर्भाग्य से मैंने लगभग दो हफ्तों को एक ही निष्कर्ष तक पहुंचाया: क्रॉस-संकलन कम से कम configure स्क्रिप्ट विफल होने का कारण बनता है (परिणामस्वरूप config.h फाइलों में गलत परिणाम)। मैंने आलेख में उपयोग की जाने वाली वही तकनीकों का "आविष्कार" किया। लेकिन एक साफ निर्माण के बाद भी, परिणामी स्थैतिक पुस्तकालय पूरी तरह से काम नहीं कर सका। डिबगिंग के घंटे ने कोई उपयोगी जानकारी नहीं निभाई। [चेतावनी: मैं कोई तरह का विन्यास उपकरण विशेषज्ञ नहीं हूँ। एक गुरु शायद मेरी गलती देखी होगी। तो यह जाता है।] मुझे साफ Android.mk बनाने में कुछ दिन लगे। परिणामस्वरूप लाइब्रेरी ने पहली बार सभी परीक्षणों को चलाया। और यह विकास उपकरणों के कई revs के माध्यम से साफ से पोर्ट किया गया है।

दुर्भाग्य से configure का उपयोग करने वाली लाइब्रेरी का निर्माण ऑटो उपकरण के बिना लक्षित वातावरण के लिए अपने config.h का निर्माण करना है। यह उतना बुरा नहीं हो सकता जितना लगता है। आईएमई सिस्टम वास्तव में उनके configure वातावरण में वास्तव में उपयोग करने की तुलना में अधिक परिभाषित करते हैं। वास्तविक निर्भरताओं का एक स्पष्ट विचार प्राप्त करना भविष्य के रिफैक्टरिंग के दौरान कठिन प्रयासों का भुगतान कर सकता है।

Autotool केवल जीएनयू सिस्टम पर अच्छा है और पार संकलन के लिए उपयोग वास्तव में, थकाऊ भ्रामक है, त्रुटियों की संभावना या भी असंभव हो सकता है:

लेख से सारांश बयान यह सब कहते हैं। यहां वर्णित विधि एक हैक है और इसे अपने जोखिम पर इस्तेमाल किया जाना चाहिए।

क्षमा करें मेरे पास अधिक सकारात्मक सुझाव नहीं है।

+0

मैं आपके अवलोकन से पूरी तरह से सहमत हूं। 'Config.h.in' से' config.h' की पीढ़ी एक क्रॉस-कंपाइल वातावरण में असंभव है। हालांकि, विन्यास को मूल रूप से 'शायद संभवतः' काम चलाना, लेकिन यह एक अन्य जानवर है :)। – Samveen

3

यहां चीजों को अन्य तरीकों से करने का एक समाधान है: मानक मेकफ़ाइल से बाहरी पुस्तकालय और एंड्रॉइड पैकेज दोनों का निर्माण।

एक शर्त के रूप में, आप आदेश पंक्ति Android विकास करने के लिए आवश्यक सब कुछ स्थापित करने की आवश्यकता:

  • एक स्वसंपूर्ण toolchain, देख प्रलेखन एंड्रॉयड NDK में शामिल;
  • चींटी।

उदाहरण की संरचना है:

: बाहरी पुस्तकालय और प्रत्येक निर्देशिका में Makefile और एक शीर्ष स्तर के साथ एक ही स्तर पर एंड्रॉयड स्रोतों के लिए एक निर्देशिका, पुनरावर्ती Makefile के लिए एक निर्देशिका

AR=/path/to/standalone/bin/arm-linux-androideabi-ar 
CC=/path/to/standalone/bin/arm-linux-androideabi-gcc 

libmylib.a: mylib.o 
    $(AR) rcs libmylib.a mylib.o 

mylib.o: mylib.c 
    $(CC) -c mylib.c -o mylib.o 

android/Makefile प्रदान कर रहा है निर्माण करने के लिए नियम:

Makefile 
mylib/ 
    Makefile 
android/ 
    Makefile 

mylib/Makefile एक स्थिर पुस्तकालय बनाता है एंड्रॉइड पैकेज:

  • हमें संशोधित होने पर mylib की प्रतिलिपि बनाने की निर्भरता की आवश्यकता है;
  • हम jni/ndkmake.c फ़ाइल का उपयोग mylib पर कॉल को लपेटने और एंड्रॉइड विशिष्ट सामग्री प्रदान करने के लिए कर रहे हैं;
  • एंड्रॉइड पैकेज जावा स्रोतों और साझा लाइब्रेरी पर निर्भर करता है।या तो एक रिलीज पैकेज या किसी डिबग एक निर्माण करने के लिए release (डिफ़ॉल्ट) और debug:

Makefile दो लक्ष्य प्रदान करता है।

NDK_BUILD=/path/to/ndk-build 
JAVASRC=src/com/example/ndkmake/NdkMake.java 

release: bin/NdkMake-release-unsigned.apk 

debug: bin/NdkMake-debug.apk 

bin/NdkMake-release-unsigned.apk: libs/armeabi/libndkmake.so $(JAVASRC) 
ant release 

bin/NdkMake-debug.apk: libs/armeabi/libndkmake.so $(JAVASRC) 
ant debug 

libs/armeabi/libndkmake.so: jni/ndkmake.c jni/libmylib.a 
$(NDK_BUILD) 

jni/libmylib.a: ../mylib/libmylib.a 
cp ../mylib/libmylib.a jni/libmylib.a 

Android.mk फ़ाइल एक पहले से बनाए गए के रूप में, निर्माण में स्थिर पुस्तकालय शामिल करने के लिए नियमों को प्रदान करता है। हम LOCAL_EXPORT_C_INCLUDES का उपयोग कर mylib लाइब्रेरी से शीर्षलेख शामिल कर रहे हैं।

LOCAL_PATH := $(call my-dir) 

include $(CLEAR_VARS) 
LOCAL_MODULE := ndkmake 
LOCAL_SRC_FILES := ndkmake.c 
LOCAL_STATIC_LIBRARIES := mylib-prebuilt 
include $(BUILD_SHARED_LIBRARY) 

include $(CLEAR_VARS) 
LOCAL_MODULE := mylib-prebuilt 
LOCAL_SRC_FILES := libmylib.a 
LOCAL_EXPORT_C_INCLUDES := ../mylib/ 
include $(PREBUILT_STATIC_LIBRARY) 

अब हम केवल दो उपनिर्देशिका बनाने के लिए एक उच्च-स्तरीय Makefile की जरूरत है:

all: libmylib package 

libmylib: 
    cd mylib && $(MAKE) 

package: 
    cd android && $(MAKE) 

पुस्तकालय का कोई भी परिवर्तन, JNI सूत्रों के या जावा सूत्रों के पुनर्निर्माण की एक ट्रिगर किया जाएगा पैकेज।

+0

आपकी सलाह के लिए धन्यवाद। क्या आप कुछ बिंदुओं को स्पष्ट कर सकते हैं: 1) क्या मतलब है "एनडीके सामग्री के लिए एक बिल्ड नियम जोड़ें" क्या नियम बनाते हैं? आप एंड्रॉइड.एमके फाइलों में सामान्य रूप से निर्दिष्ट आदेशों का मतलब है? 2) मैं इस स्टैंडअलोन टूलचेन के बारे में जानकारी कहां पा सकता हूं? धन्यवाद! – thatidiotguy

+0

आप एनडीके के साथ भेजे गए दस्तावेज में स्टैंडअलोन टूलचेन्स के बारे में अधिक जानकारी प्राप्त कर सकते हैं, यहां एक ऑनलाइन प्रति है: http://www.kandroid.org/ndk/docs/STANDALONE-TOOLCHAIN.html एनडीके के निर्माण नियम के लिए, मेरा मतलब है Android.mk रखना, लेकिन अपने मेकफ़ाइल से ndk-build चलाएं (मेरा उदाहरण देखें) – Guillaume

+0

क्या मैं सीधे संकलित सी ऑब्जेक्ट्स से लिंक कर सकता हूं? उदाहरण के लिए, अगर मैं अपने सी सॉफ्टवेयर पर अभी करता हूं तो यह 3 '.so' फाइलों को आउटपुट करेगा। क्या जेएनआई विधियों के साथ सी फ़ाइल बनाने का कोई तरीका है जो पुस्तकालय फ़ाइलों में ऑब्जेक्ट्स से लिंक करता है? – thatidiotguy

4

मेरा उत्तर Gene के उत्तर के साथ सबसे अच्छा काम करता है।

./configure कॉन्फ़िगरेशन फ़ाइल का निर्माण प्रत्येक परीक्षण के लिए C कोड के छोटे स्निपेट को संकलित (और संभवतः चल रहा है) पर आधारित है। संकलन-केवल परीक्षणों को क्रॉस-कंपाइल वातावरण में सफलतापूर्वक परीक्षण किया जा सकता है। हालांकि, संकलन और रन परीक्षण एक क्रॉस-कंपाइल वातावरण में चलाने के लिए असंभव हैं। config.h बनाने के लिए प्रत्येक परीक्षण की सफलता config.h.in टेम्पलेट में एक समान चर सेट करती है।

इस प्रकार, रूपांतरण की प्रक्रिया शुरू करने के लिए, आप उपकरणों के पार संकलक सेट (शायद NDK से वाले) को CPP, CC, LD और अन्य उपकरणों का सेट और फिर ./configure चलाने की आवश्यकता होगी। एक बार ऐसा करने के बाद, आपको अपने लक्षित वातावरण से मेल खाने के लिए config.h को सही करने की आवश्यकता होगी। यह आपकी सबसे महत्वपूर्ण और सबसे त्रुटि प्रवण चरण है।

Android.mk के लिए, यह Makefile.am के करीब एक प्रारूप का पालन करता है जिसे आसानी से इसमें परिवर्तित किया जा सकता है। और Makefile को अनदेखा कर सकते हैं, क्योंकि Makefile.am से उत्पन्न होते हैं।

की file (संस्करण 5.11), मैं निम्नलिखित विकल्पों के साथ कॉन्फ़िगर भाग गया एक उदाहरण लेते हैं,

./configure --host arm-toshiba-linux-androideabi --build x86_64-linux-gnu \ 
      --prefix=/data/local/ host_alias=arm-linux-androideabi \ 
      "CFLAGS=--sysroot=~/ndk/platforms/android-8/arch-arm -Wall -Wextra" \ 
      "CPPFLAGS=--sysroot=~/ndk/platforms/android-8/arch-arm" \ 
      CPP=arm-linux-androideabi-cpp 

अगले कदम के रूप में नीचे src/Makefile.am लेने के लिए किया गया था:

MAGIC = $(pkgdatadir)/magic 
lib_LTLIBRARIES = libmagic.la 
include_HEADERS = magic.h 

bin_PROGRAMS = file 

AM_CPPFLAGS = -DMAGIC='"$(MAGIC)"' 
AM_CFLAGS = $(CFLAG_VISIBILITY) @[email protected] 

libmagic_la_SOURCES = magic.c apprentice.c softmagic.c ascmagic.c \ 
     encoding.c compress.c is_tar.c readelf.c print.c fsmagic.c \ 
     funcs.c file.h readelf.h tar.h apptype.c \ 
     file_opts.h elfclass.h mygetopt.h cdf.c cdf_time.c readcdf.c cdf.h 
libmagic_la_LDFLAGS = -no-undefined -version-info 1:0:0 
if MINGW 
MINGWLIBS = -lgnurx -lshlwapi 
else 
MINGWLIBS = 
endif 
libmagic_la_LIBADD = $(LTLIBOBJS) $(MINGWLIBS) 

file_SOURCES = file.c 
file_LDADD = libmagic.la 
CLEANFILES = magic.h 
EXTRA_DIST = magic.h.in 
HDR= $(top_srcdir)/src/magic.h.in 
BUILT_SOURCES = magic.h 

magic.h:  ${HDR} 
     sed -e "s/X.YY/$$(echo @[email protected] | tr -d .)/" < ${HDR} > [email protected] 

और बनाने इस से Android.mk

अंतिम और सबसे महत्वपूर्ण कदम लक्ष्य प्रणाली की स्थिति को सटीक रूप से प्रतिबिंबित करने के लिए config.h को संशोधित करना था। यह एक मैन्युअल प्रक्रिया होगी जिसे मैं मुख्य रूप से config.log में देखकर, हेडर में देखकर और "invoking" Google को शामिल करने के लिए वर्कअराउंड नहीं दे सकता। इस श्रम के फल on XDA उपलब्ध हैं।

संबंधित मुद्दे