2014-06-19 11 views
5

Występuje konflikt "duplikatów plików" podczas budowania projektu nadrzędnego z dwoma modułami bibliotecznymi, które korzystają z tej samej biblioteki współużytkowanej libc++_shared.so.Jak wykluczyć duplikaty współdzielonych bibliotek C (.so) w wielozadaniowym systemie Android?

(UWAGA. Nie uważam tego za „duplikat pytanie” Znam kilka podobnych stanowisk, które pomogły mi zajść tak daleko, jednak żadnych postów dostarczyły odpowiedzi, który działa w moim przypadku z udziałem . Artefakty NDK:.)

Kompilacja działała poprawnie, gdy miałem tylko 1 taki moduł biblioteczny. Dodanie drugiego modułu bibliotecznego powoduje teraz konflikt.

Rozważmy następującą strukturę projektu: 1 projekt rodzic, 2 projekty „dziecko” - ale każdy projekt znajduje się na poziomie samego katalogu (czyli nie zagnieżdżane hierarchicznie)

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) 

Biblioteka Moduł A1 zależy zarówno Bibliotece Moduły B1 & C1.
A1 -> B1
A1 -> C1

Projekty B i C mają zarówno kodu opartego NDK i budować/test prawidłowo. Obie są zależne od udostępnionej biblioteki libc++_shared.so.

Jednak podczas budowy project, pojawia się następujący błąd podczas zadania :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 

Co ja próbowałem dotąd

  1. próbowałem dodać sugerowana zamknięcie pliku build.gradle, ale który plik build.gradle należy dodać do? Dodałem zamknięcie do bgA1, bgB1 i bgC1 (po jednym na raz), bez powodzenia.
  2. Sugerowane zamknięcie mówi o użyciu exclude 'lib/armeabi-v7a/libc++_shared.so'. Każdy moduł biblioteki "child" buduje plik libc++_shared.so pod ścieżką libc++_shared.so. Jednak zauważyłem, że moduł biblioteki nadrzędnej kopiuje plik libc++_shared.so pod jni/armeabi-v7a/libc++_shared.so wewnątrz struktury katalogów build/exploded-aar. (Patrz wyżej) Czy zamiast tego zamiast zamknięcia należy przeczytać: exclude 'jni/armeabi-v7a/libc++_shared.so (tj. jni vs. lib)?
  3. Ponieważ używam wtyczki Gradle 0.9.1, spróbowałem użyć pickFirst zamiast exclude, ale to też się nie udało.

Czy ktoś może pomóc w określeniu sposobu konfiguracji zamknięcia `packagingOptions 'dla mojego konkretnego przypadku?

Dziękuję za pomoc!

Odpowiedz

1

Wpadłem na ten sam problem i nie miałem szczęścia z wykluczeniem lub pickFirst. Więc użyłem nieco brzydkiego rozwiązania. Chodzi o to, aby utworzyć folder "native-libs" w katalogu kompilacji głównego projektu, skopiować wszystkie wymagane pliki * .so z projektów biblioteki ndk, a następnie powiedzieć systemowi kompilacji, aby spakował te biblioteki w apk.

W moim głównym projektu (projekt APP), I jawnie zdefiniować listę modułów, które zawierają kody NDK na której polegam

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

A potem, „depend_ndk.gradle” jest skrypt zewnętrzna że Gradle zawiera

// 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 
} 
+0

W jaki sposób uruchamiana jest aplikacja PackageApplication? w aplikacji - nie widzę tego na kompilacjach debugowania ... więc moje pliki APK do debugowania są w tym ... Dzięki. –

+0

Masz rację, mam problemy z pobieraniem funkcji copyDependingNativeLibs automatycznie. Myślę, że dodanie go jako zależności dla pkgTask nie jest właściwym rozwiązaniem. Nie miałem czasu na znalezienie rozwiązania, więc na razie uruchamiam aplikację "./gradlew app: copyDependingNativeLibs", kiedy zmieniam część natywną. – Julien