Android — определить LOCAL_SRC_FILES в ndk {} DSL

Я хотел бы знать, возможно ли определить LOCAL_SRC_FILES в блоке gradle.build ndk {}.

Я в настоящее время использую:

dependencies {
classpath 'com.android.tools.build:gradle:1.3.0'
}

в моем файле gradle.build верхнего уровня.

Мой файл jni модуля gradle.build выглядит так:

apply plugin: 'com.android.library'

dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
}

android {
compileSdkVersion 11
buildToolsVersion "22.0.1"
def jniSrc = System.getProperty("user.home") + "/srcs/jni"
defaultConfig {
ndk {
moduleName "core"stl "gnustl_shared"cFlags "-std=c++11"}
}

sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
jni.srcDirs = ["${jniSrc}"]
}
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
jniDebuggable true
}
}

productFlavors {
x86 {
ndk {
abiFilter "x86"}
}
arm {
ndk {
abiFilter "armeabi-v7a"}
}
mips {
ndk {
abiFilter "mips"}
}
}
}

Причина, по которой я спрашиваю, состоит в том, что в моих источниках jni есть код, предназначенный для разных платформ, не только для Android, но также для iOS и WinRT.

Я немного неохотно перехожу на экспериментальный com.android.tools.build:gradle-experimental:0.2.0, но если вышеупомянутый модуль решает проблему, я могу попробовать.

Я также не хотел бы использовать:

jni.srcDirs = []

и переопределить создание Android.mk и, таким образом, использовать свой собственный, учитывая, что я не уверен, смогу ли я впоследствии отладить C ++ непосредственно из Android Studio (хотя я могу ошибаться, хотя я определенно не являюсь опытным пользователем Android Studios плагин ndk).

Спасибо заранее,

Manos

6

Решение

С экспериментальным плагином 0.4.0 возможно исключить файлы из сборки NDK по шаблону, например

android.sources {
main {
jni.source {
srcDirs = ["~/srcs/jni"]
exclude "**/win.cpp"}
}
}

Благодаря Пол Спарк!

Постскриптум (благодаря rajveer): не пропустите Build/Clean после того, как вы измените exclude!

Старый ответ

К сожалению, это не поддерживается текущими подключаемыми модулями. Даже «Экспериментальный» плагин позволяет только добавлять каталоги. Я рекомендую сохранить традиционный 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
}
}

ОБНОВИТЬ

buildNative не производит отладочную настройку. Именно при запуске Android Native отладочная конфигурация, Android Studio жалуется, что она Не удалось найти папку, содержащую объектные файлы с символами в модуле приложения.

Я предлагаю следующий обходной путь, который я тестировал только в сценарии, когда нативные источники разделены (по крайней мере) на два каталога: специфичные для Android файлы (я буду называть их Мост JNI) находятся в отдельном каталоге, а остальные в другом месте. Обходной путь включает создание статической библиотеки с NDK-сборки и связать его с минимальным набором объектов, которые будут извлекать все необходимые символы из этой библиотеки.

Для простоты предположим, что файлы для 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 в build.gradle.

ОБНОВЛЕНИЕ 2

Это все еще возможно, благодаря jforce, увидеть «Свяжите отдельный исходный файл с проектом Android Studio«!

11

Другие решения