Как исключить дубликаты общих библиотек C (.so) в мультипроектной сборке Android?

Я получаю конфликт «дубликаты файлов» при создании родительского проекта с двумя библиотечными модулями, которые используют один и тот же libc++_shared.so общая библиотека

(НОТАПожалуйста, не считайте это «дублирующим вопросом». Я прочитал несколько связанных постов, которые помогли мне зайти так далеко. Тем не менее, ни один пост не дал ответ, который работает в моем случае с участием Артефакты ндк.)

Сборка работала правильно, когда у меня был только 1 такой библиотечный модуль. Добавление второго библиотечного модуля создает конфликт.

Рассмотрим следующую структуру проекта: 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)

Библиотечный модуль A1 зависит от обоих библиотечных модулей B1. & С1.
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

Что я уже пробовал

  1. Я попытался добавить предложенное закрытие к своему build.gradle файл, но который build.gradle файл, в который я должен добавить это? Я добавил закрытие bgA1, bgB1, а также bgC1 (по одному), но безуспешно.
  2. Предлагаемое закрытие говорит, чтобы использовать exclude 'lib/armeabi-v7a/libc++_shared.so', Каждый «дочерний» библиотечный модуль создает libc++_shared.so файл под build/lib дорожка. Однако я заметил, что модуль родительской библиотеки копирует libc++_shared.so файл под jni/armeabi-v7a/libc++_shared.so внутри build/exploded-aar структура каталогов. (См. Выше). Вместо закрытия следует читать exclude 'jni/armeabi-v7a/libc++_shared.so (Т.е. jni против lib)?
  3. Так как я использую плагин Gradle 0.9.1, я попытался использовать pickFirst на месте exclude, но это тоже не увенчалось успехом.

Может кто-нибудь помочь определить, как мне настроить закрытие packageOptions для моего конкретного случая?

Спасибо за помощь!

6

Решение

Я столкнулся с той же проблемой, и мне не повезло с exclude или pickFirst. Поэтому я использовал несколько уродливый обходной путь. Идея состоит в том, чтобы создать папку «native-libs» в каталоге сборки основного проекта, скопировать туда все необходимые файлы * .so из проектов библиотеки ndk, а затем указать системе сборки упаковать эти библиотеки в 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'

И затем, ‘depen_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
}
1

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