Ответ 1
С экспериментальным плагином 0.4.0 можно исключить файлы из NDK по шаблону, например.
android.sources {
main {
jni.source {
srcDirs = ["~/srcs/jni"]
exclude "**/win.cpp"
}
}
}
Благодаря Paul Spark!
PS (спасибо rajveer): не пропустите Build/Clean
после изменения exclude
!
Старый ответ
К сожалению, это не поддерживается текущими плагинами gradle. Даже "экспериментальный" плагин позволяет добавлять каталоги. Я рекомендую сохранить традиционный Android.mk, который надежно выполняет эту работу.
Я также рекомендую не устанавливать jni.srcDirs = []
, а сохранять ${jniSrc}
, чтобы Android Studio отображал эти файлы для легкого доступа и подсветки синтаксиса. Если вы установите правильные значения cppFlags
и cFlags
, вы также сможете использовать перекрестные ссылки через заголовки.
Трюк состоит в том, чтобы отключить регулярные задачи сборки NDK и вместо этого ввести задачу buildNative
:
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
}
Подобный подход работает для 'com.android.tools.build:gradle-experimental:0.2.0'
, но сопоставление задач отличается:
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 не создает отладочную установку. В частности, при запуске отладочной конфигурации Android Native, Android Studio жалуется, что не удалось найти папку, содержащую объектные файлы, с символами в приложении модуля.
Я предлагаю следующее обходное решение, которое я тестировал только в сценарии, когда родные источники разделены (по крайней мере) двумя каталогами: файлы, специфичные для Android (я буду называть их мостом JNI), находятся в отдельном каталоге, а отдых в другом месте. Обходной путь предполагает создание статической библиотеки с ndk-build и связывание ее с минимальным набором объектов, которые вытаскивают из этой библиотеки все необходимые символы.
Для простоты предположим, что файлы в Android ( Application.mk, Android.mk и "android-jni.cpp" находятся в каталоге ~/srcs/jni
, в то время как независимые от платформы файлы находятся в ~/srcs
и других подкаталогах.
Вот соответствующий фрагмент 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"]
}
}
}
Файл ~/srcs/Android.mk может выглядеть следующим образом:
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)
Для LOCAL_MODULE
важно Android.mk указать имя, которое вы используете для LOCAL_MODULE
в сборке .gradle.
ОБНОВЛЕНИЕ 2
Возможно, это возможно, благодаря jforce, см. "Связать отдельный исходный исходный файл с проектом Android Studio"!