quarkusio/quarkus

Gradle build with KSP fails with "circular dependency" after Quarkus 2.13.0

Opened this issue ยท 16 comments

Describe the bug

When using KSP (Kotlin Symbol Processing, see https://kotlinlang.org/docs/ksp-overview.html), the Gradle build fails with a "circular dependency" starting with Quarkus 2.13.0 (up to the latest 2.14.2). It worked fine in 2.12.3.

Expected behavior

Build succeeds

Actual behavior

Build fails with circular dependency:

FAILURE: Build failed with an exception.

* What went wrong:
Circular dependency between the following tasks:
:backend:kspKotlin
+--- :backend:quarkusGenerateCode
|    \--- :backend:processResources
|         \--- :backend:kspKotlin (*)
\--- :backend:quarkusGenerateCodeDev
     \--- :backend:processResources (*)

(*) - details omitted (listed previously)

How to Reproduce?

Reproducer: quarkus-reproducer.zip

Steps to reproduce:

  1. ./gradlew clean build (will fail)
  2. In gradle.properties, change quarkusVersion from 2.13.0.Final to 2.12.3.Final.
  3. ./gradlew clean build (will succeed)

If quarkusVersion is greater or equal to 2.13.0.Final, it will fail in the same way, including the latest version (2.14.2.Final).

Output of uname -a or ver

Darwin C02YK01PLVCG-ML 21.6.0 Darwin Kernel Version 21.6.0: Mon Aug 22 20:17:10 PDT 2022; root:xnu-8020.140.49~2/RELEASE_X86_64 x86_64

Output of java -version

openjdk version "17.0.3" 2022-04-19

GraalVM version (if different from Java)

No response

Quarkus version or git rev

2.13.0

Build tool (ie. output of mvnw --version or gradlew --version)

Gradle 7.6

Additional information

This occurs in at least Gradle 7.5.1 and 7.6.

/cc @evanchooly, @geoand, @glefloch, @quarkusio/devtools

@glefloch @aloubyansky did we change something in the Gradle plugin?

@glefloch it appears #27764 is what breaks it.

Has this been addressed yet? I am also receiving this error on Quarkus 2.14.2 and KSP 1.6.21-1.0.6.

I've managed to mitigate the problem on my side, with a below snippet in my build.gradle.kts file:

project.afterEvaluate {
        tasks.findByPath("app:quarkusGenerateCode")?.let {
            it.setDependsOn(it.dependsOn.map { it as Provider<*> }.filter { it.get() !is ProcessResources })
        }
        tasks.findByPath("app:quarkusGenerateCodeDev")?.let {
            it.setDependsOn(it.dependsOn.map { it as Provider<*> }.filter { it.get() !is ProcessResources })
        }
    }

It's not perfect though, as it removing a ProcessResources task from a dependency list, in a submodule "app". It's where quarkus is in my project.
Hope this will help others.

Edit:
I came with a different approach for all who have a multimodule project with a Quarkus dependency spread all around:

project.afterEvaluate {
    getTasksByName("quarkusGenerateCode", true).forEach { task ->
        task.setDependsOn(task.dependsOn.map { it as Provider<Task> }.filter { it.get().name != "processResources" })
    }
    getTasksByName("quarkusGenerateCodeDev", true).forEach { task ->
        task.setDependsOn(task.dependsOn.map { it as Provider<Task> }.filter { it.get().name != "processResources" })
    }
}

It also is less save as it cast provider as Provider (but Kotlin says it Any type), so class cast may occur, though it didn't in my case. Then it compares name, finding the "processResources" by name.

Still seeing this issue on 2.16.3.

@Augustyn is your workaround only applicable to multi-module projects? Trying something similar on a smaller project I'm getting a big mess of Gradle errors:

FAILURE: Build failed with an exception.

* What went wrong:
Some problems were found with the configuration of task ':compileTestKotlin' (type 'KotlinCompile').
  - Gradle detected a problem with the following location: 'C:\projects\build\classes\java\quarkus-test-generated-sources'.
    
    Reason: Task ':compileTestKotlin' uses this output of task ':compileQuarkusTestGeneratedSourcesJava' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
    
    Possible solutions:
      1. Declare task ':compileQuarkusTestGeneratedSourcesJava' as an input of ':compileTestKotlin'.
      2. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#dependsOn.
      3. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#mustRunAfter.
    
    Please refer to https://docs.gradle.org/8.0.1/userguide/validation_problems.html#implicit_dependency for more details about this problem.
  - Gradle detected a problem with the following location: 'C:\projects\build\classes\java\quarkus-test-generated-sources\grpc'.
    
    Reason: Task ':compileTestKotlin' uses this output of task ':compileQuarkusTestGeneratedSourcesJava' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
    
    Possible solutions:
      1. Declare task ':compileQuarkusTestGeneratedSourcesJava' as an input of ':compileTestKotlin'.
      2. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#dependsOn.
      3. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#mustRunAfter.
    
    Please refer to https://docs.gradle.org/8.0.1/userguide/validation_problems.html#implicit_dependency for more details about this problem.
  - Gradle detected a problem with the following location: 'C:\projects\build\classes\java\quarkus-test-generated-sources\avdl'.
    
    Reason: Task ':compileTestKotlin' uses this output of task ':compileQuarkusTestGeneratedSourcesJava' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
    
    Possible solutions:
      1. Declare task ':compileQuarkusTestGeneratedSourcesJava' as an input of ':compileTestKotlin'.
      2. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#dependsOn.
      3. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#mustRunAfter.
    
    Please refer to https://docs.gradle.org/8.0.1/userguide/validation_problems.html#implicit_dependency for more details about this problem.
  - Gradle detected a problem with the following location: 'C:\projects\build\classes\java\quarkus-test-generated-sources\avpr'.
    
    Reason: Task ':compileTestKotlin' uses this output of task ':compileQuarkusTestGeneratedSourcesJava' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
    
    Possible solutions:
      1. Declare task ':compileQuarkusTestGeneratedSourcesJava' as an input of ':compileTestKotlin'.
      2. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#dependsOn.
      3. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#mustRunAfter.
    
    Please refer to https://docs.gradle.org/8.0.1/userguide/validation_problems.html#implicit_dependency for more details about this problem.
  - Gradle detected a problem with the following location: 'C:\projects\build\classes\java\quarkus-test-generated-sources\avsc'.
    
    Reason: Task ':compileTestKotlin' uses this output of task ':compileQuarkusTestGeneratedSourcesJava' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
    
    Possible solutions:
      1. Declare task ':compileQuarkusTestGeneratedSourcesJava' as an input of ':compileTestKotlin'.
      2. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#dependsOn.
      3. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#mustRunAfter.

Still seeing this issue on 2.16.3.

@Augustyn is your workaround only applicable to multi-module projects? Trying something similar on a smaller project I'm getting a big mess of Gradle errors:

FAILURE: Build failed with an exception.

* What went wrong:
Some problems were found with the configuration of task ':compileTestKotlin' (type 'KotlinCompile').
  - Gradle detected a problem with the following location: 'C:\projects\build\classes\java\quarkus-test-generated-sources'.
    
    Reason: Task ':compileTestKotlin' uses this output of task ':compileQuarkusTestGeneratedSourcesJava' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
    
    Possible solutions:
      1. Declare task ':compileQuarkusTestGeneratedSourcesJava' as an input of ':compileTestKotlin'.
      2. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#dependsOn.
      3. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#mustRunAfter.
    
    Please refer to https://docs.gradle.org/8.0.1/userguide/validation_problems.html#implicit_dependency for more details about this problem.
  - Gradle detected a problem with the following location: 'C:\projects\build\classes\java\quarkus-test-generated-sources\grpc'.
    
    Reason: Task ':compileTestKotlin' uses this output of task ':compileQuarkusTestGeneratedSourcesJava' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
    
    Possible solutions:
      1. Declare task ':compileQuarkusTestGeneratedSourcesJava' as an input of ':compileTestKotlin'.
      2. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#dependsOn.
      3. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#mustRunAfter.
    
    Please refer to https://docs.gradle.org/8.0.1/userguide/validation_problems.html#implicit_dependency for more details about this problem.
  - Gradle detected a problem with the following location: 'C:\projects\build\classes\java\quarkus-test-generated-sources\avdl'.
    
    Reason: Task ':compileTestKotlin' uses this output of task ':compileQuarkusTestGeneratedSourcesJava' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
    
    Possible solutions:
      1. Declare task ':compileQuarkusTestGeneratedSourcesJava' as an input of ':compileTestKotlin'.
      2. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#dependsOn.
      3. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#mustRunAfter.
    
    Please refer to https://docs.gradle.org/8.0.1/userguide/validation_problems.html#implicit_dependency for more details about this problem.
  - Gradle detected a problem with the following location: 'C:\projects\build\classes\java\quarkus-test-generated-sources\avpr'.
    
    Reason: Task ':compileTestKotlin' uses this output of task ':compileQuarkusTestGeneratedSourcesJava' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
    
    Possible solutions:
      1. Declare task ':compileQuarkusTestGeneratedSourcesJava' as an input of ':compileTestKotlin'.
      2. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#dependsOn.
      3. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#mustRunAfter.
    
    Please refer to https://docs.gradle.org/8.0.1/userguide/validation_problems.html#implicit_dependency for more details about this problem.
  - Gradle detected a problem with the following location: 'C:\projects\build\classes\java\quarkus-test-generated-sources\avsc'.
    
    Reason: Task ':compileTestKotlin' uses this output of task ':compileQuarkusTestGeneratedSourcesJava' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
    
    Possible solutions:
      1. Declare task ':compileQuarkusTestGeneratedSourcesJava' as an input of ':compileTestKotlin'.
      2. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#dependsOn.
      3. Declare an explicit dependency on ':compileQuarkusTestGeneratedSourcesJava' from ':compileTestKotlin' using Task#mustRunAfter.

Yes, his code was applicable to multi-module projects but I believe he also shared a snippet for single module projects:

project.afterEvaluate {
    getTasksByName("quarkusGenerateCode", true).forEach { task ->
        task.setDependsOn(task.dependsOn.map { it as Provider<Task> }.filter { it.get().name != "processResources" })
    }
    getTasksByName("quarkusGenerateCodeDev", true).forEach { task ->
        task.setDependsOn(task.dependsOn.map { it as Provider<Task> }.filter { it.get().name != "processResources" })
    }
}
cogman commented

This works for Quarkus 3

project.afterEvaluate {
  getTasksByName("quarkusGenerateCode", true).forEach { task ->
    task.setDependsOn(task.dependsOn.filterIsInstance<Provider<Task>>().filter { it.get().name != "processResources" })
  }
  getTasksByName("quarkusGenerateCodeDev", true).forEach { task ->
    task.setDependsOn(task.dependsOn.filterIsInstance<Provider<Task>>().filter { it.get().name != "processResources" })
  }
}

it seem the problem fixed in quarkus@3.7.1 ?
i update quarkus version and clean build script, found that after delete the code block and build still success๐ŸŽ‡๐ŸŽ‡

I guess it might be a consequence of #38249, which was also included in 3.7.0.
Thanks for checking @Inori-Lover. I'll close this issue but please re-open anyone for whom it appears to be not fixed. Thanks.

This issue has not been resolved for me on 3.7.1.

Circular dependency between the following tasks:
:manager:kspKotlin
+--- :manager:quarkusGenerateCode
|    \--- :manager:processResources
|         \--- :manager:kspKotlin (*)
\--- :manager:quarkusGenerateCodeDev
     +--- :manager:processResources (*)
     \--- :manager:quarkusGenerateCode (*)

Seeing the same issue as @FWest98. Please re-open.

@aloubyansky To prevent this from going out of sight - the issue is not resolved yet.

FYI this is happening on latest quarkus 3.9.3 using Kotlin/dataframe#657

@cogman comment fixes it.

Ok, thanks for the info, I'm re-opening it.

quarkus-reproducer.zip
Reproducer updated to version 3.9.3