Gradle - Multi-Project Builds

Gradle - Multi-Project Builds

  1. https://docs.gradle.org/current/userguide/intro_multi_project_builds.html
  2. https://discuss.gradle.org/t/multiproject-within-a-multiproject/42303

For a long-lived (aka - something you’ll maintain and may grow) multi-module project, I’d suggest following the idiomatic gradle structure: https://github.com/jjohannes/idiomatic-gradle. But there’s a lot to unpack there, so it may not be the ideal thing to start with. Once you grok it though, that structure scales incredibly well, and allows you to avoid duplicating lots of configuration (via ‘precompiled script plugins’, largely in the build-logic project in that repo), and make use of build caching without having to modify things.

Different ways to organize nested projects

https://discuss.gradle.org/t/multiproject-within-a-multiproject/42303

I’m in the beginnings of converting a large baseline from ‘ant’ to ‘gradle’. I’d like to avoid restructuring as much as possible and have run into a snag with what I would call a multiproject within a multiproject. Assume I have the following:

ProjectA
  |
  ProjectB
  ProjectC
  | - ProjectD
  | - ProjectE
  1. ProjectA - settings.gradle contains: include(‘ProjectB’, ‘ProjectC’)

  2. ProjectC - settings.gradle contains: include(‘ProjectD’, “ProjectE’)

  3. In ProjectA: ./gradlew build

  4. Expectation: build ProjectB, then traverse ProjectC and build ProjectD and ProjectE

  5. Result: only ProjectB is actually built

If I manually change directory to ProjectC and ./gradlew build, ProjectD and ProjectE are built.

What am I doing wrong? ProjectC is just the example created from running gradle init and selecting options for a Java multiproject.

In ProjectA: ./gradlew tasks --all

Other tasks reports ProjectB:compileJava, but there is no ProjectC:compileJava or whatever task would traverse into ProjectD and ProjectE.

See https://stackoverflow.com/questions/13595610/gradle-nested-multi-projects-with-project-compile-dependencies

Solution

Which option you use in your situation is more a question of taste or isolation or organisation, both would work if you do it properly.

Option 1

  1. You can either have one big multi-project build and only the one settings.gradle.kts file in the root project.
  2. Ensure ProjectA/settings.gradle has include(‘ProjectB’, ‘ProjectC:ProjectD’, ‘ProjectC:ProjectE’).

Option 2

Use Composite Builds

See

  1. https://docs.gradle.org/current/userguide/composite_builds.html
  2. https://docs.gradle.org/current/samples/sample_composite_builds_basics.html

Approach:

  1. You could make ProjectC with subprojects ProjectD and ProjectE an own “stand-alone” build with own settings script, that you then include as sub build instead of sub project in ProjectA.
  2. With this approach, use includeBuild instead of include.

Including a standalone multi-project inside another multi-project

https://discuss.gradle.org/t/including-a-standalone-multi-project-inside-another-multi-project/22606

Hello, I’ve been bashing my head against this problem and have not found a solution here nor on SO. My situations is relatively straight forward. I have an existing multi-project build, lets call it ‘legacy’, that for various reasons cannot be modified*. I also have a new multi-project build, lets call it ‘root’, that I would like to include legacy in as a sub-project. The directory structure looks like this:

root
    | - build.grade
    | - settings.gradle
    A
    | - build.gradle
    B
    | - build.gradle
        legacy
          | -build.gradle
          | settings.gradle
            C
            | - build.gradle
            D
            | - build.gradle

Important file contents:

  1. C/build.gradle = …compile project(’:D’) …
  2. legacy/settings.gradle = include ‘C’ include ‘D’

No matter what I configure for root/settings.gradle I either get Project with path ':D' could not be found in project ':B:legacy:C' or the whole legacy tree is ignored

Is there any way to make the legacy branch and root play nicely?

Note: Legacy cannot be drastically changed, but if there is a simple solution that would allow legacy to continue operating as a standalone project (it is currently a git submodule of root) then that could be entertained

Answer:

What you’re describing could be accomplished with a composite build. https://docs.gradle.org/current/userguide/composite_builds.html

This is the only way if you want the legacy build to remain completely untouched and standalone. You can reference dependencies from the legacy build in the root build by using external dependencies that are automatically substituted for project dependencies.


Links to this note