当前位置: 首页 > 教程 > Gradle >

Gradle多项目构建

精华
小牛编辑
100浏览
2023-03-14

Gradle可以轻松处理各种大小规模的项目。小项目由一个单一的构建文件和一个源代码树构成。 大项目可以将其拆分成更小的,相互依赖的模块,以便更容易理解。Gradle完美支持这种多项目构建的场景。

多项目构建的结构

这种构建有各种形状和大小,但它们都有一些共同的特点 -

  • 在项目的根目录或主目录中都有一个settings.gradle文件。
  • 根目录或主目录都有一个build.gradle文件。
  • 具有自己的*.gradle构建文件的子目录(某些多项目构建可能会省略子项目构建脚本)。

要列出构建文件中的所有项目,可以使用以下命令。

D:/water>gradle -q projects

如果命令执行成功,将获得以下输出。

D:/water>gradle -q projects

------------------------------------------------------------
Root project
------------------------------------------------------------

Root project 'water'
+--- Project ':bluewhale'
/--- Project ':krill'

To see a list of the tasks of a project, run gradle <project-path>:tasks
For example, try running gradle :bluewhale:tasks

报告将显示每个项目的描述(如果指定)。可以使用以下命令指定描述。 将其粘贴到build.gradle文件中。

description = 'The shared API for the application'

指定常规构建配置

在根项目中的build.gradle文件中,常规配置可以应用于所有项目或仅应用于子项目。

allprojects {
   group = 'com.example.gradle'
   version = '0.1.0'
}

subprojects {
   apply plugin: 'java'
   apply plugin: 'eclipse'
}

这指定了一个公共com.example.gradle组和一个0.1.0版本到所有项目。subprojects 闭合所有应用对子项目通用配置,但不对根项目应用,如:allprojects闭合。

项目指定配置和依赖关系

核心uiutil子项目也可以有自己的build.gradle文件,如果它们有特定的需求,那么一般不会应用根项目配置。

例如,ui项目通常具有对核心项目的依赖性。所以在ui项目中需要有配置自己的build.gradle文件来指定这个依赖。

dependencies {
   compile project(':core')
   compile 'log4j:log4j:1.2.17'
}

项目依赖项可使用项目方法指定。

Gradle多项目构建的示例

定义公共行为

让我们看看下面的一个例子的项目树。这是一个多项目构建,其中包含一个名为water的根项目和一个名称为bluewham的子项目。在这个示例中,我们把在创建一个目录D:/water,作为根项目的目录。
多项目树 - waterbluewham项目的构建布局如下图所示 -

water/
  build.gradle
  settings.gradle
  bluewhale/

首先,创建一个文件 settings.gradle 并写入以下代码内容 -

include 'bluewhale'

bluewhale项目的构建脚本在哪里? 在Gradle中构建脚本是可选的。显然,对于单个项目构建,如果没有构建脚本那么项目是没有意义的。但对于多项目构建情况不同。让我们看看water项目的构建脚本并执行它,创建一个文件build.gradle 并写入以下代码:

Closure cl = { task -> println "I'm $task.project.name" }
task hello << cl
project(':bluewhale') {
    task hello << cl
}

并执行 gradle -q hello 输出结果如下 -

D:/water>gradle -q hello
I'm water
I'm bluewhale

Gradle允许从构建脚本中访问多项目构建的任何项目。 Project API提供了一个名称为project()的方法,它将一个路径作为参数,并返回此路径的Project对象。
为每个项目显式添加任务是不方便的。我们可以稍微做一下调整,先将另一个名称为krill的项目添加到多项目构建中。
现在目录结构看起来如下所示 -

water/
  build.gradle
  settings.gradle
  bluewhale/
  krill/

再次编辑 settings.gradle 将以下代码加入到文件中 -

include 'bluewhale', 'krill'

现在我们已经重写 water 构建脚本并将其放在一行中。
将文件water项目中的 build.gradle 并写入以下代码:

allprojects {
    task hello << { task -> println "I'm $task.project.name" }
}

并执行 gradle -q hello 输出结果如下 -

D:/water>gradle -q hello
I'm water
I'm bluewhale
I'm krill

这是如何工作的? Project API提供了一个属性allprojects,它返回当前项目及其下面所有子项目的列表。 如果使用闭包调用allprojects,则闭包的语句将委派给与所有项目相关联的项目。当然也可以通过allprojects.each进行迭代,但这将更冗长。

其他构建系统使用继承作为定义公共行为的主要方法。Gradle也为项目提供继承,您将在后面看到。但Gradle使用配置注入作为定义公共行为的常用方式。这是一种非常强大和灵活的配置多项目构建的方式。共享配置的另一种可能性是使用公共外部脚本。

子项目配置

Project API还提供了一个仅用于访问子项目的属性。

定义公共行为

定义所有项目和子项目的公共行为,编辑 build.gradle 文件使用以下代码 -

allprojects {
    task hello << {task -> println "I'm $task.project.name" }
}
subprojects {
    hello << {println "- I depend on water"}
}

并执行 gradle -q hello 输出结果如下 -

D:/water>gradle -q hello
I'm water
I'm bluewhale
- I depend on water
I'm krill
- I depend on water

注意两个代码片段引用“hello”任务。 第一个,它使用“task”关键字,构建任务并提供它的基本配置。第二部分不使用“task”关键字,因为它进一步配置现有的“hello”任务。只能在项目中构建一次任务,但可以添加任意数量的代码块以提供其他配置。

添加指定行为

可以在常见行为之上添加指定的行为。要应用这个特定的行为,通常将项目特定的行为放在项目的构建脚本中。我们可以为 bluewhale 项目添加项目特定的行为,如下所示:
编辑 build.gradle 文件使用以下代码 -

allprojects {
    task hello << {task -> println "I'm $task.project.name" }
}
subprojects {
    hello << {println "- I depend on water"}
}
project(':bluewhale').hello << {
    println "- I'm the largest animal that has ever lived on this planet."
}

并执行 gradle -q hello 输出结果如下 -

D:/water>gradle -q hello
I'm water
I'm bluewhale
- I depend on water
- I'm the largest animal that has ever lived on this planet.
I'm krill
- I depend on water

正如上面所说的,通常把项目特定的行为放入这个项目的构建脚本中。现在重构代码并向krill项目添加一些项目特定的行为。

定义 krill 项目的具体行为

构建布局如下图中所示 -

water/
  build.gradle
  settings.gradle
  bluewhale/
    build.gradle
  krill/
    build.gradle

settings.gradle 文件的内容 -

include 'bluewhale', 'krill'

bluewhale/build.gradle 文件的内容 -

hello.doLast {
  println "- I'm the largest animal that has ever lived on this planet."
}

krill/build.gradle 文件的内容 -

hello.doLast {
  println "- The weight of my species in summer is twice as heavy as all human beings."
}

build.gradle 文件的内容 -

allprojects {
    task hello << {task -> println "I'm $task.project.name" }
}
subprojects {
    hello << {println "- I depend on water"}
}

并执行 gradle -q hello 输出结果如下 -

D:/water>gradle -q hello
I'm water
I'm bluewhale
- I depend on water
- I'm the largest animal that has ever lived on this planet.
I'm krill
- I depend on water
- The weight of my species in summer is twice as heavy as all human beings.

参考

  • https://docs.gradle.org/current/userguide/multi_project_builds.html
  • https://www.petrikainulainen.net/getting-started-with-gradle/