Reputation: 377
I pretty much read through almost every question in stackoverflow about the subject. I browsed documentation and work-notes of other people who are using AS + NDK + gradle to build an aar that would be included by other app.
I was able to build the .so in a different multi-project setup where the structure was different from the one shown in one aspect: it didn't have the first jni/ layer.
I added that extra jni layer so that I'd have a sharedObjectLib#2/ hierarchy. In that jni/ dir, all i have is a single Android.mk whose sole purpose is to include $(call all-subdir-makefiles). After I did that, gradle build reports the NDK failure:
"Error:(89) Android NDK: WARNING: There are no modules to build in this project!"
What I can't seem to be able to do is build multiple shared objects '.so' as part of the aar.
I would really like to know if (a) it is doable; and (b) some pointers to links and/or examples of gradle.build files that actually do that.
Here is the structure I currently have - skipping the usual directories created by Android Studio (v. 1.2.2, btw).
--rootProject/
--build.gradle
--gradle.properties
--local.properties
--settings.gradle
--rootProject.iml
--app/
--moduleProjectThatBuildsAAR/
--build.gradle
--build/
--libs
--src/
--main/
--res/
--AndroidManifest.xml
--jni/
--Android.mk (does include $(call all-subdir-makefiles))
--Application.mk
--sharedObjectLib#1/
--build.gradle
--src/
-- androidTest/
-- main/
--java/
--jni/
-- Android.mk
-- Application.mk
-- *.c and *.h files
--libs/
--obj/
-- build.gradle
It's pretty convoluted and I am hoping the experts would help with simplification.
thanks!
Upvotes: 1
Views: 1684
Reputation: 381
I am using 1.2.2 and found it easy to build the simple NDK projects from the many tutorials floating around, but frustratingly difficult to build an NDK project of any complexity. I will summarize what I found, but I highly suggest reading this blog and this StackOverflow.
I found that Android Studio would completely ignore the
Android.mk file I created, and instead auto-generate its own.
To correct this, I had to first hack the build.gradle
script for my project, located at project/app/build.gradle
.
You could probably hack the top-level build.gradle, if desired.
This may be what is happening in your case. The auto-generated Android.mk looks in jni/ for .c source files and finds nothing there.
This is my build.gradle. I build on a Windows box, so I hacked it for Windows only. Uncomment the lines if you are using OSX or Linux.
project/app/build.gradle:
//import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "com.sample.app"
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
//ENABLE CUSTOM ANDROID.MK >>
sourceSets.main.jni.srcDirs= [] //Disable automatic ndk-build.
sourceSets.main.jniLibs.srcDir 'src/main/libs'
//Call regular ndk-build script from app directory
task ndkBuild(type: Exec) {
workingDir file('src/main')
commandLine getNdkBuildCmd()
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn { ndkBuild }
}
task cleanNative(type: Exec) {
workingDir file('src/main')
commandLine getNdkBuildCmd(), 'clean'
}
clean.dependsOn cleanNative
}
//ENABLE CUSTOM ANDROID.MK <<
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.0'
compile 'com.google.android.gms:play-services:7.5.0'
}
//ENABLE CUSTOM ANDROID.MK >>
def getNdkDir() {
if (System.env.ANDROID_NDK_ROOT != null)
return System.env.ANDROID_NDK_ROOT
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
def ndkdir = properties.getProperty('ndk.dir', null)
if (ndkdir == null)
throw new GradleException("NDK location not found. Define location with ndk.dir in the local.properties file")
return (ndkdir)
}
def getNdkBuildCmd() {
def ndkbuild = getNdkDir() + "/ndk-build.cmd"
// def ndkbuild = getNdkDir() + "/ndk-build"
// if (Os.isFamily(Os.FAMILY_WINDOWS))
// ndkbuild += ".cmd"
return ndkbuild
}
//ENABLE CUSTOM ANDROID.MK <<
Upvotes: 2