Talavera316
Talavera316

Reputation: 67

Gradle build: how to set up a multilevel project (3+ levels)?

I am having troubles with seting up 3 level gradle multi-project:

Level_1_Proj
│
├── Level_2_Proj_A
│   │ 
│   ├── Level_3_Proj_C
│   └── Level_3_Proj_D
│
└── Level_2_Proj_B
    │
    ├── Level_3_Proj_E
    └── Level_3_Proj_F

I would like to be able to:

  1. set up dependencies between projects of the same level in the build script, like:
 dependencies {
     project('Level_2_Proj_A') {
         dependencies {
             implementation project('Level_2_Proj_B')
         }
     }
 }
  1. also want to be able to build (the subtree) starting the bash command [$gradle build] at any level [then build down the projects' subtree]

I have achieved building from the middle and bottom levels, but I cannot setup the build from the top level. Getting error:

A problem occurred evaluating project ‘Level_2_Proj_A’. Project with path ‘Level_3_Proj_C’ could not be found in project ‘Level_2_Proj_A’.

Is it possible? If so, how to configure? Thanks

Upvotes: 2

Views: 1862

Answers (1)

afterburner
afterburner

Reputation: 2781

Alright, here's how I managed to get it working. Given the following directory structure:

.
├── A
│   ├── C
│   │   └── build.gradle.kts
│   ├── D
│   │   └── build.gradle.kts
│   └── build.gradle.kts
├── B
│   ├── E
│   │   └── build.gradle.kts
│   ├── F
│   │   └── build.gradle.kts
│   └── build.gradle.kts
├── build.gradle.kts
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle.kts

The settings.gradle.kts has the following content:

rootProject.name = "multi-module-build"

include(":A")
include(":A:C")
include(":A:D")
include(":B")
include(":B:E")
include(":B:F")

Each build.gradle.kts has a call task that prints the name path of the project, e.g. Inside the C project:

tasks.register("call") {
    println(":A:C")
}

Inside the A project:

tasks.register("call") {
    dependsOn(":A:C:call")
    dependsOn(":A:D:call")
    println(":A")
}

tasks["build"].dependsOn(":A:call")

The tasks["build"].dependsOn(":A:call") tells Gradle to invoke :A:call when building. The two dependsOn inside the call definition for A invoke the subproject call tasks.

There is a similar structure available for B.

When running gradle build at root level, this is the output I get:

:A
:B
:A:C
:A:D
:B:E
:B:F

When running gradle build inside the A subproject, I get:

:A
:A:C
:A:D

When running it inside :A:C, I don't get any output because I haven't specified that C's build task should depend on call, but that could easily be done. Let me know if this doesn't work for you. I've used the Kotlin DSL for gradle, but you're perfectly free to change it to the Groovy variant.

Upvotes: 2

Related Questions