了解使用子项目和组合构建构建 Gradle 项目的基础知识。
步骤 1. 关于多项目构建
通常,构建包含多个项目,例如将在您的生态系统中部署的共享库或单独的应用程序。
在 Gradle 中,多项目构建包括:
-
settings.gradle(.kts)
代表您的 Gradle 构建的文件,包括所需的子项目,例如 include("app", "model", "service") -
build.gradle(.kts)
以及相应子目录中每个子项目的源代码
我们的构建当前由一个名为 的根项目组成authoring-tutorial
,它有一个app
子项目:
. (1)
├── app (2)
│ ... (3)
│ └── build.gradle.kts (4)
└── settings.gradle.kts (5)
1 | The authoring-tutorial root project |
2 | The app subproject |
3 | The app source code |
4 | The app build script |
5 | The optional settings file |
. (1)
├── app (2)
│ ... (3)
│ └── build.gradle (4)
└── settings.gradle (5)
1 | The authoring-tutorial root project |
2 | The app subproject |
3 | The app source code |
4 | The app build script |
5 | The optional settings file |
步骤 2. 将另一个子项目添加到构建中
想象一下,我们的项目正在增长,需要一个自定义库才能运行。
让我们创造这个想象lib
。首先,创建一个lib
文件夹:
mkdir lib
cd lib
创建一个名为的文件build.gradle(.kts)
并向其中添加以下行:
plugins {
id("java")
}
repositories {
mavenCentral()
}
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:5.9.3")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
implementation("com.google.guava:guava:32.1.1-jre")
}
tasks.named<Test>("test") {
useJUnitPlatform()
}
tasks.register("task3"){
println("REGISTER TASK3: This is executed during the configuration phase")
}
tasks.named("task3"){
println("NAMED TASK3: This is executed during the configuration phase")
doFirst {
println("NAMED TASK3 - doFirst: This is executed during the execution phase")
}
doLast {
println("NAMED TASK3 - doLast: This is executed during the execution phase")
}
}
plugins {
id 'java'
}
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.3'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'com.google.guava:guava:32.1.1-jre'
}
test {
useJUnitPlatform()
}
tasks.register('task3') {
println('REGISTER TASK3: This is executed during the configuration phase')
}
tasks.named('task3') {
println('NAMED TASK3: This is executed during the configuration phase')
doFirst {
println('NAMED TASK3 - doFirst: This is executed during the execution phase')
}
doLast {
println('NAMED TASK3 - doLast: This is executed during the execution phase')
}
}
你的项目应该是这样的:
.
├── app
│ ...
│ └── build.gradle.kts
├── lib
│ └── build.gradle.kts
└── settings.gradle.kts
.
├── app
│ ...
│ └── build.gradle
├── lib
│ └── build.gradle
└── settings.gradle
让我们向lib
子项目添加一些代码。创建一个新目录:
mkdir -p lib/src/main/java/com/gradle
创建一个 Java 类,CustomLib
在名为的文件中调用CustomLib.java
,源代码如下:
package com.gradle;
public class CustomLib {
public static String identifier = "I'm a String from a lib.";
}
该项目现在应具有以下文件和目录结构:
.
├── app
│ ├── build.gradle.kts
│ └── src
│ └── main
│ └── java
│ └── authoring
│ └── tutorial
│ └── App.java
├── lib
│ ├── build.gradle.kts
│ └── src
│ └── main
│ └── java
│ └── com
│ └── gradle
│ └── CustomLib.java
└── settings.gradle.kts
.
├── app
│ ├── build.gradle
│ └── src
│ └── main
│ └── java
│ └── authoring
│ └── tutorial
│ └── App.java
├── lib
│ ├── build.gradle
│ └── src
│ └── main
│ └── java
│ └── com
│ └── gradle
│ └── CustomLib.java
└── settings.gradle
但是,lib
子项目不属于构建,您将无法执行task3
,直到将其添加到settings.gradle(.kts)
文件中。
要添加lib
到构建中,请settings.gradle(.kts)
相应地更新根目录中的文件:
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0"
}
rootProject.name = "authoring-tutorial"
include("app")
include("lib") // Add lib to the build
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0'
}
rootProject.name = 'authoring-tutorial'
include('app')
include('lib') // Add lib to the build
让我们将lib
子项目添加为app
依赖项app/build.gradle(.kts)
:
dependencies {
implementation(project(":lib")) // Add lib as an app dependency
}
dependencies {
implementation(project(':lib')) // Add lib as an app dependency
}
更新app
源代码以便导入lib
:
package authoring.tutorial;
import com.gradle.CustomLib;
public class App {
public String getGreeting() {
return "CustomLib identifier is: " + CustomLib.identifier;
}
public static void main(String[] args) {
System.out.println(new App().getGreeting());
}
}
最后,让我们app
使用以下命令运行./gradlew run
:
$ ./gradlew run
> Configure project :app
> Task :app:processResources NO-SOURCE
> Task :lib:compileJava
> Task :lib:processResources NO-SOURCE
> Task :lib:classes
> Task :lib:jar
> Task :app:compileJava
> Task :app:classes
> Task :app:run
CustomLib identifier is: I'm a String from a lib.
BUILD SUCCESSFUL in 11s
8 actionable tasks: 6 executed, 2 up-to-date
我们的根项目构建authoring-tutorial
现在包括两个子项目,app
和lib
。
app
依赖于取决于lib
。您可以lib
独立于app
.然而,要构建app
,Gradle 也会构建lib
。
第 3 步:了解组合构建
复合构建只是包含其他构建的构建。
复合构建允许您:
-
从项目构建中提取构建逻辑(并在子项目中重复使用它)
-
组合通常独立开发的构建(例如插件和应用程序)
-
将大型构建分解为更小、更独立的块
步骤 4. 将构建添加到构建中
让我们在构建中添加一个插件。首先,创建一个新目录,license-plugin
名为gradle
:
cd gradle
mkdir license-plugin
cd license-plugin
进入gradle/license-plugin
目录后,运行gradle init
.确保Gradle plugin
为以下任务选择项目以及其他选项init
:
$ gradle init --dsl kotlin --type kotlin-gradle-plugin --project-name license
$ gradle init --dsl groovy --type groovy-gradle-plugin --project-name license
对于任何其他提示,请选择默认值。
你的项目应该是这样的:
.
├── app
│ ...
│ └── build.gradle.kts
├── lib
│ ...
│ └── build.gradle.kts
├── gradle
│ ├── ...
│ └── license-plugin
│ ├── settings.gradle.kts
│ └── plugin
│ ├── gradle
│ │ └── ....
│ ├── src
│ │ ├── functionalTest
│ │ │ └── ....
│ │ ├── main
│ │ │ └── kotlin
│ │ │ └── license
│ │ │ └── LicensePlugin.kt
│ │ └── test
│ │ └── ...
│ └── build.gradle.kts
│
└── settings.gradle.kts
.
├── app
│ ...
│ └── build.gradle
├── lib
│ ...
│ └── build.gradle
├── gradle
│ ├── ...
│ └── license-plugin
│ ├── settings.gradle
│ └── plugin
│ ├── gradle
│ │ └── ....
│ ├── src
│ │ ├── functionalTest
│ │ │ └── ....
│ │ ├── main
│ │ │ └── groovy
│ │ │ └── license
│ │ │ └── LicensePlugin.groovy
│ │ └── test
│ │ └── ...
│ └── build.gradle
│
└── settings.gradle
花点时间查看LicensePlugin.kt
代码LicensePlugin.groovy
和gradle/license-plugin/settings.gradle(.kts)
文件。值得注意的是,这是一个完全独立的构建,具有自己的设置文件和构建脚本:
rootProject.name = "license"
include("plugin")
rootProject.name = 'license'
include('plugin')
要将我们的license-plugin
构建添加到根项目,请settings.gradle(.kts)
相应地更新根文件:
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0"
}
rootProject.name = "authoring-tutorial"
include("app")
include("subproject")
includeBuild("gradle/license-plugin") // Add the new build
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0'
}
rootProject.name = 'running-tutorial-groovy'
include('app')
include('lib')
includeBuild('gradle/license-plugin')
./gradlew projects
您可以通过在根文件夹中运行来查看根项目的结构authoring-tutorial
:
$ ./gradlew projects
------------------------------------------------------------
Root project 'authoring-tutorial'
------------------------------------------------------------
Root project 'authoring-tutorial'
+--- Project ':app'
\--- Project ':lib'
Included builds
\--- Included build ':license-plugin'
我们的根项目构建authoring-tutorial
现在包括两个子项目app
和lib
,以及另一个构建license-plugin
.
在项目根目录中运行:
-
./gradlew build
- 构建app
和lib
-
./gradlew :app:build
- 构建app
和lib
-
./gradlew :lib:build
-lib
仅构建 -
./gradlew :license-plugin:plugin:build
-license-plugin
仅构建
使用 Gradle 设计项目架构的方法有很多种。
多项目构建非常适合组织具有许多模块的项目,例如mobile-app
、web-app
、api
、lib
、 以及documentation
它们之间具有依赖关系的项目。
复合(包含)构建非常适合分离构建逻辑(即约定插件)或测试系统(即修补库)
下一步: 设置文件>>