Gradle的核心并没有为构建的自动化提供太多直接的帮助,更多的特性是由插件完成的。比如编译java代码也是由插件完成的。插件可以增加新的任务(比如JavaCompile
),domain对象(比如SourceSet
),约定(比如,java代码放在src/main/java
),以及一些其他的对象,也包括从其他插件扩展出来的对象。
把插件应用到项目中可以扩展项目的功能,它可以做以下事情:
通过应用插件比直接通过构建脚本来实现的好处多多,比如:
在Gradle中有两种插件:脚本插件和二进制插件。脚本插件是额外的构建脚本,进一步配置构建,常常用于声明一些操作构建的方法,它们通常在构建内部使用。二进制插件是实现了Plugin的类,并且通过编程方式来操作构建,二进制插件可以在构建脚本中,也可以在buildSrc中,也可以以jar的方式导入。
插件通常开始只是一个脚本插件,但是随着代码价值的增加,便会迁移成二进制插件,以便分享出来给其他人使用
要想使用插件的封装逻辑,只需两步就可以,第一步解析插件,第二步把插件应用到目标中,目标通常就是项目。
解析插件意思就是找到给定包含插件的jar的正确版本,并把它添加到脚本的classpath中,一旦插件被解析,它的API就能在构建脚本中使用,脚本插件可以以应用它们的文件路径和URL自解析,核心的二进制插件作为Gradle的一部分来自动解析。
应用插件实际上就是在应用插件的项目上执行插件的Plugin.apply(T)
方法。应用插件的是idempotent
的,也就是你可以多次应用任意插件。
使用插件最常见的用例就是解析插件并将它应用到当前项目。用于这是最常见的用例,因此建议构建脚本的编写者,一步就可以包含这两个步骤。
apply from: 'other.gradle'
脚本插件是可以自动解析的,它可以是相对于项目目录的本地路径,也可以是个http的远程路径,
你可以通过插件的id来应用插件,对插件来说id是唯一标识符,同时也是插件的名字。Gradle的核心插件比较特殊,你只需提供id的简称就可以,比如核心javaPlugin,使用简称java
就可以引入,但是对于之外的二进制插件则必须使用全称,比如com.github.foo.bar
。
插件简单的说就是实现了Plugin
接口的类,Gradle将核心插件作为发布的一部分提供出来,这意味着核心插件可以自动解析。但是非核心的二进制插件就需要在应用之前得到解析,它通常通过下面几种方式实现:
新的插件DSL提供一种简洁而方便的定义插件依赖的方法,它和Gradle的插件官网一起工作,可以非常方便的访问核心库和社区库的插件。插件的DSL代码块其实是在配置PluginDependenciesSpec
实例。
使用核心插件可以使用简称
plugins {
id 'java'
}
如果从插件官网使用社区版插件,就需要使用全称了
plugins {
id 'com.jfrog.bintray' version '0.4.1'
}
这种添加插件的方法不至于方便,插件DSL的处理方法可以更早更快的解析插件,使得Gradle可以做一些聪明的事情:
在执行剩余的构建脚本之前,它需要在这种方式下更早更快的指定插件,它也需要插件的定义在某种程度上是静态的
新的plugins{}
块并不支持所有的groovy代码,它的约束是为了幂等(每次都产生相同的结果)的和无副作用(在任何时候都是安全的)
格式如下:
plugins {
id «plugin id» version «plugin version» [apply «false»]
}
«plugin version»
和«plugin id»
必须是常量,文字或字符串,apply
则必须是bool类型(可以用于快速禁用插件),如果写了其他之外的语句,将会引起编译错误。
plugins {}
在构建脚本中还需要是顶级语句,不能嵌套在其他结构内部,比如if-esle
条件结构或者for
循环结构。
plugins {}
目前仅仅可以使用在构建脚本中,而不能使用在脚本插件,settings.gradle
和初始化脚本。
在多项目构建中,你可能想吧插件应用到一部分或者所有的子项目,而不是根项目,plugins {}
默认的行为是快速解析和应用插件,但是你可以通过apply false
来告诉Gradle不要应用插件,然后通过apply plugin: «plugin id»
应用到子项目中。
settings.gradle
include 'helloA','helloB','goodbyeC'
build.gradle
plugins {
id 'com.lastsweetop.plugin.greeting' version '0.4' apply false
id 'com.lastsweetop.plugin.goodbye' version '0.4' apply false
}
subprojects { subproject ->
if (subproject.name.startsWith('hello')) {
apply plugin: 'com.lastsweetop.plugin.greeting'
}
if (subproject.name.startsWith('goodbye')) {
apply plugin: 'com.lastsweetop.plugin.goodbye'
}
}
如果你运行gradle hello
你将会看到只有helloA
和helloB
两个子项目应用了greeting
插件
± % gradle hello
> Task :helloA:hello
Hello from the GreetingPlugin
> Task :helloB:hello
Hello from the GreetingPlugin
BUILD SUCCESSFUL in 0s
2 actionable tasks: 2 executed
默认情况下,plugins {}
DSL将会从Gradle插件官网下载插件,但很多构建者想从自己的私有Maven仓库下载Gradle插件,因为可能需要私有的实现细节,而且可以更好的控制插件的可用性。
为了指定自定义的插件资源库,需要在settings.gradle
中使用pluginManagement {}
下嵌套的repositories {}
块
pluginManagement {
repositories {
maven {
url 'http://127.0.0.1:8081/repository/sweetop/'
}
gradlePluginPortal()
}
}
这会告诉Gradle首先在http://127.0.0.1:8081/repository/sweetop/
资源库中查找,如果没有找到然后才会寻找官方的插件资源库,如果你不想寻找官方资源库,可以去掉gradlePluginPortal()
插件解析规则允许你修改插件在plugins {}
块中的请求模式,比如修改插件请求的版本或者明确指定实现插件的工件位置。
为了修改解析规则,你需要在pluginManagement {}
中使用resolutionStrategy {}
pluginManagement {
resolutionStrategy {
eachPlugin {
if (requested.id.namespace=="com.lastsweetop.plugin") {
useModule('com.lastsweetop.plugin:helloPlugin:0.4')
}
}
}
repositories {
maven {
url 'http://127.0.0.1:8081/repository/sweetop/'
}
gradlePluginPortal()
}
}
这会明确指定插件需要的jar,而不是插件内部指定的jar坐标。
pluginManagement {}
块必须出现在settings.gradle
文件中,而且必须是文件的第一个块,自定义的Maven资源库中必须包含插件标记工件。
由于plugins {}
的DSL块只定义了插件的id和版本,Gradle需要一种方式可以查找实现了插件的工件,Gradle会以plugin.id:plugin.id.gradle.plugin:plugin.version
这样的格式去匹配插件标记工件,这个标记工件依赖于实际的插件实现,而且是由java-gradle-plugin
来发布的。
例如,helloPlugin项目会使用maven-publish
插件和java-gradle-plugin
插件的组合将com.lastsweetop.plugin.greeting
和com.lastsweetop.plugin.goodbye
插件发布到Maven仓库中,
apply plugin: 'groovy'
apply plugin: 'maven-publish'
apply plugin: 'java-gradle-plugin'
gradlePlugin {
plugins {
hello {
id = "com.lastsweetop.plugin.greeting"
implementationClass = "com.lastsweetop.plugin.GreetingPlugin"
}
goodbye {
id = "com.lastsweetop.plugin.goodbye"
implementationClass = "com.lastsweetop.plugin.GoodbyePlugin"
}
}
}
publishing {
repositories {
maven {
url "http://127.0.0.1:8081/repository/sweetop/"
credentials {
username 'admin'
password 'admin123'
}
}
}
}
运行gradle publish
会在maven资源库产生如下的资源样式:
二进制插件可以被发布成外部的jar文件,然后通过将其增加到构建脚本的classpath中来进一步应用插件。外部的jar想要添加到构建脚本的classpath中需要使用buildscript {}
块
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:0.4.1"
}
}
apply plugin: "com.jfrog.bintray"