您无法使用 gradle 构建静态库,即使使用实验性插件也是如此。您可以使用预构建的库,或者使用ndk-build 构建它并使用 gradle 插件将其链接到共享对象。
这是一个例子:
假设我们有这样的目录结构:
- 项目(build.gradle、gradle.properties 等)
- jni_static(Application.mk、Android.mk、静态库的 cpp 文件)
- 应用程序(build.gradle、src/main 等)
以下是 project/app/build.gradle 的相关部分:
// look for NDK directory
import org.apache.tools.ant.taskdefs.condition.Os
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
def ndkBuild = properties.getProperty('ndk.dir') + '/ndk-build'
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
ndkBuild += '.cmd'
}
apply plugin: 'com.android.model.application'
… 依赖关系、模型 { compileOptions 等。
// static lib is built with ndk-build
def LOCAL_MODULE = "static"
def appAbi = "armeabi-v7a"
def ndkOut = "build/intermediates/$LOCAL_MODULE"
def staticLibPath = "$ndkOut/local/$appAbi/lib${LOCAL_MODULE}.a"
// To guarantee that the intermediates shared library is always refreshed,
// we delete it in gradle task rmSO.
task rmSO(type: Delete) {
delete 'build/intermediates/binaries/debug/lib/armeabi-v7a', 'libshared.so'
delete 'build/intermediates/binaries/debug/obj/armeabi-v7a', 'libshared.so'
}
// in file jni/Android.mk there is a section for LOCAL_MODULE=static
// which builds the static library
task buildStaticLib(type: Exec, description: 'Compile Static lib via NDK') {
commandLine "$ndkBuild", "$staticLibPath", "NDK_APPLICATION_MK=../jni_static/Application.mk",
"NDK_PROJECT_PATH=../jni_static", "NDK_OUT=$ndkOut"
dependsOn rmSO
}
task cleanNative(type: Exec, description: 'Clean JNI object files') {
commandLine "$ndkBuild", "clean", "NDK_APPLICATION_MK=../jni_static/Application.mk",
"NDK_PROJECT_PATH=../jni_static", "NDK_OUT=$ndkOut"
}
clean.dependsOn cleanNative
tasks.all {
task ->
// link of the shared library depends on build of the static lib
if (task.name.startsWith('link')) {
task.dependsOn buildStaticLib
}
// before build, make sure the intermediate so is not stuck there
if (task.name.startsWith('package')) {
task.dependsOn rmSO
}
}
// build the wrapper shared lib around the static lib using the experimental plugin
model {
android.ndk {
moduleName = "shared"
cppFlags += "-std=c++11"
ldFlags += "$staticLibPath".toString()
ldLibs += "log"
stl = "gnustl_static"
abiFilters += "$appAbi".toString()
}
android.sources {
main.jni.source {
srcDirs = ["jni_shared"]
}
}
}
重要:共享库的源代码应该在一个单独的目录中,这样静态库的源代码不在它里面或者下面。这是因为实验插件无法排除srcDirs下的一些文件。