This repo shows one possibility to structure a Gradle project when you want:
- Centralized and maintainable build configuration and custom build logic
- No dependency hell through smart dependency management with dependency rules and analysis
There are three variations of this available:
- How to set up a Gradle project for Java
- How to set up a Gradle project for Android
- How to set up a Gradle project for Java Module System
The structure though, is good for any kind of project you may build with Gradle (Kotlin, Groovy, Scala, ...)
This is following the same patterns as idiomatic-gradle but is closer to a full setup that also takes the aspect of continuously changing dependencies into account.
Pick one of these similar videos to get a quick overview:
Different structuring concerns are summarized in commits if you like to explore things one-by-one:
- Folder structure
A basic structure with all the places to put build configuration. Puts everything, which is not a dependency declaration of a concrete subproject, into thegradle/
folder. (Which is a choice, you can put things in different places and still follow the rest of this setup.) - Settings plugin
A settings convention plugin to configure the project structure, repositories, and build locations. - Dependency rules
Dependency rules to add more metadata as input to dependency resolution where needed. - Base convention plugins
Configure things shared by all projects - like setting a version and consistent resolution. - Versions
Put all versions into a platform; use BOMs where available for libraries that consist of multiple components. - Java convention plugins
Configure Java project specifics for compilation and testing in several convention plugins that you use in yourbuild.gradle.kts
files. - Application convention plugins
A specific project is the:app
project which assembles the final application. This is a good place to also aggregate other information like test result and coverage reports for the whole project. It is also the place where you often need custom tasks - e.g. to generate additional resources. - Lifecycle Tasks and Root project
Add lifecycle tasks through a convention plugin for the rootbuild.gradle.kts
. - Customized dependency analysis
You have to take care of your dependencies and versions regularly: When your project evolves and when new versions of external dependencies are released. Team members not so familiar with the build setup might need to touch only these places. Put some dependency analysis in place to help everyone to keep the build tidy over time.- Use the superb dependency-analysis-gradle-plugin
- Write some small custom analysis code that produces actionable error messages that fit your project structure
- gradle.properties
Tune Gradle performance by settinggradle.properties
.
- Declare dependencies
Declare dependencies between subprojects and external components in thebuild.gradle.kts
files.- Video: Declaring Dependencies
- The example has quite some conflicts which are correctly resolved thanks to our dependency rules. Explore in a build scan: https://scans.gradle.com/s/hpjtkjwwhcpzu/dependencies
- Android plugins
Here, the Application plugins are changed into Android plugins and adjusted to target Android App development using the Android Gradle Plugins.- This repo focuses on general project structuring and dependency management with Gradle and does not go into many Android specifics. I recommend to check out https://github.com/android/nowinandroid in addition for that.
- module-info.java files
Usemodule-info.java
files to develop Java Modules. These files already include dependency information. - Java Module System Plugins
Use my Java Module System plugins to enable Gradle to extract the dependency information from themodule-info.java
files and to extend the dependency rules to for Java Module specific information. - Customized dependency analysis (Java Modules)
Adjusts the above for Java Modules. The java-module-dependencies plugin already brings some analysis tasks.
- If you have a question, please ask in an issue.
- The concrete things done in all places (custom tasks, components used in dependencies, additional plugins applied, etc.) are just examples. If you, for example, need to use additional Gradle plugins you can add these in the corresponding place, keeping the suggested structure.
- This setup uses a platform project to centralize dependency versions. An alternative approach is to use a dependency version catalog.
If you prefer to use a catalog, because it is the better fit in your case, you can still follow the setup proposed here (just without the
gradle/platform
project).