我有一個靜態庫Foo,由共享庫Bar使用。 Bar是我的Android應用程序加載的本地共享庫。 Foo包含僅由Java代碼調用的JNI函數,而不是Bar中的任何C++代碼。因此,當構建共享庫(Bar)時,那些JNI函數會從靜態庫(Foo)中剝離出來。我目前正在使用一種有點冒險的方法來防止這種情況發生。防止函數鏈接到共享庫時從靜態庫中剝離?
因此,在這種情況下,有沒有辦法告訴編譯器在鏈接時不去掉JNI(或任何)函數?
我有一個靜態庫Foo,由共享庫Bar使用。 Bar是我的Android應用程序加載的本地共享庫。 Foo包含僅由Java代碼調用的JNI函數,而不是Bar中的任何C++代碼。因此,當構建共享庫(Bar)時,那些JNI函數會從靜態庫(Foo)中剝離出來。我目前正在使用一種有點冒險的方法來防止這種情況發生。防止函數鏈接到共享庫時從靜態庫中剝離?
因此,在這種情況下,有沒有辦法告訴編譯器在鏈接時不去掉JNI(或任何)函數?
他們沒有被剝奪,他們被忽略。當共享庫鏈接時,鏈接器只會使用實際使用的函數提取目標文件。 (這是如何定義靜態庫的工作。)
我相信將「 - 整個歸檔」標誌傳遞給鏈接器將導致它從靜態庫拉入所有的目標文件。你可以在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可能會有效。
讓我們從基本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-first39 LOCAL_WHOLE_STATIC_LIBRARIES := libtwolib-first
又一次的樣品作品!
謝謝!那正是我需要的。 – 2017-02-10 21:53:57
fadden - 對於我們中間的密集人員 - 你能發表一個關於如何設置Android.mk文件(至少與鏈接相關的兩行)的快速示例嗎? – EboMike 2010-08-31 05:49:39