How to set up a larger Gradle project
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 four 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
- How to set up a Gradle project for Kotlin
- How to set up a Gradle project for Java and Spring Boot
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:
And here is an overview in a thread on Mastodon:
Project Overview
Different structuring concerns are summarized in commits if you like to explore things one-by-one:
Any kind of project
- 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. Uses org.gradlex:build-parameters to pass environment variables into the build. - Dependency rules
Dependency rules to add more metadata as input to dependency resolution where needed. (uses org.gradlex:java-ecosystem-capabilities). - 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 base convention plugins
Configure Java project specifics for compilation and testing in several convention plugins. - Java library convention plugins
Combine convention plugins to different concrete library types that you use in yourbuild.gradle.kts
files. Test Fixtures- (Optional) Video: Publishing Libraries
- Java 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
- Video: Clean Compile Classpaths with the Dependency Analysis Plugin
- gradle.properties
Tune Gradle performance by settinggradle.properties
.
Any kind of project (except Java Module System)
- 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 projects
- 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.
Java Module System projects
- 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. - jlink Task
If the project only uses real modules (i.e. everything is, or gets patched to be, a module withmodule-info
) you can add a task to usejlink
to package the application.
Kotlin JVM projects
- Add Kotlin plugin and Kotlin specific compile configuration
The setup is similar to the Java project, only that we add the Kotlin JVM plugin on top. The plugins that were calledorg.example.java
were renamed toorg.example.kotlin
(which makes no difference in the functionality).
Overview of your Convention Plugins
There is a help task that you can use to get a diagram of the convention plugins defined in the project:
./gradlew :plugins:analysePluginApplicationOrder
The task generates a PlantUML file that you can render, for example, with the PlantUML IntelliJ plugin.
Notes
- 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).
FAQ
List of questions asked in issues so far.
- Why is the :app project special?
- Dependency Analysis: How to ignore dependencies added by plugins?
- Dependency Analysis: How to remove dependencies added by plugins?
- How many convention plugins should be used?
- How to customize the wrapper task?
- Kotlin branch: Why is there a special handling of kotlin-stdlib?
More questions or points you would like to discuss? Please open an issue.