2010-08-23 94 views
7

我有一個靜態庫Foo,由共享庫Bar使用。 Bar是我的Android應用程序加載的本地共享庫。 Foo包含僅由Java代碼調用的JNI函數,而不是Bar中的任何C++代碼。因此,當構建共享庫(Bar)時,那些JNI函數會從靜態庫(Foo)中剝離出來。我目前正在使用一種有點冒險的方法來防止這種情況發生。防止函數鏈接到共享庫時從靜態庫中剝離?

因此,在這種情況下,有沒有辦法告訴編譯器在鏈接時不去掉JNI(或任何)函數?

回答

7

他們沒有被剝奪,他們被忽略。當共享庫鏈接時,鏈接器只會使用實際使用的函數提取目標文件。 (這是如何定義靜態庫的工作。)

我相信將「 - 整個歸檔」標誌傳遞給鏈接器將導致它從靜態庫拉入所有的目標文件。你可以在gcc鏈接行上用「-Wl,-whole-archive」提供它。你需要在指定你的庫之後用「-Wl,-no-whole-archive」來關注它,否則ld會繼續爲它遇到的任何其他靜態庫行爲,這可能不是你想要的行爲。另請參閱Linux系統上的ld(1)手冊頁。

完成同樣事情的另一種方法是輸出一個巨大的.o文件而不是.a文件。

編輯: 簡單的命令行例如,使用桌面上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* 

(你必須使用 「/usr/lib/libz.a」 而不是 「-lz」 在這裏因爲後者找到了共享庫/usr/lib/libz.so。)

我還沒有使用過NDK,但是看起來像將這些標誌添加到LOCAL_LDFLAGS可能會有效。

+0

fadden - 對於我們中間的密集人員 - 你能發表一個關於如何設置Android.mk文件(至少與鏈接相關的兩行)的快速示例嗎? – EboMike 2010-08-31 05:49:39

6

讓我們從基本two-libs sample from NDK開始。這裏是原來的Android.mk文件:

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靜態庫的一部分。

首先,讓我們重現您的問題。這種變化是簡單的:

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

如果運行修改過的項目,您會收到以下錯誤:

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鏈接()條目。

現在讓我們來解決這個問題:

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

又一次的樣品作品!

+1

謝謝!那正是我需要的。 – 2017-02-10 21:53:57