Gradle 学习笔记
以下示例内容来自udacity
基础知识
// 常见示例,示例来源: taskgroovy{} println"Hello Groovy!"// classclassJavaGreeter{publicvoidsayHello(){System.out.println("Hello Java!")} } JavaGreetergreeter = newJavaGreeter() greeter.sayHello() // 类型推断deffoo = 6.5// 获取变量值,其他脚本语言中也常见println"foo has value: $foo"//{}中为表达式println"Let's do some math. 5 + 6 = ${5 + 6}"// 内置属性,获取class 类型println"foo is of type: ${foo.class} and has value: $foo"foo = "a string"println"foo is now of type: ${foo.class} and has value: $foo"// 函数,无需书写return,默认返回最后一个表达式的值defdoubleIt(n){n + n } foo = 5println"doubleIt($foo) = ${doubleIt(foo)}"foo = "foobar"println"doubleIt($foo) = ${doubleIt(foo)}"// 无括号调用函数defnoArgs(){println"Called the no args function" } defoneArg(x){println"Called the 1 arg function with $x"x } deftwoArgs(x, y){println"Called the 2 arg function with $x and $y"x + y } oneArg500// Look, Ma! No parentheses!twoArgs200, 300noArgs() //noArgs // Doesn't work//twoArgs oneArg 500, 200 // Also doesn't work as it's ambiguoustwoArgsoneArg(500), 200// Fixed the ambiguity
闭包和对象
taskgroovy{} deffoo = "One million dollars"// 定义闭包defmyClosure ={println"Hello from a closure"println"The value of foo is $foo" } // 闭包传递myClosure() defbar = myClosuredefbaz = barbaz() // lambdadefdoubleIt ={x -> x + x} defapplyTwice(func, arg){func(func(arg)) } foo = 5deffooDoubledTwice = applyTwice(doubleIt, foo) println"Applying doubleIt twice to $foo equals $fooDoubledTwice"// list示例defmyList = ["Gradle", "Groovy", "Android"]def printItem ={item -> println "Listitem: $item"}myList.each(printItem)// class 和 对象class GroovyGreeter{ String greeting = "Defaultgreeting" def printGreeting(){println "Greeting: $greeting"}}def myGroovyGreeter = new GroovyGreeter()myGroovyGreeter.printGreeting()myGroovyGreeter.greeting = "Mycustomgreeting"myGroovyGreeter.printGreeting()// 委托def greetingClosure ={ greeting = "Settingthegreetingfromaclosure" printGreeting() } // greetingClosure() // This doesn't work, because `greeting` isn't defined greetingClosure.delegate = myGroovyGreeter greetingClosure() // This works as `greeting` is a property of the delegate
- 依赖关系
- 基本关系:单依赖配置
- dependsOn: 依赖于另外一个task, 被依赖的task需要先执行
task putOnSocks{doLast{println "Putting on Socks." } } task putOnShoes{dependsOn "putOnSocks" doLast{println "Putting on Shoes." } } - finalizedBy: 一个任务执行完后,需要跟随执行的任务(终结/尾随任务)
task eatBreakfast{finalizedBy "brushYourTeeth" doLast{println "Om nom nom breakfast!" } } task brushYourTeeth{doLast{println "Brushie Brushie Brushie." } } - shouldRunAfter: A shouldRunAfter B,意味着:
- 只执行task A。 task B 不会执行
- 如果taskA,B都需要执行,则需要先执行B,再执行A。
task takeShower{doLast{println "Taking a shower." } } task putOnFragrance{shouldRunAfter "takeShower" doLast{println "Smellin' fresh!" } }
- dependsOn: 依赖于另外一个task, 被依赖的task需要先执行
- 多依赖配置
task getReady{// Remember that when assigning a collection to a property, we need the // equals sign dependsOn = ["takeShower", "eatBreakfast", "putOnShoes"] } // 灵活配置 putOnShoes.mustRunAfter takeShower task getEquipped{dependsOn tasks.matching{task -> task.name.startsWith("putOn")} doLast{println "All geared up!" } }
- 基本关系:单依赖配置
- 类型化任务
- 特定操作的任务,如文件拷贝、删除、压缩,gradle提供了许多内置的限定类型的任务
// 拷贝taskcopyWeb(type: Copy){from'src/web'from('src/docs'){include'*.txt'into'help' } into'build/web' } // 压缩taskbundleWeb(type: Zip, dependsOn: copyWeb){baseName = 'web'destinationDir = file('build') from'build/web'exclude'images/**' } // 解压taskunpackBundle(type: Copy, dependsOn: bundleWeb){fromzipTree('build/web.zip') into'build/exploded' } // 删除taskdeleteHelp(type: Delete, dependsOn: copyWeb){delete'build/web/help' }
- 自定义类型任务
// 定义 class HelloNameTask extends DefaultTask{String firstName // TaskAction注解说明从类中创建的任务操作 @TaskAction void doAction(){println "Hello, $firstName" } } // 使用 task helloName(type: HelloNameTask){firstName = 'Jeremy' }
- 特定操作的任务,如文件拷贝、删除、压缩,gradle提供了许多内置的限定类型的任务
- 增量构建
- 自动增量构建,避免重复构建
- Gradle 会跟踪每个任务的输入输出,任务执行前,会保存该任务使用的输入快照。如果一个任务没有任务快照或者快照发生改变,则Gradle会重新执行该任务。同理,如果输入没有发生改变,而且输出自上次任务之后也没被更改过,则Gradle则会跳过任务执行
- 脚本参数传递,如下面的
task printGreeting示例,如何将greeting参数值传递到脚本中task printGreeting{doLast{println greeting } }gradle.properties文件中定义greeting = "Hello from a properties file"- 命令行直接传递:
gradle printGreeting -Pgreeting="Hello from the command line" - 脚本内部定义
ext{greeting = "Hello from inside the build script" } - 优先级:脚本内部定义 > 命令行 >
properties文件
- 故障排除和记录
- 日志级别,从高到低
- ERROR: Error messages, -
- QUIET: -q, 包括程序打印信息
- WARNING: Warning messages
- LIFECYCLE: default, 从当前开始运行的任务构建话费的总时间以及是否构建成功
- INFO: -i, 详细介绍每个任务所需的以及其他高级事件
- DEBUG: -d, 会输出大量Gradle的内部信息
- 输出程序执行stacktrace
- gradle -s # 部分堆栈信息
- gradle -S # 完全堆栈信息
- 日志级别,从高到低
- 构建生命周期
- initialization: 多个项目的构建设置
- configuration: 决定运行哪个task,以及task运行顺序
- execution: 运行
- 进行各种项目构建之前,优先考虑基础plugin,官方文档
- 依赖管理
- 中央仓库配置:
// 本地仓库配置repositories{flatDir{dirs'libs' } } // 最常见的配置方式,mavenCentral, mavenLocal, jcenter都是常用的代码库repositories{mavenCentral() mavenLocal() jcenter() } // maven,ivy 解析repositories{maven{url'https://repo.foo.org/m2' } } repositories{ivy{url'https://repo.foo.org/ivy'credentials{username'user'password'secret' } } } // 支持的协议包括:HTTP,HTTPS,SFTP repositories{ivy{url'file:///home/user/repo' } }
- 中央仓库配置:
- 依赖配置
dependencies{compile'com.google.guava:guava:18.0'// 与上面的配置等价// compile group: 'com.google.guava', name: 'guava', version: '18.0'// 本地文件compilefiles('libs/foo.jar', 'libs/bar.jar') // 目录树,依赖多个文件compilefileTree(dir: 'libs', include: '*.jar') }
- 依赖报告
gradle dependencies查看项目依赖报告,包括传递依赖gradle dependencies --configuration runtime查看运行时间配置的依赖gradle dependencyInsight --dependency commons-logging查看项目中使用的特定依赖,可用于依赖冲突查看
- 自定义依赖配置
// 自定义依赖配置 configurations{custom } dependencies{custom 'com.google.guava:guava:18.0' } // compile阶段依赖会在testCompile阶段继续使用,有种“继承”的感觉 dependencies{compile 'commons-logging:commons-logging:1.1.3' testCompile 'junit:junit:4.12' } - Test
testCompile 'junit:junit:4.12'添加合适的测试依赖gradle testtest构建,自动执行test代码build/reports/tests/index.html自动生成的test报告
- 插件检索
- wrapper 意味着Gradle版本也是版本控件,考证所有人的gradle版本是一致的
gradle wrapper生成Gradle wrapper- wrapper使用
./gradlew tasks
- wrapper 配置gradle版本
wrapper{gradleVersion = '2.14.1' }
- 增量构建内部原理