How to eliminate duplication of C shared libraries (.so) in Multi-Project Android Build?

I get a "duplicate file" conflict when creating a parent project with two library modules that use the same shared library libc++_shared.so .

( NOTE : Please do not consider this a “duplicate question.” I read several related posts that helped me get this far. However, none of the posts gave an answer that works in my case with NDK artifacts.)

The assembly worked correctly when I had only 1 such library module. Adding a second library module now creates a conflict.

Consider the following project structure: one parent project, 2 "child" projects, but each project is at the same directory level (i.e. not hierarchically nested)

 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) 

Library module A1 depends on both library modules B1 and C1.
A1 → B1
A1 → C1

Projects B and C have NDK-based code and build / verify correctly. Both depend on the shared libc++_shared.so .

However, when creating project A, I get the following error during the task :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 

What have i tried so far

  • I tried to add the proposed closure to my build.gradle file, but to which build.gradle file do I add it? I added a bgA1 to bgA1 , bgB1 and bgC1 (one at a time), without any success.
  • The proposed closure uses exclude 'lib/armeabi-v7a/libc++_shared.so' . Each "child" library module creates a libc++_shared.so along the build/lib path. However, I noticed that the parent library module copies the libc++_shared.so to jni/armeabi-v7a/libc++_shared.so inside the build/exploded-aar directory structure. (See above). Should I read exclude 'jni/armeabi-v7a/libc++_shared.so (i.e. jni vs lib ) instead of closing?
  • Since I'm using the Gradle plugin 0.9.1, I tried using pickFirst instead of exclude , but that also failed.

Can someone help determine how I can configure the closure of `packagingOptions' for my current case?

Thank you for your help!

+5
source share
1 answer

I ran into the same problem and had no luck with exclude or pickFirst. So I used a somewhat ugly workaround. The idea is to create a “native-libs” folder in the build directory of the main project, copy all the necessary .so files from the ndk library projects, and then tell the build system to pack these libs into apk.

In my main project (application project), I clearly define a list of modules that contain ndk codes on which I depend

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

And then, 'depend_ndk.gradle' is a gradle external script that contains

 // 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 } 
+1
source

Source: https://habr.com/ru/post/977518/


All Articles