Gradle talk, Javarsovia 2010

8,495 views

Published on

Slides from my Gradle talk, Javarsovia 2010.

Published in: Technology, Education

Gradle talk, Javarsovia 2010

  1. 1. Gradle Tomek Kaczanowski http://kaczanowscy.pl/tomek 2010
  2. 2. IMPORTANT All code samples are compatible with version 0.9-preview-3 2010
  3. 3. There are no simple builds 2010
  4. 4. 2010
  5. 5. • 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
  6. 6. 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
  7. 7. Intro 2010
  8. 8. 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
  9. 9. 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
  10. 10. 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
  11. 11. 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
  12. 12. 2010
  13. 13. 2010
  14. 14. 2010
  15. 15. MyProject • Core – Classes used by UI subprojects – Java • UI:Web – Web application • UI:Swing – Desktop application – Groovy 2010
  16. 16. . |-- build.gradle `-- src |-- main | `-- java `-- test `-- java Convention over configuration 2010
  17. 17. . |-- build.gradle `-- src |-- main | `-- java `-- test `-- java apply plugin: 'java' Convention over configuration 2010
  18. 18. . |-- build.gradle `-- src |-- main | `-- java `-- test `-- java apply plugin: 'java' apply plugin: 'java' version="1.0-SNAPSHOT" archivesBaseName = "whatever" Configuration libsDirName="build/artifacts" is always possible 2010
  19. 19. . . |-- build.gradle |-- build.gradle `-- src |-- src |-- main `-- test | `-- java `-- test `-- java apply plugin: 'java' Configuration is always possible 2010
  20. 20. . . |-- build.gradle |-- build.gradle `-- src |-- src |-- main `-- test | `-- java `-- test `-- java apply plugin: 'java' sourceSets { apply plugin: 'java' main { java { srcDir 'src' } } test { Configuration java { srcDir 'test' is always } possible } } 2010
  21. 21. . apply plugin: 'java' |-- build.gradle `-- src |-- main | `-- java `-- test `-- java Convention over configuration 2010
  22. 22. . apply plugin: 'java' |-- build.gradle `-- src repositories { |-- main mavenCentral() | `-- java } `-- test `-- java dependencies { compile 'org.hibernate:hibernate:3.1.3', 'commons-lang:commons-lang:2.5' testCompile 'junit:junit:4.8.1' } Convention over configuration 2010
  23. 23. apply plugin: 'java' repositories { Groups of mavenCentral() dependencies } 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' } 2010
  24. 24. apply plugin: 'java' <?xml version="1.0" encoding="UTF-8"?> <project name="simple" default="dist" basedir="."> <project xmlns="http://maven.apache.org/POM/4.0.0" <property name="src" location="src/main/java" /> version = '1.0-SNAPSHOT' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <property name="srcTest" location="src/test/java" /> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 <property name="build" location="build" /> repositories { http://maven.apache.org/maven-v4_0_0.xsd"> <property name="dist" location="${build}/lib" /> mavenCentral() <modelVersion>4.0.0</modelVersion> } <groupId>pl.gradle</groupId> <path id="classpath.test"> <artifactId>simple</artifactId> <pathelement location="libs/junit-4.8.1.jar" /> dependencies { <packaging>jar</packaging> <pathelement location="${srcTest}" /> testCompile 'junit:junit:4.8.1' <version>1.0-SNAPSHOT</version> <pathelement location="${build}/classes" /> } <dependencies> <pathelement location="${build}/test-classes" /> <dependency> </path> <groupId>junit</groupId> <artifactId>junit</artifactId> <target name="init"> <version>4.8.1</version> <mkdir dir="${build}/classes" /> <scope>test</scope> <mkdir dir="${build}/test-classes" /> </dependency> </target> </dependencies> <build> <target name="compile" depends="init"> <plugins> <javac srcdir="${src}" destdir="${build}/classes" /> <plugin> </target> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <target name="testCompile" depends="init"> <configuration> <javac srcdir="${srcTest}" destdir="${build}/test-classes"> <source>1.5</source> <classpath refid="classpath.test" /> <target>1.5</target> </javac> </configuration> </target> </plugin> <target name="test" depends="testCompile"> </plugins> <junit fork="yes" haltonfailure="yes"> </build> <batchtest fork="yes"> </project> <fileset dir="${srcTest}"> <include name="**/*Test.java" /> <include name="**/Test*.java" /> </fileset> Convention </batchtest> <classpath refid="classpath.test" /> <formatter type="plain"/> </junit> over </target> <target name="dist" depends="compile"> <mkdir dir="${dist}" /> <jar jarfile="${dist}/simple.jar" basedir="${build}/classes" /> configuration </target> <target name="clean"> <delete dir="${build}" /> </target> </project> 2010
  25. 25. repositories { mavenCentral() } More on repositories 2010
  26. 26. repositories { mavenCentral() mavenRepo urls: More on 'http://download.java.net/maven2' flatDir name: 'localRepository', repositories dirs: 'lib'' } 2010
  27. 27. repositories { mavenCentral() mavenRepo urls: More on 'http://download.java.net/maven2' flatDir name: 'localRepository', repositories dirs: 'lib'' } // Maven2 layout someroot/[organisation]/[module]/[revision]/[module]-[revision].[ext] // Typical layout for an ivy repository someroot/[organisation]/[module]/[revision]/[type]s/[artifact].[ext] //Simple layout (the organization is not used, no nested folders.) someroot/[artifact]-[revision].[ext] 2010
  28. 28. apply plugin: 'java' apply plugin: 'maven' Maven artifacts configure(install.repositories. upload – local mavenInstaller) { repo pom.project { version '1.0-Maven' groupId 'myGroup' artifactId 'myArtifact' } } 2010
  29. 29. apply plugin: 'java' apply plugin: 'maven' Maven artifacts configure(install.repositories. upload – local mavenInstaller) { repo pom.project { version '1.0-Maven' groupId 'myGroup' artifactId 'myArtifact' } } ~/.m2/repository/myGroup/myArtifact/ |-- 1.0-Maven | |-- myArtifact-1.0-Maven.jar | `-- myArtifact-1.0-Maven.pom `-- maven-metadata-local.xml 2010
  30. 30. Maven artifacts upload – remote repo 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") } } } 2010
  31. 31. Core 2010
  32. 32. 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
  33. 33. 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
  34. 34. Gradle – custom logic • Directly within build script (build.gradle) – Any Groovy code – Can import 3rd party classes 2010
  35. 35. 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
  36. 36. 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
  37. 37. 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
  38. 38. Custom logic : ”how” described in task class 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.namen") } println "GENERATING REPORT" new File('build/report.txt') << text } } 2010
  39. 39. Custom logic : ”what” described in build.gradle 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 } 2010
  40. 40. Gradle – custom logic 2010
  41. 41. Web UI apply plugin: 'war' repositories { ... } dependencies { ... } |-- build.gradle `-- src Convention `-- main |-- java over |-- resources configuration `-- webapp 2010
  42. 42. Web UI apply plugin: 'war' :war - Generates a war archive with all the compiled classes, repositories { the web-app content and the ... libraries. } dependencies { ... } Convention over configuration 2010
  43. 43. Web UI apply plugin: 'war' :war - Generates a war archive apply plugin: 'jetty' with all the compiled classes, the web-app content and the repositories { libraries. ... } :jettyRun - Uses your files as dependencies { and where they are and deploys ... them to Jetty. } :jettyRunWar - Assembles the webapp into a war and deploys it to Jetty. 2010
  44. 44. Web UI 2010
  45. 45. Gradle & Ant – import of build.xml <project> <target name="hello"> <echo>Hello, from Ant</echo> </target> </project> 2010
  46. 46. 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
  47. 47. 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 :myTask depends on hello ant task 2010
  48. 48. Gradle & Ant – use of Ant tasks task zip << { ant.zip(destfile: 'archive.zip') { fileset(dir: 'src') { include(name: '**.xml') exclude(name: '**.java') } } 2010
  49. 49. 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
  50. 50. 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
  51. 51. Desktop UI - Groovy apply plugin: 'groovy' repositories { mavenCentral() } dependencies { groovy "org.codehaus.groovy:groovy-all:1.7.3" } 2010
  52. 52. Desktop UI - Groovy apply 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
  53. 53. Desktop UI 2010
  54. 54. 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
  55. 55. Multi-module build multi |-- build.gradle |-- settings.gradle |-- core | `-- ... `-- ui |-- swing | `-- ... `-- web `-- ... 2010
  56. 56. Multi-module build multi |-- build.gradle |-- settings.gradle |-- core | `-- ... |-- frontend | |-- swing | | `-- ... | |-- android | | `-- ... | `-- web | `-- ... `-- backend `-- swing `-- ... 2010
  57. 57. Multi-module build multi |-- build.gradle |-- settings.gradle |-- core | `-- ... `-- ui |-- swing | `-- ... `-- web `-- ... include "core", "ui:swing", "ui:web" 2010
  58. 58. Multi-module build 2010
  59. 59. Multi-module build – how many build.gradle files? multi multi |-- build.gradle |-- build.gradle |-- settings.gradle |-- settings.gradle |-- core |-- core | `-- ... | |-- build.gradle `-- ui | `-- ... |-- swing `-- ui | `-- ... |-- swing `-- web | |-- build.gradle `-- ... | `-- ... `-- web configure(:core) { | |-- build.gradle ... `-- ... } ... 2010
  60. 60. 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
  61. 61. 2010
  62. 62. 2010
  63. 63. 2010
  64. 64. 2010
  65. 65. 2010
  66. 66. 2010
  67. 67. 2010
  68. 68. Use Gradle for your next project 2010
  69. 69. Links • http://gradle.org • http://gradle.biz • http://docs.codehaus.org/display/GRADLE/ Cookbook • http://docs.codehaus.org/display/GRADLE/ Releases 2010
  70. 70. Thank you Tomek Kaczanowski http://kaczanowscy.pl/tomek Would be great if you could provide some feedback at tkaczano@poczta.onet.pl 2010

×