设置多项目Gradle构建

时间:2014-12-03 10:18:35

标签: gradle idiomatic multi-project

我正在为遗留系统设置多模块Gradle构建(替换当前的Ant构建)。但是,我是Gradle的新手,我不知道最好的方法是什么。我想做得对,因为这个构建脚本将会存在很长时间。我已经找到了一种方法可以做一些有效的方法,但是当我在谷歌周围阅读并阅读StackOverflow的答案时,我看到人们使用不同的方式,在我的情况下 - 它不起作用。但也许我做错了什么。我也一直在阅读Gradle in Action一书,但在那里找不到这个特殊的问题。

我的项目根目录中有一个build.gradle文件,其中包含一堆子目录,每个子目录都包含一个子项目。其中大多数是常规Java项目,但也有一些战争和耳朵,这需要一些特殊的包装爱。每个子项目都有自己的build.gradle文件,此时只包含依赖项列表,仅此而已。

我的项目根目录中的build.gradle文件看起来像这样(为了简洁,我省略了War的内容):

configure(javaProjects()) {
    jar.doFirst {
        manifest {
            ...
        }
    }
}

configure(earProjects()) {
    apply plugin: 'ear'

    ear.doFirst {
        manifest {
            ...
        }
    }
}

Set<String> javaProjects() {
    subprojects - earProjects()
}

Set<String> earProjects() {
    subprojects.findAll { it.name.endsWith(".ear") }
}

我以这种方式做事的唯一原因是因为这是我尝试的第一个解决方案,我可以在我的情况下工作。然而,现在脚本正在增长,它开始感觉有点笨重。此外,doFirst似乎有点尴尬。

但是当我查看StackOverflow时,我看到了使用这样的结构的建议:

allprojects {
    tasks.withType(Jar) {
        manifest {
            ...
        }
    }

    tasks.withType(Ear) {
        manifest {
            ...
        }
    }
}

这似乎更好,但我似乎无法以这种方式重写我的脚本。我得到像这样的错误:

Cannot change configuration ':some.subproject:compile' after it has been resolved.

我不知道如何处理此错误,而且出于某种原因,我似乎无法谷歌。

所以,我的问题是:我确实做错了吗?或者更确切地说:以一种不是惯用的Gradle方式?为了可维护性,我想尽可能地做事。如果是这样的话:我该如何处理错误消息?

1 个答案:

答案 0 :(得分:4)

一般情况下,您应该执行第二个代码段中描述的内容:

allprojects {
    tasks.withType(Jar) {
        manifest {
            ...
        } 
    }
}

但是这还有一些限制,这还不够。您获得的错误消息意味着您修改了编译配置 AFTER 配置已经解决。例如,当您执行类似

的操作时,就会发生这种情况
configurations.compile.files.each...

在配置阶段(例如,在您的清单块中,如上所示)和另一个地方(例如,在您的子项目build.gradle文件中):

dependencies{
    compile "org.acme:somelib:1.2.3"
}

另一个问题是,每次调用构建脚本时都会解决编译依赖关系,即使没有触发jar任务也是如此。

建议的解决方法是替换

tasks.withType(Jar) {
    manifest {
        ...
    } 
}

tasks.withType(Jar) {
    doFirst{
        manifest {
             ...
        } 
    }
}

这意味着解析配置会推迟到gradle的执行阶段,并且只在需要时才会触发。

在多项目构建中配置项目时,您可以将每个代码段视为整个配置的一部分。你没有“两次”配置项目,但你在不同的地方配置项目的不同方面。

这是当前gradle配置模型的已知限制。

您仍然可以使用

configure(earProjects()) {
}

这里没关系。 IMO只是个人偏好的问题。 gradle项目本身使用'configure'。

我个人更喜欢在项目build.gradle文件中应用 Ear war 等插件,将项目标记为ear / war项目。

要在所有ear项目中共享通用配置,您可以在root build.gradle文件中使用以下内容:

allprojects{
     plugins.withType(EarPlugin){
         // only applied if it is a ear project
         // put ear specific logic here
     }
}