Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NDK Dev in an Android library project with Gradle & Android Studio

I've been trying to hack on a Gradle managed Android project that uses JNI and I'm having a bit of trouble. I understand NDK support is still relatively new and mostly undocumented, but I have managed to find the basic elements for shoe-horning it into a Gradle build. Apparently the trick is to include all of your native code under src/main/jni and drop the following in one of your configs (e.g. in the defaultConfig block):

ndk {
    moduleName "mylib"
}

The problem is that when I try to build my project, the ndk plugin generates an Android.mk file which includes absolute paths to the native source. This causes make to choke as it STILL considers the paths to be relative. In my case I have a simple library project with 1 cpp source/header combo under src/main/jni and I use this gradle.build:

apply plugin: 'android-library'

android {
    compileSdkVersion 19
    buildToolsVersion "19.0.3"

    defaultConfig {
        minSdkVersion 9
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
        ndk {
            moduleName "mylib"
        }
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:19.+'
}

Running the build generates this Android.mk under build/ndk/debug:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := mylib
LOCAL_SRC_FILES := \
    /Users/clifton/dev/Multi/MultiAndroid/lib/src/main/jni/Android.mk \
    /Users/clifton/dev/Multi/MultiAndroid/lib/src/main/jni/myNativeSectionTextProvider.cpp \

LOCAL_C_INCLUDES += /Users/clifton/dev/Multi/MultiAndroid/lib/src/main/jni
LOCAL_C_INCLUDES += /Users/clifton/dev/Multi/MultiAndroid/lib/src/debug/jni

include $(BUILD_SHARED_LIBRARY)

…which, when run generates this error:

make: *** No rule to make target `/Users/clifton/dev/Multi/MultiAndroid/lib/build/ndk/debug//Users/clifton/dev/Multi/MultiAndroid/lib/src/main/jni/myNativeSectionTextProvider.cpp', needed by `/Users/clifton/dev/Multi/MultiAndroid/lib/build/ndk/debug/obj/local/armeabi-v7a/objs/mylib//Users/clifton/dev/Multi/MultiAndroid/lib/src/main/jni/myNativeSectionTextProvider.o'.  Stop.

…because the absolute paths are converted mistakenly to relative. If I manually edit the file and change the paths to relative like so:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := mylib
LOCAL_SRC_FILES := \
    ../../../src/main/jni/Android.mk \
    ../../../src/main/jni/myNativeSectionTextProvider.cpp \

LOCAL_C_INCLUDES += ../../../src/main/jni
LOCAL_C_INCLUDES += ../../../src/debug/jni

include $(BUILD_SHARED_LIBRARY)

...I then get this error:

/Users/clifton/dev/Multi/MultiAndroid/lib/build/ndk/debug/../../../src/main/jni/com_craig_multiandroid_app_NativeSectionTextProvider.h:2:17: fatal error: jni.h: No such file or directory

My question is what can I do to fix this? I started to hack my own custom gradle support for .aar builds but got lost trying to figure out which Gradle task is responsible for generating the .aar file. (The Gradle docs, while plentiful, make it difficult to find the details on a specific Android Gradle task API.) I have a partially working gradle.build which will run ndk-build via cmd line, generate the .so but I can't figure out how to (or even if I should) inline the .so inside the .aar. I am using Android Studio 0.5.7 and Gradle 1.11. I've pulled Gradle source a few months ago which is how I figured out how to inline the .so and gdbserver files in a regular .apk project but those rules don't seem to apply to .aar projects. Has anyone else attempted this? Where can I go for answers?

like image 757
Cliff Avatar asked Apr 28 '14 15:04

Cliff


People also ask

Where do I put Android NDK?

Select the NDK (Side by side) checkbox and the checkboxes below it that correspond to the NDK versions you want to install. Android Studio installs all versions of the NDK in the android-sdk /ndk/ directory.

What can I do with Android NDK?

The Native Development Kit (NDK) is a set of tools that allows you to use C and C++ code with Android, and provides platform libraries you can use to manage native activities and access physical device components, such as sensors and touch input.

How do I know if NDK is installed?

Open your Android Studio Preference (or "File->Settings") > Appearance & Behavior > System Settings > Android SDK. You can find the path to your SDK and NDK, which is in the same directory.


1 Answers

I figured it out finally! You have to use the latest NDK for the newer Gradle NDK support. My local.properties (and my ~/.bashrc) was pointing to android-ndk-r8e to work around broken gdb-server support in android-ndk-r9d however when I updated to android-ndk-r9d my gradle build began to work without the extra hacks. So in summary, the above example DOES work so long as your local.properties points to version 9b+ of the NDK.

like image 60
Cliff Avatar answered Oct 01 '22 04:10

Cliff