google / protobuf-gradle-plugin

Protobuf Plugin for Gradle
Other
1.77k stars 273 forks source link

'explodeCodeSourceDebug' uses this output of task 'generateDebugProto' without declaring an explicit or implicit dependency after Gradle update to 8.0.2 #683

Open ivanalvarado opened 1 year ago

ivanalvarado commented 1 year ago

We're experiencing the following error after updating gradle from 7.6.1 -> 8.0.2

A problem was found with the configuration of task ':my-library:generateDebugProto' (type 'GenerateProtoTask').
  - Gradle detected a problem with the following location: '/path/to/MyProject/my-library/build/generated/source/proto/debug'.

    Reason: Task ':my-library:explodeCodeSourceDebug' uses this output of task ':my-library:generateDebugProto' 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 ':my-library:generateDebugProto' as an input of ':my-library:explodeCodeSourceDebug'.
      2. Declare an explicit dependency on ':my-library:generateDebugProto' from ':my-library:explodeCodeSourceDebug' using Task#dependsOn.
      3. Declare an explicit dependency on ':my-library:generateDebugProto' from ':my-library:explodeCodeSourceDebug' using Task#mustRunAfter.

    Please refer to https://docs.gradle.org/8.0.2/userguide/validation_problems.html#implicit_dependency for more details about this problem.

This appears like a misconfiguration at the plugin level, but not entirely sure.

We've added a workaround by adding the following to the affected module:

afterEvaluate {
    tasks.forEach {task ->
        if (task.name.contains("explodeCodeSourceDebug")) {
            task.dependsOn("generateDebugProto")
        }
        if (task.name.contains("explodeCodeSourceRelease")) {
            task.dependsOn("generateReleaseProto")
        }
    }
}
JamesXNelson commented 3 weeks ago

We're seeing a similar-ish issue on gradle 8.9:

FAILURE: Build failed with an exception.

* What went wrong:
A problem was found with the configuration of task ':proto:dh-protodoc:processResources' (type 'ProcessResources').
  - Gradle detected a problem with the following location: '/home/bender/dev/deephaven/iris/sanluis/proto/dh-protodoc/src/main/proto'.

    Reason: Task ':proto:dh-protodoc:processResources' uses this output of task ':proto:dh-protodoc:getProtos' 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 ':proto:dh-protodoc:getProtos' as an input of ':proto:dh-protodoc:processResources'.
      2. Declare an explicit dependency on ':proto:dh-protodoc:getProtos' from ':proto:dh-protodoc:processResources' using Task#dependsOn.
      3. Declare an explicit dependency on ':proto:dh-protodoc:getProtos' from ':proto:dh-protodoc:processResources' using Task#mustRunAfter.

Worked around it via:

tasks.named('processResources') {
  dependsOn('getProtos')
}

For posterity, we have other proto builds that work fine. The one that is breaking is only doing protodocs:

We added a new task to sync all available .proto files into a single project to build a single page doc:

// Register a sync task to synchronize proto files
tasks.register('getProtos', Sync).configure {
  Sync getProtos ->
    getProtos.destinationDir = new File(projectDir, 'src/main/proto')
    getProtos.from(project(':proto').subprojects.findAll{ it.name.startsWith('proto-') }*.file('src/main/proto'))
}

Complete proto-related wiring here:

// Configure the Protobuf plugin
protobuf {
  protoc { artifact = "com.google.protobuf:protoc:${protocVersion}" }
  plugins {
    doc {
      artifact = "io.github.pseudomuto:protoc-gen-doc:1.5.1"
    }
  }

  // Configure tasks for generating Protobuf files
  generateProtoTasks {
    all().each {
      generateProtoTask ->
        generateProtoTask.dependsOn ':proto:dh-protodoc:getProtos'
        generateProtoTask.doFirst {
          project.configurations.names.findResults { it.startsWith('protobufToolsLocator') ? it : null }.each {
            String name ->
              project.configurations.findByName(name).files.each {
                File f ->
                  f.setExecutable(true, true)
              }
          }
        }
        generateProtoTask.doFirst {
          delete generateProtoTask.outputs
        }
        generateProtoTask.builtins {
          remove java
        }
        // Use proto-gen-doc to generate docs into a single html file at proto/dh-protodoc/build/docs/index.html
        generateProtoTask.plugins {
          doc {
            option 'html,index.html'
          }
        }
    }
  }
}

It looks like the generateProtoTask.dependsOn we added which was fine in gradle 7.X is no longer happy in 8.X.

Is there maybe something that changed such that src/main/proto has become a dependency of processResources, and our generateProtoTask.dependsOn 'getProtos' should have been processResources.dependsOn instead?