The Hand That Rocks The Gradle

A few more month passed, and much has happened in the clojure scene. Clojure 1.1.0 was released in 2009-12. The clojure plugin clj-gradle has been renamed to clojuresque and updated to 1.3. Clojars.org, which is a community repo of clojure libraries accessable via mvn and ivy is online. I’ve done some clojure talks, added a few people to my clojure army. :)

But it means my previous two posts on clojure and gradle are very outdated. So I figure it’s time to share my current clojure and gradle setup. It’s much more simple now. The only thing you are required to do before following this, is to have gradle 0.8 setup. That’s it.

First you need to setup a sandbox directory. Inside the directory, you want to create a file build.gradle
Here is what I use.

buildscript {
  repositories {
    mavenRepo name: 'clojars', urls: 'http://clojars.org/repo'
  }
  dependencies {
    classpath 'clojuresque:clojuresque:1.3.0'
  }
}

usePlugin(clojuresque.ClojurePlugin)

group = 'yourgrouphere'
version = '1.0.0'

warnOnReflection = true
aotCompile = true

clojureSnapshotsRepo(repositories)
clojarsRepo(repositories)
gradleHomeRepo(repositories)

repositories {
  mavenCentral()
  mavenRepo urls: "http://build.clojure.org/releases"
}

dependencies {
  compile 'org.clojure:clojure:1.2.0-master-SNAPSHOT'
  compile 'org.clojure:clojure-contrib:1.2.0-master-SNAPSHOT'
  compile 'enlive:enlive:1.0.0-SNAPSHOT'
  compile 'org.ccil.cowan.tagsoup:tagsoup:1.2'
//  compile 'org.clojure:clojure:1.1.0'
//  compile 'org.clojure:clojure-contrib:1.1.0'
}

configureClojarsDeploy(uploadArchives)

task initProject(description: 'Initialize project directory structure.') << {
  ['clojure'].each {
  convention.sourceSets.all*."${it}".srcDirs*.each { it.mkdirs() }
  }
}

task copyToLib(dependsOn: configurations.default.buildArtifacts, type: Copy) {
  into('build/lib')
  from configurations.default
  from configurations.default.allArtifacts*.file
}

It has a couple of helpful targets. The initProject setup the src subdirectories for you. If you have groovy and java code, you can of course append to that. The copyToLib target will copy all the jars into build/lib.

The script also set up clojars.org repo for you. In fact, it pulls clojuresque from it. I also enable mvn central repo, as well as the build.clojure.org repo to pull either release or nightly snapshot version of the clojure and clojure-contrib.

I also went ahead and added enlive to the dependencies to show you how to add dependencies from clojars.org. No, it’s not a typo. It really is enlive:enlive:1.0.0-SNAPSHOT. Beacuse in clojars.org, the name of the project is used in both group and artifact id. It doesn’t follow the java convention. The tagsoup dependency is because of enlive. That one is from mvn repo and does follow the java convention.

You’ll see I have the 1.1.0 release for clojure and clojure-contrib commented out. It’s very important you use matching clojure and clojure-contrib version. I tend to do my development using the bleeding edge version. But if you want to swtich back to release. It’s as easy as comment out the two 1.2.0 entries, and uncomment the two 1.1.0 entries.

Now, let’s create src/main/clojure/mystuff/example.clj

(ns mystuff.example
    (:use net.cgrand.enlive-html)
    (:import java.net.URL)
    (:gen-class))

  (defn -main []
      (println (-> "http://www.penny-arcade.com/comic/" URL. html-resource
                     (select [:.body :img]) first :attrs :src)))

Then issue “gradle build”. If all goes well, you will get a build successful. Now issue “gradle copyToLib”. All the jars will be copied to build/lib. I named my sandbox directory blogtest. So I have a blogtest-1.0.0.jar.

Time to see the url of the latest comic.

java -cp ./clojure-1.2.0-master-SNAPSHOT.jar:./clojure-contrib-1.2.0-master-SNAPSHOT.jar:./enlive-1.0.0-SNAPSHOT.jar:./tagsoup-1.2.jar:./blogtest-1.0.0.jar mystuff.example
http://art.penny-arcade.com/photos/807260572_n6CMU-L.jpg

Well, that worked, even if the comic isn’t very funny today. Yes, you can in fact use wildcard for classpath if you want. :)

Comments (4)

[...] #clojure #gradle blog post with clojuresque. This is my current setup, minus the mix groovy part (here, via @wmacgyver) — After all this recent chatter discussing the pros and cons of Leiningen [...]

faenvieMarch 17th, 2010 at 7:29 pm

2 possible improvements

*1*

it should be possible write a build-script like this:

repositories {
clojureSnapshotsRepo()
//clojarsRepo()
mavenCentral()
mavenRepo urls: “http://build.clojure.org/releases”
}

dependencies {
compile gradleApi()
groovy localGroovy()

}

see gradle-mailing-list:

http://old.nabble.com/a-conventient-way-to-resolve-from-%24GRADLE_HOME-lib—to27872778.html
http://old.nabble.com/Can-I-add-other-dependency-resolvers–to27758967.html

*2*

gradle-users that copy clojuresque.jar to $GRADLE_HOME/lib/plugins
should be able to leave out the following lines

buildscript {
repositories {
mavenRepo name: ‘clojars’, urls: ‘http://clojars.org/repo’
}
dependencies {
classpath ‘clojuresque:clojuresque:1.3.0′
}
}

faenvieMarch 17th, 2010 at 7:32 pm

i forgot to mention: you need gradle-0.9-SNAPHOT for this

MMarch 17th, 2010 at 10:30 pm

Thank you for the suggestion. on 2nd change, I left the dependencies there so to avoid having to copy or download clojuresque.jar. I figure this way, it’s the least amount of effort to get started. Install gradle, and you are ready to go. It’s handy for me too, since I move around on lots of machines.

I’ll try out your first change once gradle 0.9 is released.