define LOCAL_SRC_FILES in ndk{} DSL
With experimental plugin 0.4.0, it is possible to exclude files from NDK build by pattern, e.g.
android.sources {
main {
jni.source {
srcDirs = ["~/srcs/jni"]
exclude "**/win.cpp"
}
}
}
Thanks to Paul Spark!
P.S. (thanks to rajveer): don't miss Build/Clean
after you change exclude
!
Old answer
Unfortunately this is not supported by current gradle plugins. Even the "experimental" plugin only allows to add directories. I recommend to keep the traditional Android.mk which does this job reliably.
I also recommend not to set jni.srcDirs = []
, but rather keep ${jniSrc}
to let Android Studio display these files for easy access and syntax highlight. If you set cppFlags
and cFlags
correctly, you will have full power of cross referencing through headers, too.
The trick is to disable the regular NDK build tasks, and inject a buildNative
task instead:
def ndkBuild = android.ndkDirectory
import org.apache.tools.ant.taskdefs.condition.Os
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
ndkBuild += '.cmd'
}
task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
commandLine '$ndkBuild', 'NDK_PROJECT_PATH="$jniSrc/..'
}
task cleanNative(type: Exec, description: 'Clean JNI object files') {
commandLine '$ndkBuild', 'clean', 'NDK_PROJECT_PATH="$jniSrc/..'
}
clean.dependsOn 'cleanNative'
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn buildNative
}
tasks.all {
task -> if (task.name.contains('compileDebugNdk') || task.name.contains('compileReleaseNdk')) task.enabled = false
}
Similar approach work for 'com.android.tools.build:gradle-experimental:0.2.0'
, but task matching is different:
tasks.all {
task ->
if (task.name.startsWith('compile') && task.name.contains('MainC')) {
task.enabled = false
}
if (task.name.startsWith('link')) {
task.enabled = false
}
if (task.name.endsWith("SharedLibrary") ) {
task.dependsOn buildNative
}
}
UPDATE
buildNative does not produce a debuggable setup. Specifically, when running Android Native debug configuration, Android Studio complains that it Could not locate folder containing object files with symbols within module app.
I suggest the following workaround, which I only tested in scenario when the native sources are split in (at least) two directories: the Android-specific files (I will call them JNI bridge) are in a separate directory, and the rest are elsewhere. The workaround involves building a static library with ndk-build and linking it with the minimal set of objects that will pull all necessary symbols from that library.
For simplicity, let us assume that the Android-specific files (Application.mk, Android.mk, and "android-jni.cpp" are in the directory ~/srcs/jni
, while the platform-independent files are in ~/srcs
and its other subdirectories.
Here is the relevant fragment of build.gradle:
def LOCAL_MODULE = "staticLib"
def appAbi = "armeabi-v7a"
def ndkOut = "build/intermediates/$LOCAL_MODULE"
def staticLibPath = "$ndkOut/local/$appAbi/lib${LOCAL_MODULE}.a"
task buildStaticLib(type: Exec, description: 'Compile Static lib via NDK') {
commandLine "$ndkBuild", "$staticLibPath", "NDK_PROJECT_PATH=~/srcs", "NDK_OUT=$ndkOut", "APP_ABI=$appAbi", "APP_STL=gnustl_static"
}
tasks.all {
task ->
if (task.name.startsWith('link')) {
task.dependsOn buildStaticLib
}
}
model {
android.ndk {
moduleName = "hello-jni"
abiFilters += "$appAbi".toString()
ldFlags += "$staticLib".toString()
ldLibs += "log"
cppFlags += "-std=c++11"
}
android.sources {
main.jni.source {
srcDirs = ["~/srcs/jni"]
}
}
}
The ~/srcs/Android.mk file may look like this:
LOCAL_PATH := $(call my-dir)/..
include $(CLEAR_VARS)
LOCAL_MODULE := staticLib
LOCAL_SRC_FILES := HelloJni.cpp
LOCAL_CPPFLAGS += -std=c++11
include $(BUILD_STATIC_LIBRARY)
It is important for LOCAL_MODULE
in Android.mk to fit the name you use for LOCAL_MODULE
in build.gradle.
UPDATE 2
It may still be possible, thanks to jforce, see "Link individual native source file to Android Studio project"!
define LOCAL_C_INCLUDES in gradle ndk{} DSL?
you can use CFlags and cppFlags for that:
CFLags.add '-Ipath/to/include'
and so on.
Android Studio NDK: Compile with ndk-build and get native support with Gradle Experimental
You can set up the experimental plugin to run your buildNative task instead of the built-in compile and link tasks:
tasks.all {
task ->
if (task.name.startsWith('compile') && task.name.contains('MainC')) {
task.enabled = false
}
if (task.name.startsWith('link')) {
task.enabled = false
}
if (task.name.endsWith('SharedLibrary') ) {
task.dependsOn buildNative
}
}
Related Topics
How to Completely Rename an Android Application
How to Make Push Notification With Specific Sound
Convert File: Uri to File in Android
Link Should Be Open in Same Web View in Android
Remove Items from Listview With a Custom Adapter
Onclick() to Change Button Border Color Rather Changing Button Color
Remove Span Tag With Text from String
Android Studio - Failed to Apply Plugin [Id 'Com.Android.Application']
How to Set Transparency of a Background Image Android Xml File
How to Set the Height of an Item Row in Gridlayoutmanager
Android: Textview: Remove Spacing and Padding on Top and Bottom
Pdf Not Open in Webview from Url
Retrofit 2 Json Response Json Array and Object
Remove Old Fragment from Fragment Manager
Removing Backgroundcolor of a View in Android