gradlegradle-kotlin-dslgradle-submodule

Why gradle 7.3 is incapable of finding a submodule defined using relative path?


I have a gradle project with 1 submodule, defined in the following file structure (+- refers to a directory):

+- <root>
  build.gradle.kts
  +- graph-commons
    +- core
      build.gradle.kts

The only submodule was included using the following kotlin script:

val graphCommons = project(File("./graph-commons/core"))

includeBuild(graphCommons)

When I execute ./gradlew clean assembly, I got the following error:

FAILURE: Build failed with an exception.

* Where:
Settings file '/home/peng/git/shapesafe/settings.gradle.kts' line: 2

* What went wrong:
Project with path './graph-commons/core' could not be found.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 492ms

FAILURE: Build failed with an exception.

* Where:
Settings file '/home/peng/git/shapesafe/settings.gradle.kts' line: 2

* What went wrong:
Project with path './graph-commons/core' could not be found.

What went wrong? Why the valid path "./graph-commons/core" cannot be identified by gradle?

The project is uploaded and tested on github:

https://github.com/tribbloid/shapesafe/runs/4280805005?check_suite_focus=true


Solution

  • Gradle does not work this way. A project path refers to a gradle project path, not to a file path. See https://docs.gradle.org/current/userguide/multi_project_builds.html#multi_project_builds

    Edit: As mentioned in the comments, the project(File) method that is available in the settings.gradle.kts is a special method allowing to receive a ProjectDescriptor whose directory points to the given file. The project must be present already e.g. by including it via include(String...) first.

    I first thought you tried to use the DependencyHandler#project(Map) method in some way, which is the usual way to refer to project dependencies. Gradle separates between dependencies and multi-project setup. In the settings.gradle.kts you usually setup the project structure while you declare dependencies in each build.gradle.kts. When using includeBuild you merely depend on the build of another completely separate project. When you then want to declare a dependency to a project from that included build you usually use the project's artifact coordinates to do so. This way the build still works when removing the includeBuild declaration.

    If you want to use composite builds see here for basic usage: https://docs.gradle.org/current/samples/sample_composite_builds_basics.html You will have to coordinate the artifact publishing and corresponding dependencies to make it work like a normal multi-project. Something like this:

    graph-commons
    |build.gradle.kts -> group = "org.scala-lang"; version = "1.0";
    |settings.gradle.kts -> include(":graph-commons-core")
    |graph-commons-core
    ||build.gradle.kts
    
    shapesafe
    |settings.gradle.kts -> includeBuild("../graph-commons")
    |core
    ||build.gradle.kts -> dependencies { implementation("org.scala-lang:graph-commons-core:1.0") }