美文网首页
自定义 Gradle 插件

自定义 Gradle 插件

作者: simplehych | 来源:发表于2021-03-09 15:51 被阅读0次

    GitHub仓库代码

    自定义 Gradle 插件三种方式:

    1. build script
    2. buildSrc
    3. Standalone project 独立 - 本地repo
      3.1. Standalone project 独立 - 远程

    方式1: build script

    在构建脚本 build.gradle 中直接编写自定义插件的源代码。
    好处:可以自动编译并包含在构建脚本的classpath中,不需要再去声明。
    不足:这种方式实现的插件在构建脚本之外是不可见的,不能复用。

    // 方式一 build script
    // 项目根目录下 build.gradle 或者模块下 build.gradle 均可
    class GreetingPlugin implements Plugin<Project> {
    
        @Override
        void apply(Project project) {
            //新建task hello
            project.task('task_hello') {
                doLast {
                    println 'Hello from the GreetingPlugin in app'
                }
            }
        }
    }
    //引入插件
    apply plugin: GreetingPlugin
    

    验证:

    ▶ ./gradlew task_hello
    
    > Task :task_hello
    Hello from the GreetingPlugin in root
    
    > Task :app:task_hello
    Hello from the GreetingPlugin in app
    

    方式2:buildSrc

    该方式完整的目录结构

    buildSrc
    ├──.gradle
    ├── build
    ├── build.gradle
    └── src
        └── main
            └── groovy
                └── com
                    └── buildsrc
                        └── GreetingExtensionPlugin.groovy
    
    

    操作步骤:

    1. 在工程的根目录下新建 buildSrc 文件夹,rebuild工程 buildSrc 下会生成 .gradle + build 文件。

    buildSrc 名字是规定的,不能出错。XXX、buildXXX等其他文件夹rebuild不能生成文件。

    1. 在 buildSrc 文件夹下新建 build.gradle 文件,内容如下
    apply plugin: 'groovy'
    sourceSets {
        main{
            groovy {
                srcDir 'src/main/groovy'
            }
            resources {
                srcDir 'src/main/resources'
            }
        }
    }
    
    //apply plugin: 'java-library'
    //sourceSets {
    //    main{
    //        groovy {
    //            srcDir 'src/main/java'
    //        }
    //        resources {
    //            srcDir 'src/main/resources'
    //        }
    //    }
    //}
    
    1. 依次创建文件夹 buildSrc/src/main/groovy
    2. 创建包名 com/buildsrc ,新建插件代码类
    package com.buildsrc
    
    import org.gradle.api.Plugin
    import org.gradle.api.Project
    
    class GreetingExtensionPlugin implements Plugin<Project> {
    
        @Override
        void apply(Project project) {
            // Add the 'greeting' extension object
            def extension = project.extensions.create('greeting', GreetingExtension)
    
            // Add a task that uses configuration from the extension object
            project.tasks.create('task_buildSrc_greeting') {
                doLast {
                    println "${extension.message} from ${extension.greeter}"
                    println project.greeting
                }
            }
        }
    }
    
    class GreetingExtension {
        String message
        String greeter
    }
    
    1. 在项目或Module的 build.gradle 引入插件
    //build.gradle
    //引入 1  不import会提示找不到GreetingExtensionPlugin
    //import com.buildsrc.GreetingExtensionPlugin 
    //apply plugin: GreetingExtensionPlugin
    // or 引入 2
    apply plugin: com.buildsrc.GreetingExtensionPlugin
    
    greeting {
        message = 'hello'
        greeter = 'GreetingExtensionPlugin'
    }
    
    1. 验证
    ▶ ./gradlew task_buildSrc_greeting
    
    > Task :app:task_buildSrc_greeting
    hello from GreetingExtensionPlugin
    extension 'greeting'
    

    扩展属性:自定义插件代码中有一句def extension = project.extensions.create('greeting', GreetingExtension),使用这种方式来给插件代码传递参数。

    如果修改代码重新编译报错或不生效,可删除build文件夹重试
    存在GreetingExtensionPlugin/GreetingExtension飘红情况提示已经存在,不影响运行

    方式3:Standalone project 独立 - 本地repo

    上面两种自定义插件都只能在自己的项目中使用,如果想在其他项目中也能复用,可以创建一个单独的项目并把这个项目发布成一个JAR,这样多个项目中就可以引入并共享这个JAR。通常这个JAR包含一些插件,或者将几个相关的task捆绑到一个库中,或者是插件和task的组合, Standalone project创建步骤:

    1. 在Android Studio的rootProject目录下新建一个Module,类型随便选一个就行(如 Android Module),后面会有大的改动。(也可以选择IDEA来开发,IDEA中可以直接创建groovy组件)
    2. 清空Module目录下build.gradle中的所有内容,删除其他所有文件
    3. 在Module中创建src/main/groovy的目录,然后再创建包名文件夹。在main目录下再新建resources/META-INF/gradle-plugins目录,在这个目录下编写一个和插件id名字相同的.properties文件,这样Gradle就可以找到插件实现了。

    示例插件功能:新建build目录,并新建个文件写入内容
    完成项目目录如下:

    ├── build.gradle
    └── src
        └── main
            ├── groovy
            │   └── com
            │       └── example
            │           └── plugin
            │               └── CustomPlugin.groovy
            └── resources
                └── META-INF
                    └── gradle-plugins
                        └── com.example.plugin.properties
    
    
    1. 新建AndroidModule,如命名为 CustomPluginModule;清空build.gradle内容,删除其他所有文件
    2. 修改 build.gradle 内容如下:
    plugins {
        id 'groovy'
        id 'maven-publish'
        id 'maven'
    }
    
    sourceSets {
        main{
            groovy {
                srcDir 'src/main/groovy'
            }
            resources {
                srcDir 'src/main/resources'
            }
        }
    }
    
    dependencies {
        implementation gradleApi()
        implementation localGroovy()
    }
    
    repositories {
        mavenCentral()
    }
    
    group = 'com.example.plugin'
    version = '1.0.1-SNAPSHOT'
    publishing {
        repositories {
            maven {
                url = uri("$rootDir/repo")
            }
        }
        publications {
            maven(MavenPublication) {
                from components.java
            }
        }
    }
    
    1. 新建 src/main/groovy 目录,在其路径下创建包名目录如 com.example.plugin ,并创建一个名为 CustomPlugin.groovy` 的文件,内容如下:
    package com.example.plugin
    
    import org.gradle.api.DefaultTask
    import org.gradle.api.Plugin
    import org.gradle.api.Project
    import org.gradle.api.tasks.TaskAction
    
    class CustomPlugin implements Plugin<Project> {
    
        @Override
        void apply(Project project) {
            project.tasks.create('writeToFile', CustomPluginTask) {
                destination = { project.greetingFile }
                doLast {
                    println project.file(destination).text
                }
            }
        }
    }
    
    class CustomPluginTask extends DefaultTask {
        def destination
    
        File getDestination() {
            //创建路径为destination的file
            project.file(destination)
        }
    
        @TaskAction
        def greet() {
            def file = getDestination()
            file.parentFile.mkdirs()
            //向文件中写入文本
            file.write('hello world')
        }
    }
    
    1. 创建 resources/META-INF/gradle-plugins 目录,并创建以 Plugin ID 命名的文件 com.example.plugin.properties (与使用相关 apply plugin: 'com.example.plugin' ) 写入如下内容:
    // 插件的入口对应的类文件全路径 CustomPlugin.groovy
    implementation-class=com.example.plugin.CustomPlugin
    
    1. 发布该插件到本地项目repo,build.gradle 中的 publishing 任务(注意命令为publish
    ▶ ./gradlew publish  
    

    或在Android Studio的右上角打开Gradle,执行:plugin分组中的publish命令,执行完成后,会在项目根目录下生成repo仓库。

    repo
    └── com
        └── example
            └── plugin
                └── custompluginmodule
                    ├── 1.0.1-SNAPSHOT
                    │   ├── custompluginmodule-1.0.1-20210309.061711-1.jar
                    │   ├── custompluginmodule-1.0.1-20210309.061711-1.jar.md5
                    │   ├── custompluginmodule-1.0.1-20210309.061711-1.jar.sha1
                    │   ├── custompluginmodule-1.0.1-20210309.061711-1.jar.sha256
                    │   ├── custompluginmodule-1.0.1-20210309.061711-1.jar.sha512
                    │   ├── custompluginmodule-1.0.1-20210309.061711-1.module
                    │   ├── custompluginmodule-1.0.1-20210309.061711-1.module.md5
                    │   ├── custompluginmodule-1.0.1-20210309.061711-1.module.sha1
                    │   ├── custompluginmodule-1.0.1-20210309.061711-1.module.sha256
                    │   ├── custompluginmodule-1.0.1-20210309.061711-1.module.sha512
                    │   ├── custompluginmodule-1.0.1-20210309.061711-1.pom
                    │   ├── custompluginmodule-1.0.1-20210309.061711-1.pom.md5
                    │   ├── custompluginmodule-1.0.1-20210309.061711-1.pom.sha1
                    │   ├── custompluginmodule-1.0.1-20210309.061711-1.pom.sha256
                    │   ├── custompluginmodule-1.0.1-20210309.061711-1.pom.sha512
                    │   ├── maven-metadata.xml
                    │   ├── maven-metadata.xml.md5
                    │   ├── maven-metadata.xml.sha1
                    │   ├── maven-metadata.xml.sha256
                    │   └── maven-metadata.xml.sha512
                    ├── maven-metadata.xml
                    ├── maven-metadata.xml.md5
                    ├── maven-metadata.xml.sha1
                    ├── maven-metadata.xml.sha256
                    └── maven-metadata.xml.sha512
    
    1. 配置插件,在项目的根目录添加classpath和maven对应的本地uri
    buildscript {
        repositories {
            google()
            jcenter()
            // 第五步发布的repo路径
            maven {
                url = uri("$rootDir/repo")
            }
        }
        dependencies {
            ...
            classpath "com.example.plugin:custompluginmodule:1.0.1-SNAPSHOT"
        }
    }
    
    allprojects {
        ...
    }
    
    1. 引用插件
    //方式三  Standalone project
    apply plugin: 'com.example.plugin'
    ext.greetingFile="$buildDir/hello.txt"
    
    1. 验证,执行插件任务(CustomPlugin中编写的writeToFile)
    ▶ ./gradlew writeToFile
    
    > Task :app:writeToFile
    hello world
    

    方式3.1:Standalone project 独立 - 发布本地maven

    1. 安装Nexus服务
      Mac可直接使用brew安装
    brew install nexus
    

    Windows下载安装 https://www.sonatype.com/nexus/repository-oss-download

    1. 运行Nexus服务
    ▶ nexus run
            _   __
           / | / /__  _  ____  _______
          /  |/ / _ \| |/_/ / / / ___/
         / /|  /  __/>  </ /_/ (__  )
        /_/ |_/\___/_/|_|\__,_/____/
    
      Sonatype Nexus (3.30.0-01)
    
    Hit '<tab>' for a list of available commands
    and '[cmd] --help' for help on a specific command.
    Hit '<ctrl-d>' or 'system:shutdown' to shutdown.
    ...
    -------------------------------------------------
    Started Sonatype Nexus OSS 3.30.0-01
    -------------------------------------------------
    
    

    输入system:shutdown 停止服务

    1. 打开Nexus本地仓库地址 http://localhost:8081/ ,点击设置图标
    Nexus Repository Mananger
    1. Nexus创建仓库,如plugin-releases
    2. build.gradle 增加上传任务
    // 发布-nexus服务maven上传
    apply plugin: 'maven'
    uploadArchives{
        repositories{
            mavenDeployer{
                //正式发布仓库
                repository(url:"http://localhost:8081/repository/plugin-releases/"){
                    authentication(userName:"admin",password:"admin")
                }
                //快照版本的仓库
    //            snapshotRepository(url:"http://localhost:8081/repository/plugin-snapshots/"){
    //                authentication(userName:"admin",password:"admin")
    //            }
    
                pom.project {
                    //版本号,如果是快照版本,其版本号后面应该添加-SNAPSHOT,否则不能正常识别上传
                    version '1.0.0'
                    //一般写项目名称即可
                    artifactId 'customplugin'
                    //组别,类似包名,保证唯一性
                    groupId 'com.example.pluginhappy'
                    //打包格式
                    packaging 'aar'
                    //描述
                    description 'plugin'
                }
            }
        }
    }
    
    1. 执行上传任务
    ▶ ./gradlew uploadArchives
    
    1. 项目更路径build.gradle 添加插件配置
    buildscript {
        repositories {
           ...
            //方式四  Standalone project - maven仓库 - 配置
            maven {
                url 'http://localhost:8081/repository/plugin-releases/'
            }
        }
        dependencies {
          ...
            //方式四  Standalone project - maven仓库 - 配置
            classpath "com.example.pluginhappy:customplugin:1.0.0"
        }
    }
    
    allprojects {
        repositories {
            google()
            jcenter()
        }
    }
    

    插件的依赖方式 classpatch,类似库的 compile

    1. 引入插件
    //方式三、四  Standalone project - 本地repo
    // 通过 plugin id 引入插件
    apply plugin: 'com.example.plugin'
    ext.greetingFile="$buildDir/hello.txt"
    
    1. 验证
    ▶ ./gradlew writeToFile   
    
    > Task :writeToFile
    hello world
    

    方式3.2:Standalone project 独立 - 发布中央仓库

    1. 注册sonatype账号:【申请上传资格】
      https://issues.sonatype.org/secure/Signup!default.jspa

    2. 登录
      https://issues.sonatype.org/secure/Dashboard.jspa

    3. 新建Issue
      https://issues.sonatype.org/secure/CreateIssue.jspa?issuetype=21&pid=10134

    需要审核,Status状态从OPEN变成RESOLVED表示成功!如果中间有问题按Comment提示修改即可

    1. 查看Maven仓库
      https://s01.oss.sonatype.org/#view-repositories
      https://s01.oss.sonatype.org/

    2. 上传

    apply plugin: 'maven'
    uploadArchives{
        repositories{
            mavenDeployer{
                //正式发布仓库
    //            repository(url:"https://s01.oss.sonatype.org/content/repositories/releases/"){
    //                authentication(userName:"admin",password:"admin")
    //            }
                //快照版本的仓库
                snapshotRepository(url:"https://s01.oss.sonatype.org/content/repositories/snapshots/"){
                    authentication(userName:"admin",password:"admin")
                }
    
                pom.project {
                    //版本号,如果是快照版本,其版本号后面应该添加-SNAPSHOT,否则不能正常识别上传
                    version '0.0.1-SNAPSHOT'
                    //一般写项目名称即可
                    artifactId 'customplugin'
                    //组别,类似包名,保证唯一性
                    groupId 'com.github.simplehych'
                    //打包格式
                    packaging 'aar'
                    //描述
                    description 'plugin'
                }
            }
        }
    }
    

    执行上传命令

    ▶ ./gradlew uploadArchives
    
    1. 使用
    buildscript {
        repositories {
            ...
            // 方式五 Standalone project - 中央maven仓库 - 配置
            maven {
                url 'https://s01.oss.sonatype.org/content/repositories/snapshots/'
            }
        }
        dependencies {
            ...
            //方式五  Standalone project - 中央maven仓库 - 配置
            classpath "com.github.simplehych:customplugin:0.0.1-SNAPSHOT"
        }
    }
    
    //方式三、四、五  Standalone project - 本地repo
    // 通过 plugin id 引入插件
    apply plugin: 'com.example.plugin'
    ext.greetingFile = "$buildDir/hello.txt"
    

    参考资料

    感谢以下文章作者
    Gradle官网
    Gradle系列之初识Gradle
    Gradle理论与实践四:自定义Gradle插件
    Maven(6) Java上传本地jar包到maven中央仓库

    相关文章

      网友评论

          本文标题:自定义 Gradle 插件

          本文链接:https://www.haomeiwen.com/subject/boyvqltx.html