I am using Gradle 3.0.1 in Android studio (3) trying to compile FFMPEG and armeabi-v7a has two shared libraries one with neon and one without. Typically in the old days before gradle, ndkbuild would compile my project without any issues, now with gradle and new ndkbuild, a bunch of issues showed up. The below isn't exactly how my code is but you can checkout my code in https://github.com/matthewn4444/VPlayer_lib. I have 3 questions about building in gradle with ndk.
I prebuilt 2 versions of libffmpeg.so, one for armeabi-v7a in neon and other without. I have a module for application-neon and application in the Android.mk file. I am not sure if there is a way to have just 1 .so file but since FFMPEG is complex I didn't want to wrap neon calls just to create one shared library.
My first question is, is it possible to just have 1 shared library in ndk to import into java with neon and non-neon support that links to larger 3rd party libraries or is having 2 separate libraries easier?
If I try to compile other architectures like arm64-v8a I will get an error:
* What went wrong:
Execution failed for task ':VPlayer_library:externalNativeBuildDebug'.
> Unexpected native build target application-neon. Valid values are: <projects>
This is because in my Android.mk file I have a module for non-neon and one for neon mainly for armeabi-v7a. I get the error above because the neon module is only available for armeabi-v7a, arm 64 will not have one so that error pops up on compile. If i create a dummy neon build it will allow the project to compile but then it bundles that fake neon shared library into the apk. I was thinking of building it like this and then having all dummy shared libraries removed from arm64, x86 etc from the build section before merging the shared libraries into the apk.
My second question is, is there a way to bypass this error or have special targets for specific architectures when building (abiFilters) without all this hacking? Code is below.
Android.mk
... <the module for normal application project>
ifdef FEATURE_NEON
include $(CLEAR_VARS)
LOCAL_ALLOW_UNDEFINED_SYMBOLS=false
LOCAL_MODULE := application-neon
LOCAL_SRC_FILES := application.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/$(TARGET_ARCH_ABI)/include \
$(LOCAL_PATH)/application
LOCAL_SHARED_LIBRARY := application-neon
LOCAL_LDLIBS += -landroid
LOCAL_LDLIBS += -llog -ljnigraphics -lz -lm -g $(LOCAL_PATH)/ffmpeg-build/$(TARGET_ARCH_ABI)/libffmpeg-neon.so
include $(BUILD_SHARED_LIBRARY)
else
# This is the dummy app to get the project to compile.
include $(CLEAR_VARS)
LOCAL_MODULE := application-neon
LOCAL_ALLOW_UNDEFINED_SYMBOLS=false
include $(BUILD_SHARED_LIBRARY)
endif
-------------------------------------------------------
build.gradle
externalNativeBuild {
ndkBuild {
targets "application", "cpufeatures", "application-neon" // fails for 'arm64-v8a' without that dummy module
}
}
Next, when I change the abiFilters, it will include all the architectures that I built before besides the ones I selected. For example, if I built
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
then....
ndk {
abiFilters 'arm64-v8a'
}
and made an apk and then decided to only build arm64-v8a and built an apk, all the armeabi-v7a shared libraries are also in the apk. Android studio does not delete the other architectures compiled data from the build folder but bundles them into the apk as well. So for now I have a gradle task to remove them from build folder (the code is at the end).
My third question is if I did something wrong or if there is something easier I can do that does not require the gradle code below?
def deleteOtherArchFromFolder(config, path) {
new File(path).listFiles().each { folder ->
if (!config.ndk.abiFilters.contains(folder.name)) {
delete {
delete folder
}
}
}
}
task prebuildTask() {
doLast {
def config = android.defaultConfig
// delete the obj files in build directory
deleteOtherArchFromFolder(config, project.buildDir.absolutePath + '/intermediates/ndkBuild/debug/obj/local')
}
}
preBuild.dependsOn(prebuildTask)
Thanks in advance!