Preventing functions from being stripped from a static library when linked into a shared library?

前端 未结 2 1143
孤独总比滥情好
孤独总比滥情好 2020-12-10 15:35

I have a static library, Foo, that is used by a shared library, Bar. Bar is the native shared library loaded by my Android app. Foo contains JNI functions that are only call

2条回答
  •  感情败类
    2020-12-10 16:12

    Let's start with the basic two-libs sample from NDK. Here is its original Android.mk file:

     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)
    

    Note that the JNI function is located in second.c which is not part of the libtwolib-first static library.

    First, let us reproduce your problem. The change is simple:

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

    If you run the modified project, you will get the following error:

    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)
    

    You explained this problem precisely: the linker "stripped out" the "unused" Java_com_example_twolibs_TwoLibs_add() entry.

    Now let us fix this:

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

    And again the sample works!

提交回复
热议问题