Upload
lamanh
View
229
Download
0
Embed Size (px)
Citation preview
Introduction to Gradle
Hans Dockter - Gradle Inc.Jan 21, 2010
• A general purpose build system• It comes with a Groovy DSL and a Java core.• Provides build-in support for Java, Groovy,
Scala, Web, OSGi projects.• Gradle provides exciting solutions for many of the
big pain points you often have with current builds.
2
What is Gradle?
What is Gradle?
Gradle is declarative
You specify the WHAT
Gradle figures out the HOW
Source Set Sample
apply: ʻjavaʼ
dependencies { testCompile 'junit:junit:4.7' integrationTestCompile 'commons-collections:commons-collections:3.2'}
sourceSets { integTest { java.srcDir file('src/int-test/java') resources.srcDir file('src/int-test/resources') compileClasspath = sourceSets.main.classes + sourceSets.test.classes + configurations.integrationTestCompile runtimeClasspath = classes + compileClasspath }}
Plugins
apply ʻjavaʼ
dependencies { testCompile 'junit:junit:4.7' integrationTestCompile 'commons-collections:commons-collections:3.2'}
sourceSets {
> gradle classes
> gradle test
> gradle assemble
Dependencies
usePlugin(ʻjavaʼ)configurations { integrationTestCompile.extends testRuntime }dependencies { compile 'org.springframework:spring-core:3.0' testCompile 'junit:junit:4.7' integrationTestCompile 'commons-collections:commons-collections:3.2'}sourceSets { integTest { java.srcDir file('src/int-test/java') resources.srcDir file('src/int-test/resources') compileClasspath = sourceSets.main.classes + sourceSets.test.classes + configurations.integrationTestCompile runtimeClasspath = classes + compileClasspath }}
The how for the source set
> gradle integTestClasses
sourceSets { integTest { java.srcDir file('src/int-test/java') resources.srcDir file('src/int-test/resources') compileClasspath = sourceSets.main.classes + sourceSets.test.classes + configurations.integrationTestCompile runtimeClasspath = classes + compileClasspath }}
Autowiring
sourceSets { integTest { java.srcDir file('src/int-test/java') resources.srcDir file('src/int-test/resources') compileClasspath = sourceSets.main.classes + sourceSets.test.classes + configurations.integrationTestCompile runtimeClasspath = classes + compileClasspath }}
> gradle -t:integTestClasses -> :classes, :testClasses
Typed Tasks
sourceSets { integTest { ... }}
task integrationTest(type: Test, dependsOn: jar) { testClassesDir = sourceSets.integTest.classesDir classpath = sourceSets.integTest.runtimeClasspath options.systemProperties['jar.path'] = jar.archivePath}
> gradle -t:integrationTest -> :classes, :integrationTestClasses, :jar, :testClasses
SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.
Gradle is
declarativewithout
being rigid
The Build Language
Source Sets
Dependencies
Configurations
Archives
ProjectsArtifacts
Custom Tasks
Plugins
• Many source dirs per project• Dependencies per source dir• JDK per source dir• Many artifacts per project• Multiple projects per source directory
12
Build Language Examples
Deep API
tasks.withType(Jar).allObjects { jarTask -> jarTask.manifest.mainAttributes(Provider: "Gradle Inc.") }
tasks.withType(Compile).allObjects { compile -> compile.options.fork.executable = “$pathToJavac” }
sourceSets.allObjects { sourceSet -> // add task with name obfuscate + sourceSet.name // task with name classes + sourceSet.name depends on obfuscate // obfuscate depends on compile + sourceSet.name}
dependencies.allObjects { dependency -> throwExceptionIfDependencyIsGPL(dependency) }
Extensible Domain Objects
tasks.withType(Jar).allObjects { jarTask ->jarTask.osgi = new DefaultOsgiManifest()jarTask.doFirst { task -> importOsgiManifestIntoManifest(task) }
}...task myJar(type: Jar) { osgi.include(...) }
dependencies.allObjects { dependency ->dependency.maven = new DefaultMavenDescriptor()
}...dependencies { compile(“commons-lang:commons-lang:3.2”) { maven.optional = true }}
Rich API
usePlugin ʻjavaʼ
test {whenTestFails { test -> println(ʻTest Failed:ʼ + test.name)}
}
task analyzeFailedTests(dependsOn: test) << {List failedTests = test.failedTests // do something
}
Custom Tasks
task hello(type: HelloTask)
task greeting(type: HelloTask) { greeting = 'greetings from HelloTask'}
class HelloTask extends DefaultTask { def String greeting = 'hello from HelloTask'
@TaskAction def printGreeting() { println greeting }}
Custom Plugins
class GreetingPlugin implements Plugin { def void use(Project project) { project.task('hello') << { println "Hello from the GreetingPlugin" } project.greetingDate = new Date() }}
apply type: org.gradle.GreetingPlugin
apply url: ʻhttp://github.com/hansd/huglins/raw/master/greetings.gradleʼ
task hello << { println "Hello from the GreetingPlugin"}project.greetingDate = new Date()
Custom Declarative Elements
usePlugin ʻeditionsʼ
productEditions {enterprise core, plugins, powerAddonspublic core, plugins, openApi
}
> gradle enterpriseEditionZip> gradle publicEditionTar
SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.
ExtensibleBuild Language
instead of a Build Framework
XML and the What
It does not matter muchwhether a build systemuses XML or Groovy for
declaring things.
SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.
Often not all
aspectsof a build
can be solved with the default
declarative elements.
Simple Imperative Examples
apply id: ʻjavaʼ
task date << { println “Today is ${new Date()}” }
task someTask(dependsOn: compile) << { println ʻCount the number of compiled classesʼ}
compile.doFirst { println ʻCompilation will start nowʼ}
> gradle dateToday is Tue Oct 20 15:27:03 CDT 2009
Imperative/Declarative
usePlugin ʻgroovyʼ
task ide << { copy { from configurations.runtime into ʻmyLibDirʼ }}
task sources << {sourceSets.test.allGroovy.matching {include '**/*Demo*' }.files.each {
println “$it.absolutePath”}
}
SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.
Pleaseno
messybuild scripts
SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.
ExecutionHeaven
• Evaluate the build scripts– They configure the WHAT and HOW of the build.
• Build a DAG of tasks to be executed – Includes test, compile, compileTests, ... tasks
• Execute the tasks of the DAG
26
Build Lifecycle
> gradle test
• Hooks for customizing all phases of the lifecycle• The DAG is exposed to the build script
Deep Execution API
version = ʻ1.0ʼgradle.taskGraph.whenReady { graph ->
if (!graph.hasTask(“release”)) { version += ʻ-ʼ + System.currentTimeMillis()}
}compile.doFirst { compileTask -> println build.taskGraph.allTasks if (gradle.taskGraph.hasTask(ʻcodeGenerationʼ)) { compileTask.include ʻsomePackageʼ } }build.taskGraph.beforeTask { task -> println(“Free memory: “ + Runtime.runtime.freeMemory())}build.taskGraph.afterTask { task, exception -> if (task instanceof Jetty && exception != null) { // do something }}
28
Smart Exclusion
> gradle A -x B Executes A and E
A
B
C
D
E depends on
29
Smart Merging
> gradle clean compile; gradle test
test
compileclean
resources
> gradle clean compile test
depends on
Camel Case Execution
task myNameIsPrettyLong << { println 'Long name'}
task someOtherTask(dependsOn: myNameIsPrettyLong) << { println "Other task"}
> gradle sOtherT -x myNaIPOther task
Rules
tasks.addRule("Pattern: uploadTo<ID>") { String taskName -> if (taskName.startsWith("uploadTo")) { task(taskName) << { // add task println "Uploading to: " + (taskName - 'uploadTo') } }}task groupPing(dependsOn: [uploadTo1, uploadTo2])
> gradle uploadTo545Uploading to 545
> gradle groupUploadUploading to 1Uploading to 2
SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.
Performanceis one of the
biggestpain points
of complex builds.
• No clean required for a reliable build• Based on the input, output and task state, Gradle
decides whether to execute a task or not• This is a generic service that can be easily made
use of by custom tasks.
33
Incremental Builds
jar input: ʻbuild/classesʼjar state: compression ratejar output: ʻbuild/libs/classes.jarʼ
• Specify number of threads• Specify fork frequency• Pipelines for multiple process configurations
(jdk14, jdk15)• Remote Listeners
34
Native Multi-Process Test Runners
SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.
IntegratingwithAntand
Maven
Using Ant tasks
ant { taskdef name: "groovyc", classname: "org.groovy.ant.Groovyc" groovyc srcdir: "src", destdir: "${webinf}/classes", { classpath {# fileset dir: "lib" {# include name: "*.jar" }# pathelement path: "classes" } javac source: "1.5", target: "1.5", debug: "on" }}
Deep Integration withAnt Builds
> gradle helloHello, from Gradle...Here comes Ant...[ant:echo] Hello, from Ant
<project> <target name="hello" depends="intro"> <echo>Hello, from Ant</echo> </target></project>
ant.importBuild 'build.xml'
hello.doFirst { println 'Here comes Ant' }task intro << { println 'Hello, from Gradle'}
• Integration with Maven repositories
– autogeneration of pom.xml
– install to local Maven repo
– deploy to any remote Repo
– full maven metadata generation
• Integration of Maven builds in the future
38
Integrating with Maven
Dependency Management
usePlugin(ʻjavaʼ)
configurations { allJar.extends runtime}
dependencies { compile "commons-lang:commons-lang:3.1", "org.hibernate:hibernate:3.2" runtime “mysql:mysql-connector-java:5.1.6” testCompile "junit:junit:4.4" allJar "commons-io:commons-io:1.4"}
task jarAll(type: Jar) { merge(configurations.allJar.files)}
Dependency Management
dependencies { compile("org.hibernate:hibernate:3.2") { exclude module:cglib }}
• Transitive Dependencies• Excludes per configuration or dependency• Very flexible repository handling• Based on Apache Ivy• Powerful API
• Arbitrary Multiproject Layout• Configuration Injection• Separate Config/Execution Hierarchy• Partial builds
41
Multi-Project Builds
Gradle GUI
> gradle --gui
Gradle Wrapper
>./gradlew assemble
• Very active community (mailing-list, patches, issues)• Apache v2 license.• Excellent user’s guide (200+ pages) + many samples• Frequent releases, multiple commits per day• Quality is king:
– 2800 unit tests, Many hundreds of integration test– Healthy codebase– low defect rate
• Commiter -> Steve Appling, Hans Dockter, Tom Eyckmans, Adam Murdoch, Russel Winder
44
Project Background
Q&A