Gradle自定義插件和發(fā)布
這篇文章講解的是如何自定義gradle插件摊欠,并以本地依賴和遠(yuǎn)程依賴的方式來集成。
本文大體結(jié)構(gòu)和內(nèi)容基于:gradle官網(wǎng)的教程:開發(fā)自定義gradle插件
約定俗成的說法:
- 插件消費者項目:使用對應(yīng)插件的項目吸占。
- 開發(fā)插件的項目:獨立的,用來開發(fā)gradle插件的項目。
開始:
自定義gradle插件的三種形式:
- 直接在項目中寫一個插件,并由build.gradle直接應(yīng)用來使用汉规。
- 在獨立的項目中開發(fā)插件,并以本地依賴的形式集成驹吮。
- 在獨立的項目中開發(fā)插件针史,并以遠(yuǎn)程依賴的形式集成。
1 直接在項目中寫插件并應(yīng)用
2 在獨立的項目中開發(fā)一個插件钥屈,本地依賴
2.1 新建一個獨立的java類項目
用idea或者android studio新建一個module或者新建一個project都可以悟民,只要是能夠輕易打出jar包的項目即可。
2.1.1 build.gradle中引入gradle api的依賴
首先篷就,自定義插件類的編寫射亏,需要實現(xiàn)org.gradle.api.Plugin
接口,這個不是jdk的類竭业,而是gradle提供的接口智润,因此必須對gradle的api做一個依賴。
那么在項目的build.gradle
中寫入:
plugins {
id 'groovy'
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
//我們需要實現(xiàn)gradle的Plugin<T>接口未辆,來做自定義插件窟绷,因此依賴gradle api
implementation gradleApi()
//依賴gradle提供的groovy sdk,在編寫自定義插件的時候咐柜,用groovy更快兼蜈。
implementation localGroovy()
}
sourceCompatibility = "7"
targetCompatibility = "7"
我的例子并沒有用到groovy,所以去掉上面的localGroovy
拙友,并將groovy
插件換成java
插件也可以为狸。
2.1.2 創(chuàng)建并配置.properties文件。
其次遗契,我們寫出來的插件最終作為jar包被插件消費者項目引用辐棒,那么插件消費者項目要如何在jar包中找到我們org.gradle.Plugin
接口的實現(xiàn)類呢?以及我們在哪里定義我們的插件的id呢牍蜂?
那么漾根,需要在路徑:src/main/resources/META-INF/gradle-plugins/
下,創(chuàng)建一個aa.bb.cc.properties
名字的文件鲫竞,里面容為:
implementation-class=你的Plugin<T>接口實現(xiàn)類的全路徑名辐怕,例如:aa.bb.cc.MyPlugin
那么此時,消費者項目能夠找到插件接口實現(xiàn)類从绘,并且秘蛇,properties
文件的名字就作為你的插件id其做。
2.1.3 寫一個簡單的插件,生成一個task
package com.william.customplugin;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
/**
* date: 2019/9/6 0006
*
* @author hwj
* description 插件
*/
public class GreetingPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.task("hello", new Action<Task>() {
@Override
public void execute(Task task) {
task.doLast(new Action<Task>() {
@Override
public void execute(Task task) {
System.out.println("task hello---doLast");
}
});
}
});
}
}
以上赁还,所有的代碼編寫工作完成了妖泄。
貼出此時項目的結(jié)構(gòu):
/customPlugin
│ .gitignore
│ build.gradle
│
└─src
└─main
├─java
│ └─com
│ └─william
│ └─customplugin
│ GreetingPlugin.java
│
└─resources
└─META-INF
└─gradle-plugins
com.william.customplugin.properties
2.2 構(gòu)建項目的產(chǎn)物:jar包
注意,在這一步艘策,有兩種實現(xiàn)方案:
- 直接用build類型的gradle腳本打出一個jar包蹈胡,然后將jar包復(fù)制粘貼到插件消費者項目。
- 用gradle的
maven
或者maven-publish
插件朋蔫,來將打包的jar包發(fā)布到指定的本地路徑中罚渐。
我們先看第一種方式:
2.2.1 用build類型的gradle腳本打包
執(zhí)行
/customPlugin
$ gradlew build
構(gòu)建產(chǎn)物在:./build/libs/customPlugin.jar
此時拿到了jar包。其中包含了我們寫的org.gradle.Plugin
接口的實現(xiàn)類驯妄。
2.2.2 用maven類型的腳本打包并發(fā)布在指定的本地路徑
打開插件開發(fā)項目荷并,我們需要發(fā)布一個maven類型的軟件包。gradle為maven類型的軟件包發(fā)布提供了兩種插件:maven
和maven-publish
青扔,前者已經(jīng)被廢棄源织,現(xiàn)在最新的是后者,我們這里用后者插件來實現(xiàn)構(gòu)件一個maven類型的軟件包微猖。
我們參考的是maven-publish
文檔的最簡單的發(fā)版配置:
group = 'org.example'
version = '1.0'
publishing {
publications {
myLibrary(MavenPublication) {
from components.java
}
}
repositories {
maven {
name = 'myRepo'
url = "file://${buildDir}/repo"
}
}
}
將上述的配置移植到我們的插件開發(fā)項目的build.gradle中谈息,如下:
plugins {
id 'groovy'
id 'maven-publish'
}
group = "com.william.customplugin"
version = "1.0"
publishing {
publications {
myLibrary(MavenPublication) {
from components.java
}
}
//倉庫配置
repositories {
maven {
//name這個屬性是用來指定倉庫名字的,貌似在這里沒什么用凛剥,注釋掉侠仇。
//name = 'myRepo'
//指定發(fā)布倉庫的路徑
url = "./build/repo"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation gradleApi()
implementation localGroovy()
}
sourceCompatibility = "7"
targetCompatibility = "7"
接下來就是執(zhí)行一個task,來構(gòu)建并發(fā)布了犁珠。
maven-publish
腳本帶來了task publish
逻炊,他會執(zhí)行所有的發(fā)布任務(wù)。而我們這里只有一個發(fā)布任務(wù)犁享,所以執(zhí)行他就好了余素。
gradlew publish
===>
14:45:49: Executing task 'publish'...
Executing tasks: [publish] in project C:\AndroidProject\KotlinSimpleTest\customPlugin
> Task :customPlugin:generatePomFileForMyLibraryPublication
> Task :customPlugin:compileJava UP-TO-DATE
> Task :customPlugin:compileGroovy NO-SOURCE
> Task :customPlugin:processResources UP-TO-DATE
> Task :customPlugin:classes UP-TO-DATE
> Task :customPlugin:jar UP-TO-DATE
> Task :customPlugin:publishMyLibraryPublicationToMavenRepository
> Task :customPlugin:publish
BUILD SUCCESSFUL in 4s
5 actionable tasks: 2 executed, 3 up-to-date
14:45:53: Task execution finished 'publish'.
OK,現(xiàn)在跑去./build/repo
下面找我們的軟件包吧饼疙。
├─repo
│ └─com
│ └─william
│ └─customplugin
│ └─customPlugin
│ │ maven-metadata.xml
│ │ maven-metadata.xml.md5
│ │ maven-metadata.xml.sha1
│ │
│ └─1.0
│ customPlugin-1.0.jar
│ customPlugin-1.0.jar.md5
│ customPlugin-1.0.jar.sha1
│ customPlugin-1.0.pom
│ customPlugin-1.0.pom.md5
│ customPlugin-1.0.pom.sha1
輸出的整個包多了很多東西,我們用普通的`build`命令打出來的jar包慕爬,只有一個單獨的jar包窑眯,而用`maven-publish`插件打出來的包,囊括了完整的全路徑名医窿,帶有pom文件用于描述依賴磅甩,帶有maven元數(shù)據(jù)等等,這是一個完整的姥卢、可用于分發(fā)的軟件了
2.3 在插件消費者項目中使用插件
2.3.1 直接使用本地的jar包中的插件卷要。
拿到j(luò)ar包后渣聚,把他放在一個可以被找到的路徑,我把他放在了插件消費者項目的根目錄的gradle_plugin_libs/
目錄下僧叉。
└─gradle_plugin_libs
customPlugin.jar
一般來說奕枝,安卓項目都采用的是gradle的multi-project-build組織類型,所以我打算在根目錄下讓gradle對我的腳本進(jìn)行一個依賴瓶堕,以便子項目不需要再自己去聲明對腳本的依賴隘道。
即rootProject/build.gradle
下:
buildscript{
repositories{
//...
}
dependencies{
classpath 'com.android.tools.build:gradle:3.4.1'
//...
//注意,之類不能用classpath郎笆,因為classpath指定的是以標(biāo)準(zhǔn)的maven格式構(gòu)建的軟件包谭梗。
//我們這里是直接用jar的,classpath識別不了宛蚓,會報錯激捏。因此用classpath files()
classpath files ('./gradle_plugin_libs/customPlugin.jar')
}
}
//..
隨意地找一個項目的構(gòu)建腳本,寫上:apply plugin: 'com.william.customplugin'
凄吏。(注意远舅,插件Id是properties文件的名字)
執(zhí)行命令:gradlew hello
--> 輸出: task hello---doLast
大功告成~
2.3.2 使用本地maven倉庫下的jar包中的插件
將2.2.2節(jié)構(gòu)建出的軟件包整個復(fù)制到gradle_plugin_libs/
中。
修改根目錄構(gòu)建腳本:rootProject/build.gradle
buildscript{
repositories{
//...
//指定一個maven倉庫的路徑
maven {
url uri('./gradle_plugin_libs')
}
}
dependencies{
//...
//用標(biāo)準(zhǔn)的classpath方法竞思,來找到我們的插件
classpath('com.william.customplugin:customPlugin:1.0')
}
}
//..
執(zhí)行gradlew hello
表谊,輸出和上一節(jié)一樣。
大功告成~
2.4 如何測試插件盖喷?
待補充
3 在獨立的項目中開發(fā)一個插件爆办,遠(yuǎn)程依賴
上面我們對插件進(jìn)行了本地依賴的方式來使用,現(xiàn)在我們將我們的插件打出的軟件包上傳到遠(yuǎn)程倉庫上课梳,讓別的開發(fā)者也能快速地集成距辆。
3.1 新建一個獨立的java類項目
我們就用上述的那個插件開發(fā)項目,不用再新建了暮刃。
3.2 將構(gòu)建的jar包上傳到一個遠(yuǎn)程倉庫
遠(yuǎn)程倉庫有兩個類型:
- 大家所熟知的中央倉庫:例如
mavenCentral
跨算,jcenter
,jitpack
- 普通的遠(yuǎn)程倉庫
他們本質(zhì)上都是一樣的椭懊,只是那3個中央倉庫是用的人最多的诸蚕。
我們現(xiàn)在通過bintray
這個軟件包發(fā)行平臺,來上傳并管理我們的軟件包氧猬。
bintray
用于上傳maven類型的軟件包有3種方式背犯,我們的其中一種是通過gradle的方式:https://github.com/bintray/gradle-bintray-plugin。這是bintray官方開發(fā)的上傳插件盅抚,專門用于打包和上傳maven類型的軟件包到bintray上面漠魏,選項多,可自定義程度高妄均,使用復(fù)雜柱锹。
在github上有一個快捷方便的第三方開發(fā)者開發(fā)的插件:https://github.com/novoda/bintray-release
只需要一個代碼塊就能完成bintray上傳的配置哪自,這里我們用這個簡單的插件來做演示,當(dāng)然大家可以根據(jù)自己業(yè)務(wù)的需求選擇負(fù)責(zé)度和功能性更高的官方插件禁熏。
3.2.1 創(chuàng)建bintray賬號
在這一步壤巷,要完成的事項如下:
- 創(chuàng)建bintray賬號
- 創(chuàng)建一個要上傳該軟件包的倉庫
- 在上述倉庫下創(chuàng)建一個package,即創(chuàng)建一個軟件包匹层,軟件包需要和你后面上傳的軟件包名字相同隙笆。(我很納悶為什么一定要創(chuàng)建了一個包才能上傳,不能上傳的時候沒有包bintray就自己創(chuàng)建嗎升筏,真是奇怪撑柔,我在這一步停滯了很久...)
3.2.2 配置bintray上傳腳本
plugins {
id 'groovy'
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation gradleApi()
implementation localGroovy()
}
sourceCompatibility = "7"
targetCompatibility = "7"
//以上是默認(rèn)的內(nèi)容,以下是上傳腳本的配置您访,可以說是非常簡潔了铅忿。
//應(yīng)用插件
apply plugin: 'com.novoda.bintray-release'
//上傳配置
publish {
userOrg = "huangwilliam33333"http://組織,如果沒有創(chuàng)建組織灵汪,就直接填寫用戶名檀训。
groupId = 'com.william'//group
artifactId = 'customPlugin'//module
publishVersion = '1.0'//版本
desc = '自定義測試用的插件'//描述
website = 'htttp://www.baidu.com'//網(wǎng)站,隨便填
bintrayUser = "huangwilliam33333"http://用戶名
bintrayKey = "xxx"http://bintray秘鑰
dryRun = false//如果這個是true享言,則只是運行峻凫,而不會上傳,要配置成false
}
執(zhí)行gradlew clean build bintrayUpload
上傳成功览露。
3.3 在另一個項目中依賴這個遠(yuǎn)程倉庫荧琼,并使用該插件
到插件消費者項目中:
我們還是在根目錄應(yīng)用插件:
buildscript {
ext.kotlin_version = '1.3.41'
repositories {
google()
jcenter()
//因為還沒有將軟件包加入到Jcenter,所以要指明maven地址
maven{
url "https://dl.bintray.com/huangwilliam33333/maven"
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath 'com.novoda:bintray-release:0.9.1'
//依賴插件
classpath('com.william:customPlugin:1.0')
}
}
插件的使用和前面一樣差牛。
3.4 如何測試插件
待補充
參考資料:
講到了bintray創(chuàng)建了倉庫后還要創(chuàng)建軟件包才能上傳
https://stackoverflow.com/questions/35302414/adding-local-plugin-to-a-gradle-project