I want to use android studio integration with ndkbuild.
My "native" part of project build only for armeabi-v7a-hard and x86,
and all works fine if I just run ndk-build in jni directory.
I have proper lines in Application.mk:
APP_ABI := armeabi-v7a-hard x86
To integration project into android studio I added such lines into build.gradle:
externalNativeBuild {
ndkBuild {
path 'src/lib/jni/Android.mk'
}
}
But for some reason gradle build try build native code with APP_ABI=armeabi and failed, because of my code can only be build with armeabi-v7a-hard.
So how can I tell gradle to build my code only for armeabi-v7a-hard and x86,
or just not ignore APP_ABI line from Application.mk?
I try such variant:
defaultConfig {
ndk {
abiFilters 'x86', 'armeabi-v7a-hard'
}
}
but gradle failed with such message:
ABIs [armeabi-v7a-hard] are not available for platform and will be
excluded from building and packaging. Available ABIs are [armeabi,
armeabi-v7a, arm64-v8a, x86, x86_64, mips, mips64].
Note, that I use ndk 10, not last one (ndk 13), where there is armeabi-v7a-hard, and ndk.dir in local.properties to right value.
Link provided by #Titan is all you need to set the ABI.
The reason why it might not be working is because armeabi-v7a-hard is deprecated in 2015, so targeting it is resulting in this issue. You should target armeabi-v7a as per this this post
Related
I am working on an android native project which uses C++ code. I am using CMake to build C++ libraries. I am specifying CMake arguments like this in build.gradle:
cmake {
arguments "--warn-uninitialized",
"-DANDROID_TOOLCHAIN=clang",
"-DANDROID_STL=c++_shared",
"-DANDROID_PLATFORM=android-21",
"-DAPP_ALLOW_MISSING_DEPS=true",
"-DSHARED_LIBRARY=1",
"-DOFFLINE_SYNC_SUPPORT_ENABLED=0",
"-DT5_TARGET_PLATFORM=Android",
"-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a",
"-DANDROID_ABI=armeabi-v7a"
What I want gradle is to build libraries only for armeabi-v7a as specified in cmake arguments but gradle by default is building code for all ABIs.
Though abiFilters can be used in gradle but my gradle build is being invoked by command-line where user has to specify ABI in command line and libs only for that ABI should be built. Like ./gradlew v7 should only build armeabi-v7a libs.
Getting an error when trying to fix error -
No toolchains found in the NDK toolchains folder for ABI with prefix mips64el-linux-android
Do not want to upgrade as afraid it might break my application and need to use NDK to work with C++.
After following steps for workaround to fix the error -
Error: No toolchains found in the NDK toolchains folder for ABI with prefix: llvm
New error:
Expected caller to ensure valid ABI: MIPS
Any help on how to fix the issue.
You should specify an ABI filter.
You haven't mentioned how you are building. If you're using Gradle, then you put something like this in the defaultConfig block in your build.gradle:
ndk {
abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
}
If you're invoking ndk-build directly, then you put this on the ndk-build command line:
APP_ABI=armeabi-v7a arm64-v8a x86 x86_64
Or inside your Application.mk:
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
The ABI filter I showed is just an example. It's up to you to decide which ones you want to build for. arm64-v8a and armeabi-v7a are by far the most common ones among Android devices.mips, mips64 and armeabi are no longer supported by the NDK.
From your TOP-LEVEL build.gradle, change your classpath for android gradle plugin to 3.2.1 or higher.
classpath 'com.android.tools.build:gradle:3.2.1'
Or for other options, please check here: Three options for solving this kind of issue
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!
I have removed mips, but am still getting the warning
Error:(81) Android NDK: Application targets deprecated ABI(s): mips64
Error:(82) Android NDK: Support for these ABIs will be removed in a future NDK release.
Error:(82) Android NDK: Support for these ABIs will be removed in a future NDK release.
Error:(81) Android NDK: Application targets deprecated ABI(s): mips
Application.mk
APP_ABI := armeabi-v7a x86
APP_PLATFORM := android-10
UPDATES
build.gradle for ndk
sourceSets.main.jni.srcDirs = []
externalNativeBuild {
ndkBuild {
path 'src/main/jni/Android.mk'
}
}
I fixed the problem by adding:
android {
.
.
versionName "1.0"
ndk {
abiFilters 'x86'
abiFilters 'armeabi-v7a'
moduleName "your-library-name"
}
to the app/build.gradle
It appears that Android Studio was not removing the previous cached NDK builds from the .externalNativeBuild directory from my project. After manually deleting them the process build correctly with no errors.
go to files and click invalidate cache/restart
I have an Android Library project which has a part in C/C++ via Android NDK. I want to build my native code for all architectures. If i set minSdkVersionto 21 it all works fine. but i need to have lower minSdkVersion(SDK 19) if i set minSdkVersion to 19 the ARM64-v8a version is not built. I know that there are no ARM64-v8a devices running SDK 19. How can i achieve to have all platforms built in one APK and have minSdkVersion 19?
Actually, there is typo in "minimumSdkVersion". The right attribute is "minSdkVersion".
However, arm64-v8a library should be successfully built for API 19, because NDK build scripts will automatically take right set of platform headers and libraries.
If you are using Gradle build scripts try to set it as one of target ABIs:
ndk {
abiFilters 'arm64-v8a', 'armeabi-v7a'
}
Then, explicitly set target platform for native build. If you use CMake, then in gradle script set:
externalNativeBuild {
cmake {
arguments '-DANDROID_PLATFORM=android-19'
}
}
If you use ndk-build, then in your Application.mk set:
APP_PLATFORM := android-19
I hope that helps. Please, write details if it will not build.