Android Gradle build with sub projects

Jestem obecnie w trakcie konwersji jednego z naszych projektów do Gradle z maven. Struktura folderów jest następująca:

gitRoot
    settings.gradle
    build.gradle
    ProjectA
        build.gradle
        src/main/java
    Libraries
        SomeLib (git submodule)
        ProjectBRoot (git submodule)
            settings.gradle
            build.gradle
            ProjectB
                build.gradle
                src/main/java
            Libraries
                FacebookSDK/facebook
                    build.gradle
                    src

Więc już to wygląda na skomplikowane. Ale chodzi o to, że ProjectB jest projektem biblioteki i powinien być w stanie być budowany i pakowany oddzielnie, dlatego ma swoje własne ustawienia.gradle i o ile mogę powiedzieć, że wydaje się działać ok, mam go budynku i jego znalezienie facebook w porządku.

The ProjectB / build.gradle zawiera ten linia

compile project(':libraries:facebook-android-sdk:facebook')

The ProjectBRoot / settings.gradle zawiera ten wiersz

include ':ProjectB', ':libraries:facebook-android-sdk:facebook'

GitRoot / settings.gradle zawiera ten wiersz

include ':ProjectA', ':Libraries:ProjectBRoot:ProjectB'

Projekt/budowa.gradle zawiera ten wiersz

compile project(':Libraries:ProjectBRoot:ProjectB')

Kiedy uruchamiam build dostaję ten błąd

The TaskContainer.add() method has been deprecated and is scheduled to be removed in Gradle 2.0. Please use the create() method instead.

FAILURE: Build failed with an exception.

* Where:
Build file '/gitRoot/Libraries/ProjectBRoot/ProjectB/build.gradle' line: 17

* What went wrong:
A problem occurred evaluating project ':Libraries:ProjectBRoot:ProjectB'.
> Project with path ':libraries:facebook-android-sdk:facebook' could not be found in project ':Libraries:ProjectBRoot:ProjectB'.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 4.652 secs

Więc domyślam się, co złego jest to, że facebook nie jest w bezpośrednim podfolderze z ProjectB...ale to nie ma znaczenia podczas budowania w ProjectBRoot. Jest to prawdopodobnie spowodowane twarzą, którą odwołuję się do ProjectB bezpośrednio, a nie za pośrednictwem projektu.budować, ale próbowałem i to również nie działa. Czy ktoś może mi pomóc, przejrzałem dokumentację i nie mówi o wielu projektach, które mają swoje własne ustawienia.gradle files i myślę, że to właśnie mnie wkurza.

Update:

Więc podążałem za odpowiedzią Xav i jestem teraz w stanie budować z wiersza poleceń, jednak nie mogę importować / budować z android studio. Wiem, że problemem jest wciąż z projektem facebook. Błąd, który otrzymuję, polega na tym, że nie można skonfigurować ProjectB.

 Gradle: A problem occurred configuring project ':ProjectA'.
   > Failed to notify project evaluation listener.
     > A problem occurred configuring project ':Libraries:ProjectBRoot:ProjectB'.
       > Failed to notify project evaluation listener.
         > Configuration with name 'default' not found.

Błąd jest spowodowany przez linię

 compile project(':facebook-sdk')

Wewnątrz ProjectB / build.gradle

Author: Stoyan, 2013-06-07

5 answers

Ustawienia.gradle musi zdefiniować wszystkie moduły. Nie ładuje innych ustawień.gradle Znalezione w drzewie, aby załadować więcej modułów.

Będziesz musiał albo

  1. Zdefiniuj moduł dla facebook SDK w Ustawieniach najwyższego poziomu.gradle. Tak, jest zbędny z innymi ustawieniami.gradle.

  2. Opublikować projekt B jakoś (jak również jego zależności, więc w tym przypadku biblioteka SDK facebook), gdzieś (repozytorium artefaktów korporacyjnych na przykład) i uzyskać do niego dostęp z Projekt A.

Chociaż #1 jest lepszy, sprawia, że zależność ProjectB -> Facebook jest trudna, ponieważ ścieżka będzie różna w zależności od ustawień.gradle używany. Jednym ze sposobów na naprawienie tego problemu jest rozdzielenie nazwy/ścieżki modułu od jego faktycznej lokalizacji na dysku. odbywa się to wewnątrz ustawień.plik gradle.

W Ustawieniach najwyższego poziomu.gradle file, do

include 'facebook-sdk'
project(':facebook-sdk').projectDir = new File('Libraries/ProjectBRoot/Libraries/FacebookSDK/facebook')

W ustawieniu.plik gradle wewnątrz projektu B, zrób to samo z inną ścieżką względną:

include 'facebook-sdk'
project(':facebook-sdk').projectDir = new File('Libraries/FacebookSDK/facebook')

To sprawia, że oba ustawienia projektu definiują ten sam moduł "facebook-sdk" znajdujący się w tym samym absolutnym miejscu na dysku.

Wszystkie projekty zależne od tego modułu powinny po prostu zadeklarować zależność jako

compile project(':facebook-sdk') 
 94
Author: Xavier Ducrohet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-07 16:59:20

To nie jest odpowiedź, której szukasz, ale...

Spędziłem około 4 dni próbując przenieść moją złożoną strukturę projektu (podobnie jak twój), do gradle. W końcu porzuciłem całą koncepcję podprojektu (ponieważ w moim przypadku po prostu nie działało) i zdecydowałem się użyć lokalnego podejścia do repozytoriów maven, jak opisano w tym artykule: http://www.flexlabs.org/2013/06/using-local-aar-android-library-packages-in-gradle-builds

Więc w mojej bibliotece projekty, które miały podprojekty, w zasadzie stworzyłem kompletne projekty biblioteczne dla każdego z nich, a następnie użyłem powyższego linku, aby opublikować je w lokalnym repozytorium maven. Następnie w projekcie nadrzędnym usunąłem wszelkie odniesienia do projektów podrzędnych, a w zależności po prostu odwołałem się do opublikowanych bibliotek. A potem w moim głównym projekcie usunąłem wszystkie odniesienia do podprojektów i odwołałem się do opublikowanych lokalnych wersji maven moich bibliotek.

W końcu wszystko działa bardzo dobrze, ale zajęło to trochę czasu, aby wszystko zmienić. Miałem około 6 projektów bibliotecznych z podprojektami, że to podprojekty itp., a teraz wszystko działa dobrze.

Rzeczą, której nie lubię w systemach takich jak Gradle i Maven jest to, że naprawdę oczekują, że zmienisz " jak " ustrukturyzujesz swój kod/projekty. Tak więc, jeśli migrujesz do Gradle zamiast zaczynać od Gradle, proces ten może być dość frustrujący. Jak już to rozgryziesz, następnym razem będzie o wiele łatwiej;)

 5
Author: stuckless,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-07 14:30:24

Po prostu miałbym aplikację z bibliotekami na tym samym poziomie. Nadal można budować i pakować każdą bibliotekę w oparciu o kompilację.plik gradle. Może mi czegoś brakuje, ale struktura nie jest tak ważna, jak to, co jest w budowie.pliki gradle. ProjectB nadal może zależeć od Facebook ' a, nawet jeśli znajdują się one na tym samym poziomie folderów.

 4
Author: GrkEngineer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-07 01:53:24

Miałem ten sam problem, w moim przypadku po prostu zapomniałem dodać projekt w settings.gradle. Potem zadziałało

 2
Author: Weslor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-29 11:38:58

W końcu udało mi się zbudować projekt (bez błędów gradle). Odpowiedź od Xaviera była bardzo pomocna.

Spędzam prawie 3 dni próbując skonfigurować mój projekt, wiem, że jestem bardzo blisko finsihed, ale mam nieoczekiwany wyjątek najwyższego poziomu na ostatnim etapie procesu budowania gradle (dexDebug).

Moja konfiguracja projektu jest bardzo podobna do Stoyana, jednak mam wiele projektów bibliotek Androida, które odwołują się do bibliotek obsługujących Androida. Sugeruję, że jeśli masz problemy kompilując swój górny projekt root (błąd mówiący wsparcie android jest już dodany), niż trzeba przenieść jar do oddzielnego projektu biblioteki Androida (rozkładać / oddzielać do samodzielnej instancji).

Przykład

--| ProjectARoot
--| ProjectA (where main/java etc are)
  --| build.gradle
--| settings.gradle
--| libraries
  --| ProjectBRoot
    --| settings.gradle
    --| ProjectB
    --| libraries
       --| android-supports (android lib project)
         --| libs
           --| android-support-v4.jar
           --| android-support-v13.jar
         --| build.gradle
       --| libA
         --| build.gradle (referencing android-supports)'

Przykład build scrip for libA refering Android supports projects

buildscript {
  repositories {
      maven { url 'http://repo1.maven.org/maven2' }
  }
  dependencies {
      classpath 'com.android.tools.build:gradle:0.4'
  }
}
apply plugin: 'android-library'

dependencies {
  compile project(':android-support')
}

android {
  compileSdkVersion 17
  buildToolsVersion "17.0.0"

  defaultConfig {
      minSdkVersion 7
      targetSdkVersion 17
  }
}

// top root settings.gradle

include 'ProjectB', 'android-support', ':ProjectA' (notice Project B is first than android-support and lastly Project A)

project(':android-support').projectDir = new File('libraries/ProjectBRoot/libraries/android-support')
project(':ProjectB').projectDir = new File('libraries/ProjectBRoot/ProjectB')

Aktualnie kiedy uruchamiam Gradle build dostaję ten błąd

:ProjectA:dexDebug

UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.IllegalArgumentException: already added: Landroid/support/v4/accessibilityservice/AccessibilityServiceInfoCompat;
at com.android.dx.dex.file.ClassDefsSection.add(ClassDefsSection.java:123)
at com.android.dx.dex.file.DexFile.add(DexFile.java:163)
at com.android.dx.command.dexer.Main.processClass(Main.java:490)
at com.android.dx.command.dexer.Main.processFileBytes(Main.java:459)
at com.android.dx.command.dexer.Main.access$400(Main.java:67)
at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:398)
at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:245)
at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:131)
at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:109)
at com.android.dx.command.dexer.Main.processOne(Main.java:422)
at com.android.dx.command.dexer.Main.processAllFiles(Main.java:333)
at com.android.dx.command.dexer.Main.run(Main.java:209)
at com.android.dx.command.dexer.Main.main(Main.java:174)
at com.android.dx.command.Main.main(Main.java:91)
1 error; aborting
:ProjectA:dexDebug FAILED
 1
Author: Mike Kuasinski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-08 00:30:55