如何在多项目Android Build中排除重复的C共享库(.so)?

Jac*_*raw 6 c++ android android-ndk android-gradle-plugin

在构建具有两个库模块的父项目时会出现"重复文件"冲突,这两个库模块使用相同的libc++_shared.so共享库.

(注意:请不要认为这是一个"重复的问题".我已经阅读了几篇相关的帖子,这些帖子帮助我做到了这一点.但是,没有帖子提供了一个在我的案例中涉及NDK工件的答案.)

当我只有一个这样的库模块时,构建工作正常.添加第二个库模块现在正在产生冲突.

考虑以下项目结构:1个父项目,2个"子"项目 - 但每个项目位于相同的目录级别(即不按层次结构嵌套)

ProjectA/   (Parent)
    LibraryModuleA1/
        build/exploded-aar/com.package.name/
            LibraryModuleB1/<version>/jni/armeabi-v7a/libc++_shared.so
            LibraryModuleC1/<version>/jni/armeabi-v7a/libc++_shared.so
        build.gradle    (bgA1)
    Test_APK_Module A1T/
        build.gradle    (bgA1T)
    build.gradle    (bgPA)

ProjectB/
    LibraryModuleB1/  (Uses NDK)
        build/lib/armeabi-v7a/libc++_shared.so
        build.gradle    (bgB1)
    build.gradle    (bgPB)

ProjectC/
    LibraryModuleC1/  (Uses NDK)
        build/lib/armeabi-v7a/libc++_shared.so
        build.gradle    (bgC1)
    build.gradle    (bgPC)
Run Code Online (Sandbox Code Playgroud)

库模块A1依赖于库模块B1和C1.
A1 - > B1
A1 - > C1

项目B和C都具有基于NDK的代码并正确构建/测试.两者都依赖于libc++_shared.so共享库.

但是,在构建项目A时,我在:LibraryModuleA1:packageDebugTest任务期间收到以下错误:

Error: duplicate files during packaging of APK   /ProjectA/LibraryModuleA1/build/apk/LibraryModuleA1-debug-test-unaligned.apk
    Path in archive: lib/armeabi-v7a/libc++_shared.so
    Origin 1:  /ProjectA/LibraryModuleA1/build/exploded-aar/com.package.name/LibraryModuleB1/<version>/jni/armeabi-v7a/libc++_shared.so
    Origin 2:  /ProjectA/LibraryModuleA1/build/exploded-aar/com.package.name/LibraryModuleC1/<version>/jni/armeabi-v7a/libc++_shared.so
You can ignore those files in your build.gradle:
    android {
      packagingOptions {
        exclude 'lib/armeabi-v7a/libc++_shared.so'
      }
    }

* What went wrong:
Execution failed for task ':LibraryModuleA1:packageDebugTest'.
> Duplicate files copied in APK lib/armeabi-v7a/libc++_shared.so
    File 1: /ProjectA/LibraryModuleA1/build/exploded-aar/com.package.name/LibraryModuleC1/<version>/jni/armeabi-v7a/libc++_shared.so
    File 2: /ProjectA/LibraryModuleA1/build/exploded-aar/com.package.name/LibraryModuleC1/<version>/jni/armeabi-v7a/libc++_shared.so

:LibraryModuleA1:packageDebugTest FAILED
Run Code Online (Sandbox Code Playgroud)

我到目前为止所做的一切

  1. 我试图将建议的闭包添加到我的build.gradle文件中,但是build.gradle我将它添加到哪个文件中?我已将闭包添加到bgA1,bgB1bgC1(一次一个),但没有成功.
  2. 建议的关闭说要使用exclude 'lib/armeabi-v7a/libc++_shared.so'.每个"子"库模块都libc++_shared.sobuild/lib路径下构建文件.但是,我注意到父库模块将libc++_shared.so文件复制jni/armeabi-v7a/libc++_shared.sobuild/exploded-aar目录结构中.(见上文)封闭是否应该读取exclude 'jni/armeabi-v7a/libc++_shared.so (即 jnilib)?
  3. 由于我使用的是Gradle插件0.9.1,我尝试使用pickFirst代替exclude,但这也没有成功.

有人可以帮助确定我应该如何配置我的给定案例的`packagingOptions'闭包?

谢谢您的帮助!

Jul*_*ien 2

我遇到了同样的问题,但排除或 pickFirst 没有运气。所以我使用了一个有点丑陋的解决方法。这个想法是在主项目的构建目录中创建一个“native-libs”文件夹,从那里复制 ndk 库项目中所有必需的 *.so 文件,然后告诉构建系统将这些库打包到 apk 中。

在我的主项目(应用程序项目)中,我明确定义了包含我所依赖的 ndk 代码的模块列表

// Ndk stuff. We have to explicitely manage our NDK dependencies
ext.jniProjects = [project(':ndklib1'), project(':ndklib2'), project(':ndklib3')]
apply from: '../depend_ndk.gradle'
Run Code Online (Sandbox Code Playgroud)

然后,“depend_ndk.gradle”是一个 gradle 外部脚本,其中包含

// Build helper for projects that depends on a native library with a NDK part
// Define the list of ndk library you depend on in project main file :
//   ext.jniProjects = [project(':ndklib1')]
//   apply from : 'depend_ndk.gradle'
buildscript {
    repositories {
        jcenter()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.12.+'
    }
}
import com.android.build.gradle.tasks.PackageApplication

// As a workaround, we create a new 'native-libs' folder in the current project and
// copy all the .so we depend on into it
def ndkLibsDir = new File(buildDir, 'native-libs')
ndkLibsDir.mkdir()

task copyDependingNativeLibs(type: Copy) {
    // Doc for copy http://www.gradle.org/docs/current/dsl/org.gradle.api.tasks.Copy.html
    println 'jniProjects ' + jniProjects
    jniProjects.each {
        from(new File(it.buildDir, 'native-libs')) {
            include '**/*.so'
        }
    }
    into ndkLibsDir
}

tasks.withType(PackageApplication) { pkgTask ->
    pkgTask.jniFolders = new HashSet<File>()
    pkgTask.jniFolders.add(ndkLibsDir)
    pkgTask.dependsOn copyDependingNativeLibs
}
Run Code Online (Sandbox Code Playgroud)