2010-08-23 17 views
7

मेरे पास एक स्थिर लाइब्रेरी है, Foo, जिसका उपयोग साझा लाइब्रेरी, बार द्वारा किया जाता है। बार मेरे एंड्रॉइड ऐप द्वारा लोड की गई देशी साझा लाइब्रेरी है। फू में जेएनआई फ़ंक्शन शामिल हैं जिन्हें केवल जावा कोड द्वारा बुलाया जाता है, न कि बार में किसी भी C++ कोड द्वारा। इस वजह से, साझा पुस्तकालय (बार) बनाया गया है, जब उन जेएनआई कार्यों स्थिर पुस्तकालय (फू) से बाहर हो जाते हैं। मैं वर्तमान में ऐसा होने से रोकने के लिए थोड़ा हैकी विधि का उपयोग कर रहा हूं।किसी साझा लाइब्रेरी में लिंक होने पर फ़ंक्शंस को एक स्थिर लाइब्रेरी से छीनने से रोकना?

तो, इस मामले में, संकलन करने के लिए जेएनआई (या किसी भी) कार्यों को पट्टी करने के लिए संकलक को बताने का कोई तरीका नहीं है?

उत्तर

7

वे छीन नहीं रहे हैं, उन्हें अनदेखा कर रहे हैं। जब साझा लाइब्रेरी लिंक होती है, तो लिंकर केवल उन ऑब्जेक्ट फ़ाइलों में खींच रहा है जो वास्तव में उपयोग किए जाते हैं। (यह कैसे स्थिर libs काम करने के लिए निर्धारित किए जाते हैं।)

मैं लिंकर करने के लिए "--whole-संग्रह" झंडा गुजर मानना ​​है कि यह एक स्थिर पुस्तकालय से सभी वस्तु फ़ाइलों में खींचने के लिए कारण होगा। आप इसे "-Wl, -whole-archive" के साथ जीसीसी लिंक लाइन पर प्रदान कर सकते हैं। आपको अपनी लाइब्रेरी निर्दिष्ट करने के बाद "-Wl, -no-whole-archive" के साथ इसका पालन करने की आवश्यकता है, या ld किसी भी अन्य स्थिर पुस्तकालयों के लिए व्यवहार जारी रखेगा, जो संभवतः आपके इच्छित व्यवहार की संभावना नहीं है। लिनक्स सिस्टम पर एलडी (1) मैन पेज भी देखें।

एक ही चीज़ को पूरा करने का एक और तरीका एक .a फ़ाइल के बजाय एक बड़े पैमाने पर .o फ़ाइल आउटपुट करना है।

संपादित करें: सरल कमांड लाइन उदाहरण के लिए, डेस्कटॉप पर libz का उपयोग कर:

% echo "int main() { return 0; }" > foo.c 
% gcc -o foo /usr/lib/libz.a foo.c 
% ls -s foo 
12 foo* 
% gcc -o foo -Wl,-whole-archive /usr/lib/libz.a -Wl,-no-whole-archive foo.c 
% ls -s foo 
104 foo* 

(आप के बजाय "-lz" "/usr/lib/libz.a" यहाँ का उपयोग करना क्योंकि उत्तरार्द्ध साझा लाइब्रेरी /usr/lib/libz.so पाता है।)

मैंने एनडीके का अधिक उपयोग नहीं किया है, लेकिन ऐसा लगता है कि LOCAL_LDFLAGS में झंडे जोड़ने से चाल चल सकती है।

+0

fadden - हमारे बीच घने के लिए - क्या आप एक त्वरित उदाहरण पोस्ट कर सकते हैं कि आपको Android.mk फ़ाइल को सेट करने की आवश्यकता होगी (कम से कम दो पंक्तियां जोड़ने के लिए प्रासंगिक हैं)? – EboMike

6

चलिए मूल two-libs sample from NDK से शुरू करते हैं।

1 # Copyright (C) 2009 The Android Open Source Project 
2 # 
3 # Licensed under the Apache License, Version 2.0 (the "License"); 
4 # you may not use this file except in compliance with the License. 
5 # You may obtain a copy of the License at 
6 # 
7 #  http://www.apache.org/licenses/LICENSE-2.0 
8 # 
9 # Unless required by applicable law or agreed to in writing, software 
10 # distributed under the License is distributed on an "AS IS" BASIS, 
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
12 # See the License for the specific language governing permissions and 
13 # limitations under the License. 
14 # 
15 
16 # the purpose of this sample is to demonstrate how one can 
17 # generate two distinct shared libraries and have them both 
18 # uploaded in 
19 # 
20 
21 LOCAL_PATH:= $(call my-dir) 
22 
23 # first lib, which will be built statically 
24 # 
25 include $(CLEAR_VARS) 
26 
27 LOCAL_MODULE := libtwolib-first 
28 LOCAL_SRC_FILES := first.c 
29 
30 include $(BUILD_STATIC_LIBRARY) 
31 
32 # second lib, which will depend on and include the first one 
33 # 
34 include $(CLEAR_VARS) 
35 
36 LOCAL_MODULE := libtwolib-second 
37 LOCAL_SRC_FILES := second.c 
38 
39 LOCAL_STATIC_LIBRARIES := libtwolib-first 
40 
41 include $(BUILD_SHARED_LIBRARY) 

ध्यान दें कि JNI समारोह second.c में स्थित है जो libtwolib-first स्थिर पुस्तकालय का हिस्सा नहीं है: यहाँ अपने मूल Android.mk फ़ाइल है।

सबसे पहले, हम आपकी समस्या को पुन: उत्पन्न करते हैं।

E/AndroidRuntime(4213): FATAL EXCEPTION: main 
E/AndroidRuntime(4213): java.lang.UnsatisfiedLinkError: add 
E/AndroidRuntime(4213):  at com.example.twolibs.TwoLibs.add(Native Method) 
E/AndroidRuntime(4213):  at com.example.twolibs.TwoLibs.onCreate(TwoLibs.java:39) 
E/AndroidRuntime(4213):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 
E/AndroidRuntime(4213):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627) 
E/AndroidRuntime(4213):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679) 
E/AndroidRuntime(4213):  at android.app.ActivityThread.access$2300(ActivityThread.java:125) 
E/AndroidRuntime(4213):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033) 
E/AndroidRuntime(4213):  at android.os.Handler.dispatchMessage(Handler.java:99) 
E/AndroidRuntime(4213):  at android.os.Looper.loop(Looper.java:123) 
E/AndroidRuntime(4213):  at android.app.ActivityThread.main(ActivityThread.java:4627) 
E/AndroidRuntime(4213):  at java.lang.reflect.Method.invokeNative(Native Method) 
E/AndroidRuntime(4213):  at java.lang.reflect.Method.invoke(Method.java:521) 
E/AndroidRuntime(4213):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:871) 
E/AndroidRuntime(4213):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:629) 
E/AndroidRuntime(4213):  at dalvik.system.NativeStart.main(Native Method) 

आप ठीक इस समस्या को विस्तार से बताया:: लिंकर "बाहर छीन लिया" "अप्रयुक्त" Java_com_example_twolibs_TwoLibs_add

... 
27 LOCAL_MODULE := libtwolib-first 
28 LOCAL_SRC_FILES := first.c second.c 
... 
36 LOCAL_MODULE := libtwolib-second 
37 LOCAL_SRC_FILES := 

आप संशोधित परियोजना चलाते हैं, तो आपको निम्न त्रुटि प्राप्त होगा: परिवर्तन सरल है() प्रवेश।

अब हम इसे ठीक करते हैं:

            
 
  
             39 LOCAL_STATIC_LIBRARIES := libtwolib-first
            
  
39 LOCAL_WHOLE_STATIC_LIBRARIES := libtwolib-first

और फिर नमूना काम करता है!

+1

धन्यवाद! यही वही था जो मुझे चाहिए था। –

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