So I got this project in kotlin that consists of multiple sub projects. All of them are link with single settings.gradle
file. It was all working fine until after a week of coding another part I noticed that i get a lot of compilation errors from one of the modules. So I started digging and found out that Intellij couldn't import classes from another sub project even though it is dependent on it via api project(':lib:content:model')
. I couldn't figure out the reason why it stopped working and tried to build the project without intellij, just with graddlew. Then i got strange error:
command: ./gradlew :lib:game:model:build
FAILURE: Build failed with an exception.
* What went wrong:
Circular dependency between the following tasks:
:lib:game:model:classes
\--- :lib:game:model:compileJava
--- :lib:game:model:compileKotlin
| --- :lib:game:model:jar
| | --- :lib:game:model:classes (*)
| | --- :lib:game:model:compileJava (*)
| | --- :lib:game:model:compileKotlin (*)
| | \--- :lib:game:model:kaptKotlin
| | --- :lib:game:model:jar (*)
| | \--- :lib:game:model:kaptGenerateStubsKotlin
| | \--- :lib:game:model:jar (*)
| \--- :lib:game:model:kaptKotlin (*)
\--- :lib:game:model:jar (*)
(*) - details omitted (listed previously)
I tried to google my way out of it but none of the suggestions from the internet worked for me. The strangest thing is that it USED to work when i was writing it previously. Then i just switched to another module and when i came back it was all like this, broken =(
I tried to isolate bugged code into test and ended up with lib
module containing two sub modules content
and game
. Another one is project-types
module where I store gradle plugins to overcome configuration duplication. content
project just have one subproject called model
and game
project has three: api
, impl
, and also 'model`.
lib->game->model
project depends on lib->content->model
lib->game->impl
project depends in lib->game->api
So another really strange thing is that lib->game->impl
WORKD just fine and compiles even when he is dependent on lib->game->api
. But the same thing doesn't work for 'lib->game->model' which uses THE SAME mechanism to depend on 'lib->content->model'
So I'm lost and don't know what to do. There is a good reason I need all of them to be different projects but I don't want to put myself through the hell of publishing new artifact to local repo every time I change code in one of them. Can someone please help me fix it T-T
My ./gradlew -q projects
output:
------------------------------------------------------------
Root project 'test'
------------------------------------------------------------
Root project 'test'
\--- Project ':lib'
--- Project ':lib:content'
| \--- Project ':lib:content:model'
\--- Project ':lib:game'
--- Project ':lib:game:api'
--- Project ':lib:game:impl'
\--- Project ':lib:game:model'
Included builds
\--- Included build ':project-types'
project-types
contains common
and kotlin-project
sub projects.
common
build.gradle:
plugins {
id 'groovy-gradle-plugin'
}
repositories {
mavenCentral()
}
and commons.gradle
file inside src:
plugins {
id 'java'
}
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
implementation 'com.fasterxml.jackson.core:jackson-core:2.13.4'
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.13.4'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.4'
implementation 'com.fasterxml.jackson.module:jackson-module-paranamer:2.13.4'
implementation 'org.slf4j:slf4j-api:1.7.36'
implementation 'ch.qos.logback:logback-classic:1.2.11'
implementation 'commons-io:commons-io:2.11.0'
implementation 'org.apache.commons:commons-lang3:3.12.0'
implementation 'commons-codec:commons-codec:1.15'
}
kotlin-project
build.gradle file:
dependencyResolutionManagement {
repositories {
mavenLocal()
mavenCentral()
gradlePluginPortal()
google()
}
}
rootProject.name = 'project-types'
include 'commons'
include 'kotlin-project'
and it's kotlin-project.gradle
file inside src:
plugins {
id 'commons'
id 'org.jetbrains.kotlin.jvm'
id 'org.jetbrains.kotlin.kapt'
}
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
implementation 'org.jetbrains.kotlin:kotlin-reflect'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.6.4'
implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.1'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.9.1'
testImplementation 'org.mockito:mockito-junit-jupiter:4.8.1'
testImplementation 'org.mockito.kotlin:mockito-kotlin:4.0.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.1'
}
test {
useJUnitPlatform()
}
compileKotlin {
kotlinOptions.jvmTarget = '17'
kotlinOptions.freeCompilerArgs = ['-Xjsr305=strict', '-Xemit-jvm-type-annotations']
}
compileTestKotlin {
kotlinOptions.jvmTarget = '17'
kotlinOptions.freeCompilerArgs = ['-Xjsr305=strict', '-Xemit-jvm-type-annotations']
}
kapt {
correctErrorTypes = true
}
So my main projects structure is:
My ./setting.gradle
file content:
rootProject.name = 'test'
includeBuild 'project-types'
include 'lib:game'
include 'lib:game:model'
include 'lib:game:api'
include 'lib:game:impl'
include 'lib:content'
include 'lib:content:model'
./build.gradle
file content
plugins {
id 'org.jetbrains.kotlin.jvm' version "1.7.21" apply false
id 'org.jetbrains.kotlin.kapt' version "1.7.21" apply false
}
repositories {
mavenCentral()
}
./lib/content/model/build.gradle
file content:
plugins {
id 'kotlin-project'
}
group 'cvazer.test'
version '1.0.0'
dependencies {
}
./lib/game/api/build.gradle
file content:
plugins {
id 'kotlin-project'
}
group 'cvazer.test'
version '1.0.0'
dependencies {
}
./lib/game/impl/build.gradle
file content:
plugins {
id 'kotlin-project'
}
group 'cvazer.test'
version '1.0.0'
dependencies {
api project(':lib:game:api')
}
./lib/game/model/build.gradle
file content: (The one with the problem)
plugins {
id 'kotlin-project'
}
group 'cvazer.test'
version '1.0.0'
dependencies {
api project(':lib:content:model')
}
CodePudding user response:
Gradle has issues resolving dependencies when two subproject names are the same, even if the paths are different.
- https://github.com/gradle/gradle/issues/847
- Gradle multiprojects with same name, different paths
- https://discuss.gradle.org/t/dependency-substitution-wrong-with-more-than-one-sub-project-with-same-name/7253
You have two subprojects, both called 'model'
:lib:game:model
:lib:content:model
Gradle can't distinguish between them.
I would recommend renaming your subprojects to flatter, without nesting, and making the names of each subproject unique.
└── lib/
├── game
├── game-model
├── game-api
├── game-impl
├── content
└── content-model