Search code examples
gradlegradle-kotlin-dsl

Gradle includeBuild vs implementation project


What is the key difference between includeBuild(...) and implementation(project(...)) in the Gradle build system? I cannot really see the usecase difference after reading the documentation:

  1. https://docs.gradle.org/current/userguide/declaring_dependencies.html#sub:project_dependencies
  2. https://docs.gradle.org/current/userguide/composite_builds.html#separate_composite

What I am trying to do: Share same codebase for two separate projects: data classes (kotlix.serialization), external database dao, interfaces. It is not a full library but just some code snippets.

How can I connect the two projects in Intellij so that type hinting works?


Solution

  • Composite Build (by using includeBuild) is a way to create a dependency between autonomous Gradle Projects.
    Project import, is a way to create a dependency between two modules within a same Gradle Project.

    Composite Build is far more powerful and is also meant to be the new way of factorizing gradle configuration between multiple projects that you traditionally do with the buildSrc technique. I found this "Structuring Large Projects" article to be easier to read than the "Composite Builds" doc.

    An excellent sample project that demonstrates the power of Composite Builds can be found in Gradle sample_structuring_software_projects.

    Project dependency case

    The tree would look like this:

    settings.gradle.kts
    module1/build.gradle.kts
    module2/build.gradle.kts
    

    And you are declaring a dependency in module1/build.gradle.kts like this:

    dependencies {
       implementation(project("com.domain:module2"))
    }
    

    The dependency will be resolved only if both projects are declared as sub-modules of a common root project.

    It means you have a root settings.gradle.kts like this:

    rootProject.name = "rootProject"
    include(":module1")
    include(":module2")
    

    Composite build case

    The projects do not need to have common "umbrella" root project. Each project is a totally independent project.

    One project can simply declare a dependency on the other project (without even the target project knowing about it).

    Tree:

    project1/build.gradle.kts
    project1/settings.gradle.kts
    project2/build.gradle.kts
    project2/settings.gradle.kts
    

    In project1/settings.gradle.kts:

    rootProject.name = "project1"
    includeBuild("../project2") //No more ':' as it is not a module
    

    In project2/settings.gradle.kts:

    rootProject.name = "project2"
    

    In project1/build.gradle.kts like this:

    dependencies {
       implementation("com.domain:project2")
    }