Hi, I have a question about how to order the execu...
# community-support
l
Hi, I have a question about how to order the execution of tasks in a multi-module project. I know, normally gradle does verify which sub-projects and tasks depend on each other and normally this does work quite well, but our build in our build-pipeline has the same error described in https://github.com/gradle/gradle/issues/27576 which prevents us from building the project. The exact error we get is
Copy code
org.gradle.internal.execution.WorkValidationException: A problem was found with the configuration of task ':yedi-domain:kaptKotlin' (type 'KaptWithoutKotlincTask').
  - Gradle detected a problem with the following location: '/data/home/agent-02/agent/work/7bfe31a37ea5b299/idoc-model/build/libs/idoc-model-5.24.40.1-RC-gradle-fix-1.jar'.
    
    Reason: Task ':domain:kaptKotlin' uses this output of task ':idoc-model:sourcesJar' 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 ':idoc-model:sourcesJar' as an input of ':domain:kaptKotlin'.
      2. Declare an explicit dependency on ':idoc-model:sourcesJar' from ':domain:kaptKotlin' using Task#dependsOn.
      3. Declare an explicit dependency on ':idoc-model:sourcesJar' from ':domain:kaptKotlin' using Task#mustRunAfter.
    
    For more information, please refer to <https://docs.gradle.org/8.4/userguide/validation_problems.html#implicit_dependency> in the Gradle documentation.
What can I do to insure that the module
idoc-model
, especially the tasks sourcesJar, run before
domain:kaptKotlin
? We tried something like
Copy code
afterEvaluate {
    tasks.named("kaptKotlin") {
        dependsOn(":idoc-model:sourcesJar")
   }
}
in the domain
build.gradle
file, which worked sometimes on the build pipeline but did not work locally under special circumstances (starting Spring Boot in IntelliJ). To make it work locally again we had to change the depending task from
:idoc-model:sourcesJar
to
:idoc-model:build
Any thoughts on how to tackle this problem?
j
Generally, any solution based on
dependOn
and related ones are patches. The real issue is those tasks are not setting the input/outputs correctly.
As you are not the owner of those tasks, I would open an issue on YouTrack so they can fix the Kapt task.
Anyway, without a reproducer it is hard to know, it is not good that one project depends on the task from another project, I don't know if this is done by a Kapt or a configuration you are setting up
l
Thanks for the info! May I ask, what it means that the task does not set the input/outputs correctly? what is an expected output of a task in this situation?
j
I think the real problem is the other part:
it is not good that one project depends on the task from another project
what is the gradle configuration for those two modules?
Are you doing some manual configuration with kapt/jar tasks?
l
thats more or less the whole configuration:
Copy code
// idoc-model build.gradle
plugins {
    id 'org.unbroken-dome.xjc'
}

xjc {
    srcDirName = 'resources'
}


task sourcesJar(type: Jar) {
    duplicatesStrategy = 'include'
}
and
Copy code
// domain build.gradle
dependencies {
    implementation project(':idoc-model')
    implementation "com.querydsl:querydsl-jpa"
    kapt "com.querydsl:querydsl-apt:jpa
    // ...
}

afterEvaluate {
    tasks.named("kaptKotlin") {
        dependsOn(":idoc-model:sourcesJar")
   }
}
in the resources folder are
.xsd
files which are transformed into java classes
and these java classes are used in
:domain
and
:domain:kaptKotlin
presumable needs these classes
j
I don't know what that plugin is, but when a plugin generates code like Java classes, it is generated in the same module, and the other module depends on the module in which the code has been generated. Generating code inside a different module is done by default or is a setup you are doing?
l
the code is generated by
xjc
and the task
:xjcGenerate
which is part of
gradle build
j
but those classes are generated in the same module, or in the folders of the second module
l
sorry for the late reply, they are getting generated in the
:idoc-model
module and the
:domain
module uses them
v
Some notes: • any explicit
dependsOn
where on the left-hand side is not a lifecycle task is a code smell and as Javi said more a sign that task outputs are not wired properly to task inputs, the possible solutions in that message are actually all just duct-tape and not a proper solution in practically all cases •
afterEvaluate
is highly discouraged. The main gain you get from using it are timing problems, ordering problems, and race conditions. It is like using
SwingUtilities.invokeLater
or
Platform.runLater
to "fix" a GUI problem. It just does symptom treatment, delaying the problem to a later, harder to reproduce, harder to debug, and harder to fix point in time. • One of the most usual cases for this error are overlapping or wrongly declared outputs, so for example task
A
and task
B
both have directory
X
as output directory and write a file into it, then task
C
depends on outputs of
A
and you get that error message for
B
and
C
as due to the overlapping outputs the files in
X
are considered output for both,
A
and
B
wrongly. • The other most usual case for this error is, if you actually do not wire task outputs to task inputs properly, or do not properly and safely share things between projects, but configure paths manually and thus missing task dependencies. • What makes me 🤔 is,
idoc-model-5.24.40.1-RC-gradle-fix-1.jar
does not look to me like something a task called
sourcesJar
should produce, because a
sourcesJar
typically generates a file ending with
-sources.jar
, so maybe indeed somehow the outputs of your
sourcesJar
task are wrong. • But as Javi said, it is hard to give concrete advice without seeing the project or at least an MCVE