Reputation: 19937
Using Android NDK r18b
(with clang
tool chain) and Android Studio 3.2.1
.
Relevant part of my mylib.gradle
:
task ndkBuild(type: Exec) {
commandLine "${ndkDir}/ndk-build${ndkExt}"
}
My Application.mk
:
APP_PLATFORM := android-17
APP_ABI := armeabi-v7a
# APP_OPTIM := release
APP_CFLAGS += -D_BSD_SOURCE
And relevant part of my 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)
The static library mylib_jni.so
is successfully built. I then run the following command (from the NDK):
arm-linux-androideabi-readelf -a mylib_jni.so
In the output I can see the names of all non-static methods in lib1
and lib2
(not whole libraries as can be seen above). How is this possible? How can I get some outputs from the ndk-build
command with information about why the symbols are not stripped? (I cannot find the options.txt
for my NDK build step.)
Upvotes: 3
Views: 4819
Reputation: 57173
I am afraid you are confused between strip and visibility=hidden.
The former is a separate, post-linker, step of building a shared library. Its purpose is to reduce the size of the file (which will be packed into APK) by removing some extra information that the linker leaves for debugging purposes. Note that gradle (in Android Studio 3.2+) performs this strip even later, when the native libraries from all modules are merged together.
Strip affects the size of the file, but not the visibility of symbols.
Hiding symbols is another technique to reduce the size of the binaries. It is also highly recommended, to reduce exposure of your libraries to reverse engineering.
This does not happen by default. You must explicitly add this compiler flag:
APP_CFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden
You may combine this with discarding of unused functions:
APP_CFLAGS += -ffunction-sections -fdata-sections
APP_LDFLAGS += -Wl,--gc-sections
You must explicitly mark the external functions with
__attribute__ ((visibility ("default")))
Luckily, thanks to jni.h, this attribute is set for all JNIEXPORT
funcitons.
If you use prebuilt static libraries, you may need also
APP_LDFLAGS += -Wl,--exclude-libs,ALL
Consider also providing version script
LOCAL_LDFLAGS += -Wl,-version-script -Wl,mylib_jni.vs
Upvotes: 11