Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Demystifying Gradle DSL

Demystifying Gradle DSL

Slides from my talk at the GrailsConf 2015, New Delhi.

Kunal Dabir

January 10, 2015
Tweet

More Decks by Kunal Dabir

Other Decks in Programming

Transcript

  1. About  the  Talk • Prerequisites   • Basic  understanding  of

     build  systems   • Some  exposure  to  Gradle   • Beginner  level  of  exposure  to  Groovy/Java   ! • Takeaways   • Learn  a  trick  or  two  to  read  and  write  DSLs   • A  simpler  way  to  look  at  Gradle  Scripts 2
  2. Introduction  (About  me) • Love  writing  code  in  Groovy,  Java,

     Ruby,  Scala  and   JavaScript  (CoffeeScript).     • Work  at  ThoughtWorks   • Co-­‐organizer  of  Pune  Java  User  Group   • Projects  hosted  on  Github   • (want  to  get  better  at)  running,  playing  drums  and   writing  book 3
  3. Domain  Specific  Language • “A  Domain  Specific  Language  (DSL)  is

     a  programming   language  designed  specifically  to  express  solutions  to   problems  in  a  specific  domain”   ! ! ! ! ! • http://c2.com/cgi/wiki?DomainSpecificLanguage   • http://en.wikipedia.org/wiki/Domain-­‐specific_language 5
  4. Example  of  DSL ! create("my-­‐project")  {      dir("src/main/java")  {

             file("Hello.java")  {              """       ………              """.stripIndent()          }      }      file  "build.gradle",  "apply  plugin:  'java'"      file  "README.md",  "#  Hello  World  Project"   }   ! ! Directree:    https://github.com/kdabir/directree 6
  5. Example  of  DSL ! create("my-­‐project")  {      dir("src/main/java")  {

             file("Hello.java")  {              """                  public  static  void  main(String[]  args){                          System.out.println("Hello  World");                  }              """.stripIndent()          }      }      file  "build.gradle",  "apply  plugin:  'java'"      file  "README.md",  "#  Hello  World  Project"   }   Directree:    https://github.com/kdabir/directree 7
  6. External  v/s  Internal  DSL   • Internal   • Sinatra

        • Ratpack   • Gradle   • MarkupBuilder   !     ! ! ! ! ! ! ! ! ! ! • External     • Apache  httpd  config   • Gherkin  (cucumber)   • Make   • Markdown   ! ! ! 8
  7. External  v/s  Internal  DSL   • Groovy  MarkupBuilder   !

       builder.html  {          body  {              h1  "hello  MarkupBuilder"          }      }   ! • Markdown   !    #  hello  Markdown 9
  8. Gradle  intro • an  advanced  build  system   • follows

     conventions   • yet  very  flexible   • Groovy  build  scripts   • rich  domain  model  for  build   • …  And  much  more 11
  9. Follows  Conventions • Create  a  build.gradle  file  in  project  root

     :   !    apply  plugin:  'java'   ! • A  valid  minimal  Java  project  build  file   • It  can  build  a  Jar  of  project   • Uses  conventional  src/main/java  for  source  files 12
  10. Provides  Flexibility • For  example,  Changing  source  directories:   !

       sourceSets  {          main.java.srcDir  'src'          test.java.srcDir  'test'      } 13
  11. Reuses  Existing  Infrastructure • Find  dependencies  in  MavenCentral   !

       repositories  {          mavenCentral()      }   ! • And  use  them  in  your  project   !    dependencies  {          compile  'org.slf4j:slf4j-­‐api:1.7.9'          testCompile  'junit:junit:4.10'      }   14
  12. Supports  Adding  Extra  Behaviour • By  defining  custom  tasks  

    !    task  sayHello  <<  {          println  "Hello  Gradle  users"      }   15
  13. Lists • Defining   !        def  list

     =  []              list  =  [1,2,3]       • Accessing   !        println  list[2] 17
  14. Maps • Defining   !        def  map

     =  [:]              map  =  [a:4,  b:5]       • Accessing   !        println  map.a              println  map['b']   18
  15. Closures • Declaring   !        def  closure

     =  {}              closure  =  {  println  "closure  is  powerful"}   ! • Calling   !          closure.call()              closure()              closure("groovy")   19
  16. Closure  Parameters • Sometimes  it’s  magic   !    

       closure  =  {  println  "$it  is  powerful"}              closure("groovy")   !        //  groovy  is  powerful       • Multiple  parameters   !        def  adder  =  {a,b  -­‐>  a  +  b}              println  adder(1,2)   20
  17. Methods   • Declaring  a  method  that  takes  a  Map

      !        def  method(Map  options)  {                def  a  =  options.a  ?:  10                def  b  =  options.b  ?:  20          }   ! 21
  18. Methods   • Calling   !        method([a:30,b:40])

         ! • Can  also  be  called  like   !        method(a:30,  b:40)      ! • Optionally   !        method(a:20) 22
  19. Methods   • A  method  that  takes  a  Closure  

    !        def  repeat(int  a,  Closure  c)  {                a.times  {  c.call()  }          } 23
  20. Methods   • Calling   !        repeat(2,

     {println  "fun  begins"})   ! • Can  also  be  called  like   !        repeat(2)  {                println  "fun  begins"          } 24
  21. How  it  starts      apply  plugin:  'java'    

     apply(plugin:  'java')      apply([plugin:  'java']) 26
  22. How  it  starts      apply  plugin:  'java'    

     apply(plugin:  'java')      apply([plugin:  'java'])      project.apply([plugin:  'java']) 26
  23. And  the  credit  goes  to… Project void apply(Map<String, ?> options)!

    Configures this project using plugins or scripts. The following options are available: !•! from: A script to apply to the project. Accepts any path supported by Project.uri(). !•! plugin: The id or implementation class of the plugin to apply to the project. !•! to: The target delegate object or objects. Use this to configure objects other than the project. For more detail, see ObjectConfigurationAction. ! • http://www.gradle.org/docs/current/dsl/ org.gradle.api.Project.html#org.gradle.api.Project:apply(java.util.Map) 27
  24. Project  API • Central  API  to  the  Gradle  build  script

      • Available  as  ‘project’  reference  in  build  script   • Build  Script  is  evaluated  against  the  instance  of  this   project  object.   • Available  implicitly  in  the  script  top  level*   • methods/properties  are  looked  up  on  this  object   by  default.   • One  project  per  build.gradle 29
  25. Project  Object • Properties   void  setDescription(String  description)   Sets

     a  description  for  this  project.   ! • Methods   boolean  delete(Object...  paths)   Deletes  files  and  directories.   ! • Script  blocks   void  dependencies(Closure  configureClosure)   Configures  the  dependencies  for  this  project. 30
  26. Project  Properties • Setting  project  properties  like  :   !

       group  =  'org.example'      version  =  '0.1'      description  =  'An  awesome  groovy  library'   ! • Find  properties  declared  on  Project  API.     • Make  sure  they  are  not  read-­‐only. 31
  27. Project  Properties • Getters  and  Setters  on  project  object.  

      getBuildDir()/setBuildDir(Object  path)   • Can  be  set  using  groovy  property  notation     buildDir  =  “…”   ! • Extra  properties   • can  be  declared  using  ext  namespace.     ext.myProp  =  “abc”   • it  becomes  property  of  project       println  project.myProp 32
  28. Where  do  methods  come  from  ? ! • Methods  defined

     on  Project  itself   • Find  those  in  Project  API  Documentation   ! • Methods  declared  in  the  build  file   • def  myMethod  … 33
  29. Where  do  methods  come  from  ? • Extension/Conventions  added  by

     plugins   • Plugins  can  add  more  methods  to  project   • like  sourceSets  is  added  by  java  plugin   ! • Each  task  becomes  a  method  on  project   • Each  task  name  becomes  a  method   ! ! taskA { description = “some task” }! • so  that  task  can  be  easily  referenced  in  a  script   ! •  Methods  of  parent  project 34
  30. Script  Blocks ! repositories  {      mavenCentral()   }

          can  be  rewri`en  as:     ! project.repositories  ({      mavenCentral()   }) 36
  31. Script  Blocks • Special  methods   • Takes  in  a

     Closure  as  parameter   • Delegates  to  a  special  Handler  whose  methods  are   available  in  the  block’s  context   ! ! ! ! ! http://www.gradle.org/docs/current/dsl/org.gradle.api.Project.html#N1486F   37
  32. Script  Blocks  -­‐  Example ! repositories  {  …  }  

    ! • RepositoryHandler  Handles  the  methods  calls   made  in  context  of  repositories  script  block   • Methods  like     mavenCentral()     jcenter()     ivy()   ! http://www.gradle.org/docs/current/dsl/org.gradle.api.artifacts.dsl.RepositoryHandler.html   38
  33. Script  Blocks  -­‐  Another  Example ! dependencies  {  …  }

      ! • Delegates  to  DependencyHandler   • Executes  the  closure  in  against  the   DependenciesHandler   • methods  like  compile,  testCompile   ! ! http://www.gradle.org/docs/current/dsl/org.gradle.api.artifacts.dsl.DependencyHandler.html 39
  34. Script  Blocks allprojects { } Configures this project and each

    of its sub-projects. ! artifacts { } Configures the published artifacts for this project. ! buildscript { } Configures the build script classpath for this project. ! configurations { } Configures the dependency configurations for this project. ! dependencies { } Configures the dependencies for this project. ! repositories { } Configures the repositories for this project. ! sourceSets { } Configures the source sets of this project. ! subprojects { } Configures the sub-projects of this project. ! publishing { } Configures the PublishingExtension added by the publishing plugin. 40
  35. Creating  Task  Objects • Project  works  as  a  Task  Factory

      • Project  has  overloaded  task  method   • All  of  which  return  an  instance  of  Task 42
  36. Creating  Task  Objects ! task(String  name)   ! ! task(String

     name,  Closure  configureClosure)   ! ! task(Map<String,?>  args,  String  name)   ! ! task(Map<String,?>  args,  String  name,                 Closure  configureClosure)   43
  37. Task  Action  -­‐  the  concise  way ! ! ! task

     sayHello  <<  {      println  "Hello  Gradle  user"   } 44
  38. Task  Config ! ! ! sayHello  {      group

     =  "my  tasks"      description  =  "greets  user"   } 45
  39. Config  as  map ! ! ! task  sayBye  (description  :

     "says  bye",                              group  :  "my  tasks") 46
  40. Task  object’s  methods ! ! ! sayBye.doLast  {    

     println  "B-­‐bye"   }   ! ! ! http://www.gradle.org/docs/current/javadoc/org/gradle/api/Task.html   47
  41. Available  Tasks ! ! $  gradle  tasks   …  

    My  tasks  tasks   -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐   sayBye  -­‐  says  bye   sayHello  -­‐  greets  user 48
  42. Execute  tasks   ! ! $  gradle  sH  sB  

    :sayHello   Hello  Gradle  user   :sayBye   B-­‐bye   ! 49
  43. Bookmark  These ! • Read  the  DSL   • http://www.gradle.org/docs/current/dsl/

        ! ! • Read  the  JavaDoc   • http://www.gradle.org/docs/current/javadoc/   50