# Composite build including multi-project builds

**URL:** https://discuss.gradle.org/t/composite-build-including-multi-project-builds/48810
**Category:** Help/Discuss
**Created:** [July 3, 2024, 9:06am UTC](https://discuss.gradle.org/t/composite-build-including-multi-project-builds/48810 "2024-07-03T09:06:36Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![SimonVleugels](https://avatars.discourse-cdn.com/v4/letter/s/9e8a1a/32.png) [@SimonVleugels](https://discuss.gradle.org/u/SimonVleugels)
#### Post date: [July 3, 2024, 9:06am UTC](https://discuss.gradle.org/t/composite-build-including-multi-project-builds/48810/1 "2024-07-03T09:06:36Z")

</div>

Hi,

We have a multi-repo setup with every repo containing multiple projects. Cross repo dependencies do exist which are defined using `includeBuild("../repoB")` in settings.gradle.

Now we are able to build every repo separately by going inside the repo and running `gradle build`. We would also like to be able to do a full build of all repositories.

Our directory structure is as follow:

```gradle
root
├── settings.gradle
├── repoA
│ ├── settings.gradle
│ ├── projectA
│ | ├── build.gradle
│ | └── src/main/java/org/sample/my-app/Main.java
│ └── projectB
│ ├── build.gradle
│ └── src/main/java/org/sample/my-app/Main.java
└── repoB
    ├── settings.gradle
    ├── projectA
    | ├── build.gradle
    | └── src/main/java/org/sample/my-app/Main.java
    └── projectB
        ├── build.gradle
        └── src/main/java/org/sample/my-app/Main.java

```

In `root/settings.gradle` we added

```gradle
includeBuild './repoA'
includeBuild './repoB'

```

When doing `gradle build`, the build tasks in both projects are not run.  
Any idea what we’re doing wrong?

Thanks.

---

<div class="post-metadata">

### Author: ![Vampire](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/vampire/32/9082_2.png) [@Vampire](https://discuss.gradle.org/u/Vampire)
#### Post date: [July 3, 2024, 11:32am UTC](https://discuss.gradle.org/t/composite-build-including-multi-project-builds/48810/2 "2024-07-03T11:32:13Z")

</div>

The first thing you do wrong is, that you use `gradle`, you should always use the Gradle wrapper. 🙂  
But that is unrelated to your question.

When you do `gradle build` (or `./gradlew build`), then the `build` task of all projects in the given build that have such a task is executed.

But this logic does only work within one build.  
In your composite build `root`, `repoA` and `repoB` are separate builds and to those this logic does not apply, as it does not cross build boundaries.

If you know each included build has a `build` task, you could for example do something like this in the `root` project’s build script:

```kotlin
tasks.build {
    dependsOn(
        gradle.includedBuilds.map { it.task(":build") }
    )
}

```

But be aware that this would only depend on the `build` task in the root project of those builds, like when doing `./gradlew :build` instead of `./gradlew build` within `repoA` or `repoB`.

---

<div class="post-metadata">

### Author: ![SimonVleugels](https://avatars.discourse-cdn.com/v4/letter/s/9e8a1a/32.png) [@SimonVleugels](https://discuss.gradle.org/u/SimonVleugels)
#### Post date: [July 3, 2024, 12:18pm UTC](https://discuss.gradle.org/t/composite-build-including-multi-project-builds/48810/3 "2024-07-03T12:18:47Z")

</div>

Thank you for your response.

I added your snipped in `root/build.gradle` and get following error:

```gradle
Could not find method build() for arguments [build_7kfwdttl4bo3clu8pg62oi22v$_run_closure1@7de51ae3] on task set of type org.gradle.api.internal.tasks.DefaultTaskContainer

```

`gradle :build` in both repositories this works more or less:

```gradle
> Task :buildSrc:extractPluginRequests UP-TO-DATE
> Task :buildSrc:generatePluginAdapters UP-TO-DATE
> Task :buildSrc:compileJava UP-TO-DATE
> Task :buildSrc:compileGroovy NO-SOURCE
> Task :buildSrc:compileGroovyPlugins UP-TO-DATE
> Task :buildSrc:pluginDescriptors UP-TO-DATE
> Task :buildSrc:processResources UP-TO-DATE
> Task :buildSrc:classes UP-TO-DATE
> Task :buildSrc:jar UP-TO-DATE
> Task :compileJava NO-SOURCE
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE
> Task :jar UP-TO-DATE
> Task :sourcesJar UP-TO-DATE
> Task :assemble UP-TO-DATE
> Task :compileTestJava NO-SOURCE
> Task :processTestResources NO-SOURCE
> Task :testClasses UP-TO-DATE
> Task :test NO-SOURCE
> Task :check UP-TO-DATE
> Task :build UP-TO-DATE

```

I assume I have to create a build task which depend on all the build tasks of the projects?

Maybe you did already noticed, but we are new to gradle and making a POC for the migration from maven to gradle.

---

<div class="post-metadata">

### Author: ![Vampire](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/vampire/32/9082_2.png) [@Vampire](https://discuss.gradle.org/u/Vampire)
#### Post date: [July 3, 2024, 12:31pm UTC](https://discuss.gradle.org/t/composite-build-including-multi-project-builds/48810/4 "2024-07-03T12:31:46Z")

</div>

Ah, yeah, if the build script is otherwise empty, no `build` task exists.  
This task is added by the `lifecycle-base` plugin.  
You can of course create the task yourself, or you just apply the `lifecycle-base` plugin.

Btw. I highly recommend you switch to Kotlin DSL.  
By now it is the default DSL, you immediately get type-safe build scripts, actually helpful error messages if you mess up the syntax, and an amazingly better IDE support if you use a good IDE like IntelliJ IDEA or Android Studio.

---

<div class="post-metadata">

### Author: ![SimonVleugels](https://avatars.discourse-cdn.com/v4/letter/s/9e8a1a/32.png) [@SimonVleugels](https://discuss.gradle.org/u/SimonVleugels)
#### Post date: [July 3, 2024, 12:53pm UTC](https://discuss.gradle.org/t/composite-build-including-multi-project-builds/48810/5 "2024-07-03T12:53:06Z")

</div>

Now I get following error. Maybe we should (if we still easily can) switch to kotlin.

```gradle
> No signature of method: com.google.common.collect.SingletonImmutableList.map() is applicable for argument types: (build_7kfwdttl4bo3clu8pg62oi22v$_run_closure1$_closure2) values: [build_7kfwdttl4bo3clu8pg62oi22v$_run_closure1$_closure2@35f8d824]
  Possible solutions: max(), max(groovy.lang.Closure), max(java.util.Comparator), tap(groovy.lang.Closure), pop(), min()

```

build.gradle:

```gradle
plugins {
    id 'base'
}

tasks.build {
    dependsOn(
        gradle.includedBuilds.map { it.task(":build") }
    )
}

```

---

<div class="post-metadata">

### Author: ![Vampire](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/vampire/32/9082_2.png) [@Vampire](https://discuss.gradle.org/u/Vampire)
#### Post date: [July 3, 2024, 1:54pm UTC](https://discuss.gradle.org/t/composite-build-including-multi-project-builds/48810/6 "2024-07-03T13:54:40Z")

</div>

Yeah, that’s indeed because what I sent is Kotlin DSL but you try to use it in Groovy DSL. 😃  
Replace `map` with `collect` which is the Groovy equivalent of `map` in Kotlin, then it should probably also work with Groovy DSL.

But yes, switching to Kotlin DSL imho is a good idea. 🙂

---

<div class="post-metadata">

### Author: ![Vampire](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/vampire/32/9082_2.png) [@Vampire](https://discuss.gradle.org/u/Vampire)
#### Post date: [July 3, 2024, 1:55pm UTC](https://discuss.gradle.org/t/composite-build-including-multi-project-builds/48810/7 "2024-07-03T13:55:57Z")

</div>

Btw. `base` != `lifecycle-base`.  
It also works with that, as `base` sits on top of `lifecycle-base` and so applies it.  
But it does more than you need in this case, so `lifecycle-base` would be enough, but you can also use `base`, doesn’t matter too much.
