Date post: | 26-Jan-2015 |
Category: |
Technology |
Upload: | tomek-kaczanowski |
View: | 104 times |
Download: | 0 times |
2010
Gradle
Tomek Kaczanowskihttp://kaczanowscy.pl/tomek
Gradle
2010
IMPORTANT
All code samples are compatible with version
0.9-preview-3
2010
There are no simple builds
2010
2010
• Flexible build tool
• Based on convention over configuration idea
• Groovy (DSL)
• Open source
• Project Manager: Hans Docter
• GitHub
• First release: April 2008
making the impossible possible, the possible easy, and the easy elegant
-- Moshé Feldenkrais
2010
Table of Contents• Warm-up
– Command line, GUI, tasks, DAG
• Competition– Ant, Maven & Co
• MyProject: Core, UI:Web, UI:Swing– CoC + customization
– Compilation (Java, Groovy), JAR/WAR,
– artifacts handling (repositories & dependencies),
– custom logic (tasks)
– Gradle & Ant
– Multi-module builds• Layout
• Partial builds
2010
Intro
2010
Intro - DAG
• Read and manipulate graph of tasks, e.g.:
task release(dependsOn: assemble) << { println 'We release now‘
}
gradle.taskGraph.whenReady { taskGraph ->
if (taskGraph.hasTask(':release')) { version = '1.0‘
} else {version = '1.0-SNAPSHOT‘
} }
2010
Intro - DAG
• Read and manipulate graph of tasks, e.g.:
gradle.taskGraph.beforeTask { Task task -> println "executing $task ..."}
gradle.taskGraph.afterTask { Task task, TaskState state ->
if (state.failure) {println "FAILED"
}else {
println "done"}
}
2010
Intro - summary
• DSL• Command line, GUI (+ IDE plugins)
– Reports– Prunning of tasks tree (-x)– User friendly (camel case, dry run)
• Rich tasks layer– Tasks dependencies– DAG– Runtime manipulation
2010
Frameworkitis is the disease that a framework
wants to do too much for you or it does it in a way that you don't want but you can't change it. It's fun to get all this functionality for free, but it hurts when the free functionality gets in the way. […] To get the desired behavior you start to fight against the framework. And at this point you often start to lose, because it's difficult to bend the framework in a direction it didn't anticipate.
[…] Frameworks try to be in control and tell you when to do what. A toolkit gives you the building blocks but leaves it up to you to be in control.
Erich Gamma, www.artima.com
2010
2010
2010
2010
MyProject• Core
– Classes used by UI subprojects– Java
• UI:Web– Web application
• UI:Swing– Desktop application– Groovy
2010
Conventionover
configuration
.|-- build.gradle`-- src |-- main | `-- java `-- test `-- java
2010
Conventionover
configuration
.|-- build.gradle`-- src |-- main | `-- java `-- test `-- java
apply plugin: 'java'
2010
Configurationis always possible
.|-- build.gradle`-- src |-- main | `-- java `-- test `-- java
apply plugin: 'java'
version="1.0-SNAPSHOT"
archivesBaseName = "whatever"
libsDirName="build/artifacts"
apply plugin: 'java'
2010
Configurationis always possible
.|-- build.gradle`-- src |-- main | `-- java `-- test `-- java
apply plugin: 'java'
.|-- build.gradle|-- src`-- test
2010
Configurationis always possible
.|-- build.gradle`-- src |-- main | `-- java `-- test `-- java
apply plugin: 'java'
.|-- build.gradle|-- src`-- test
apply plugin: 'java'
sourceSets { main { java { srcDir 'src' } } test { java { srcDir 'test' } }}
2010
Conventionover
configuration
.|-- build.gradle`-- src |-- main | `-- java `-- test `-- java
apply plugin: 'java'
2010
Conventionover
configuration
.|-- build.gradle`-- src |-- main | `-- java `-- test `-- java
apply plugin: 'java'
repositories { mavenCentral()}
dependencies { compile 'org.hibernate:hibernate:3.1.3', 'commons-lang:commons-lang:2.5' testCompile 'junit:junit:4.8.1'}
2010
apply plugin: 'java'
repositories { mavenCentral()}
configurations { pmd}
dependencies { compile 'org.hibernate:hibernate:3.1.3', 'commons-lang:commons-lang:2.5' testCompile 'junit:junit:4.8.1' pmd 'pmd:pmd:4.2.5'}
Groups of dependencies
2010
apply plugin: 'java'
version = '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testCompile 'junit:junit:4.8.1'
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>pl.gradle</groupId>
<artifactId>simple</artifactId> <packaging>jar</packaging>
<version>1.0-SNAPSHOT</version> <dependencies>
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId>
<version>4.8.1</version> <scope>test</scope>
</dependency> </dependencies>
<build> <plugins>
<plugin> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source>
<target>1.5</target> </configuration>
</plugin> </plugins>
</build></project>
<project name="simple" default="dist" basedir=".">
<property name="src" location="src/main/java" />
<property name="srcTest" location="src/test/java" /><property name="build" location="build" />
<property name="dist" location="${build}/lib" />
<path id="classpath.test">
<pathelement location="libs/junit-4.8.1.jar" /><pathelement location="${srcTest}" />
<pathelement location="${build}/classes" /> <pathelement location="${build}/test-classes" />
</path>
<target name="init"> <mkdir dir="${build}/classes" /> <mkdir dir="${build}/test-classes" />
</target>
<target name="compile" depends="init"> <javac srcdir="${src}" destdir="${build}/classes" />
</target>
<target name="testCompile" depends="init"> <javac srcdir="${srcTest}" destdir="${build}/test-classes"> <classpath refid="classpath.test" />
</javac></target>
<target name="test" depends="testCompile"> <junit fork="yes" haltonfailure="yes">
<batchtest fork="yes"> <fileset dir="${srcTest}">
<include name="**/*Test.java" /> <include name="**/Test*.java" />
</fileset> </batchtest> <classpath refid="classpath.test" />
<formatter type="plain"/> </junit>
</target><target name="dist" depends="compile">
<mkdir dir="${dist}" /> <jar jarfile="${dist}/simple.jar" basedir="${build}/classes" />
</target><target name="clean"> <delete dir="${build}" />
</target></project>
Conventionover
configuration
2010
repositories { mavenCentral()}
More onrepositories
2010
repositories { mavenCentral() mavenRepo urls: 'http://download.java.net/maven2' flatDir name: 'localRepository', dirs: 'lib''}
More onrepositories
2010
More onrepositories
// Maven2 layoutsomeroot/[organisation]/[module]/[revision]/[module]-[revision].[ext]
// Typical layout for an ivy repositorysomeroot/[organisation]/[module]/[revision]/[type]s/[artifact].[ext]
//Simple layout (the organization is not used, no nested folders.)someroot/[artifact]-[revision].[ext]
repositories { mavenCentral() mavenRepo urls: 'http://download.java.net/maven2' flatDir name: 'localRepository', dirs: 'lib''}
2010
apply plugin: 'java'apply plugin: 'maven'
configure(install.repositories.mavenInstaller) { pom.project { version '1.0-Maven' groupId 'myGroup' artifactId 'myArtifact' } }
Maven artifacts upload – local
repo
2010
apply plugin: 'java'apply plugin: 'maven'
configure(install.repositories.mavenInstaller) { pom.project { version '1.0-Maven' groupId 'myGroup' artifactId 'myArtifact' } }
Maven artifacts upload – local
repo
~/.m2/repository/myGroup/myArtifact/
|-- 1.0-Maven
| |-- myArtifact-1.0-Maven.jar
| `-- myArtifact-1.0-Maven.pom
`-- maven-metadata-local.xml
2010
configurations { deployerJars}
dependencies { deployerJars "org.apache.maven.wagon:wagon-ssh:1.0-beta-2"}
uploadArchives { repositories.mavenDeployer { configuration = configurations.deployerJars repository(url: "scp://myrepo.com/releases") { authentication(userName: "me", password: "pass") } }}
Maven artifacts upload – remote repo
2010
Core
2010
Core - summary
• Very concise build.gradle file– DSL– Convention over configuration
• Configuration is always possible
• Backward compatibility– Respects standards (layout a'la Maven)– Ivy & Maven dependencies and repositories
2010
Gradle & Maven – dependencies and repositories
• Full backward compatibility• Download from and upload to Maven
repos– Including generation of pom files
• Gradle offers more than Maven– Uses Apache Ivy– Mercury (Maven 3) will be supported
2010
Gradle – custom logic
• Directly within build script (build.gradle)– Any Groovy code– Can import 3rd party classes
2010
Gradle – custom logic
• Directly within build script (build.gradle)– Any Groovy code– Can import 3rd party classes
• Custom tasks– build.gradle says ”what”– ”how” described in task class
2010
Gradle – custom logic
• Directly within build script (build.gradle)– Any Groovy code– Can import 3rd party classes
• Custom tasks– build.gradle says ”what”– ”how” described in task class
• Custom plugins– More powerful than tasks, but still very easy to create– Some shipped with Gradle:
• Java, Groovy, Scala, War, Jetty, Maven, Code Quality, OSGi, Eclipse, Project Report
2010
Gradle – custom logic
• Directly within build script (build.gradle)– Any Groovy code– Can import 3rd party classes
• Custom tasks– build.gradle says ”what”– ”how” described in task class
• Custom plugins– More powerful than tasks, but still very easy to create– Some shipped with Gradle:
• Java, Groovy, Scala, War, Jetty, Maven, Code Quality, OSGi, Eclipse, Project Report
2010
public class ReportTask extends DefaultTask {
def FileCollection jars
@TaskAction def createReport() { def text = new StringBuilder() text.append("gradle -v".execute().text) jars.each { text.append("\t- $it.name\n") } println "GENERATING REPORT" new File('build/report.txt') << text }}
Custom logic :”how” described in task class
2010
import org.gradle.sample.report.ReportTask
configurations { myDependencies}
dependencies { ... myDependencies 'org.jmock:jmock:2.5.1'}
task generateReport(type: ReportTask) { jars = configurations.runtime + configurations.myDependencies}
Custom logic :”what” described in build.gradle
2010
Gradle – custom logic
2010
Web UIapply plugin: 'war'
repositories { ...}
dependencies { ...}
Conventionover
configuration
|-- build.gradle
`-- src
`-- main
|-- java
|-- resources
`-- webapp
2010
Web UIapply plugin: 'war'
repositories { ...}
dependencies { ...}
Conventionover
configuration
:war - Generates a war archive with all the compiled classes, the web-app content and the libraries.
2010
Web UI:war - Generates a war archive with all the compiled classes, the web-app content and the libraries.
:jettyRun - Uses your files as and where they are and deploys them to Jetty.
:jettyRunWar - Assembles the webapp into a war and deploys it to Jetty.
apply plugin: 'war'apply plugin: 'jetty'
repositories { ...}
dependencies { ...}
2010
Web UI
2010
Gradle & Ant – import of build.xml
<project> <target name="hello"> <echo>Hello, from Ant</echo> </target></project>
2010
Gradle & Ant – import of build.xml
<project> <target name="hello"> <echo>Hello, from Ant</echo> </target></project>
ant.importBuild "build.xml"
task myTask(dependsOn: hello) << { println "depends on hello ant task"}
2010
Gradle & Ant – import of build.xml
<project> <target name="hello"> <echo>Hello, from Ant</echo> </target></project>
ant.importBuild "build.xml"
task myTask(dependsOn: hello) << { println "depends on hello ant task"}
>gradle myTask:hello[ant:echo] Hello, from Ant:myTaskdepends on hello ant task
2010
Gradle & Ant – use of Ant tasks
task zip << {
ant.zip(destfile: 'archive.zip') {
fileset(dir: 'src') {
include(name: '**.xml')
exclude(name: '**.java')
}
}
2010
Gradle & Ant – use of Ant tasks
task zip << {
ant.zip(destfile: 'archive.zip') {
fileset(dir: 'src') {
include(name: '**.xml')
exclude(name: '**.java')
}
}
task dist(type: Zip) {
from 'src/dist‘
from configurations.runtime
into('libs‘)
}
2010
Gradle & Ant - summary
• Ant targets = Gradle tasks• Import of build.xml• Use of Ant
– ant object available in every build.gradle• AntBuilder used beneath
– some Ant tasks rewritten• for optimization purposes and to be consistent
with other concepts of Gradle
• Gradle = Ant with a boost
2010
Desktop UI - Groovyapply plugin: 'groovy'
repositories { mavenCentral()}
dependencies { groovy "org.codehaus.groovy:groovy-all:1.7.3"}
2010
Desktop UI - Groovyapply plugin: 'groovy'
repositories { mavenCentral()}
dependencies { groovy "org.codehaus.groovy:groovy-all:1.7.3"}
task run (dependsOn: build) << { ant.java(classname: 'org.gradle.sample.ui.swing.SwingApp', fork: true, classpath: "${sourceSets.main.runtimeClasspath.asPath}")}
2010
Desktop UI
2010
Web & Desktop UI - summary
• Convention over configuration makes things easy
• Jetty plugin available out-of-the-box• Many JVM languages supported
– Java, Groovy, Scala
2010
Multi-module build
multi|-- build.gradle|-- settings.gradle|-- core| `-- ...`-- ui |-- swing | `-- ... `-- web `-- ...
2010
Multi-module build
multi|-- build.gradle|-- settings.gradle|-- core| `-- ...|-- frontend| |-- swing| | `-- ...| |-- android| | `-- ...| `-- web| `-- ...`-- backend `-- swing `-- ...
2010
Multi-module build
multi|-- build.gradle|-- settings.gradle|-- core| `-- ...`-- ui |-- swing | `-- ... `-- web `-- ...
include "core", "ui:swing", "ui:web"
2010
Multi-module build
2010
Multi-module build – how many build.gradle files?
multi|-- build.gradle|-- settings.gradle|-- core| `-- ...`-- ui |-- swing | `-- ... `-- web `-- ...
multi|-- build.gradle|-- settings.gradle|-- core| |-- build.gradle| `-- ...`-- ui |-- swing | |-- build.gradle | `-- ... `-- web | |-- build.gradle `-- ...
configure(:core) { ...}
...
2010
Multi-module build - summary
• Layout – its up to you• Number of build.gradle files – you decide• Smart (partial) builds• Project treated as tasks
– You can depend on them
2010
2010
2010
2010
2010
2010
2010
2010
Use
Gradlefor your next project
2010
Links
• http://gradle.org• http://gradle.biz• http://docs.codehaus.org/display/GRADLE/
Cookbook• http://docs.codehaus.org/display/GRADLE/
Releases
2010
Thank you
Tomek Kaczanowskihttp://kaczanowscy.pl/tomek
Would be great if you could provide some feedback [email protected]