Reputation: 973
I am working on a new android app using OpenCV (C++ not Java) and I am new to both opencv and the NDK. I have it building (and running) succesfully using the Gradle file below and in Android Studio I can select a variant and hit build (e.g. x86).
I have 2 questions:
Can i achieve a build without specifying all the same libs for each variant. Is there any way I can make the build system just pick up the libraries each time since they are all inside the project and organised by architecture name?
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.0.0"
defaultConfig {
applicationId "uk.co.xxx.androidcppimagereader"
minSdkVersion 17
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
def libsDir = projectDir.path + "/libs/"
productFlavors {
x86 {
versionCode Integer.parseInt("3" + defaultConfig.versionCode)
ndk {
abiFilter "x86"
moduleName "Processing"
stl "gnustl_static"
cFlags "-I/opt/local/include/opencv -I/opt/local/include"
ldLibs libsDir + "x86/libopencv_core.a"
ldLibs libsDir + "x86/libopencv_ts.a"
ldLibs libsDir + "x86/libopencv_contrib.a"
ldLibs libsDir + "x86/libopencv_ml.a"
ldLibs libsDir + "x86/libopencv_java.so"
ldLibs "log"
ldLibs "z", "jnigraphics"
}
}
armv7 {
versionCode Integer.parseInt("2" + defaultConfig.versionCode)
ndk {
abiFilter "armeabi-v7a"
moduleName "Processing"
stl "gnustl_static"
cFlags "-I/opt/local/include/opencv -I/opt/local/include"
ldLibs libsDir + "armeabi-v7a/libopencv_core.a"
ldLibs libsDir + "armeabi-v7a/libopencv_ts.a"
ldLibs libsDir + "armeabi-v7a/libopencv_contrib.a"
ldLibs libsDir + "armeabi-v7a/libopencv_ml.a"
ldLibs libsDir + "armeabi-v7a/libopencv_java.so"
ldLibs "log"
ldLibs "z", "jnigraphics"
}
}
arm {
versionCode Integer.parseInt("1" + defaultConfig.versionCode)
ndk {
abiFilter "armeabi"
moduleName "Processing"
stl "gnustl_static"
cFlags "-I/opt/local/include/opencv -I/opt/local/include"
ldLibs libsDir + "armeabi/libopencv_core.a"
ldLibs libsDir + "armeabi/libopencv_ts.a"
ldLibs libsDir + "armeabi/libopencv_contrib.a"
ldLibs libsDir + "armeabi/libopencv_ml.a"
ldLibs libsDir + "armeabi/libopencv_java.so"
ldLibs "log"
ldLibs "z", "jnigraphics"
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
}
Upvotes: 4
Views: 5289
Reputation: 1031
Use the keyword "fat" after you have defined all architectures that you plan to include in your apk in the build.gradle file as highlighted in the code below . This will build a FAT binary. Watch this video for more details https://www.youtube.com/watch?v=kFtxo7rr2HQ
arm {
versionCode Integer.parseInt("1" + defaultConfig.versionCode)
ndk {
abiFilter "armeabi"
moduleName "Processing"
stl "gnustl_static"
cFlags "-I/opt/local/include/opencv -I/opt/local/include"
ldLibs libsDir + "armeabi/libopencv_core.a"
ldLibs libsDir + "armeabi/libopencv_ts.a"
ldLibs libsDir + "armeabi/libopencv_contrib.a"
ldLibs libsDir + "armeabi/libopencv_ml.a"
ldLibs libsDir + "armeabi/libopencv_java.so"
ldLibs "log"
ldLibs "z", "jnigraphics"
}
fat // <- HERE
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
Upvotes: 3
Reputation: 14463
In order to have your libs correctly linked, you have to declare different ldLibs per architecture as you're currently doing.
Unfortunately this isn't possible to do this from gradle with the current plugin if you're build for all architectures at once.
In my view, the best solution would be to deactivate the built-in (currently deprecated) ndk support and use regular Android.mk / Application.mk files instead. Your build.gradle would look like this:
import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.1"
defaultConfig {
applicationId "uk.co.xxx.androidcppimagereader"
minSdkVersion 17
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
sourceSets.main {
jniLibs.srcDir 'src/main/libs' //set libs as default directory for .so files inclusion, instead of jniLibs
jni.srcDirs = [] //disable automatic ndk-build call
}
// call regular ndk-build(.cmd) script from app directory
task ndkBuild(type: Exec) {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine 'ndk-build.cmd', '-C', file('src/main').absolutePath
} else {
commandLine 'ndk-build', '-C', file('src/main').absolutePath
}
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
}
Upvotes: 1