Convert antbuilder to gradle

I have a build script written in Groovy using antbuilder. I’m trying to convert this to gradle (to prove to my manager that Gradle is better). The tasks I am using are to get some build dependecies from Ivy and then execute a groovy task on my source. It looks like this…

def ant = new AntBuilder()
File scriptFile = new File(this.getClass().protectionDomain.codeSource.location.path)
File scriptDir = scriptFile.parentFile
File srcDir = new File(scriptDir, 'src')
File binDir = new File(scriptDir, 'bin')
if (binDir.isDirectory()) ant.delete(dir: binDir.path, failonerror: true)
  // get build dependencies with Ivy
File buildIvyFile = new File(scriptDir, 'build.ivy.xml')
ant.echo "Resolving dependencies with Ivy using ${buildIvyFile}"
ant.taskdef(name: 'ivy_resolve',
 classname: 'org.apache.ivy.ant.IvyResolve')
ant.taskdef(name: 'ivy_cachepath', classname: 'org.apache.ivy.ant.IvyCachePath')
ant.ivy_resolve(file: buildIvyFile.path, log: 'quiet')
ant.ivy_cachepath(pathid: 'ivy.path')
ant.echo
"Ivy classpath"
ant.path(refid: 'ivy.path').each { ant.echo "
$it" }
  ant.echo "Compiling src to [$binDir]"
ant.mkdir(dir: binDir.path)
ant.taskdef(name: 'groovyc', classname: 'org.codehaus.groovy.ant.Groovyc')
ant.groovyc(srcdir: srcDir.path, destdir: binDir.path, listfiles: false , classpathref: 'ivy.path')

When I run this as a groovy script it works and i get output like this…

$ groovy e.groovy
   [delete] Deleting directory /home/tauser02/build/groovy-lib/bin
     [echo] Resolving dependencies with Ivy using /home/tauser02/build/groovy-lib/build.ivy.xml
[ivy_resolve] :: Apache Ivy 2.3.0 - 20130110142753 :: http://ant.apache.org/ivy/ ::
[ivy_resolve] :: loading settings :: url = jar:file:/home/tauser02/groovy/lib/ivy-2.3.0.jar!/org/apache/ivy/core/settings/ivysettings.xml
     [echo] Ivy classpath
     [echo]
 /home/tauser02/.ivy2/cache/log4j/log4j/bundles/log4j-1.2.17.jar
     [echo]
 /home/tauser02/.ivy2/cache/org.slf4j/jul-to-slf4j/jars/jul-to-slf4j-1.7.7.jar
     [echo]
 /home/tauser02/.ivy2/cache/commons-io/commons-io/jars/commons-io-2.4.jar
     [echo]
 /home/tauser02/.ivy2/cache/commons-net/commons-net/jars/commons-net-3.3.jar
     [echo]
 /home/tauser02/.ivy2/cache/dom4j/dom4j/jars/dom4j-1.6.1.jar
     [echo]
 /home/tauser02/.ivy2/cache/javax.mail/mail/jars/mail-1.4.7.jar
     [echo] Compiling src to [/home/tauser02/build/groovy-lib/bin]
    [mkdir] Created dir: /home/tauser02/build/groovy-lib/bin
  [groovyc] Compiling 45 source files to /home/tauser02/build/groovy-lib/bin

now I know I can just throw all that code into a task as ant builder is available to me via the ant var. When I that i get this…

$ gradle compile_groovy
:compile_groovy
[ant:echo] Resolving dependencies with Ivy using /home/tauser02/.gradle/caches/2.0/scripts/build_1cfc3qinok0ilc9r72t8ho4h59/ProjectScript/no_buildscript/build.ivy.xml
:compile_groovy FAILED
  FAILURE: Build failed with an exception.
  * Where:
Build file '/home/tauser02/build/test/build.gradle' line: 22
  * What went wrong:
Execution failed for task ':compile_groovy'.
> taskdef class org.apache.ivy.ant.IvyResolve cannot be found
   using the classloader AntClassLoader[]
  * Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
  BUILD FAILED
  Total time: 8.64 secs

However, gradle cannot find the ivy taskdef classes probably because gradle does not ship with the ivy jar that ships with groovy. I’m sure there is a better way to deal with this and I have been beating my head against chapter 50 in the users guide but I am not getting any closer. what is the ‘Gradle’ way to do this?

The best way to do this is just convert it to a script using the groovy plugin. Something like:

apply plugin: 'groovy'
  // You can leave this out if you use the default src/main/groovy dir instead
sourceSets {
  main {
    groovy {
      srcDirs = [ 'src' ]
    }
  }
}
  repositories {
  ivy {
    url 'http://your.ivy.repo'
  }
}
  dependencies {
  compile 'log4j:log4j:1.4.12'
  compile 'org.slf4j:jul-to-slf4j:1.7.7'
  // etc...
}

Then you can just run groovyCompile. You’ll need to convert whatever is in your ivy settings to set up the repository properly.

typo - the task is ‘compileGroovy’ not ‘groovyCompile’

what ivy urls do i put in there so Gradle behaves like Groovy Grab ?

The same one(s) you have defined in your ivy settings file. If you’re not sure, it might be easier to just use maven central instead - the dependencies above should all be available:

repositories {
    mavenCentral()
}

I don’t have a ivy settings file. I’ve a feeling that Groovy comes with one in some jar. I’ll poke around…

it looks like Groovy has this under groovy/grape/defaultGrapeConfig.xml

<ivysettings>
  <settings defaultResolver="downloadGrapes"/>
  <resolvers>
    <chain name="downloadGrapes" returnFirst="true">
      <filesystem name="cachedGrapes">
        <ivy pattern="${user.home}/.groovy/grapes/[organisation]/[module]/ivy-[revision].xml"/>
        <artifact pattern="${user.home}/.groovy/grapes/[organisation]/[module]/[type]s/[artifact]-[revision](-[classifier]).[ext]"/>
      </filesystem>
      <ibiblio name="localm2" root="file:${user.home}/.m2/repository/" checkmodified="true" changingPattern=".*" changingMatcher="regexp" m2compatible="true"/>
      <!-- todo add 'endorsed groovy extensions' resolver here -->
      <ibiblio name="jcenter" root="http://jcenter.bintray.com/" m2compatible="true"/>
      <ibiblio name="codehaus" root="http://repository.codehaus.org/" m2compatible="true"/>
      <ibiblio name="ibiblio" m2compatible="true"/>
      <ibiblio name="java.net2" root="http://download.java.net/maven/2/" m2compatible="true"/>
    </chain>
  </resolvers>
</ivysettings>

I see 3 url’s in there. So, maybe respositories should look like this?

repositories {
  ivy {
      url 'http://jcenter.bintray.com/'
      url 'http://repository.codehaus.org/'
      url 'http://download.java.net/maven/2/'
  }
}

I’m not sure what the ibiblio is without a root

<ibiblio name="ibiblio" m2compatible="true"/>

ok, looks like just adding mavenCentral works. However, there is feature of Ivy where it has an attribute called conf that you can pass in “master” to get only the jar you are asking for and not other dependencies that are brought in by default. Here are the original dependencies I was using with Ivy…

<dependencies>
        <dependency org="log4j" name="log4j" rev="1.2.17" conf="master"/>
        <dependency org="org.slf4j" name="jul-to-slf4j" rev="1.7.7" conf="master"/>
        <dependency org="commons-io" name="commons-io" rev="2.4" conf="master"/>
        <dependency org="commons-net" name="commons-net" rev="3.3" conf="master"/>
        <dependency org="dom4j" name="dom4j" rev="1.6.1" conf="master"/>
        <dependency org="javax.mail" name="mail" rev="1.4.7" conf="master"/>
     </dependencies>

Note the conf. If i add that in gradle like this…

dependencies {
    compile(
        [group: "log4j", name: "log4j", version: "1.2.17", conf: 'master' ],
        [group: "org.slf4j", name: "jul-to-slf4j", version: "1.7.7", conf: 'master' ],
        [group: "commons-io", name: "commons-io", version: "2.4", conf: 'master' ],
        [group: "commons-net", name: "commons-net", version: "3.3", conf: 'master' ],
        [group: "dom4j", name: "dom4j", version: "1.6.1" , conf: 'master'],
        [group: "javax.mail", name: "mail", version: "1.4.7", conf: 'master' ]
    )
}

i get this error…

No such property: conf for class: org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency_Decorated

If you’re looking to prevent downloading transitive dependencies, you can turn it off for a given dependency as such:

compile(group: "log4j", name: "log4j", version: "1.2.17") { transitive = false}

Or for the entire configuration (ie all dependencies in that configuration):

configurations {
  compile { transitive = false }
}

You would have to list each url in a separate ivy block. You’d also need to specify that they are maven compatible:

ivy {
  url 'http://repositoru.codehaus.org/'
  layout "maven"
}

Note that jcenter is a pre-configured repository like mavenCentral(). You can just use jcenter() instead of listing out the full ivy {…} block.