美文网首页
gradle学习笔记(tmp)

gradle学习笔记(tmp)

作者: 以梦为马驾驾驾 | 来源:发表于2022-04-03 16:38 被阅读0次

    gradle学习笔记

    优点:

    1. 支持了各种不同的依赖传递管理, 本地文件系统jar包, 还是maven, ivy的方式
    2. 是第一个构建集成工具, 可以将ant tasks, maven pom 转化成一个gradle脚本
    3. 方便移植
    4. gradle wrapper, 哪怕本地没有gradle, 也可以构建, 且还是用的设定好的版本
    5. 使用动态语言编写脚本很强大, groovy, 而不是xml, 且还有无其他好处, 等用到再体会吧
    6. 申明式的(个人感觉)

    安装

    jvm 参数配置, gradle 运行时的jvm参数可以通过: GRADLE_OPTS 或者是 JAVA_OPTS来设置, 且同时生效, 但是注意, JAVA_OPTS 的修改对其他java应用是共享的

    基础

    概念差别

    Projects 和 tasks的差异

    gradle的构建是由单个或者多个projects组成的, 每个projects包括许多可构建组成部分, 可以是一个jar包, 或者一个web app, 或者其他项目产生的压缩包, jar包等. 而project内部由各个tasks组成, 每个task代表了执行过程中的一个原子操作, 像编译, 打包, 生产javadoc, 发布到仓库等.

    入门

    定义task

    task hello {
      doLast{
        println 'hello world'
      }
    }
    task hello {
        println 'hello'   //这是采用闭包的方式定义的task
    }
    

    groovy

    采用groovy作为脚本语言, 它的语法十分简单, 在我看来又像java , 又像python , 还像scala.

    class Example {
        static void main(String[] args) {
            int x = 4;
            int X = 6;
            println("sum of x and X is: " + (x+X));
        }
        
    }
    

    变量定义, 基本数据类型, 基本运算符都与java类似, 循环 不过多了个for-in, 方法的定义也差不多, 不过它对闭包的支持比java好些.

    使用groovy定义gradle任务

    task count << {
        4.times {println '$it'}  // 相当于 4.times { it -> println(it) }   
    }
    

    任务(task)构建

    任务依赖关系

    dependsOn: xxx , 且task的申明定义顺序与依赖顺序无关

    task hello << {
        println 'hello'
    }
    
    task intro(dependsOn: hello) {
        println 'i am gradle'
    }
    
    
    
    延迟依赖
    延迟依赖的作用是什么?

    在多项目构建中, 可以让taskX在taskY之前的定义, 且taskX依赖taskY.

    动态任务

    什么是动态任务: 任务的行为定义是推迟的, 推迟到被选择的时候, 依据传入的参数变化

    4.times { count ->
        task "task$counter" << {
            println "i am task number $counter"
        }
    }
    

    执行

    > gradle -q task1
    i am task number 1    //执行task1, task1的任务在被选择的时候被定义, 且行为也确定下来, 这是语言的特性还是?
    

    任务创建后, 需要通过api进行相互之间的访问, 于是, 可以通过api , 增加任务之间的依赖, 这是否可以称之为动态依赖.

    task0.dependsOn task2, task3 // 任务0,1,2,3都是上面的动态任务创建的
    
    > gradle -q task0
    i am task number 2
    ................ 3
    ................ 0
    

    通过api给任务增加行为, 类似于python的动态添加方法以及切面行为, 比如给任务添加doFirst, doLast,分别会被添加到任务执行的开头和结尾, 当任务执行时候, 会按照特定顺序执行, 另外 << 是doLast的简写方式.

    hello << {xxx}等同于 hello.doLast {xxx}
    
    短标记法

    通过 someTask.name 访问到任务的属性, 还可以通过 ext 为task增加自定义属性

    task myTask {
        ext.myPro = "myPro"
    }
    
    task printSomeProp << {
        println myTask.myPro
    }
    
    调用Ant 任务

    许多老的项目都是用ant构建, 或者从ant转化而来. Ant任务是gradle中的一等公民, gradle用grovvy对ant任务进行了整合, 自带AntBuilder, 这样Gradle中调用Ant任务比在 build.xml 中更方便和强大.

    利用AntBuilder 创建任务, 执行任务
    task loadfile << {
        def files = file('../ddddir').listFiles().sort()
        files.each { File file -> 
            if (file.isFile()) {
                ant.loadFile(srcFile: file, property: file.name)
                println " ** $file.name **"
                println "${ant.properties[file.name]}"
            }   
        }
    }
    

    gradle -q loadfile

    定义默认任务

    defaultTasks ..., .... 这个语法可以在build.gradle 文件的开头定义默认任务, 并且在执行的时候gradle -q 就可以, 而不用指定任务名.

    DAG配置
    task distribution << {
        println "We build the zip with version=$version"
    }
    task release(dependsOn: 'distribution') << {
        println 'We release now'
    }
    gradle.taskGraph.whenReady {taskGraph ->
        if (taskGraph.hasTask(release)) {
            version = '1.0'
        } else {
            version = '1.0-SNAPSHOT'
        }
    }
    

    whenReady会在已发布的任务之前影响到已发布任务的执行, 在这里发布的命令如果是distribution, 那么回事1.0-snapshot, 而如果是release, 则是1.0

    实战

    gradle是通用工具,通过脚本构建可以实现任意的构建

    java构建

    gradle已经提供了java插件来适应java程序相似的流程: 编译源码, 单元测试, 创建jar包. 且插件还为工程定义了许多默认值, 比如源码的位置等等, 而工程遵循插件的默认值会让脚本文件更加简单, 当插件不满足时, 也可以自定义插件.

    使用在build.gradleapply plugin: 'java'

    这样就为工程添加了java的插件, 和内置的任务. 默认值的工程结构:

    project
      + build
      + src/main/java
      + src/main/resources
      + src/test/java
      + src/test/resources
    

    Gradle 默认会从 src/main/java 搜寻打包源码,在 src/test/java 下搜寻测试源码。并且 src/main/resources 下的所有文件按都会被打包,所有 src/test/resources 下的文件 都会被添加到类路径用以执行测试。所有文件都输出到 build 下,打包的文件输出到 build/libs 下.

    构建项目的任务

    > gradle build
    :compileJava
    :processResources
    :classes
    :jar
    :assemble
    :compileTestJava
    :processTestResources
    :testClasses
    :test
    :check
    :build
    BUILD SUCCESSFUL
    

    JDK在编译的时候,会或许系统的编码, 如果用的是windows系统, 可能是GBK编码, 需要在gradle中设置下:

    tasks.withType(JavaCompile) {
        options.encoding = "UTF-8"
    }
    

    参考: https://blog.csdn.net/weixin_42356453/article/details/119828358

    clean

    删除build目录以及所有构建完成的文件.

    assemble

    编译并且打包jar/war文件, 但不会执行单测.

    check

    编译并且测试代码, 有些插件还会增强这个任务的功能, 比如Code-quality 插件执行的CheckStyle

    外部依赖

    gradle集成了各种依赖传递管理的方式

    maven
    repositories {
        mavenCentral()   
    }
    

    其他添加依赖的方式如:

    dependencies {
        compile group: xxx, name: yyyy, version: zzz
        testCompile group: xx, name: yy, version: zz
    }
    

    自定义项目

    sourceCompatibility=11  // 项目源码版本, 还可以设置目标字节码版本
    version= '1.0'
    jar {
        manifest {
            attributes 'Implementation-Title': 'Gradle Quickstart', 'Implementation-Version': version
        }
    }
    

    为test添加属性

    test {
        systemProperties 'proterty': 'value'
    }
    

    定义属性,添加属性, 以控制脚本行为

    发布项目
    uploadArchives {
        repositories {
            flatDir {
                dirs 'repos'
            }
        }
    }
    

    执行gradle uploadArchives 将jar包发布

    多项目构建

    需要在根目录中创建一个setting.gradle 来指明构建需要包含的项目

    include "shard", "api", "services:webservice", "services:shared"
    

    看lucene的

    pluginManagement {
        repositories {
            mavenCentral()
            gradlePluginPortal()
        }
    }
    
    rootProject.name = "lucene-root"
    
    includeBuild("dev-tools/missing-doclet")
    
    include "lucene:analysis:common"
    include "lucene:analysis:icu"
    include "lucene:analysis:kuromoji"
    include "lucene:analysis:morfologik"
    include "lucene:analysis:morfologik.tests"
    include "lucene:analysis:nori"  
    
    公共配置

    多项目构建, 有些公共配置, 可以写在根目录的配置里, 子项目会迭代访问它并将其注入到自己的配置中

    subprojects {
        apply plugin: 'java'
        apply plugin: 'xxxx'
        repositories {
            mavenCentral()
        }
        version = '1.0'
        dependencies {
            testComple 'junit:junit:4.11'
        }
        version = '1.0'
        jar {
          manifest.attribute provider: 'gradle'
        }
    
    }
    
    多项目的工程依赖

    项目之间的依赖是在子项目的构建文件build.gradle 中的定义的, 比如需要先build shared, 再build api, 即api 依赖shared, 那么在api的构建文件里:

    dependencies {
        compile project(':shared')
    }
    
    多项目工程的构建发布

    api/build.gradle

    task dist(type: zip) {
       dependsOn spiJar
       from 'src/dist'
        into('libs') {
            from spiJar.archivePath
            from configuration.runtime
        }
    }
    
    artifacts {
        archives dist
    }
    

    依赖管理基础

    什么是依赖管理?

    答: 一: gradle 需要知道项目构建或者运行所需要的一些文件, 以及如何找到文件, 这成为项目的依赖. 二: 项目构建完成后, 需要自动上传到某些地方, 称之为发布.

    工程的依赖, 需要开发人员告诉gradle, 工程依赖什么, 他们在哪里, gradle 会帮助开发人员将它们加入到构建中, 如果在远程, 比如maven或者ivy库, 就会下载, 这个过程称之为: 依赖解决.

    而依赖的自身也可能会依赖其他依赖, 这叫做: 依赖传递, gradle在构建的时候也会深入寻找它们.

    最后构建完成, 需要发布到某个地方被使用, 什么需要被发布, 发布到哪里, 以什么样的形式发布出去, 这个过程叫做: 发行.

    依赖配置

    比如java, java的依赖, 在不同工程的不同时期可以不同, 有些只需要在编译的时候需要,有些只需要运行时有就可.

    compile

    编译范围依赖在所有的 classpath 中可用,同时它们也会被打包

    runtime

    runtime 依赖在运行和测试系统的时候需要,但在编译的时候不需要。比如,你可能在编译的时候只需要 JDBC API JAR,而只有在运行的时候才需要 JDBC 驱动实现

    testCompile

    测试期编译需要的附加依赖

    testRuntime

    测试运行期需要

    不同的插件提供了不同的标准配置,你甚至也可以定义属于自己的配置项。

    外部依赖

    和maven类似, 需要三元组 group:name:version来定位一个依赖. 三元组前是依赖的不同阶段.

    仓库

    如果不使用中央仓库: mavenCentral()

    repositories {
        maven {
            url "http://repo.mycompany.com/maven2"
            或者 
            url = uri("http://xxx")
        }
    }
    repositories {
        ivy {
            url "http://repo.mycompany.com/repo"
        }
    }
    repositories { // 本地
        ivy {
            // URL can refer to a local directory
            url "../local-repo"
        }
    }
    
    发布
    uploadArchives {
        repositories {
            ivy {
                credential {
                    username: xx
                    password: uu
                }
                url "http:/......"
            }
        }
    }
    

    当发布到maven仓库时候, 语法换一下, 且需要maven插件的支持以生成对应的pom.xml

    apply plugin: 'maven'
    uploadArchives {
        repositories {
            mavenDeployer {
                repository(url: "file://localhost/tmp/myRepo/")
            }
        }
    }
    

    todos

    1. 编写脚本
    2. 任务详细
    3. 使用文件
    4. 调用ant
    5. 构建环境
    6. java插件
    7. scala插件
    8. osgi插件
    9. checkstyle插件

    相关文章

      网友评论

          本文标题:gradle学习笔记(tmp)

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