How to structure a growing Gradle project with smart dependency management?

Overview

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:

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:

Project Overview

Different structuring concerns are summarized in commits if you like to explore things one-by-one:

Any kind of project

Any kind of project (except Java Module System)

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

Kotlin JVM projects

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).
Comments
  • Kotlin Gradle plugin loaded multiple times

    Kotlin Gradle plugin loaded multiple times

    When running gradle on this project I get the following message:

    The Kotlin Gradle plugin was loaded multiple times in different subprojects, which is not supported and may break the build.
    This might happen in subprojects that apply the Kotlin plugins with the Gradle 'plugins { ... }' DSL if they specify explicit versions, even if the versions are equal.
    Please add the Kotlin plugin to the common parent project or the root project, then remove the versions in the subprojects.
    If the parent project does not need the plugin, add 'apply false' to the plugin line.
    See: https://docs.gradle.org/current/userguide/plugins.html#sec:subprojects_plugins_dsl
    The Kotlin plugin was loaded in the following projects: ':application-plugins', ':base-plugins'
    

    This sounds bad. Is it bad?

    setup bug 
    opened by phreed 2
  • Ignore dependency order for injected implementations

    Ignore dependency order for injected implementations

    When using a gradle plugin (internal or external such as detekt) it can sometimes inject implementations at the top of the list. These can 1) have a version and 2) aren't injected in the correct order so the version checking and order checking features of the analysis plugins don't really work.

    Is there a way when doing the filtering (https://github.com/jjohannes/gradle-project-setup-howto/blob/87c42549a63e13933e35db960132eda869f632b9/gradle/plugins/dependency-analysis-plugins/src/main/kotlin/org.example.dependency-analysis.gradle.kts#L12-L19) to ignore injected depedencies?

    question 
    opened by jbaxleyiii 1
  • The `:app` project is special

    The `:app` project is special

    Just how special :app is not clear from the documentation.

    Process to reproduce.

    • [ ] clone the project's git repository
    • [ ] git mv app foo
    • [ ] ./gradlew build -> see error below
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Could not determine the dependencies of task ':bespin:compileJava'.
    > Could not resolve all dependencies for configuration ':bespin:compileClasspath'.
       > Project with path ':app' could not be found in project ':bespin'.
    

    Resolution:

    • [ ] change :app to :foo in two files
      • [ ] ./gradle/plugins/base-plugins/src/main/kotlin/org.example.consistent-resolution.gradle.kts
      • [ ] ./gradle/plugins/base-plugins/src/main/kotlin/org.example.root.gradle.kts

    This may be the intended behavior but it was not what I expected. The documentation around :app including dependencies should get some attention. My specific issue was that I created an application with a different name. It was unable to resolve any dependencies unless it shared that dependency with :app.

    question 
    opened by phreed 1
  • Don't opt in to public build scans for all people that clone this repo to build scans without accepting the ToS.

    Don't opt in to public build scans for all people that clone this repo to build scans without accepting the ToS.

    Seems like this will start sending data to scans.gradle.com for anyone that clones and builds the project without them accepting the terms of service?

    https://github.com/jjohannes/gradle-project-setup-howto/blob/8f7ec35e2a44724824b9f2ffd29e4da984591983/gradle/settings/src/main/kotlin/org.example.settings.settings.gradle.kts#L35-L41

    My suggestion would be to just remove that block completely and let people gets scans with --scan if they want them. (or they can add in a config like above if they want that)

    suggestion 
    opened by yogurtearl 1
  • Kotlin Project

    Kotlin Project

    I have a Kotlin project. Do you have an example like gradle-project-setup-howto with a kotlin-plugin convention? I tried to modify https://github.com/jjohannes/understanding-gradle/compare/main...phreed:main but it does not seem to be correct.

    suggestion 
    opened by phreed 1
  • Using plugins in conventions

    Using plugins in conventions

    Hello Jendrik,

    I hope this is the appropriate forum to ask this question.

    We have a large multi-project build, following much of the best practices outlined here and in the Gradle User Guide but I am struggling to understand the best practices for applying plugins to our conventions.

    There are two ways in which I've applied plugins to our projects:

    1. Create separate convention plugins for each variant of the plugins to apply, as this repository has done under gradle/plugins/java-library-plugins

           In this case, I could end up with a considerable amount of conventions such as:

    java-library-with-text-fixtures java-library-published java-library-with-jmh java-library-with-text-fixtures-and-jmh java-library-published-and-jmh java-library-publish-with-text-fixtures-and-jmh

    1. Apply all the common conventions to all java-library projects

           In this case, I would minimize the amount of conventions plugins I need to write and when a developer creates a new subproject, simply applying java-library will give you access to things like JMH and Test Fixtures already configured and ready to be used.

           The issue I've found with using this technique is that the configuration time can be dramatically increased throughout the project. There might be subprojects that don't use JMH or Test Fixtures even though these plugins are being applied needlessly increasing the configuration time.

           I've been using the incubating configuration on demand feature and that has improved our configuration time.



    This seems to be a trade-off between ease of use and build speed. I'm wondering your thoughts on the best way to approach applying plugins to our conventions in a large multi-project build. question 
    opened by Chasson1992 2
  • Provide an example of testing precompiled script plugins using GradleTestKit and ProjectBuilder

    Provide an example of testing precompiled script plugins using GradleTestKit and ProjectBuilder

    Provide examples of testing the precompiled script plugins using GradleTestKit and separately using ProjectBuilder, show casing pros/cons of each approach.

    suggestion 
    opened by yogurtearl 1
  • Build Failed Creating `base-plugins.jar`

    Build Failed Creating `base-plugins.jar`

    This is not a problem with the project itself. It may be a Gradle problem. It is probably a Windows 11 vs. Gradle problem.

    The build fails with the following error:

    FAILURE: Build failed with an exception.
    
    * What went wrong:
    A problem occurred configuring project ':platform'.
    > java.util.concurrent.ExecutionException: org.gradle.api.GradleException: Failed to create Jar file C:\Users\feisele\.gradle\caches\jars-9\447ff4e774d837b8b39c9410a295e1b9\base-plugins.jar.
    

    When I look in the C:\Users\feisele\.gradle\caches\jars-9\447ff4e774d837b8b39c9410a295e1b9 folder I see a base-plugins.jar.lock.lock file. Removing this file does not correct the problem. The suffix on that file seems suspicious to me.

    question 
    opened by phreed 1
Owner
Jendrik Johannes
Jendrik Johannes
A libre smart powered comic book reader for Android.

Seeneva A libre smart powered comic book reader for Android. Translation: Русский • • Features • Speech balloons zooming • OCR and TTS • Performance •

Seeneva comic book reader 130 Jan 7, 2023
A lightweight, simple, smart and powerful Android routing library.

RxRouter Read this in other languages: 中文, English A lightweight, simple, smart and powerful Android routing library. Getting started Setting up the d

Season 323 Nov 10, 2022
Gestor is an innovative open-source application for universal Minecraft mod management.

Gestor Gestor is an innovative open-source application for universal Minecraft mod management. About It combines three types of tools into a single ap

GestorMC 11 Dec 9, 2021
A local storage management library for Kotlin Multiplatform Mobile iOS and android

A local storage management library for Kotlin Multiplatform Mobile iOS and android Features iOS and Android local storage in one interface Provides ge

LINE 20 Oct 30, 2022
Solid - A CLI that tries to cover a dry-run phase for liquibase database change management

solid a CLI that tries to cover a dry-run phase for liquibase database change ma

Giovanni Panice (mos_) 1 Jan 28, 2022
A kotlin multiplatform BLS12-381 implementation for chia key management

KBLS KBLS is a kotlin multiplatform BLS12-381 implementation built for creating cross platform chia applications. Tips are much appreciated and will d

ChiaChat 7 Nov 21, 2022
Built with Jetpack compose, multi modules MVVM clean architecture, coroutines + flow, dependency injection, jetpack navigation and other jetpack components

RickAndMortyCompose - Work in progress A simple app using Jetpack compose, clean architecture, multi modules, coroutines + flows, dependency injection

Daniel Waiguru 9 Jul 13, 2022
Dependency Injection library for Kotlin Multiplatform, support iOS and Android

Multiplatform-DI library for Kotlin Multiplatform Lightweight dependency injection framework for Kotlin Multiplatform application Dependency injection

Anna Zharkova 32 Nov 10, 2022
Lightweight Kotlin DSL dependency injection library

Warehouse DSL Warehouse is a lightweight Kotlin DSL dependency injection library this library has an extremely faster learning curve and more human fr

Osama Raddad 18 Jul 17, 2022
Dependency Injection library for Compose Multiplatform, Koin wrapper.

?? Cokoin Injection library for Compose (Multiplatform and Jetpack), Koin wrapper. It uses @Composable functions to configure KoinContext and Scopes.

Bruno Wieczorek 57 Dec 29, 2022
A composite Github Action to execute the Kotlin Script with compiler plugin and dependency caching!

Kotlin Script Github Action Kotlin can also be used as a scripting language, which is more safer, concise, and fun to write than bash or python. Githu

Suresh 9 Nov 28, 2022
Actions are things that run, with parameters. Serves as a common dependency for a variety of Cepi extensions.

Actions Actions that take in customizable paramaters, an optional target, and do things. Installation Download the jar from Releases OR compile it you

Cepi 1 Jan 9, 2022
PackageReferenceComparison - Do app/module dependencies that share a dependency use the same Singleton ref?

PackageReferenceComparison Do app/module dependencies that share a dependency us

Liam Niehus-Staab 0 Feb 3, 2022
🍭 GithubSearchKMM - Github Repos Search - Android - iOS - Kotlin Multiplatform Mobile using Jetpack Compose, SwiftUI, FlowRedux, Coroutines Flow, Dagger Hilt, Koin Dependency Injection, shared KMP ViewModel, Clean Architecture

GithubSearchKMM Github Repos Search - Kotlin Multiplatform Mobile using Jetpack Compose, SwiftUI, FlowRedux, Coroutines Flow, Dagger Hilt, Koin Depend

Petrus Nguyễn Thái Học 50 Jan 7, 2023
Boilerplate code for implementing MVVM in Android using Jetpack libraries, coroutines, dependency injection and local persistance

MVVM Foundation This projects aims to speed up development of Android apps by providing a solid base to extend Libraries Jetpack Fragment Material3 :

Gabriel Gonzalez 2 Nov 10, 2022
Android + Kotlin + Github Actions + ktlint + Detekt + Gradle Kotlin DSL + buildSrc = ❤️

kotlin-android-template ?? A simple Github template that lets you create an Android/Kotlin project and be up and running in a few seconds. This templa

Nicola Corti 1.5k Jan 3, 2023
💫 A Gradle Plugin to generate your networking code from Swagger

Swagger Gradle Codegen A Gradle plugin to generate networking code from a Swagger spec file. This plugin wraps swagger-codegen, and exposes a configur

Yelp.com 399 Nov 28, 2022
Gradle plugin adding a task to run a Paper Minecraft server

Run Paper Run Paper is a Gradle plugin which adds a task to automatically download and run a Paper Minecraft server along with your plugin built by Gr

Jason 64 Dec 29, 2022
Gradle plugin for simplify Kotlin Multiplatform mobile configurations

Mobile Multiplatform gradle plugin This is a Gradle plugin for simple setup of Kotlin Multiplatform mobile Gradle modules. Setup buildSrc/build.gradle

IceRock Development 78 Sep 27, 2022