2010-08-23 5 views
7

Ich habe eine statische Bibliothek, Foo, die von einer gemeinsam genutzten Bibliothek, Bar verwendet wird. Bar ist die native, gemeinsam genutzte Bibliothek, die von meiner Android App geladen wird. Foo enthält JNI-Funktionen, die nur von Java-Code und nicht von jedem C++ - Code in Bar aufgerufen werden. Aus diesem Grund werden diese JNI-Funktionen aus der statischen Bibliothek (Foo) entfernt, wenn die gemeinsam genutzte Bibliothek (Bar) erstellt wird. Ich verwende derzeit eine etwas hacky Methode, um das zu verhindern.Verhindern, dass Funktionen aus einer statischen Bibliothek entfernt werden, wenn sie in eine gemeinsam genutzte Bibliothek eingebunden werden?

Also gibt es in diesem Fall eine Möglichkeit, den Compiler zu sagen, die JNI (oder irgendwelche) Funktionen nicht zu entfernen, wenn Sie verknüpfen?

Antwort

7

Sie werden nicht entkleidet, sie werden ignoriert. Wenn die gemeinsam genutzte Bibliothek verknüpft ist, zieht der Linker nur die Objektdateien mit Funktionen ein, die tatsächlich verwendet werden. (Dies ist, wie statische Bibliotheken funktionieren.)

Ich glaube, die Übergabe des Flags "--whole-archive" an den Linker bewirkt, dass alle Objektdateien aus einer statischen Bibliothek abgerufen werden. Sie können es in der gcc-Link-Zeile mit "-Wl, -whole-archive" angeben. Sie müssen nach der Angabe Ihrer Bibliothek mit "-Wl, -no-whole-archive" folgen, oder ld wird das Verhalten für alle anderen statischen Bibliotheken fortsetzen, die es trifft, was wahrscheinlich nicht das gewünschte Verhalten ist. Siehe auch die Manpage ld (1) auf einem Linux-System.

Eine andere Möglichkeit, dasselbe zu erreichen, ist die Ausgabe einer einzelnen massiven .o-Datei anstelle einer .a-Datei.

EDIT: Einfaches Kommandozeilen-Beispiel auf dem Desktop mit 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* 

(Sie haben "/usr/lib/libz.a" statt "lz" hier verwenden weil letzteres die shared library /usr/lib/libz.so findet.)

Ich habe das NDK nicht viel benutzt, aber es sieht so aus, als würde das Hinzufügen der Flags zu LOCAL_LDFLAGS den Trick machen.

+0

fadden - für die dichte unter uns - können Sie ein schnelles Beispiel, wie Sie die Android.mk-Datei einrichten müssen (mindestens die beiden Zeilen relevant für die Verknüpfung)? – EboMike

6

Beginnen wir mit der grundlegenden two-libs sample from NDK. Hier ist seine ursprüngliche Android.mk Datei:

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) 

Beachten Sie, dass die JNI-Funktion in second.c befindet, die nicht Teil der libtwolib-first statische Bibliothek ist.

Lassen Sie uns zunächst Ihr Problem reproduzieren. Die Änderung ist einfach:

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

Wenn Sie das geänderte Projekt ausführen, erhalten Sie folgende Fehlermeldung erhalten:

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) 

Sie erklären, dieses Problem genau: der Linker „gezupft“, die „nicht verwendet“ Java_com_example_twolibs_TwoLibs_add() Eintrag.

Nun wollen wir dieses Problem beheben:

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

Und wieder die Probe funktioniert!

+1

Vielen Dank! Das war genau das, was ich brauchte. –

Verwandte Themen