ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 01.01.2026

Просмотров: 1144

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Example 49.28. Partial Build and Test Single Project

Output of gradle -a :api:build

> gradle -a :api:build :api:compileJava :api:processResources :api:classes

:api:jar

:api:assemble

:api:compileTestJava

:api:processTestResources

:api:testClasses

:api:test

:api:check

:api:build

BUILD SUCCESSFUL

Total time: 1 secs

If you have just gotten the latest version of source from your version control system which included changes in other projects that :api depends on, you might want to not only build all the projects you depend on, but test them as well. The buildNeeded task also tests all the projects from the project lib dependencies of the testRuntime configuration.

Page 294 of 343

Example 49.29. Build and Test Depended On Projects

Output of gradle :api:buildNeeded

> gradle :api:buildNeeded :shared:compileJava :shared:processResources :shared:classes :shared:jar :api:compileJava :api:processResources :api:classes

:api:jar

:api:assemble

:api:compileTestJava

:api:processTestResources

:api:testClasses

:api:test

:api:check

:api:build

:shared:assemble

:shared:compileTestJava

:shared:processTestResources

:shared:testClasses

:shared:test

:shared:check

:shared:build

:shared:buildNeeded

:api:buildNeeded

BUILD SUCCESSFUL

Total time: 1 secs

You also might want to refactor some part of the :api project that is used in other projects. If you make these types of changes, it is not sufficient to test just the :api project, you also need to test all projects that depend on the :api project. The buildDependents task also tests all the projects that have a project lib dependency (in the testRuntime configuration) on the specified project.

Page 295 of 343


Example 49.30. Build and Test Dependent Projects

Output of gradle :api:buildDependents

> gradle :api:buildDependents :shared:compileJava :shared:processResources :shared:classes

:shared:jar

:api:compileJava

:api:processResources

:api:classes

:api:jar

:api:assemble

:api:compileTestJava

:api:processTestResources

:api:testClasses

:api:test

:api:check

:api:build

:services:personService:compileJava

:services:personService:processResources

:services:personService:classes

:services:personService:jar

:services:personService:assemble

:services:personService:compileTestJava

:services:personService:processTestResources

:services:personService:testClasses

:services:personService:test

:services:personService:check

:services:personService:build

:services:personService:buildDependents

:api:buildDependents

BUILD SUCCESSFUL

Total time: 1 secs

Finally, you may want to build and test everything in all projects. Any task you run in the root project folder will cause that same named task to be run on all the children. So you can just run gra to build and test all projects.

49.9. Property and method inheritance

Properties and methods declared in a project are inherited to all its subprojects. This is an alternative to configuration injection. But we think that the model of inheritance does not reflect the problem space of multi-project builds very well. In a future edition of this user guide we might write more about this.

Method inheritance might be interesting to use as Gradle'sConfiguration Injection does not support methods yet (but will in a future release).

You might be wondering why we have implemented a feature we obviously don't like that much One reason is that it is offered by other tools and we want to have the check mark in a feature comparison :). And we like to offer our users a choice.

Page 296 of 343

[22]

49.10. Summary

Writing this chapter was pretty exhausting and reading it might have a similar effect. Our final message for this chapter is that multi-project builds with Gradle are usually not difficult. There are five elements you need to remember: allprojects, subprojects, evaluationDependsOn, e and project lib dependencies. With those elements, and keeping in mind that Gradle has a distinct configuration and execution phase, you have already a lot of flexibility. But when you enter steep territory Gradle does not become an obstacle and usually accompanies and carries you to the top of the mountain.

[19] The real use case we had, was using http://lucene.apache.org/solr, where you need a separate war for each index your are accessing. That was one reason why we have created a distribution of webapps. The Resin servlet container allows us, to let such a distribution point to a base installation of the servlet container.

[20] services is also a project, but we use it just as a container. It has no build script and gets nothing injected by another build script.

[21] We do this here, as it makes the layout a bit easier. We usually put the project specific stuff into the build script of the respective projects.

[22] So we are well in the range of the 7 plus 2 Rule :)

Page 297 of 343


50

Writing Custom Task Classes

Gradle supports two types of task. One such type is the simple task, where you define the task with an action closure. We have seen these in Chapter 6, Build Script Basics. For this type of task, the action closure determines the behaviour of the task. This type of task is good for implementing one-off tasks in your build script.

The other type of task is the enhanced task, where the behaviour is built into the task, and the task provides some properties which you can use to configure the behaviour. We have seen these in Chapter 17, More about Tasks. Most Gradle plugins use enhanced tasks. With enhanced tasks, you don't need to implement the task behaviour as you do with simple tasks. You simply declar the task and configure the task using its properties. In this way, enhanced tasks let you reuse a piece of behaviour in many different places, possibly across different builds.

The behaviour and properties of an enhanced task is defined by the task's class. When yo declare an enhanced task, you specify the type, or class of the task.

Implementing your own custom task class in Gradle is easy. You can implement a custom task class in pretty much any language you like, provided it ends up compiled to bytecode. In our examples, we are going to use Groovy as the implementation language, but you could use, for example, Java or Scala. In general, using Groovy is the easiest option, because the Gradle API is designed to work well with Groovy.

50.1. Packaging a task class

There are several places where you can put the source for the task class.

Build script

You can include the task class directly in the build script. This has the benefit that the task class is automatically compiled and included in the classpath of the build script without you having to do anything. However, the task class is not visible outside the build script, and so you cannot reuse the task class outside the build script it is defined in.

buildSrc project

You can put the source for the task class in the rootProjectDir/buildSrc/src/main/ directory. Gradle will take care of compiling and testing the task class and making it available on the classpath of the build script. The task class is visible to every build script used by the

Page 298 of 343

build. However, it is not visible outside the build, and so you cannot reuse the task class outside the build it is defined in. Using the buildSrc project approach keeps separate the task declaration - that is, what the task should do - from the task implementation - that is, how the task does it.

See Chapter 52, Organizing Build Logic for more details about the buildSrc project.

Standalone project

You can create a separate project for your task class. This project produces and publishes a JAR which you can then use in multiple builds and share with others. Generally, this JAR might include some custom plugins, or bundle several related task classes into a single library. Or some combination of the two.

In our examples, we will start with the task class in the build script, to keep things simple. Then we will look at creating a standalone project.

50.2. Writing a simple task class

To implement a custom task class, you extend DefaultTask.

Example 50.1. Defining a custom task

build.gradle

class GreetingTask extends DefaultTask {

}

This task doesn't do anything useful, so let's add some behaviour. To do so, we add a method the task and mark it with the TaskAction annotation. Gradle will call the method when the task executes. You don't have to use a method to define the behaviour for the task. You could, fo instance, call doFirst() or doLast() with a closure in the task constructor to add behaviour.

Example 50.2. A hello world task

build.gradle

task hello(type: GreetingTask)

class GreetingTask extends DefaultTask { @TaskAction

def greet() {

println 'hello from GreetingTask'

}

}

Output of gradle -q hello

> gradle -q hello

hello from GreetingTask

Let's add a property to the task, so we can customize it. Tasks are simply POGOs, and when yo

Page 299 of 343



declare a task, you can set the properties or call methods on the task object. Here we add a greet property, and set the value when we declare the greeting task.

Example 50.3. A customizable hello world task

build.gradle

//Use the default greeting task hello(type: GreetingTask)

//Customize the greeting

task greeting(type: GreetingTask) { greeting = 'greetings from GreetingTask'

}

class GreetingTask extends DefaultTask {

def String greeting = 'hello from GreetingTask'

@TaskAction def greet() {

println greeting

}

}

Output of gradle -q hello greeting

> gradle -q hello greeting hello from GreetingTask greetings from GreetingTask

50.3. A standalone project

Now we will move our task to a standalone project, so we can publish it and share it with others. This project is simply a Groovy project that produces a JAR containing the task class. Here is a simple build script for the project. It applies the Groovy plugin, and adds the Gradle API as a compile-time dependency.

Example 50.4. A build for a custom task

build.gradle

apply plugin: 'groovy'

dependencies {

compile gradleApi() groovy localGroovy()

}

Note: The code for this example can be found at samples/customPlugin/plugin which is in both the binary and source distributions of Gradle.

We just follow the convention for where the source for the task class should go.

Page 300 of 343

Example 50.5. A custom task

src/main/groovy/org/gradle/GreetingTask.groovy

package org.gradle

import org.gradle.api.DefaultTask import org.gradle.api.tasks.TaskAction

class GreetingTask extends DefaultTask { String greeting = 'hello from GreetingTask'

@TaskAction def greet() {

println greeting

}

}

50.3.1. Using your task class in another project

To use a task class in a build script, you need to add the class to the build script's classpath. To d this, you use a buildscript { } block, as described in Section 52.5, “External dependencie for the build script”. The following example shows how you might do this when the JAR containing the task class has been published to a local repository:

Example 50.6. Using a custom task in another project

build.gradle

buildscript { repositories {

maven {

url uri('../repo')

}

}

dependencies {

classpath group: 'org.gradle', name: 'customPlugin', version: '1.0-SNA

}

}

task greeting(type: org.gradle.GreetingTask) { greeting = 'howdy!'

}

50.3.2. Writing tests for your task class

You can use the ProjectBuilder class to create Project instances to use when you test your

task class.

Page 301 of 343