Task dependencies aren't being inferred for manual copy task

(Jeff Sussna) #1

Continuing a question I posted on the old gradle-users forum: I need to upload some random files in addition to the jars that get built by my gradle build. I am uploading everything to a flatDir file-server repository. I tried using DefaultPublishArtifact to add my random files to the archives list, so they’d get automatically uploaded by uploadArchives. Problem is the uploaded files got version numbers added to their file names. So I dropped back to using copy tasks to upload the non-jar files.

That works fine, except when I try to wrap everything up in a single task, like:

task doEverything {


dependsOn(uploadArchives) }

The issue is that I’m trying to do this in a multi-project build. Project A has a ‘compile project’ dependency on project B. If I run ‘gradle uploadArchives’ then project B’s jar file gets built AND uploaded. But if I run ‘gradle doEverything’ only project A’s jar gets uploaded. I tried adding ‘archives project(’:B’) to my dependencies list, but that didn’t help. I can make it work by adding ‘dependsOn(’:b:uploadArchives’) to doEverything, but that seems to miss the whole spirit of automatic transitive dependency management.

(Peter Niederwieser) #2

Transitive dependency management is about artifact dependencies, not about task dependencies. It’s true that Gradle can often infer task dependencies for tasks that declare their inputs (and ‘doEverything’ doesn’t), but this feature is not a good fit here. If feasible, I’d put the ‘doEverything’ task into the parent project of A and B. Then I’d add explicit task dependencies as necessary. Instead of listing dependencies separately, you can also say things like:

doEverything.dependsOn(getTasksByName("uploadArchives", true))

This makes the task depend on all ‘uploadArchives’ tasks in this project and subprojects.

(Jeff Sussna) #3

I’m clearly missing something. If I invoke A’s uploadArchives task it uses the compile dependency on B to infer that B’s uploadArchives task should be run. But if I invoke A’s doEverything task, which in turn invokes A’s uploadArchives task, why doesn’t the same inference take place? Perhaps I am misunderstanding the semantics of “dependsOn”.

(Luke Daley) #4

Invoking a:uploadArchives won’t invoke b:uploadArchives through task dependencies. I think you are just executing “uploadArchives” and b:uploadArchives is being executed due to descendant name matching.

The project dependency from “a” to “b” (i.e. “a” has a project dependency on “b”) means that “a:uploadArchives” will cause “b:jar” to be executed, as that is the dependency that creates the file that “a” depends on.

If you run “gradle clean” for your project, you will see that the “clean” task for all projects gets executed. This is not the task dependency mechanism in action.

(Jeff Sussna) #5

You are right. If I create a doEverything task in B’s build file, it gets executed by “gradle doEverything” simply because of “include ‘B’” in my settings.gradle file.

On the other hand, getTasksByName is only returning the root project uploadArchives task, even with recursive set to true.

(Peter Niederwieser) #6

You’ll have to make sure that the uploadArchives tasks are available on the child projects before you call getTasksByName() in the parent project. If this isn’t the case already, I’d just add explicit task dependencies, e.g. ‘doEverything.dependsOn(“a:uploadArchives”)’.