Making gradle wrapper versions same for subprojects


(Kushal Kadaba) #1

I have an android project with a few submodules. Each of these submodules are android libraries themselves and are also gradle projects. The main project has a gradle/wrapper with the latest version of gradle and this gets updated often as and when new android gradle plugin versions come out. However the submodules have their own gradle/wrapper and these aren’t update at all. I haven’t paid attention to this setup this far because it has worked.
I recently updated my android gradle plugin version to 3.1.0 and the gradle wrapper version to 4.4. This gave me an error No such property: FOR_RUNTIME for class: org.gradle.api.attributes.Usage in one of the submodules. The submodule gradle version is 3.2 and the android gradle plugin version is 2.3.0.
I have a few questions about such a setup:

  1. While building the app module do the submodules use the gradle wrapper in the app module or the ones in the respective submodules?
  2. What is the idiomatic way to have such a setup?
  3. According to https://docs.gradle.org/current/userguide/gradle_wrapper.html we can add a wrapper extension to configure the gradle wrapper. How do we or is it possible to use this and mention a version so that all modules use the same gradle version and android gradle plugin version?

(James Justinic) #2

If you have a multi-project build, one version of Gradle is executing the entire build. Which one depends on the one that you reference when you run the build. Nothing stops you from running ./gradlew, ../gradlew, or path/to/gradlew to reference one other than what’s in your current working directory.

It is atypical to have more than one Gradle wrapper in a multi-project build. Even if you want to run builds from a subproject as your working directory, you can still reference the wrapper in the root project or reference subproject tasks from the root.

If you really want to keep this setup, you could define wrapper in an allprojects {...} block in the root project. You can’t just use extension because it will only affect the automatically created wrapper task, which only exists in the root project. Running the wrapper task from the root will run it in all subprojects and the versions will stay synced.

allprojects {
    task wrapper(type: Wrapper) {
        gradleVersion = '4.6'
    }
}

(Kushal Kadaba) #3

Thanks! that clears up the questions I had. However, your suggestion of using ../gradlew is not ideal if the submodule itself is a standalone project. Or am I missing something here?
In cases where a team member is working only on one submodule and doesn’t care about cloning the entire project that submodule should also have a gradle wrapper correct?


(James Justinic) #4

It just depends on what you have and what you consider a standalone build. A standalone build, even if it’s multi-project, would typically have a single wrapper in the root. If it’s truly a standalone component, I’d expect to manage the Gradle wrapper version separately from other standalone components. Keeping the other ones up to date is part of the chore. If trying to simultaneously work on multiple standalone components that are used together, use composite builds.

However, if the main goal is just to work on individual components that are usually only part of a complete application, I’d probably just always check out the top level repository (as the orchestrator) and the desired submodule without worrying about the submodule in complete isolation unless that submodule is being developed and published independently and being part of this app is not the main purpose.