- 创建任务,并在“自定义”插件中使用它
- 独立的自定义插件
- 简短的插件ID
- 使用settings.gradle自定义Gradle设置
项目信息:
摇篮版本:1.1 操作系统平台:Ubuntu 12.10 先决条件:基本了解Gradle脚本。
创建独立的自定义插件
- 创建目录结构
|-custom-plugin | |-plugin | |-src | |-main | | |-groovy | | | |-com | | | |-code4reference | | | |-gradle | | |-resources | | | |-META-INF | | | |-gradle-plugins | |-test | | |-groovy | | | |-com | | | |-code4reference | | | |-gradle |-user
这里的插件目录包含所有源代码和资源文件,而用户目录包含使用自定义插件的使用者脚本。 执行以下命令以创建目录结构。 这里的groovy文件夹包含源代码包。
$ mkdir -p custom-plugin/plugin/src/main/groovy/com/code4reference/gradle $ mkdir -p custom-plugin/plugin/src/main/resources/META-INF/gradle-plugins $ mkdir -p custom-plugin/user
- 自定义插件源代码
每个插件都应该有一个实现类来扩展Plugin类。 让我们定义插件类。
package com.code4reference.gradle; import org.gradle.api.*; class Code4ReferencePlugin implements Plugin { def void apply(Project project) { //c4rTask task has been defined below. project.task('c4rTask') << { println 'Hi from Code4Reference plugin!' } } }
将此文件放在custom-plugin / plugin / src / main / groovy / com / code4reference / gradle目录中。 在这里, c4rTask任务已定义为打印一条简单的线。
- 简短的插件ID
为了应用插件,我们通常使用一个简短的ID,例如apply plugin:'java'。 这里的“ java”是org.gradle.api.plugins.JavaPlugin类的简短插件ID。 简短的插件ID可以通过简单的步骤进行定义。 为此,我们需要创建一个属性文件,并将其放在类路径下的META-INF / gradle-plugins目录中。 文件名将是我们的短ID。 该属性文件必须包含以下所示的行,并且应指向插件实现类。 让我们将属性文件创建为code4reference.properties,并将其指向Code4ReferencePlugin类。
implementation-class=com.code4reference.gradle.Code4ReferencePlugin
- Gradle脚本生成插件
为了编译和构建此插件,我们将编写gradle脚本。 在插件目录中创建名为build.gradle的文件, 然后在其中复制下面的内容。
apply plugin: 'groovy' apply plugin: 'maven' dependencies { compile gradleApi() groovy localGroovy() } repositories { mavenCentral() } group='com.code4reference' //Group name makes easier to manager the packages. version='1.1-SNAPSHOT' uploadArchives { repositories { mavenDeployer { repository(url: uri('../repo')) } } }
在此gradle脚本中,我们使用groovy插件编译groovy源代码,并将gradleAPI声明为编译时间依赖项。 您可能已经注意到我们使用了maven插件。 它基本上会创建插件jar文件并将其存储在maven存储库中。 在这里,我们在父目录中创建名为repo的Maven存储库,并将jar文件存储在其中。
- 构建插件并放入存储库
$ gradle uploadArchives #This will put the plugin-version.jar in maven repository. :compileJava UP-TO-DATE :compileGroovy UP-TO-DATE :processResources UP-TO-DATE :classes UP-TO-DATE :jar :uploadArchives Uploading: com/code4reference/plugin/1.1-SNAPSHOT/plugin-1.1-20120816.163101-1.jar to repository remote at file:/home/rakesh/programming/mygitrepo/Code4Reference/GradleExample/custom-plugin-1/repo/ Transferring 5K from remote Uploaded 5K BUILD SUCCESSFUL Total time: 34.892 secs
- 使用settings.gradle注入设置
当执行以上命令时,gradle会从settings.gradle中获取项目名称。 如果当前目录中不存在settings.gradle文件,则它将获取当前目录的名称并将其假定为项目名称。 然后,它形成存储jar文件的路径。 文件路径约定如下/group/name/projectName/version/projectname-version-timestamp.jar 。 您可能会在上面的输出中注意到jar路径名和jar文件名带有插件字,因为当前目录名是plugin,并且gradle假定它为项目名。 如果要覆盖此属性,并将code4ReferencePlugin作为项目名称,则需要在插件目录中创建settings.gradle文件,并放入下一行。
rootProject.name = 'code4ReferencePlugin'
现在再次执行命令以生成插件jar文件。
$gradle uploadArchives compileJava UP-TO-DATE :compileGroovy UP-TO-DATE :processResources UP-TO-DATE :classes UP-TO-DATE :jar UP-TO-DATE :uploadArchives Uploading: com/code4reference/code4ReferencePlugin/1.1-SNAPSHOT/code4ReferencePlugin-1.1-20120816.164441-5.jar to repository remote at file:/home/rakesh/programming/mygitrepo/Code4Reference/GradleExample/custom-plugin-1/repo/ Transferring 5K from remote Uploaded 5K BUILD SUCCESSFUL Total time: 8.61 secs
现在问题解决了。 该jar将以名称code4ReferencePlugin- [version] -timestamp.jar生成。 如果要查找有关gradle和系统属性的更多信息,请在此处找到。
使用自定义插件
这确实是一个简单的步骤。 尽管我们使用其他插件,但是自定义插件也可以类似的方式使用。 现在在用户目录中创建另一个build.gradle文件,并复制下面给出的代码。
buildscript {
repositories {
maven {
url uri('../repo')
}
}
dependencies {
classpath group: 'com.code4reference',
name: 'code4ReferencePlugin',
version: '1.1-SNAPSHOT'
}
}
apply plugin: 'code4reference'
build.gradle脚本访问父目录中存在的Maven存储库。 我们还定义了依赖关系,该依赖关系基本上是从Maven访问jar文件的特定版本。 最后但并非最不重要的一点是,我们应用简短的插件ID“ code4reference”。 要运行此gradle脚本,请在用户目录中的终端上执行以下命令。
$ gradle c4rTask #Remember we have created c4rTask in Code4ReferencePlugin class.
#You will get the following output.
:c4rTask
Hi from Code4Reference plugin!
BUILD SUCCESSFUL
Total time: 3.908 secs
Voilà! 您刚刚创建了自定义插件,并在其他项目脚本中使用了它。 您可以在此处找到本教程的源代码。 Code4参考
现在,将涵盖以下主题。
- 定义自定义任务类
- 将参数传递给自定义插件任务
- 嵌套参数
- 测试自定义插件
项目信息:
项目名称:Gradle自定义插件
摇篮版本:1.1 操作系统平台:Ubuntu 12.10 先决条件:基本了解Gradle脚本。
在这里,我们将遵循第一部分中列出的相同目录层次结构。
- 定义自定义任务
让我们定义一个名为Code4ReferenceTask的自定义类,该类扩展了DefaultTask类,并将此文件放在保存Code4ReferencePlugin.groovy的同一文件夹中。 这个类包含一个名为showMessage(),这是标注有@TaskAction方法。 执行任务时,Gradle会调用此方法。
package com.code4reference.gradle; import org.gradle.api.DefaultTask import org.gradle.api.tasks.TaskAction class Code4ReferenceTask extends DefaultTask { @TaskAction def showMessage() { println '----------showMessage-------------' } }
现在,我们需要在Code4ReferencePlugin.groovy中进行一些小的修改,以包含自定义任务。 修改后的Code4ReferencePlugin类如下。
package com.code4reference.gradle; import org.gradle.api.*; class Code4ReferencePlugin implements Plugin { def void apply(Project project) { //Define the task named c4rTask of type Code4ReferenceTask project.task('c4rTask', type: Code4ReferenceTask) } }
您可能会注意到,与过去的实现相比,只有突出显示的行已更改。 现在,“ c4rTask”是Code4ReferenceTask类型的。 在插件目录中执行gradle uploadArchives命令。 这将更新Maven存储库中的jar文件。 现在,使用相同的旧build.gradle在用户目录中执行以下命令。 我们将获得以下输出。
$gradle c4rTask :c4rTask ----------showMessage------------- BUILD SUCCESSFUL Total time: 14.057 secs
- 将参数传递给自定义插件任务
上面的实现是最简单的,并没有做很多事情。 如果我们想将Gradle脚本的参数传递给该任务怎么办? 我们可以通过访问扩展对象来实现。 Gradle项目具有一个关联的ExtensionContainer对象,该对象有助于跟踪传递给插件类的所有设置和属性。 让我们定义一个扩展类,它可以容纳参数并将其传递给Task类。 Code4ReferencePlugin类中的突出显示的行有助于将参数传递给Task类。
package com.code4reference.gradle; import org.gradle.api.*; //For passing arguments from gradle script. class Code4ReferencePluginExtension { String message = 'Hello from Code4Reference' String sender = 'Code4Reference' } class Code4ReferencePlugin implements Plugin { def void apply(Project project) { project.extensions.create('c4rArgs', Code4ReferencePluginExtension) project.task('c4rTask', type: Code4ReferenceTask) } }
我们已将Code4ReferencePluginExtension定义为Extension类,其中包含两个变量message和sender。 这些用作自定义任务的参数。 我们需要修改Code4RefernceTask类以访问参数。 高亮显示的行已添加到以前的Code4ReferenceTask类实现中。
package com.code4reference.gradle; import org.gradle.api.DefaultTask import org.gradle.api.tasks.TaskAction class Code4ReferenceTask extends DefaultTask { @TaskAction def showMessage() { println '------------showMessage-------------------' println 'From : ${project.c4rArgs.sender},\ message : ${project.c4rArgs.message}' } }
在插件目录中执行gradle uploadArchives命令。 这将更新Maven存储库中的jar文件。 另外,我们需要更新用户目录中的build.gradle。
//custom-plugin-2/user buildscript { repositories { maven { url uri('../repo') } } dependencies { classpath group: 'com.code4reference', name: 'code4ReferencePlugin', version: '1.2-SNAPSHOT' } } apply plugin: 'code4reference' c4rArgs { sender = 'Rakesh' message = 'Hello there !!!!' }
您可能已经注意到,已经添加了c4rArgs闭包,并且在闭包中设置了发件人和消息变量。 这两个变量可在showMessage()方法中访问。 现在运行用户目录中存在的build.gradle。 我们得到以下输出。
$gradle c4rTask :c4rTask -------------------------showMessage----------------------------- From : Rakesh, message : Hello there !!!! BUILD SUCCESSFUL Total time: 15.817 secs
- 嵌套参数
如果我们想传递嵌套参数怎么办? 我们可以通过嵌套扩展对象来实现。 这是Code4ReferencePlugin类的代码。 此类中仅添加了突出显示的行。
package com.code4reference.gradle; import org.gradle.api.*; //Extension class for nested argumetns class C4RNestedPluginExtention { String receiver = 'Admin' String email = 'admin@code4reference.com' } //For keeping passing arguments from gradle script. class Code4ReferencePluginExtension { String message = 'Hello from Code4Reference' String sender = 'Code4Reference' C4RNestedPluginExtention nested = new C4RNestedPluginExtention() } class Code4ReferencePlugin implements Plugin { def void apply(Project project) { project.extensions.create('c4rArgs', Code4ReferencePluginExtension) project.c4rArgs.extensions.create('nestedArgs',C4RNestedPluginExtention) project.task('c4rTask', type: Code4ReferenceTask) } }
现在也该修改Code4ReferenceTask类。 在此类中添加了突出显示的行,以访问嵌套的参数。
package com.code4reference.gradle; import org.gradle.api.DefaultTask import org.gradle.api.tasks.TaskAction class Code4ReferenceTask extends DefaultTask { @TaskAction def showMessage() { println '------------showMessage-------------------' println 'From : ${project.c4rArgs.sender},\ message : ${project.c4rArgs.message}' println 'To : ${project.c4rArgs.nestedArgs.receiver},\ email : ${project.c4rArgs.nestedArgs.email}' } }
在插件目录中再次执行gradle uploadArchives命令以更新Maven存储库中的jar文件。 现在,修改用户目录中存在的build.gradle文件以传递嵌套参数。
buildscript { repositories { maven { url uri('../repo') } } dependencies { classpath group: 'com.code4reference', name: 'code4ReferencePlugin', version: '1.2-SNAPSHOT' } } apply plugin: 'code4reference' c4rArgs { sender = 'Rakesh' message = 'Hello there !!!!' nestedArgs{ receiver = 'gradleAdmin' email = 'gradleAdmin@code4reference.com' } }
我们已在build.gradle文件中添加了突出显示的行。
- 测试插件和任务
代码测试是代码开发的重要方面。 现在,我们将为自定义任务和插件添加单元测试。 为此,我们需要为测试类创建目录结构。 我们需要将测试文件夹放在src目录中。 在插件目录中执行以下命令以创建测试目录。
$mkdir -p src/test/groovy/com/code4reference/gradle/
测试目录结构遵循用于源代码包目录的相同包目录结构。 在此目录中,放入Code4ReferencePlugin和Code4ReferenceTask的测试类。 在测试类中,ProjectBuilder用于访问项目对象。 这些测试用例易于编写,类似于Junit测试用例。 测试类的代码如下:
package com.code4reference.gradle; import org.junit.Test import org.gradle.testfixtures.ProjectBuilder import org.gradle.api.Project import static org.junit.Assert.* class Code4ReferenceTaskTest { @Test public void canAddTaskToProject() { Project project = ProjectBuilder.builder().build() def task = project.task('c4rtakstest', type: Code4ReferenceTask) assertTrue(task instanceof Code4ReferenceTask) } }
package com.code4reference.gradle; import org.junit.Test import org.gradle.testfixtures.ProjectBuilder import org.gradle.api.Project import static org.junit.Assert.* class Code4ReferencePluginTest { @Test public void code4referencePluginAddsCode4ReferenceTaskToProject() { Project project = ProjectBuilder.builder().build() project.apply plugin: 'code4reference' println 'code4referencePluginAddsCode4ReferenceTaskToProject' assertTrue(project.tasks.c4rTask instanceof Code4ReferenceTask) } }
要运行测试,请在plugin文件夹中执行以下命令。
$gradle test #For success test cases. :compileJava UP-TO-DATE :compileGroovy UP-TO-DATE :processResources UP-TO-DATE :classes UP-TO-DATE :compileTestJava UP-TO-DATE :compileTestGroovy :processTestResources UP-TO-DATE :testClasses :test BUILD SUCCESSFUL Total time: 42.799 secs $gradle test #In case of test case failure, #you can expect output similar to given below. :compileJava UP-TO-DATE :compileGroovy UP-TO-DATE :processResources UP-TO-DATE :classes UP-TO-DATE :compileTestJava UP-TO-DATE :compileTestGroovy :processTestResources UP-TO-DATE :testClasses :test com.code4reference.gradle.Code4ReferencePluginTest > code4referencePluginAddsCode4ReferenceTaskToProject FAILED java.lang.AssertionError at Code4ReferencePluginTest.groovy:14 2 tests completed, 1 failed FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':test'. > There were failing tests. See the report at: file:///home/rakesh/programming/mygitrepo/Code4Reference/GradleExample/custom-plugin-2/plugin/build/reports/tests/index.html * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. BUILD FAILED
Gradle测试提供了测试报告及其位置。 可以使用任何浏览器打开此文件以检查堆栈跟踪。
参考: Gradle自定义插件(第1部分) , 我们的JCG合作伙伴 Rakesh Cusat的Gradle自定义插件(第2部分)位于Code4Reference博客上。
翻译自: https://www.javacodegeeks.com/2012/08/gradle-custom-plugin.html