56

我目前正在将我们的一个项目从 maven 转换为 Gradle。文件夹结构如下:

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

所以它看起来已经很复杂了。但这个想法是 ProjectB 是一个库项目,它应该能够单独构建和打包,这就是它有自己的 settings.gradle 的原因,据我所知,它似乎工作正常,我有它构建它找到 facebook 就好了。

ProjectB/build.gradle 包含这一行

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

ProjectBRoot/settings.gradle 包含这一行

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

gitRoot/settings.gradle 包含这一行

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

ProjectA/build.gradle 包含这一行

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

当我运行构建时出现此错误

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

所以我对出问题的猜测是facebook不在ProjectB的直接子文件夹中......但是在ProjectBRoot中构建时这并不重要。这可能是由于我直接引用 ProjectB 而不是通过 ProjectBRoot/gradle.build 的面孔,但我尝试过,它也没有工作。有人可以帮帮我吗,我已经查看了文档,它没有谈论具有自己的 settings.gradle 文件的多个项目,我认为这就是让我感到困惑的事情。

更新:

所以我按照 Xav 的回答,现在可以使用命令行进行构建,但是我无法使用 android studio 导入/构建。我知道问题仍然出在 facebook 项目上。我得到的错误是它无法配置 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.

错误是由线路引起的

 compile project(':facebook-sdk')

在 ProjectB/build.gradle 里面

4

5 回答 5

96

settings.gradle 必须定义所有模块。它不会加载在树中找到的其他 settings.gradle 以加载更多模块。

你必须要么

  1. 在顶层 settings.gradle 中为 facebook SDK 定义一个模块。是的,它与其他 settings.gradle 是多余的。

  2. 以某种方式发布项目 B(以及它的依赖项,因此在本例中为 facebook SDK 库),某处(例如公司工件存储库)并从项目 A 访问它。

虽然 #1 更好,但它使 ProjectB -> Facebook 依赖项变得棘手,因为路径会根据所使用的 settings.gradle 有所不同。解决此问题的一种方法是将模块名称/路径与其在磁盘上的实际位置分开。这是在 settings.gradle 文件中完成的。

在您的顶级 settings.gradle 文件中,执行

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

在项目 B 中的 setting.gradle 文件中,对不同的相对路径执行相同操作:

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

这使得两个项目设置都定义了位于磁盘上相同绝对位置的相同“facebook-sdk”模块。

所有依赖于这个模块的项目都应该将依赖声明为

compile project(':facebook-sdk') 
于 2013-06-07T00:28:54.123 回答
6

这不是您要寻找的答案,但是...

我花了大约 4 天时间尝试将我复杂的项目结构(实际上很像你的)迁移到 gradle 中。最后,我放弃了整个子项目的概念(因为在我的情况下,它只是不起作用),我选择使用本地 maven 存储库方法,如本文所述:http://www.flexlabs .org/2013/06/using-local-aar-android-library-packages-in-gradle-builds

因此,在我的包含子项目的库项目中,我基本上为每个项目创建了完整的库项目,然后我使用上面的链接将它们发布到 maven 本地存储库。然后在父项目中,我删除了对子项目的所有引用,而在依赖项中,我只是引用了已发布的库。然后在我的主项目中,我删除了对子项目的所有引用,并引用了我的库的已发布 maven 本地版本。

最后,一切都很好,但确实需要一些时间来转换所有内容。我有大约 6 个带有子项目的图书馆项目,那个子项目等等,现在一切正常。

我不喜欢 Gradle 和 Maven 等系统的一点是,它们真的希望您改变构建代码/项目的“方式”。所以,如果你是迁移到 Gradle 与从 Gradle 开始,那么这个过程可能会非常令人沮丧。一旦你弄清楚了,下一次就容易多了;)

于 2013-06-07T14:30:24.700 回答
4

我只想让应用程序与库都处于同一级别。您仍然可以基于 build.gradle 文件构建和打包每个库。我可能遗漏了一些东西,但结构并不像 build.gradle 文件中的那样重要。您仍然可以让 projectB 依赖于 Facebook,即使它们处于同一文件夹级别。

于 2013-06-07T01:53:24.147 回答
3

有同样的问题,就我而言,我只是忘记将项目添加到settings.gradle. 在那之后,它起作用了

于 2015-10-29T11:38:58.953 回答
1

I have finally managed to build the project (without gradle errors). Answer from Xavier was very helpful.

I spend almost 3 days trying to setup my project, I know I am very close to be finsihed but I have UNEXPECTED TOP-LEVEL EXCEPTION at very last step of gradle build process (dexDebug).

My project setup is very similar to Stoyan's however I have multiple android-library projects that are referencing android-support libraries. I suggest that if you have problems with compiling your top root project (error saying support android is already added) than you need to move the jar into separate android library project (decompose/separate into stand alone instance).

Example

--| 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)'

Example build scrip for libA referencing 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')

Currently when I run gradle build I get this error

: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
于 2013-06-08T00:16:53.753 回答