2010-08-23 3 views
7

공유 라이브러리 Bar가 사용하는 정적 라이브러리 Foo가 있습니다. Bar는 내 Android 앱에서로드 한 기본 공유 라이브러리입니다. Foo에는 Bar의 C++ 코드가 아닌 Java 코드에 의해서만 호출되는 JNI 함수가 들어 있습니다. 이 때문에 JNI 함수는 공유 라이브러리 (Bar)가 빌드 될 때 정적 라이브러리 (Foo)에서 제거됩니다. 나는 현재 그런 일이 일어나지 않도록 약간 해키 한 방법을 사용하고 있습니다.공유 라이브러리에 링크 할 때 함수가 정적 라이브러리에서 제거되지 않도록 하시겠습니까?

그래서이 경우 링크 할 때 JNI (또는 모든) 함수를 제거하지 않도록 컴파일러에 알리는 방법이 있습니까?

답변

7

그들은 제거되지 않고있어, 무시 당하고 있습니다. 공유 라이브러리가 링크되면 링커는 실제로 사용되는 함수로 객체 파일 만 가져옵니다. (이것은 정적 라이브러리가 작동하도록 정의 된 방법입니다.) "--whole-archive"플래그를 링커에 전달하면 정적 라이브러리에서 모든 객체 파일을 가져 오게됩니다. gcc 링크 줄에 "-Wl, -whole-archive"로 제공 할 수 있습니다. 라이브러리를 지정한 후에 "-Wl, -no-whole-archive"를 따라야한다. 그렇지 않으면 ld는 발견 한 다른 정적 라이브러리의 동작을 계속할 것이다. Linux 시스템의 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를 찾습니다.

나는 NDK를 많이 사용하지 않았지만 LOCAL_LDFLAGS에 플래그를 추가하는 것이 트릭을 수행하는 것처럼 보입니다.

+0

fadden - 우리 중 밀도가 높은 경우 - Android.mk 파일을 설정하는 방법에 대한 빠른 예를 게시 할 수 있습니까? (최소한 두 줄은 연결과 관련이 있습니다)? – EboMike

6

기본 사항은 two-libs sample from NDK부터 시작합시다. JNI 함수가 libtwolib-first 정적 라이브러리의 일부가되는 second.c에 있는지

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) 

주 : 여기 원래 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

감사합니다! 그것은 내가 필요로했던 바로 그 것이었다. –

관련 문제