更新:自从我发布了这个答案后,我找到了一个更清洁的解决方案。无需修改Android.mk 文件中的任何内容。以下是app/build.gradle的相关部分(原gradle脚本属于syncopoli project。你可以找到这个build.gradle脚本here的原始最新版本:
android {
defaultConfig {
// ...
externalNativeBuild {
ndkBuild {
// I only want the following targets to be built
targets 'rsync', 'ssh'
}
}
ndk {
// add whatever ABIs you want here
abiFilters 'armeabi'
}
}
externalNativeBuild {
ndkBuild {
// all my external sources are under src/main/jni
path 'src/main/jni/Android.mk'
}
}
}
// this is the meat. It copies the binaries to appropriate location
// after externalNativeBuildRelease task is finished.
// you can change the paths to match where your binaries live and where
// you want them to go
gradle.taskGraph.afterTask { task ->
if (task.name == "externalNativeBuildRelease") {
def src = rootProject.file('app/build/intermediates/ndkBuild/release/obj/local/')
def dst = rootProject.file('app/src/main/assets/')
copy {
from(src) {
// the objs directory has all the .o files I don't care about
exclude "**/objs"
}
into dst
// this is purely for debugging purposes. it might come in handy
eachFile {
println "file = " + it.getPath()
}
}
}
}
我的src/main/jni/Android.mk有以下内容:
include $(call all-subdir-makefiles)
以前的答案
我遇到了这个问题并通过在 gradle 中创建额外的任务来手动调用 ndk-build 并将项目设置为依赖这些任务来解决它。
这是app/build.gradle的相关部分:
import org.apache.tools.ant.taskdefs.condition.Os
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
task ndkBuild(type: Exec) {
def ndkDirProperty = properties.getProperty('ndk.dir')
def ndkDirPrefix = ndkDirProperty != null ? ndkDirProperty + '/' : ''
def ndkBuildExt = Os.isFamily(Os.FAMILY_WINDOWS) ? ".cmd" : ""
commandLine "${ndkDirPrefix}ndk-build${ndkBuildExt}", '-C', file('src/main').absolutePath,
'-j', Runtime.runtime.availableProcessors()
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
// Cleanup task to remove previously generated binaries
task ndkClean(type: Exec) {
def ndkDirProperty = properties.getProperty('ndk.dir')
def ndkDirPrefix = ndkDirProperty != null ? ndkDirProperty + '/' : ''
def ndkBuildExt = Os.isFamily(Os.FAMILY_WINDOWS) ? ".cmd" : ""
commandLine "${ndkDirPrefix}ndk-build${ndkBuildExt}", '-C', file('src/main').absolutePath, 'clean'
}
tasks.withType(Delete) {
cleanTask -> cleanTask.dependsOn ndkClean
}
我还进一步修改了可执行文件的Android.mk 文件,因此最终的可执行文件最终位于assets/<target_arch_abi>/<executable。
SAVED_NDK_APP_DST_DIR := $(NDK_APP_DST_DIR)
NDK_APP_DST_DIR := assets/$(TARGET_ARCH_ABI)
...LOCAL_MODULE/LOCAL_CFLAGS/LOCAL_etc...
include $(BUILD_EXECUTABLE)
NDK_APP_DST_DIR := $(SAVED_NDK_APP_DST_DIR)
现在,运行 gradlew build 会与其余部分一起构建可执行文件。
希望这会有所帮助。