AlexG AlexG - 3 months ago 38
Java Question

Gradle: Multi-project dependency: Tasks of the same name executing together

I have a multi-project dependency in my gradle build, but there's a feature that's somewhat in my way. Whenever I call a task name that exists in both projects, it calls them both. I don't like that.

My directory structure is as follows:

[Root]
---->[projA]
----------->build.gradle
---->[projB]
----------->build.gradle


So I have projB dependent on projA in my code.
Say I have a task run in projB:

task run << {
println 'projB running'
}


And I also have a task run in projA:

task run << {
println 'projA running'
}


By calling gradle run, I would get

:run
projB running
:projA:run
projA running


Is there any way to prevent some of the tasks from having this dependency? Some of them, say clean is fine, but I'd prefer to have specific tasks separate (without having to change the naming scheme).

The equivalent of what I want can be achieved by doing either:

gradle run -x :projA:run


or

gradle :run


I want a solution that is within the build file, though.

Thanks!

Answer

That fact that projB declares a project dependency on projA is irrelevant for the behavior you are seeing. If you execute a task from the root project of a multi-project build Gradle will try to find the task in any of its subprojects with the requested name and execute it. This feature is called task execution matching. Given this default behavior there's no way Gradle could know which run task you mean when executing gradle run from the root project. I'd suggest you define what you want to execute on the command line as mentioned in my previous comment.

If you really wanted to add logic to your build script, then you could achieve it with the following code:

def taskRequests = gradle.startParameter.taskRequests
def runTaskRequest = taskRequests.find { it.args.contains('run') }

if (runTaskRequest) {
    gradle.startParameter.excludedTaskNames = [':projA:run']
}

The code provided would prevent the execution of the run task for the subproject projA if you execute the command gradle run. Keep in mind that it would also exclude :projA:run if you navigate to the projA subdirectory and run the same command. If you still want to be able to execute the run task from the subdirectory, then you'll have to build in additional logic.