使用Android NDK r18b
(带有clang
工具链)和Android Studio 3.2.1
。
我的mylib.gradle
的相关部分:
task ndkBuild(type: Exec) {
commandLine "${ndkDir}/ndk-build${ndkExt}"
}
我的Application.mk
:
APP_PLATFORM := android-17
APP_ABI := armeabi-v7a
# APP_OPTIM := release
APP_CFLAGS += -D_BSD_SOURCE
还有我的Android.mk
的相关部分:
include $(CLEAR_VARS)
LOCAL_PATH := $(BASE_PATH)
LOCAL_MODULE := mylib_jni
LOCAL_STATIC_LIBRARIES := \
lib1 \
lib2
LOCAL_WHOLE_STATIC_LIBRARIES := \
mylib_wrap \
other_wrap
include $(BUILD_SHARED_LIBRARY)
静态库mylib_jni.so
已成功构建。然后,我从NDK运行以下命令:
arm-linux-androideabi-readelf -a mylib_jni.so
在输出中,我可以在lib1
和lib2
中看到所有非静态方法的名称(如上所示,不是整个库)。 这怎么可能?如何从ndk-build
命令中获得一些输出,其中包含有关为何不删除符号的信息? (我找不到NDK构建步骤的options.txt
。)
答案 0 :(得分:4)
恐怕您在 strip 和 visibility = hidden 之间感到困惑。
former是构建共享库的独立后链接步骤。其目的是通过删除链接器为调试目的而留下的一些额外信息,以减小文件(将打包为APK)的大小。请注意,当来自所有模块的本机库合并在一起时, gradle (在Android Studio 3.2+中)甚至会在以后执行此操作。
条带影响文件的大小,但不影响符号visibility。
隐藏符号是另一种减小二进制文件大小的技术。强烈建议您使用这种方法,以减少您的库进行逆向工程的可能性。
默认情况下不会发生这种情况。您必须显式添加此编译器标志:
APP_CFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden
您可以将此与丢弃未使用的功能结合起来:
APP_CFLAGS += -ffunction-sections -fdata-sections
APP_LDFLAGS += -Wl,--gc-sections
您必须使用显式标记外部功能
__attribute__ ((visibility ("default")))
幸运的是,感谢 jni.h ,为所有JNIEXPORT
功能集设置了此属性。
如果您使用预建的静态库,则may need also
APP_LDFLAGS += -Wl,--exclude-libs,ALL
考虑还提供version script
LOCAL_LDFLAGS += -Wl,-version-script -Wl,mylib_jni.vs