Invoking custom tasks in gradle - java

I have a project with lot of sub-projects. Each sub project has its own build.gradle which contains the different tasks that needs to be run for that sub-project.
Some of the sub projects have their own specific tasks, not found in other sub projects.
Lets say sub project A has taskA and taskB as its specific tasks.
Issuing gradle clean build taskA taskB from the project A's directory invokes the tasks: taskA, taskB.
How can I modify the main build.gradle to invoke taskA and taskB when compiling sub-project A?

You can use the task dependencies for that. All you need is to make your task, which compiles your source, depending on this tasks. Let's assume, you have a compile task in your subproject, then all you need is to make this task depending on taskA and taskB, like:
compile.dependsOn taskA
compile.dependsOn taskB
It should be added into the build.gradle file root for subproject.
You can read about it in the the official user guide

Related

How to register a Gradle task after configurations have been resolved?

I have several jars with test classes in the private Maven repository. As shown below, these jars are imported by a customized configuration testJar.
dependencies {
testJar "com.example:test1:1.0"
testJar "com.example:test2:1.0"
}
I want to run these tests in separate Gradle test tasks. i.e.
Execute tests in test-1.jar with task test1.
Execute tests in test-2.jar with task test2.
Why not execute these tests in the same task?
The tests in different jars may affect each other.
To achieve this, I should register tasks test1 and test2 after the configuration testJar is resolved.
You can create additional Gradle test tasks named test*, and use the include and exclude properties to configure which task runs what subset of tests. The jar has absolutely nothing to do with running tests, because Gradle doesn’t know what tests are in it. The tests are discovered at runtime by the appropriate test engine (like JUnit 5).

How to call a Gradle task in all subprojects?

Say, I have a hierarchy of Gradle projects and some of them have java plugin applied:
root
projA
projA1
projA2 (java)
projB
projB1 (java)
projB2
projB21 (java)
projB22 (java)
projC (java)
I want to execute the test task in all subprojects where this task exists: :projA:projA2:test, :projB:projB1:test and :projC:test. Probably I will add more projects in future and I don't want to manually support a list of all test tasks in all subprojects. How can I achieve it?
One thing that came to my mind is something like the following:
// In root I iterate over all subprojects and find the task by name causing
// its creation and configuration
tasks.register("testAll") {
dependsOn subprojects.findResults { it.tasks.findByName("test") }
}
I don't like this approach as it goes against task configuration avoidance style.
Another option is to iterate over subprojects and check if the java plugin is applied there:
// In root
tasks.register("testAll") {
dependsOn subprojects.findAll { it.plugins.hasPlugin("java") }.collect { it.tasks.named("test") }
}
It works but I have a filling that I miss something simpler...
EDIT 1: Sorry for that but I forgot one important detail - I need to run tests in a subtree of projects. Say, everything down the path :projB.
Unless I'm missing something, you want to run tests for all of your submodules.
You can just...do that.
./gradlew clean test
This will run the test task in all of the subprojects that have it sufficiently configured.
If you need to run the tasks in a specific subproject, from the root project you can specify the subproject you want to run the task.
./gradlew clean :projB:test
If your subprojects have a task that needs to run after test, then you can do this in your subprojects block.
subprojects {
myTask.dependsOn("test")
}

How do I make an alias for a Gradle task?

As a part of a TDD workflow, I want to be able to check if my Java codebase compiles, but not if the tests pass.
Currently, if I run gradle build it runs the compile tasks (for source and tests) and then also executes the test task (and returns a non-zero exit code since the tests fail).
So I find that I have to run gradle build -x test to exclude the test task, and get a successful zero exit code.
What do I add to my build.gradle to define a new task, say compile that is an alias for build x test?
So far I have this, but it doesn't seem like dependsOn takes any arguments to customize the build task I want to execute:
task compile {
dependsOn build
}
I've been reading the docs here, I see different kinds of dependency chaining mechanisms, but not to disable/exclude a particular task. How does the -x flag even work then? I assumed there would be a way to control it programmatically too.
Thanks to Bjørn Vester's answer and reading the docs, I have implemented my task as follows:
task compile {
dependsOn classes
dependsOn testClasses
}
There are lots of different tasks you can run individually. For instance:
gradle classes: Will compile your "main" code.
gradle testClasses: Will compile your "main" code as well as test code.
gradle jar: Will compile your "main" code and assemble it into a jar.
None of the above will run your unit tests. On the other hand, the build task depends on all of the above, as well as the test task and more.
In general, if you like to run a particular set of tasks, you do that by defining a new task and then make dependencies to those other tasks you like to run with it. You tried that already, but instead of build you should have used something like compileJava or classes whatever other tasks you need. But always check if there isn't one already that satisfies your needs, like there are in this case. You can read about what tasks are available in Java projects in the documentation for the Gradle java plugin.

Why some Gradle subproject tasks are accessible from root project?

I couldn't find any explanation on this topic, everywhere it's just given as a fact, but I'm interested in how that works.
For example let's take 'build' task, that's provided by 'java' plugin in subproject (but not available in root project).
In root we can call 'gradle build' or 'gradle :mysubproject:build'
eqally and subprojects build task will be called.
However, in root project we cannot write 'build dependsOn
someOtherTask', because it's not available in root - java plugin
isn't added there.
What makes build task available in root? Is there some property that makes task available in parent projects?
If you call Gradle with task names as arguments in a multi-project build, each task with the specified name in any root or subproject will be executed. If you only want to execute a specific task of the given name, use task paths like :mySubProject:build for a subproject or :build for the root project.
Please note, that this has nothing to do with accessing a project in a build.gradle file. In this file, only the tasks of the current project are available. To access tasks in other projects, you could use their task container like rootProject.tasks['build'] or project(':sub').tasks['build']. However, you may run into issues, cause the tasks might not be created when you try to access them.
For task dependencies, you can simply use strings that contain absolute task paths, like dependsOn ':sub:build' or dependsOn ':build'. Using just 'build' will in this context only refer to the task with the specific name in the current project.
The build task is a lifecycle task (ie a task which doesn't actually do anything itself but it can dependsOn other tasks). See base plugins which states the following about the base plugin
Adds the standard lifecycle tasks
If you want the build task in the root project you'll need to add:
apply plugin: 'base'

create gradle task in java based plugin

I have a java based gradle plugin that does some common configurations for our gradle projects. Now I want to add tasks like (currently present in our build.gradle for each project)
task javadocJar(type: Jar) {
classifier = "javadoc"
from javadoc
}
What I need is a hint on how to do this in a java based gradle plugin.
In another plugin I already register tasks using project.getTasks().create("myTask", MyTask.class); where MyTask extends AbstractTask and has a #TaskAction method to do its duty. But I'm found no way to adapt this to work with what i want to do with the sample above.
I tried to google for a solution but until now i did not find a helpfull soution as everything i find is using groovy or something similar to my snipped above directly in the build.gradle.
Thanks in advance!
Looks like I found a solution, at least for the javadoc task...
Task javadocTask = project.getTasks().getByName("javadoc");
project.getTasks().create("javadocJar", Jar.class, task -> {
task.dependsOn(javadocTask);
task.setClassifier("javadoc");
task.from(javadocTask);
});
this seems to work... but now i have an issue with the next gradle task:
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
until now i haven't found a way to get a hand on the sourceSets varialbe in Java.
Thanks in advance! :)
response to asettoufs comment:
The docs you have linked are related to projects with sub projects. What I have are multiple single projects that are not related. For those we have a plugin that already applies some plugins and configures them. so the projects have a common configuration by just applying our plugin.
Our plugin is written in java. And should continue to be java. Now we want to move some more common build config stuff to the plugin - for example some of those basic tasks as above.
To get your the source set you can ask the convention
project.getTasks().create("sourceJar", Jar.class, task -> {
task.setClassifier("sources");
// grab the convention that holds the sourceSets
JavaPluginConvention javaConvention = project.getConvention().getPlugin(JavaPluginConvention.class);
// find our source set
SourceSet mainSourceSet = javaConvention.sourceSets.findByName('main');
// user `from` like normal
task.from(mainSourceSet.getAllSource());
});
Some source code to see how the JavaPlugin creates the sourceSet written in Java
Creating the java convention
https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java#L266
Creating the sourceSets
https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/java/org/gradle/api/plugins/JavaPlugin.java#L298

Categories

Resources